From d7917f403464960170cd336836a08f48ae09ffde Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Thu, 26 Jan 2023 09:45:22 -0600 Subject: [PATCH 01/21] Commit session when refreshing invoices --- tailbone_quickbooks/views/quickbooks/invoices.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tailbone_quickbooks/views/quickbooks/invoices.py b/tailbone_quickbooks/views/quickbooks/invoices.py index a70a8ec..4735027 100644 --- a/tailbone_quickbooks/views/quickbooks/invoices.py +++ b/tailbone_quickbooks/views/quickbooks/invoices.py @@ -318,6 +318,7 @@ class ExportableInvoiceView(MasterView): progress.session.save() else: + session.commit() if progress: progress.session.load() progress.session['complete'] = True From eaaf4375684eb6cb9c29386850f72f47263f0beb Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Thu, 26 Jan 2023 09:46:05 -0600 Subject: [PATCH 02/21] Update changelog --- CHANGELOG.md | 4 ++++ tailbone_quickbooks/_version.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99cac9f..8e09c3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to tailbone-quickbooks will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [0.1.2] - 2023-01-26 +### Changed +- Commit session when refreshing invoices. + ## [0.1.1] - 2023-01-25 ### Changed - Only include "export invoice" logic if user has perm. diff --git a/tailbone_quickbooks/_version.py b/tailbone_quickbooks/_version.py index 4984097..de58c20 100644 --- a/tailbone_quickbooks/_version.py +++ b/tailbone_quickbooks/_version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8; -*- -__version__ = '0.1.1' +__version__ = '0.1.2' From 816874cc8473a57c492b24eae1b544f5322eaf8e Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 20 Feb 2023 18:30:29 -0600 Subject: [PATCH 03/21] Refactor `Query.get()` => `Session.get()` per SQLAlchemy 1.4 --- tailbone_quickbooks/views/quickbooks/invoices.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tailbone_quickbooks/views/quickbooks/invoices.py b/tailbone_quickbooks/views/quickbooks/invoices.py index 4735027..e0931e4 100644 --- a/tailbone_quickbooks/views/quickbooks/invoices.py +++ b/tailbone_quickbooks/views/quickbooks/invoices.py @@ -342,7 +342,7 @@ class ExportableInvoiceView(MasterView): invoices = [] for uuid in uuids: - invoice = self.Session.query(model.QuickbooksExportableInvoice).get(uuid) + invoice = self.Session.get(model.QuickbooksExportableInvoice, uuid) if invoice and self.exportable(invoice): invoices.append(invoice) if not invoices: @@ -370,7 +370,7 @@ class ExportableInvoiceView(MasterView): invoices = [] for uuid in uuids: - invoice = self.Session.query(model.QuickbooksExportableInvoice).get(uuid) + invoice = self.Session.get(model.QuickbooksExportableInvoice, uuid) if invoice and self.exportable(invoice): invoices.append(invoice) if not invoices: @@ -399,7 +399,7 @@ class ExportableInvoiceView(MasterView): invoices = [] for uuid in selected: - invoice = self.Session.query(model.QuickbooksExportableInvoice).get(uuid) + invoice = self.Session.get(model.QuickbooksExportableInvoice, uuid) if invoice and invoice.status_code == invoice.STATUS_EXPORTABLE: invoices.append(invoice) else: From 18419fc861fc73dab5c8090f37b04b4f28e00ba0 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 20 Feb 2023 18:30:42 -0600 Subject: [PATCH 04/21] Catch/display error when exporting QB invoices don't let it raise to email alert --- tailbone_quickbooks/views/quickbooks/invoices.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tailbone_quickbooks/views/quickbooks/invoices.py b/tailbone_quickbooks/views/quickbooks/invoices.py index e0931e4..6e331ac 100644 --- a/tailbone_quickbooks/views/quickbooks/invoices.py +++ b/tailbone_quickbooks/views/quickbooks/invoices.py @@ -411,7 +411,16 @@ class ExportableInvoiceView(MasterView): return self.redirect(self.get_index_url()) # perform actual export and capture result - result = self.do_export(invoices) + try: + result = self.do_export(invoices) + + except Exception as error: + log.warning("failed to export invoices: %s", + [inv.uuid for inv in invoices], + exc_info=True) + self.request.session.flash(simple_error(error), 'error') + return self.redirect(self.request.get_referrer( + default=self.get_index_url())) # clear out current checkbox selection self.set_selected(set()) From 289b9dccf32120416089493219da44d24899bd1b Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 20 Feb 2023 18:56:16 -0600 Subject: [PATCH 05/21] Fix fieldname for invoice view --- tailbone_quickbooks/views/quickbooks/invoices.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tailbone_quickbooks/views/quickbooks/invoices.py b/tailbone_quickbooks/views/quickbooks/invoices.py index 6e331ac..6ff8467 100644 --- a/tailbone_quickbooks/views/quickbooks/invoices.py +++ b/tailbone_quickbooks/views/quickbooks/invoices.py @@ -87,7 +87,7 @@ class ExportableInvoiceView(MasterView): 'supplies_amount', 'quickbooks_vendor_name', 'quickbooks_vendor_terms', - 'quickbooks_vendor_bank_account', + 'quickbooks_bank_account', 'quickbooks_export_template', 'status_code', 'status_text', From 0b71e20f74f3e43960f6ec67950ac9a0249a0d43 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 20 Feb 2023 21:55:55 -0600 Subject: [PATCH 06/21] Update changelog --- CHANGELOG.md | 6 ++++++ tailbone_quickbooks/_version.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e09c3e..11ed162 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to tailbone-quickbooks will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [0.1.3] - 2023-02-20 +### Changed +- Refactor `Query.get()` => `Session.get()` per SQLAlchemy 1.4. +- Catch/display error when exporting QB invoices. +- Fix fieldname for invoice view. + ## [0.1.2] - 2023-01-26 ### Changed - Commit session when refreshing invoices. diff --git a/tailbone_quickbooks/_version.py b/tailbone_quickbooks/_version.py index de58c20..d60824a 100644 --- a/tailbone_quickbooks/_version.py +++ b/tailbone_quickbooks/_version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8; -*- -__version__ = '0.1.2' +__version__ = '0.1.3' From bc96879fe3c836a2537db7a63035e41dba67b904 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Tue, 21 Feb 2023 18:49:15 -0600 Subject: [PATCH 07/21] Show invoice amounts as currency --- tailbone_quickbooks/views/quickbooks/invoices.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tailbone_quickbooks/views/quickbooks/invoices.py b/tailbone_quickbooks/views/quickbooks/invoices.py index 6ff8467..98d9ca5 100644 --- a/tailbone_quickbooks/views/quickbooks/invoices.py +++ b/tailbone_quickbooks/views/quickbooks/invoices.py @@ -147,8 +147,10 @@ class ExportableInvoiceView(MasterView): g.set_sort_defaults('invoice_date', 'desc') g.set_link('invoice_date') - # invoice_total + # currency fields g.set_type('invoice_total', 'currency') + g.set_type('shipping_amount', 'currency') + g.set_type('supplies_amount', 'currency') # status_code g.set_enum('status_code', model.QuickbooksExportableInvoice.STATUS) @@ -212,8 +214,10 @@ class ExportableInvoiceView(MasterView): # vendor f.set_renderer('vendor', self.render_vendor) - # invoice_total + # currency fields f.set_type('invoice_total', 'currency') + f.set_type('shipping_amount', 'currency') + f.set_type('supplies_amount', 'currency') # status f.set_enum('status_code', model.QuickbooksExportableInvoice.STATUS) From 92c817dfdad154b7d7a00560a8fec449c8aa75d5 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Tue, 21 Feb 2023 19:17:29 -0600 Subject: [PATCH 08/21] Update changelog --- CHANGELOG.md | 4 ++++ tailbone_quickbooks/_version.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11ed162..04cbdb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to tailbone-quickbooks will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [0.1.4] - 2023-02-21 +### Changed +- Show invoice amounts as currency. + ## [0.1.3] - 2023-02-20 ### Changed - Refactor `Query.get()` => `Session.get()` per SQLAlchemy 1.4. diff --git a/tailbone_quickbooks/_version.py b/tailbone_quickbooks/_version.py index d60824a..483f94f 100644 --- a/tailbone_quickbooks/_version.py +++ b/tailbone_quickbooks/_version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8; -*- -__version__ = '0.1.3' +__version__ = '0.1.4' From df93a573bf3f04449a05f06760520c66cd2d8800 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sun, 14 May 2023 20:35:05 -0500 Subject: [PATCH 09/21] Stop passing `newstyle` kwarg to `Form.validate()` no longer needed --- tailbone_quickbooks/views/quickbooks/invoices.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tailbone_quickbooks/views/quickbooks/invoices.py b/tailbone_quickbooks/views/quickbooks/invoices.py index 98d9ca5..4edf951 100644 --- a/tailbone_quickbooks/views/quickbooks/invoices.py +++ b/tailbone_quickbooks/views/quickbooks/invoices.py @@ -340,7 +340,7 @@ class ExportableInvoiceView(MasterView): model = self.model form = forms.Form(schema=ToggleInvoices(), request=self.request) - if not form.validate(newstyle=True): + if not form.validate(): return {'error': "Form did not validate"} uuids = form.validated['uuids'].split(',') @@ -368,7 +368,7 @@ class ExportableInvoiceView(MasterView): model = self.model form = forms.Form(schema=ToggleInvoices(), request=self.request) - if not form.validate(newstyle=True): + if not form.validate(): return {'error': "Form did not validate"} uuids = form.validated['uuids'].split(',') From 62f50328aa48eb129d57a90ced3235edf74c1658 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Tue, 16 May 2023 14:35:06 -0500 Subject: [PATCH 10/21] Replace `setup.py` contents with `setup.cfg` --- setup.cfg | 30 +++++++++++++++++++++++ setup.py | 72 +++---------------------------------------------------- 2 files changed, 33 insertions(+), 69 deletions(-) create mode 100644 setup.cfg diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..0ed94fe --- /dev/null +++ b/setup.cfg @@ -0,0 +1,30 @@ +# -*- coding: utf-8; -*- + +[metadata] +name = tailbone-quickbooks +version = attr: tailbone_quickbooks.__version__ +author = Lance Edgar +author_email = lance@edbob.org +url = https://rattailproject.org/ +description = Tailbone integration package for Quickbooks +long_description = file: README.rst +classifiers = + Development Status :: 3 - Alpha + Environment :: Web Environment + Intended Audience :: Developers + License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+) + Natural Language :: English + Operating System :: OS Independent + Programming Language :: Python + Programming Language :: Python :: 3 + Topic :: Office/Business + Topic :: Software Development :: Libraries :: Python Modules + + +[options] +install_requires = + rattail-quickbooks + Tailbone + +packages = find: +include_package_data = True diff --git a/setup.py b/setup.py index 03eed1f..cf9b79d 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2022 Lance Edgar +# Copyright © 2010-2023 Lance Edgar # # This file is part of Rattail. # @@ -24,72 +24,6 @@ tailbone-quickbooks setup script """ -import os -from setuptools import setup, find_packages +from setuptools import setup - -here = os.path.abspath(os.path.dirname(__file__)) -exec(open(os.path.join(here, 'tailbone_quickbooks', '_version.py')).read()) -README = open(os.path.join(here, 'README.rst')).read() - - -requires = [ - # - # Version numbers within comments below have specific meanings. - # Basically the 'low' value is a "soft low," and 'high' a "soft high." - # In other words: - # - # If either a 'low' or 'high' value exists, the primary point to be - # made about the value is that it represents the most current (stable) - # version available for the package (assuming typical public access - # methods) whenever this project was started and/or documented. - # Therefore: - # - # If a 'low' version is present, you should know that attempts to use - # versions of the package significantly older than the 'low' version - # may not yield happy results. (A "hard" high limit may or may not be - # indicated by a true version requirement.) - # - # Similarly, if a 'high' version is present, and especially if this - # project has laid dormant for a while, you may need to refactor a bit - # when attempting to support a more recent version of the package. (A - # "hard" low limit should be indicated by a true version requirement - # when a 'high' version is present.) - # - # In any case, developers and other users are encouraged to play - # outside the lines with regard to these soft limits. If bugs are - # encountered then they should be filed as such. - # - # package # low high - - 'rattail-quickbooks', # 0.1.0 - 'Tailbone', # 0.8.199 -] - - -setup( - name = "tailbone-quickbooks", - version = __version__, - author = "Lance Edgar", - author_email = "lance@edbob.org", - url = "https://rattailproject.org/", - description = "Tailbone integration package for Quickbooks", - long_description = README, - - classifiers = [ - 'Development Status :: 3 - Alpha', - 'Environment :: Web Environment', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)', - 'Natural Language :: English', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Programming Language :: Python :: 3', - 'Topic :: Office/Business', - 'Topic :: Software Development :: Libraries :: Python Modules', - ], - - install_requires = requires, - packages = find_packages(), - include_package_data = True, -) +setup() From 74bf66cd71250377616d93243c0390df1f5edcb0 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Thu, 1 Jun 2023 14:30:39 -0500 Subject: [PATCH 11/21] Update changelog --- CHANGELOG.md | 5 +++++ tailbone_quickbooks/_version.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 04cbdb5..76a95ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ All notable changes to tailbone-quickbooks will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [0.1.5] - 2023-06-01 +### Changed +- Stop passing `newstyle` kwarg to `Form.validate()`. +- Replace `setup.py` contents with `setup.cfg`. + ## [0.1.4] - 2023-02-21 ### Changed - Show invoice amounts as currency. diff --git a/tailbone_quickbooks/_version.py b/tailbone_quickbooks/_version.py index 483f94f..67ed0c1 100644 --- a/tailbone_quickbooks/_version.py +++ b/tailbone_quickbooks/_version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8; -*- -__version__ = '0.1.4' +__version__ = '0.1.5' From 831403c90a561099bd6bf9654f90db303476d767 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Wed, 9 Aug 2023 18:06:08 -0500 Subject: [PATCH 12/21] Mark exportable invoice as deleted, instead of actually deleting and allow bulk-delete, but prevent edit --- .../views/quickbooks/invoices.py | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tailbone_quickbooks/views/quickbooks/invoices.py b/tailbone_quickbooks/views/quickbooks/invoices.py index 4edf951..c8ab414 100644 --- a/tailbone_quickbooks/views/quickbooks/invoices.py +++ b/tailbone_quickbooks/views/quickbooks/invoices.py @@ -54,6 +54,8 @@ class ExportableInvoiceView(MasterView): model_class = QuickbooksExportableInvoice route_prefix = 'quickbooks.exportable_invoices' url_prefix = '/quickbooks/exportable-invoices' + editable = False + bulk_deletable = True has_versions = True labels = { @@ -171,6 +173,8 @@ class ExportableInvoiceView(MasterView): g.check_all_handler = 'allChecked' def grid_extra_class(self, invoice, i): + if invoice.deleted: + return 'warning' if not self.exportable(invoice): if invoice.status_code in (invoice.STATUS_DEPTS_IGNORED, invoice.STATUS_EXPORTED, @@ -203,6 +207,22 @@ class ExportableInvoiceView(MasterView): """ return invoice.status_code == invoice.STATUS_EXPORTABLE + def deletable_instance(self, invoice): + if invoice.deleted: + return False + if invoice.exported: + return False + return True + + def delete_instance(self, invoice): + app = self.get_rattail_app() + session = app.get_session(invoice) + invoice.deleted = app.make_utc() + # nb. when bulk-deleting, user is in different session + invoice.deleted_by = session.merge(self.request.user) + invoice.status_code = invoice.STATUS_DELETED + session.flush() + def configure_form(self, f): super(ExportableInvoiceView, self).configure_form(f) model = self.model From ddeb4545a6c7a319652c067ebae521787fd9d433 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Tue, 29 Aug 2023 22:24:58 -0500 Subject: [PATCH 13/21] Update changelog --- CHANGELOG.md | 4 ++++ tailbone_quickbooks/_version.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76a95ac..900982b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to tailbone-quickbooks will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [0.1.6] - 2023-08-29 +### Changed +- Mark exportable invoice as deleted, instead of actually deleting. + ## [0.1.5] - 2023-06-01 ### Changed - Stop passing `newstyle` kwarg to `Form.validate()`. diff --git a/tailbone_quickbooks/_version.py b/tailbone_quickbooks/_version.py index 67ed0c1..955f1d8 100644 --- a/tailbone_quickbooks/_version.py +++ b/tailbone_quickbooks/_version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8; -*- -__version__ = '0.1.5' +__version__ = '0.1.6' From 7e08dd0f8926111948c081423e2244c89d8eece6 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Tue, 16 Apr 2024 18:23:49 -0500 Subject: [PATCH 14/21] Add support for Vendor -> Quickbooks Bank Accounts field this feels a bit hacky yet, but had to introduce some new mechanisms to allow for extra template stuff while avoiding adding a new vendors/edit (etc.) template in this project, since we are using a view supplement..ugh --- .../vendors/quickbooks_bank_accounts_js.mako | 86 +++++++++++ .../quickbooks_bank_accounts_widget.mako | 58 ++++++++ tailbone_quickbooks/views/vendors.py | 134 +++++++++++++++++- 3 files changed, 277 insertions(+), 1 deletion(-) create mode 100644 tailbone_quickbooks/templates/vendors/quickbooks_bank_accounts_js.mako create mode 100644 tailbone_quickbooks/templates/vendors/quickbooks_bank_accounts_widget.mako diff --git a/tailbone_quickbooks/templates/vendors/quickbooks_bank_accounts_js.mako b/tailbone_quickbooks/templates/vendors/quickbooks_bank_accounts_js.mako new file mode 100644 index 0000000..109bb9e --- /dev/null +++ b/tailbone_quickbooks/templates/vendors/quickbooks_bank_accounts_js.mako @@ -0,0 +1,86 @@ +## -*- coding: utf-8; -*- + + diff --git a/tailbone_quickbooks/templates/vendors/quickbooks_bank_accounts_widget.mako b/tailbone_quickbooks/templates/vendors/quickbooks_bank_accounts_widget.mako new file mode 100644 index 0000000..32a6dbe --- /dev/null +++ b/tailbone_quickbooks/templates/vendors/quickbooks_bank_accounts_widget.mako @@ -0,0 +1,58 @@ +## -*- coding: utf-8; -*- + +
+ + + Add Account + +
+ +${grid.render_table_element(data_prop='quickbooksBankAccountsData')|n} + + + + diff --git a/tailbone_quickbooks/views/vendors.py b/tailbone_quickbooks/views/vendors.py index 7c3e70b..c73196d 100644 --- a/tailbone_quickbooks/views/vendors.py +++ b/tailbone_quickbooks/views/vendors.py @@ -2,7 +2,7 @@ ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2022 Lance Edgar +# Copyright © 2010-2024 Lance Edgar # # This file is part of Rattail. # @@ -24,6 +24,14 @@ Vendor views, w/ Quickbooks integration """ +import json + +import colander +from deform import widget as dfwidget +from pyramid.renderers import render +from webhelpers2.html import HTML, tags + +from tailbone import grids from tailbone.views import ViewSupplement @@ -44,14 +52,138 @@ class VendorViewSupplement(ViewSupplement): g.set_filter('quickbooks_terms', model.QuickbooksVendor.quickbooks_terms) def configure_form(self, f): + + # quickbooks_name f.append('quickbooks_name') + + # quickbooks_bank_account f.append('quickbooks_bank_account') + + # quickbooks_bank_accounts + f.append('quickbooks_bank_accounts_') + f.set_renderer('quickbooks_bank_accounts_', self.render_quickbooks_bank_accounts) + f.set_node('quickbooks_bank_accounts_', BankAccounts()) + f.set_widget('quickbooks_bank_accounts_', BankAccountsWidget()) + + # quickbooks_terms f.append('quickbooks_terms') + def render_quickbooks_bank_accounts(self, vendor, field): + accounts = getattr(vendor, 'quickbooks_bank_accounts') + if accounts: + g = make_accounts_grid() + return HTML.literal(g.render_table_element(data_prop='quickbooksBankAccountsData')) + + def objectify(self, vendor, form, data): + model = self.model + old_accounts = vendor.quickbooks_bank_accounts + new_accounts = data['quickbooks_bank_accounts_'] + + for new_account in new_accounts: + old_account = old_accounts.get(new_account['store_uuid']) + if old_account: + if old_account.account_number != new_account['account_number']: + old_account.account_number = new_account['account_number'] + else: + account = model.QuickbooksVendorBankAccount() + account.store_uuid = new_account['store_uuid'] + account.account_number = new_account['account_number'] + vendor.quickbooks_bank_accounts[account.store_uuid] = account + self.Session.add(account) + + final_store_uuids = set([a['store_uuid'] for a in new_accounts]) + for old_account in list(vendor.quickbooks_bank_accounts.values()): + if old_account.store_uuid not in final_store_uuids: + self.Session.delete(old_account) + + return vendor + + def template_kwargs(self, **kwargs): + app = self.get_rattail_app() + form = kwargs.get('form') + if form: + + # quickbooks bank accounts + vendor = kwargs['instance'] + accounts = [] + for account in vendor.quickbooks_bank_accounts.values(): + store = account.store + accounts.append({ + 'uuid': account.uuid, + 'store': f'{store.id} - {store.name}', + 'store_uuid': store.uuid, + 'store_id': store.id, + 'store_name': store.name, + 'account_number': account.account_number, + }) + accounts.sort(key=lambda a: a['store_id']) + # nb. this is needed for widget *and* readonly template + form.set_json_data('quickbooksBankAccountsData', accounts) + # TODO: these are needed by widget + stores = [] + for store in app.get_active_stores(self.Session()): + stores.append({ + 'uuid': store.uuid, + 'display': f'{store.id} - {store.name}', + }) + form.include_template('/vendors/quickbooks_bank_accounts_js.mako', { + 'store_options': stores, + }) + + return kwargs + def get_version_child_classes(self): model = self.model return [model.QuickbooksVendor] +def make_accounts_grid(): + g = grids.Grid('quickbooks_bank_accounts', + [], # empty data + columns=[ + 'store', + 'account_number', + ]) + return g + + +class BankAccount(colander.MappingSchema): + + store_uuid = colander.SchemaNode(colander.String()) + + account_number = colander.SchemaNode(colander.String()) + + +class BankAccounts(colander.SequenceSchema): + + account = BankAccount() + + +class BankAccountsWidget(dfwidget.Widget): + + def serialize(self, field, cstruct, **kw): + g = make_accounts_grid() + + g.main_actions.append( + grids.GridAction('edit', icon='edit', + click_handler='quickbooksBankAccountEdit(props.row)')) + + g.main_actions.append( + grids.GridAction('delete', icon='trash', + click_handler='quickbooksBankAccountDelete(props.row)')) + + widget = render('/vendors/quickbooks_bank_accounts_widget.mako', { + 'grid': g, + }) + + return HTML.tag('div', c=[ + HTML.literal(widget), + tags.hidden(field.name, **{':value': "quickbooksBankAccountsFinal"}), + ]) + + def deserialize(self, field, pstruct): + return json.loads(pstruct) + + def includeme(config): VendorViewSupplement.defaults(config) From 06bc1d14c996bf9b5c954f592cbe8d5bad14907a Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Tue, 30 Apr 2024 19:34:15 -0500 Subject: [PATCH 15/21] Add request object to vendor QB bank accounts grid --- tailbone_quickbooks/views/vendors.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tailbone_quickbooks/views/vendors.py b/tailbone_quickbooks/views/vendors.py index c73196d..853dc23 100644 --- a/tailbone_quickbooks/views/vendors.py +++ b/tailbone_quickbooks/views/vendors.py @@ -63,7 +63,7 @@ class VendorViewSupplement(ViewSupplement): f.append('quickbooks_bank_accounts_') f.set_renderer('quickbooks_bank_accounts_', self.render_quickbooks_bank_accounts) f.set_node('quickbooks_bank_accounts_', BankAccounts()) - f.set_widget('quickbooks_bank_accounts_', BankAccountsWidget()) + f.set_widget('quickbooks_bank_accounts_', BankAccountsWidget(request=self.request)) # quickbooks_terms f.append('quickbooks_terms') @@ -71,7 +71,7 @@ class VendorViewSupplement(ViewSupplement): def render_quickbooks_bank_accounts(self, vendor, field): accounts = getattr(vendor, 'quickbooks_bank_accounts') if accounts: - g = make_accounts_grid() + g = make_accounts_grid(self.request) return HTML.literal(g.render_table_element(data_prop='quickbooksBankAccountsData')) def objectify(self, vendor, form, data): @@ -137,9 +137,10 @@ class VendorViewSupplement(ViewSupplement): return [model.QuickbooksVendor] -def make_accounts_grid(): +def make_accounts_grid(request): g = grids.Grid('quickbooks_bank_accounts', - [], # empty data + request=request, + data=[], # empty data columns=[ 'store', 'account_number', @@ -162,7 +163,7 @@ class BankAccounts(colander.SequenceSchema): class BankAccountsWidget(dfwidget.Widget): def serialize(self, field, cstruct, **kw): - g = make_accounts_grid() + g = make_accounts_grid(self.request) g.main_actions.append( grids.GridAction('edit', icon='edit', From d39a8a7adf6062a2f5543ba01c670e50f1dade0a Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 3 Jun 2024 11:25:46 -0500 Subject: [PATCH 16/21] Update changelog --- CHANGELOG.md | 4 ++++ tailbone_quickbooks/_version.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 900982b..5cd3544 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to tailbone-quickbooks will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [0.1.7] - 2024-06-03 +### Changed +- Add support for Vendor -> Quickbooks Bank Accounts field. + ## [0.1.6] - 2023-08-29 ### Changed - Mark exportable invoice as deleted, instead of actually deleting. diff --git a/tailbone_quickbooks/_version.py b/tailbone_quickbooks/_version.py index 955f1d8..4cdc594 100644 --- a/tailbone_quickbooks/_version.py +++ b/tailbone_quickbooks/_version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8; -*- -__version__ = '0.1.6' +__version__ = '0.1.7' From 19bb5bd27f8e4fd40f15181e3f8324e7a89805ab Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 3 Jun 2024 11:26:32 -0500 Subject: [PATCH 17/21] Fix default dist filename for release task not sure why this fix was needed, did setuptools behavior change? --- tasks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks.py b/tasks.py index 9dbdd44..c35e30e 100644 --- a/tasks.py +++ b/tasks.py @@ -2,7 +2,7 @@ ################################################################################ # # Rattail -- Retail Software Framework -# Copyright © 2010-2022 Lance Edgar +# Copyright © 2010-2024 Lance Edgar # # This file is part of Rattail. # @@ -43,5 +43,5 @@ def release(c): c.run('python setup.py sdist --formats=gztar') # upload to PyPI - filename = 'tailbone-quickbooks-{}.tar.gz'.format(__version__) + filename = f'tailbone_quickbooks-{__version__}.tar.gz' c.run('twine upload dist/{}'.format(filename)) From 6bb18b47c10f62f21f81389a94ce58260ccc1c10 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Tue, 11 Jun 2024 19:04:00 -0500 Subject: [PATCH 18/21] feat: switch from setup.cfg to pyproject.toml + hatchling --- .gitignore | 3 +++ pyproject.toml | 41 +++++++++++++++++++++++++++++++++ setup.cfg | 30 ------------------------ setup.py | 29 ----------------------- tailbone_quickbooks/_version.py | 8 ++++++- tasks.py | 14 ++++------- 6 files changed, 55 insertions(+), 70 deletions(-) create mode 100644 pyproject.toml delete mode 100644 setup.cfg delete mode 100644 setup.py diff --git a/.gitignore b/.gitignore index 2e6159c..ea1abef 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ +*~ +*.pyc +dist/ tailbone_quickbooks.egg-info/ diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..a37a4ec --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,41 @@ + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + + +[project] +name = "tailbone-quickbooks" +version = "0.1.7" +description = "Tailbone integration package for Quickbooks" +readme = "README.rst" +authors = [{name = "Lance Edgar", email = "lance@edbob.org"}] +license = {text = "GNU GPL v3+"} +classifiers = [ + "Development Status :: 3 - Alpha", + "Environment :: Web Environment", + "Intended Audience :: Developers", + "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)", + "Natural Language :: English", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Topic :: Office/Business", + "Topic :: Software Development :: Libraries :: Python Modules", +] +dependencies = [ + "rattail-quickbooks", + "Tailbone", +] + + +[project.urls] +Homepage = "https://rattailproject.org" +Repository = "https://kallithea.rattailproject.org/rattail-project/tailbone-quickbooks" +Changelog = "https://kallithea.rattailproject.org/rattail-project/tailbone-quickbooks/files/master/CHANGELOG.md" + + +[tool.commitizen] +version_provider = "pep621" +tag_format = "v$version" +update_changelog_on_bump = true diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 0ed94fe..0000000 --- a/setup.cfg +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8; -*- - -[metadata] -name = tailbone-quickbooks -version = attr: tailbone_quickbooks.__version__ -author = Lance Edgar -author_email = lance@edbob.org -url = https://rattailproject.org/ -description = Tailbone integration package for Quickbooks -long_description = file: README.rst -classifiers = - Development Status :: 3 - Alpha - Environment :: Web Environment - Intended Audience :: Developers - License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+) - Natural Language :: English - Operating System :: OS Independent - Programming Language :: Python - Programming Language :: Python :: 3 - Topic :: Office/Business - Topic :: Software Development :: Libraries :: Python Modules - - -[options] -install_requires = - rattail-quickbooks - Tailbone - -packages = find: -include_package_data = True diff --git a/setup.py b/setup.py deleted file mode 100644 index cf9b79d..0000000 --- a/setup.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8; -*- -################################################################################ -# -# Rattail -- Retail Software Framework -# Copyright © 2010-2023 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 . -# -################################################################################ -""" -tailbone-quickbooks setup script -""" - -from setuptools import setup - -setup() diff --git a/tailbone_quickbooks/_version.py b/tailbone_quickbooks/_version.py index 4cdc594..4905e5d 100644 --- a/tailbone_quickbooks/_version.py +++ b/tailbone_quickbooks/_version.py @@ -1,3 +1,9 @@ # -*- coding: utf-8; -*- -__version__ = '0.1.7' +try: + from importlib.metadata import version +except ImportError: + from importlib_metadata import version + + +__version__ = version('tailbone-quickbooks') diff --git a/tasks.py b/tasks.py index c35e30e..2a3f1e0 100644 --- a/tasks.py +++ b/tasks.py @@ -24,24 +24,18 @@ Tasks for tailbone-quickbooks """ -import os - from invoke import task -here = os.path.abspath(os.path.dirname(__file__)) -exec(open(os.path.join(here, 'tailbone_quickbooks', '_version.py')).read()) - - @task def release(c): """ Release a new version of tailbone-quickbooks """ - # rebuild local tar.gz file for distribution + # rebuild package + c.run('rm -rf dist') c.run('rm -rf tailbone_quickbooks.egg-info') - c.run('python setup.py sdist --formats=gztar') + c.run('python -m build --sdist') # upload to PyPI - filename = f'tailbone_quickbooks-{__version__}.tar.gz' - c.run('twine upload dist/{}'.format(filename)) + c.run('twine upload dist/*') From 38af9dd4349d3e9fead761ad68c21dd1c85ddad1 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Tue, 11 Jun 2024 19:04:09 -0500 Subject: [PATCH 19/21] =?UTF-8?q?bump:=20version=200.1.7=20=E2=86=92=200.2?= =?UTF-8?q?.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 6 ++++++ pyproject.toml | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5cd3544..72cab08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to tailbone-quickbooks will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## v0.2.0 (2024-06-11) + +### Feat + +- switch from setup.cfg to pyproject.toml + hatchling + ## [0.1.7] - 2024-06-03 ### Changed - Add support for Vendor -> Quickbooks Bank Accounts field. diff --git a/pyproject.toml b/pyproject.toml index a37a4ec..dfa9369 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "hatchling.build" [project] name = "tailbone-quickbooks" -version = "0.1.7" +version = "0.2.0" description = "Tailbone integration package for Quickbooks" readme = "README.rst" authors = [{name = "Lance Edgar", email = "lance@edbob.org"}] From 5016ed9e6400408a8d176f65f8e2a0f2d306c8e8 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Fri, 16 Aug 2024 15:27:42 -0500 Subject: [PATCH 20/21] fix: refactor grid usage per wuttaweb --- .../quickbooks/exportable-invoices/index.mako | 2 +- tailbone_quickbooks/views/vendors.py | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tailbone_quickbooks/templates/quickbooks/exportable-invoices/index.mako b/tailbone_quickbooks/templates/quickbooks/exportable-invoices/index.mako index dc6ec4f..0469f32 100644 --- a/tailbone_quickbooks/templates/quickbooks/exportable-invoices/index.mako +++ b/tailbone_quickbooks/templates/quickbooks/exportable-invoices/index.mako @@ -97,7 +97,7 @@ this.toggleRows(uuids, checked) } - TailboneGrid.methods.allChecked = function(checkedList) { + ${grid.vue_component}.methods.allChecked = function(checkedList) { // (de-)select all visible invoices when header checkbox is clicked let checked = !!checkedList.length this.toggleRows(this.allRowUUIDs(), checked) diff --git a/tailbone_quickbooks/views/vendors.py b/tailbone_quickbooks/views/vendors.py index 853dc23..0ce3230 100644 --- a/tailbone_quickbooks/views/vendors.py +++ b/tailbone_quickbooks/views/vendors.py @@ -138,8 +138,8 @@ class VendorViewSupplement(ViewSupplement): def make_accounts_grid(request): - g = grids.Grid('quickbooks_bank_accounts', - request=request, + g = grids.Grid(request, + key='quickbooks_bank_accounts', data=[], # empty data columns=[ 'store', @@ -165,12 +165,12 @@ class BankAccountsWidget(dfwidget.Widget): def serialize(self, field, cstruct, **kw): g = make_accounts_grid(self.request) - g.main_actions.append( - grids.GridAction('edit', icon='edit', + g.actions.append( + grids.GridAction(self.request, 'edit', icon='edit', click_handler='quickbooksBankAccountEdit(props.row)')) - g.main_actions.append( - grids.GridAction('delete', icon='trash', + g.actions.append( + grids.GridAction(self.request, 'delete', icon='trash', click_handler='quickbooksBankAccountDelete(props.row)')) widget = render('/vendors/quickbooks_bank_accounts_widget.mako', { From bbded3272cb6dce4253d2e2b3ed96a4c5956aa15 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Fri, 13 Sep 2024 18:06:50 -0500 Subject: [PATCH 21/21] docs: use markdown for readme file --- README.md | 11 +++++++++++ README.rst | 14 -------------- pyproject.toml | 2 +- 3 files changed, 12 insertions(+), 15 deletions(-) create mode 100644 README.md delete mode 100644 README.rst diff --git a/README.md b/README.md new file mode 100644 index 0000000..8a0c37d --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ + +# tailbone-quickbooks + +Rattail is a retail software framework, released under the GNU General +Public License. + +This package contains software interfaces for +[Quickbooks](https://quickbooks.intuit.com/). + +Please see the [Rattail Project](https://rattailproject.org/) for more +information. diff --git a/README.rst b/README.rst deleted file mode 100644 index 343f4bf..0000000 --- a/README.rst +++ /dev/null @@ -1,14 +0,0 @@ - -tailbone-quickbooks -=================== - -Rattail is a retail software framework, released under the GNU General -Public License. - -This package contains software interfaces for `Quickbooks`_. - -.. _`Quickbooks`: https://quickbooks.intuit.com/ - -Please see the `Rattail Project`_ for more information. - -.. _`Rattail Project`: https://rattailproject.org/ diff --git a/pyproject.toml b/pyproject.toml index dfa9369..c3a0bb4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,7 @@ build-backend = "hatchling.build" name = "tailbone-quickbooks" version = "0.2.0" description = "Tailbone integration package for Quickbooks" -readme = "README.rst" +readme = "README.md" authors = [{name = "Lance Edgar", email = "lance@edbob.org"}] license = {text = "GNU GPL v3+"} classifiers = [