From f388f2d6cfcc8d39acf277f1b3740732e82672fe Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Wed, 4 Oct 2023 13:10:28 -0500 Subject: [PATCH] Add button to re-import Harvest cache time entry from API --- .../templates/harvest/time-entries/view.mako | 45 +++++++++++++++++ .../views/harvest/time_entries.py | 48 ++++++++++++++++++- 2 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 tailbone_harvest/templates/harvest/time-entries/view.mako diff --git a/tailbone_harvest/templates/harvest/time-entries/view.mako b/tailbone_harvest/templates/harvest/time-entries/view.mako new file mode 100644 index 0000000..3b36ff5 --- /dev/null +++ b/tailbone_harvest/templates/harvest/time-entries/view.mako @@ -0,0 +1,45 @@ +## -*- coding: utf-8; -*- +<%inherit file="/master/view.mako" /> + +<%def name="object_helpers()"> + ${parent.object_helpers()} + ${self.render_import_helper()} + + +<%def name="render_import_helper()"> + % if master.has_perm('import_from_harvest'): + + % endif + + +<%def name="modify_this_page_vars()"> + ${parent.modify_this_page_vars()} + % if master.has_perm('import_from_harvest'): + + % endif + + + +${parent.body()} diff --git a/tailbone_harvest/views/harvest/time_entries.py b/tailbone_harvest/views/harvest/time_entries.py index 7c85f8e..b4b67f4 100644 --- a/tailbone_harvest/views/harvest/time_entries.py +++ b/tailbone_harvest/views/harvest/time_entries.py @@ -62,7 +62,7 @@ class HarvestTimeEntryView(HarvestMasterView): g.set_link('notes') def configure_form(self, f): - super(HarvestTimeEntryView, self).configure_form(f) + super().configure_form(f) # make sure id is first field f.remove('id') @@ -84,11 +84,20 @@ class HarvestTimeEntryView(HarvestMasterView): f.remove('task_id') f.set_renderer('task', self.render_harvest_task) + # hours + f.set_renderer('hours', self.render_hours) + f.set_type('notes', 'text') f.set_type('billable_rate', 'currency') f.set_type('cost_rate', 'currency') + def render_hours(self, entry, field): + hours = getattr(entry, field) + app = self.get_rattail_app() + duration = app.render_duration(hours=hours) + return f"{hours} ({duration})" + def get_xref_buttons(self, entry): buttons = super(HarvestTimeEntryView, self).get_xref_buttons(entry) model = self.model @@ -105,6 +114,43 @@ class HarvestTimeEntryView(HarvestMasterView): return buttons + def import_from_harvest(self): + app = self.get_rattail_app() + handler = app.get_import_handler('to_rattail.from_harvest.import', require=True) + importer = handler.get_importer('HarvestTimeEntry') + importer.session = self.Session() + importer.setup() + + cache_entry = self.get_instance() + if self.oneoff_import(importer, local_object=cache_entry): + self.request.session.flash(f"{self.get_model_title()} has been " + f"(re-)imported from Harvest: {cache_entry}") + else: + self.request.session.flash("Import failed!", 'error') + + return self.redirect(self.get_action_url('view', cache_entry)) + + @classmethod + def defaults(cls, config): + route_prefix = cls.get_route_prefix() + instance_url_prefix = cls.get_instance_url_prefix() + permission_prefix = cls.get_permission_prefix() + model_title = cls.get_model_title() + + # normal defaults + cls._defaults(config) + + # import from harvest + config.add_tailbone_permission(permission_prefix, + f'{permission_prefix}.import_from_harvest', + f"Re-Import {model_title} from Harvest") + config.add_route(f'{route_prefix}.import_from_harvest', + f'{instance_url_prefix}/import-from-harvest', + request_method='POST') + config.add_view(cls, attr='import_from_harvest', + route_name=f'{route_prefix}.import_from_harvest', + permission=f'{permission_prefix}.import_from_harvest') + def defaults(config, **kwargs): base = globals()