+ % endif
+%def>
+
+<%def name="modify_this_page_vars()">
+ ${parent.modify_this_page_vars()}
+ % if master.has_perm('import_from_harvest'):
+
+ % endif
+%def>
+
+
+${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()