Add "refresh results" for QB exportable invoices
This commit is contained in:
		
							parent
							
								
									dda03fd655
								
							
						
					
					
						commit
						5738830aed
					
				
					 2 changed files with 92 additions and 5 deletions
				
			
		| 
						 | 
				
			
			@ -3,9 +3,20 @@
 | 
			
		|||
 | 
			
		||||
<%def name="grid_tools()">
 | 
			
		||||
  ${parent.grid_tools()}
 | 
			
		||||
 | 
			
		||||
  % 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)}
 | 
			
		||||
      <b-button type="is-primary"
 | 
			
		||||
                native-type="submit"
 | 
			
		||||
| 
						 | 
				
			
			@ -15,6 +26,7 @@
 | 
			
		|||
        {{ exportingInvoices ? "Working, please wait..." : `Export ${'$'}{this.exportingInvoicesCount} Invoices` }}
 | 
			
		||||
      </b-button>
 | 
			
		||||
      ${h.end_form()}
 | 
			
		||||
 | 
			
		||||
  % endif
 | 
			
		||||
</%def>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -23,9 +35,17 @@
 | 
			
		|||
  % if master.has_perm('export'):
 | 
			
		||||
      <script type="text/javascript">
 | 
			
		||||
 | 
			
		||||
        ${grid.component_studly}Data.refreshingResults = false
 | 
			
		||||
        ${grid.component_studly}Data.exportingInvoices = false
 | 
			
		||||
        ${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) {
 | 
			
		||||
            this.loading = true
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
################################################################################
 | 
			
		||||
#
 | 
			
		||||
#  Rattail -- Retail Software Framework
 | 
			
		||||
#  Copyright © 2010-2022 Lance Edgar
 | 
			
		||||
#  Copyright © 2010-2023 Lance Edgar
 | 
			
		||||
#
 | 
			
		||||
#  This file is part of Rattail.
 | 
			
		||||
#
 | 
			
		||||
| 
						 | 
				
			
			@ -29,6 +29,8 @@ import logging
 | 
			
		|||
from rattail_quickbooks.db.model import (QuickbooksExportableInvoice,
 | 
			
		||||
                                         QuickbooksExportableInvoiceDistribution,
 | 
			
		||||
                                         QuickbooksInvoiceExport)
 | 
			
		||||
from rattail.threads import Thread
 | 
			
		||||
from rattail.util import simple_error
 | 
			
		||||
 | 
			
		||||
import colander
 | 
			
		||||
from pyramid.httpexceptions import HTTPFound
 | 
			
		||||
| 
						 | 
				
			
			@ -263,12 +265,69 @@ class ExportableInvoiceView(MasterView):
 | 
			
		|||
        self.refresh_invoice(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.
 | 
			
		||||
        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):
 | 
			
		||||
        """
 | 
			
		||||
        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),
 | 
			
		||||
                        renderer='json')
 | 
			
		||||
 | 
			
		||||
        # refresh
 | 
			
		||||
        # refresh invoice
 | 
			
		||||
        config.add_route('{}.refresh'.format(route_prefix),
 | 
			
		||||
                         '{}/refresh'.format(instance_url_prefix))
 | 
			
		||||
        config.add_view(cls, attr='refresh',
 | 
			
		||||
| 
						 | 
				
			
			@ -446,6 +505,14 @@ class ExportableInvoiceView(MasterView):
 | 
			
		|||
                        request_method='POST',
 | 
			
		||||
                        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
 | 
			
		||||
        config.add_tailbone_permission(permission_prefix,
 | 
			
		||||
                                       '{}.export'.format(permission_prefix),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue