Add "refresh results" for QB exportable invoices

This commit is contained in:
Lance Edgar 2023-01-11 08:20:19 -06:00
parent dda03fd655
commit 5738830aed
2 changed files with 92 additions and 5 deletions

View file

@ -3,9 +3,20 @@
<%def name="grid_tools()"> <%def name="grid_tools()">
${parent.grid_tools()} ${parent.grid_tools()}
% if master.has_perm('export'): % if master.has_perm('export'):
${h.form(url('{}.export'.format(route_prefix)), **{'@submit': 'exportingInvoices = true'})}
${h.form(url('{}.refresh_results'.format(route_prefix)), class_='control', ref='refreshResultsForm', **{'@submit': 'refreshingResults = true'})}
${h.csrf_token(request)}
<b-button type="is-primary"
@click="refreshResults()"
icon-pack="fas"
icon-left="redo"
:disabled="refreshingResults">
{{ refreshingResults ? "Working, please wait..." : "Refresh Results" }}
</b-button>
${h.end_form()}
${h.form(url('{}.export'.format(route_prefix)), class_='control', **{'@submit': 'exportingInvoices = true'})}
${h.csrf_token(request)} ${h.csrf_token(request)}
<b-button type="is-primary" <b-button type="is-primary"
native-type="submit" native-type="submit"
@ -15,6 +26,7 @@
{{ exportingInvoices ? "Working, please wait..." : `Export ${'$'}{this.exportingInvoicesCount} Invoices` }} {{ exportingInvoices ? "Working, please wait..." : `Export ${'$'}{this.exportingInvoicesCount} Invoices` }}
</b-button> </b-button>
${h.end_form()} ${h.end_form()}
% endif % endif
</%def> </%def>
@ -23,9 +35,17 @@
% if master.has_perm('export'): % if master.has_perm('export'):
<script type="text/javascript"> <script type="text/javascript">
${grid.component_studly}Data.refreshingResults = false
${grid.component_studly}Data.exportingInvoices = false ${grid.component_studly}Data.exportingInvoices = false
${grid.component_studly}Data.exportingInvoicesCount = ${json.dumps(len(selected))|n} ${grid.component_studly}Data.exportingInvoicesCount = ${json.dumps(len(selected))|n}
${grid.component_studly}.methods.refreshResults = function() {
if (confirm("Refresh data for all search results?")) {
this.refreshingResults = true
this.$refs.refreshResultsForm.submit()
}
}
${grid.component_studly}.methods.toggleRows = function(uuids, checked) { ${grid.component_studly}.methods.toggleRows = function(uuids, checked) {
this.loading = true this.loading = true

View file

@ -2,7 +2,7 @@
################################################################################ ################################################################################
# #
# Rattail -- Retail Software Framework # Rattail -- Retail Software Framework
# Copyright © 2010-2022 Lance Edgar # Copyright © 2010-2023 Lance Edgar
# #
# This file is part of Rattail. # This file is part of Rattail.
# #
@ -29,6 +29,8 @@ import logging
from rattail_quickbooks.db.model import (QuickbooksExportableInvoice, from rattail_quickbooks.db.model import (QuickbooksExportableInvoice,
QuickbooksExportableInvoiceDistribution, QuickbooksExportableInvoiceDistribution,
QuickbooksInvoiceExport) QuickbooksInvoiceExport)
from rattail.threads import Thread
from rattail.util import simple_error
import colander import colander
from pyramid.httpexceptions import HTTPFound from pyramid.httpexceptions import HTTPFound
@ -263,12 +265,69 @@ class ExportableInvoiceView(MasterView):
self.refresh_invoice(invoice) self.refresh_invoice(invoice)
return self.redirect(self.get_action_url('view', invoice)) return self.redirect(self.get_action_url('view', invoice))
def refresh_invoice(self, invoice): def refresh_invoice(self, invoice, **kwargs):
""" """
Logic to actually refresh data for the given invoice. Logic to actually refresh data for the given invoice.
Implement as needed. Implement as needed.
""" """
def refresh_results(self):
"""
View to refresh data for all invoices in current search results.
"""
# start thread to actually do work / report progress
route_prefix = self.get_route_prefix()
key = '{}.refresh_results'.format(route_prefix)
progress = self.make_progress(key)
results = self.get_effective_data()
thread = Thread(target=self.refresh_results_thread,
args=(results, progress))
thread.start()
# show user the progress page
return self.render_progress(progress, {
'cancel_url': self.get_index_url(),
'cancel_msg': "Refresh was canceled.",
})
def refresh_results_thread(self, results, progress):
"""
Thread target, responsible for actually refreshing all
invoices in the search results.
"""
app = self.get_rattail_app()
session = self.make_isolated_session()
invoices = results.with_session(session).all()
def refresh(invoice, i):
self.refresh_invoice(invoice)
try:
app.progress_loop(refresh, invoices, progress,
message="Refreshing invoice data")
except Exception as error:
msg = "failed to refresh results!"
log.warning(msg, exc_info=True)
session.rollback()
if progress:
progress.session.load()
progress.session['error'] = True
progress.session['error_msg'] = "{}: {}".format(
msg, simple_error(error))
progress.session.save()
else:
if progress:
progress.session.load()
progress.session['complete'] = True
progress.session['success_url'] = self.get_index_url()
progress.session['success_msg'] = "Data refreshed for {} invoices".format(len(invoices))
progress.session.save()
finally:
session.close()
def select(self): def select(self):
""" """
Mark one or more invoices as selected, within the current user's session. Mark one or more invoices as selected, within the current user's session.
@ -438,7 +497,7 @@ class ExportableInvoiceView(MasterView):
permission='{}.export'.format(permission_prefix), permission='{}.export'.format(permission_prefix),
renderer='json') renderer='json')
# refresh # refresh invoice
config.add_route('{}.refresh'.format(route_prefix), config.add_route('{}.refresh'.format(route_prefix),
'{}/refresh'.format(instance_url_prefix)) '{}/refresh'.format(instance_url_prefix))
config.add_view(cls, attr='refresh', config.add_view(cls, attr='refresh',
@ -446,6 +505,14 @@ class ExportableInvoiceView(MasterView):
request_method='POST', request_method='POST',
permission='{}.export'.format(permission_prefix)) permission='{}.export'.format(permission_prefix))
# refresh results
config.add_route('{}.refresh_results'.format(route_prefix),
'{}/refresh-results'.format(url_prefix))
config.add_view(cls, attr='refresh_results',
route_name='{}.refresh_results'.format(route_prefix),
request_method='POST',
permission='{}.export'.format(permission_prefix))
# export # export
config.add_tailbone_permission(permission_prefix, config.add_tailbone_permission(permission_prefix,
'{}.export'.format(permission_prefix), '{}.export'.format(permission_prefix),