Standardize merge logic when a handler is defined for it

also adds basic merge support for products view
This commit is contained in:
Lance Edgar 2022-08-12 14:27:26 -05:00
parent 4c29a667cb
commit 409a49ba20
3 changed files with 39 additions and 28 deletions

View file

@ -108,6 +108,7 @@ class MasterView(View):
supports_set_enabled_toggle = False supports_set_enabled_toggle = False
populatable = False populatable = False
mergeable = False mergeable = False
merge_handler = None
downloadable = False downloadable = False
cloneable = False cloneable = False
touchable = False touchable = False
@ -1931,17 +1932,34 @@ class MasterView(View):
def get_merge_fields(self): def get_merge_fields(self):
if hasattr(self, 'merge_fields'): if hasattr(self, 'merge_fields'):
return self.merge_fields return self.merge_fields
if self.merge_handler:
fields = self.merge_handler.get_merge_preview_fields()
return [field['name'] for field in fields]
mapper = orm.class_mapper(self.get_model_class()) mapper = orm.class_mapper(self.get_model_class())
return mapper.columns.keys() return mapper.columns.keys()
def get_merge_coalesce_fields(self): def get_merge_coalesce_fields(self):
if hasattr(self, 'merge_coalesce_fields'): if hasattr(self, 'merge_coalesce_fields'):
return self.merge_coalesce_fields return self.merge_coalesce_fields
if self.merge_handler:
fields = self.merge_handler.get_merge_preview_fields()
return [field['name'] for field in fields
if field.get('coalesce')]
return [] return []
def get_merge_additive_fields(self): def get_merge_additive_fields(self):
if hasattr(self, 'merge_additive_fields'): if hasattr(self, 'merge_additive_fields'):
return self.merge_additive_fields return self.merge_additive_fields
if self.merge_handler:
fields = self.merge_handler.get_merge_preview_fields()
return [field['name'] for field in fields
if field.get('additive')]
return [] return []
def merge(self): def merge(self):
@ -1985,8 +2003,15 @@ class MasterView(View):
the requested merge is valid, in your context. If it is not - for *any the requested merge is valid, in your context. If it is not - for *any
reason* - you should raise an exception; the type does not matter. reason* - you should raise an exception; the type does not matter.
""" """
if self.merge_handler:
reason = self.merge_handler.why_not_merge(removing, keeping)
if reason:
raise Exception(reason)
def get_merge_data(self, obj): def get_merge_data(self, obj):
if self.merge_handler:
return self.merge_handler.get_merge_preview_data(obj)
raise NotImplementedError("please implement `{}.get_merge_data()`".format(self.__class__.__name__)) raise NotImplementedError("please implement `{}.get_merge_data()`".format(self.__class__.__name__))
def get_merge_resulting_data(self, remove, keep): def get_merge_resulting_data(self, remove, keep):
@ -2008,6 +2033,12 @@ class MasterView(View):
Merge the two given objects. You should probably override this; Merge the two given objects. You should probably override this;
default behavior is merely to delete the 'removing' object. default behavior is merely to delete the 'removing' object.
""" """
if self.merge_handler:
self.merge_handler.perform_merge(removing, keeping,
user=self.request.user)
else:
# nb. default "merge" does not update kept object!
self.Session.delete(removing) self.Session.delete(removing)
############################## ##############################

View file

@ -95,10 +95,13 @@ class PersonView(MasterView):
def __init__(self, request): def __init__(self, request):
super(PersonView, self).__init__(request) super(PersonView, self).__init__(request)
app = self.get_rattail_app()
# always get a reference to the People Handler # always get a reference to the People Handler
app = self.get_rattail_app() self.people_handler = app.get_people_handler()
self.handler = app.get_people_handler() self.merge_handler = self.people_handler
# TODO: deprecate / remove this
self.handler = self.people_handler
def make_grid_kwargs(self, **kwargs): def make_grid_kwargs(self, **kwargs):
kwargs = super(PersonView, self).make_grid_kwargs(**kwargs) kwargs = super(PersonView, self).make_grid_kwargs(**kwargs)
@ -396,31 +399,6 @@ class PersonView(MasterView):
(model.VendorContact, 'person_uuid'), (model.VendorContact, 'person_uuid'),
] ]
def get_merge_fields(self):
fields = self.handler.get_merge_preview_fields()
return [field['name'] for field in fields]
def get_merge_additive_fields(self):
fields = self.handler.get_merge_preview_fields()
return [field['name'] for field in fields
if field.get('additive')]
def get_merge_coalesce_fields(self):
fields = self.handler.get_merge_preview_fields()
return [field['name'] for field in fields
if field.get('coalesce')]
def get_merge_data(self, person):
return self.handler.get_merge_preview_data(person)
def validate_merge(self, removing, keeping):
reason = self.handler.why_not_merge(removing, keeping)
if reason:
raise Exception(reason)
def merge_objects(self, removing, keeping):
self.handler.perform_merge(removing, keeping, user=self.request.user)
def view_profile(self): def view_profile(self):
""" """
View which exposes the "full profile" for a given person, i.e. all View which exposes the "full profile" for a given person, i.e. all

View file

@ -83,6 +83,7 @@ class ProductView(MasterView):
has_versions = True has_versions = True
results_downloadable_xlsx = True results_downloadable_xlsx = True
supports_autocomplete = True supports_autocomplete = True
mergeable = True
configurable = True configurable = True
labels = { labels = {
@ -180,6 +181,7 @@ class ProductView(MasterView):
app = self.get_rattail_app() app = self.get_rattail_app()
self.products_handler = app.get_products_handler() self.products_handler = app.get_products_handler()
self.merge_handler = self.products_handler
# TODO: deprecate / remove these # TODO: deprecate / remove these
self.product_handler = self.products_handler self.product_handler = self.products_handler
self.handler = self.products_handler self.handler = self.products_handler