Add way to "ignore" a pending product
and some related tweaks for sake of grid
This commit is contained in:
		
							parent
							
								
									1fc17658ff
								
							
						
					
					
						commit
						fe4a178d43
					
				
					 3 changed files with 143 additions and 56 deletions
				
			
		|  | @ -612,10 +612,11 @@ class AlchemyNumericFilter(AlchemyGridFilter): | |||
|     """ | ||||
|     value_renderer_factory = NumericValueRenderer | ||||
| 
 | ||||
|     # expose greater-than / less-than verbs in addition to core | ||||
|     default_verbs = ['equal', 'not_equal', 'greater_than', 'greater_equal', | ||||
|                      'less_than', 'less_equal', 'between', | ||||
|                      'is_null', 'is_not_null', 'is_any'] | ||||
|     def default_verbs(self): | ||||
|         # expose greater-than / less-than verbs in addition to core | ||||
|         return ['equal', 'not_equal', 'greater_than', 'greater_equal', | ||||
|                 'less_than', 'less_equal', 'between', | ||||
|                 'is_null', 'is_not_null', 'is_any'] | ||||
| 
 | ||||
|     # TODO: what follows "works" in that it prevents an error...but from the | ||||
|     # user's perspective it still fails silently...need to improve on front-end | ||||
|  | @ -670,6 +671,14 @@ class AlchemyIntegerFilter(AlchemyNumericFilter): | |||
|     """ | ||||
|     bigint = False | ||||
| 
 | ||||
|     def default_verbs(self): | ||||
| 
 | ||||
|         # limited verbs if choices are defined | ||||
|         if self.choices: | ||||
|             return ['equal', 'not_equal', 'is_null', 'is_not_null', 'is_any'] | ||||
| 
 | ||||
|         return super().default_verbs() | ||||
| 
 | ||||
|     def value_invalid(self, value): | ||||
|         if value: | ||||
|             if isinstance(value, int): | ||||
|  |  | |||
|  | @ -7,25 +7,16 @@ | |||
|   ${product_lookup.tailbone_product_lookup_template()} | ||||
| </%def> | ||||
| 
 | ||||
| <%def name="object_helpers()"> | ||||
|   ${parent.object_helpers()} | ||||
|   % if instance.status_code == enum.PENDING_PRODUCT_STATUS_PENDING and master.has_perm('resolve_product'): | ||||
|       <nav class="panel"> | ||||
|         <p class="panel-heading">Tools</p> | ||||
|         <div class="panel-block"> | ||||
|           <div style="display: flex; flex-direction: column;"> | ||||
|             <div class="buttons"> | ||||
|               <b-button type="is-primary" | ||||
|                         @click="resolveProductInit()" | ||||
|                         icon-pack="fas" | ||||
|                         icon-left="object-ungroup"> | ||||
|                 Resolve Product | ||||
|               </b-button> | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|       </nav> | ||||
| <%def name="page_content()"> | ||||
|   ${parent.page_content()} | ||||
| 
 | ||||
|   % if master.has_perm('ignore_product') and instance.status_code in (enum.PENDING_PRODUCT_STATUS_PENDING, enum.PENDING_PRODUCT_STATUS_READY): | ||||
|       ${h.form(master.get_action_url('ignore_product', instance), ref='ignoreProductForm')} | ||||
|       ${h.csrf_token(request)} | ||||
|       ${h.end_form()} | ||||
|   % endif | ||||
| 
 | ||||
|   % if master.has_perm('resolve_product') and instance.status_code in (enum.PENDING_PRODUCT_STATUS_PENDING, enum.PENDING_PRODUCT_STATUS_READY, enum.PENDING_PRODUCT_STATUS_IGNORED): | ||||
|       <b-modal has-modal-card | ||||
|                :active.sync="resolveProductShowDialog"> | ||||
|         <div class="modal-card"> | ||||
|  | @ -80,39 +71,55 @@ | |||
|   ${parent.modify_this_page_vars()} | ||||
|   <script type="text/javascript"> | ||||
| 
 | ||||
|     ThisPageData.resolveProductShowDialog = false | ||||
|     ThisPageData.resolveProductUUID = null | ||||
|     ThisPageData.resolveProductSubmitting = false | ||||
|     % if master.has_perm('ignore_product') and instance.status_code in (enum.PENDING_PRODUCT_STATUS_PENDING, enum.PENDING_PRODUCT_STATUS_READY): | ||||
| 
 | ||||
|     ThisPage.computed.resolveProductSubmitDisabled = function() { | ||||
|         if (this.resolveProductSubmitting) { | ||||
|             return true | ||||
|         ThisPage.methods.ignoreProductInit = function() { | ||||
|             if (!confirm("Really ignore this product?\n\n" | ||||
|                          + "This will leave it unresolved, but hidden via default filters.")) { | ||||
|                 return | ||||
|             } | ||||
|             this.$refs.ignoreProductForm.submit() | ||||
|         } | ||||
|         if (!this.resolveProductUUID) { | ||||
|             return true | ||||
| 
 | ||||
|     % endif | ||||
| 
 | ||||
|     % if master.has_perm('resolve_product') and instance.status_code in (enum.PENDING_PRODUCT_STATUS_PENDING, enum.PENDING_PRODUCT_STATUS_READY, enum.PENDING_PRODUCT_STATUS_IGNORED): | ||||
| 
 | ||||
|         ThisPageData.resolveProductShowDialog = false | ||||
|         ThisPageData.resolveProductUUID = null | ||||
|         ThisPageData.resolveProductSubmitting = false | ||||
| 
 | ||||
|         ThisPage.computed.resolveProductSubmitDisabled = function() { | ||||
|             if (this.resolveProductSubmitting) { | ||||
|                 return true | ||||
|             } | ||||
|             if (!this.resolveProductUUID) { | ||||
|                 return true | ||||
|             } | ||||
|             return false | ||||
|         } | ||||
|         return false | ||||
|     } | ||||
| 
 | ||||
|     ThisPage.methods.resolveProductInit = function() { | ||||
|         this.resolveProductUUID = null | ||||
|         this.resolveProductShowDialog = true | ||||
|         this.$nextTick(() => { | ||||
|             this.$refs.productLookup.focus() | ||||
|         }) | ||||
|     } | ||||
|         ThisPage.methods.resolveProductInit = function() { | ||||
|             this.resolveProductUUID = null | ||||
|             this.resolveProductShowDialog = true | ||||
|             this.$nextTick(() => { | ||||
|                 this.$refs.productLookup.focus() | ||||
|             }) | ||||
|         } | ||||
| 
 | ||||
|     ThisPage.methods.resolveProductSubmit = function() { | ||||
|         this.resolveProductSubmitting = true | ||||
|         this.$refs.resolveProductForm.submit() | ||||
|     } | ||||
|         ThisPage.methods.resolveProductSubmit = function() { | ||||
|             this.resolveProductSubmitting = true | ||||
|             this.$refs.resolveProductForm.submit() | ||||
|         } | ||||
| 
 | ||||
|     ThisPageData.actualProduct = null | ||||
|         ThisPageData.actualProduct = null | ||||
| 
 | ||||
|     ThisPage.methods.productSelected = function(product) { | ||||
|        this.actualProduct = product | ||||
|        this.resolveProductUUID = product ? product.uuid : null | ||||
|     } | ||||
|         ThisPage.methods.productSelected = function(product) { | ||||
|            this.actualProduct = product | ||||
|            this.resolveProductUUID = product ? product.uuid : null | ||||
|         } | ||||
| 
 | ||||
|     % endif | ||||
| 
 | ||||
|   </script> | ||||
| </%def> | ||||
|  |  | |||
|  | @ -2297,16 +2297,22 @@ class PendingProductView(MasterView): | |||
| 
 | ||||
|     def configure_grid(self, g): | ||||
|         super().configure_grid(g) | ||||
|         model = self.model | ||||
| 
 | ||||
|         g.set_enum('status_code', self.enum.PENDING_PRODUCT_STATUS) | ||||
|         g.filters['status_code'].default_active = True | ||||
|         g.filters['status_code'].default_verb = 'not_equal' | ||||
|         g.filters['status_code'].default_value = str(self.enum.PENDING_PRODUCT_STATUS_RESOLVED) | ||||
| 
 | ||||
|         g.set_sort_defaults('created', 'desc') | ||||
| 
 | ||||
|         # description | ||||
|         g.set_link('description') | ||||
| 
 | ||||
|         # status_code | ||||
|         g.set_enum('status_code', self.enum.PENDING_PRODUCT_STATUS) | ||||
|         g.set_filter('status_code', model.PendingProduct.status_code, | ||||
|                      value_enum=self.enum.PENDING_PRODUCT_STATUS, | ||||
|                      default_active=True, | ||||
|                      default_verb='equal', | ||||
|                      default_value=str(self.enum.PENDING_PRODUCT_STATUS_PENDING)) | ||||
| 
 | ||||
|         # created | ||||
|         g.set_sort_defaults('created', 'desc') | ||||
| 
 | ||||
|     def configure_form(self, f): | ||||
|         super().configure_form(f) | ||||
|         model = self.model | ||||
|  | @ -2398,8 +2404,20 @@ class PendingProductView(MasterView): | |||
|         if self.creating: | ||||
|             f.remove('status_code') | ||||
|         else: | ||||
|             # f.set_readonly('status_code') | ||||
|             f.set_enum('status_code', self.enum.PENDING_PRODUCT_STATUS) | ||||
|             if self.viewing: | ||||
|                 f.set_renderer('status_code', self.render_status_code) | ||||
| 
 | ||||
|                 if (self.has_perm('ignore_product') | ||||
|                     and pending.status_code in (self.enum.PENDING_PRODUCT_STATUS_PENDING, | ||||
|                                                 self.enum.PENDING_PRODUCT_STATUS_READY)): | ||||
|                     f.set_vuejs_component_kwargs(**{'@ignore-product': 'ignoreProductInit'}) | ||||
| 
 | ||||
|                 if (self.has_perm('resolve_product') | ||||
|                     and pending.status_code in (self.enum.PENDING_PRODUCT_STATUS_PENDING, | ||||
|                                                 self.enum.PENDING_PRODUCT_STATUS_READY, | ||||
|                                                 self.enum.PENDING_PRODUCT_STATUS_IGNORED)): | ||||
|                     f.set_vuejs_component_kwargs(**{'@resolve-product': 'resolveProductInit'}) | ||||
| 
 | ||||
|         # user | ||||
|         if self.creating: | ||||
|  | @ -2415,6 +2433,42 @@ class PendingProductView(MasterView): | |||
|             if not pending.resolved: | ||||
|                 f.remove('resolved', 'resolved_by') | ||||
| 
 | ||||
|     def render_status_code(self, pending, field): | ||||
|         status = pending.status_code | ||||
|         if not status: | ||||
|             return | ||||
| 
 | ||||
|         # will just show status text by default | ||||
|         text = self.enum.PENDING_PRODUCT_STATUS.get(status, str(status)) | ||||
|         html = text | ||||
| 
 | ||||
|         # but maybe also show buttons to change status | ||||
|         buttons = [] | ||||
| 
 | ||||
|         if (self.has_perm('ignore_product') | ||||
|             and status in (self.enum.PENDING_PRODUCT_STATUS_PENDING, | ||||
|                            self.enum.PENDING_PRODUCT_STATUS_READY)): | ||||
|             buttons.append(self.make_buefy_button("Ignore Product", | ||||
|                                                   type='is-warning', | ||||
|                                                   icon_left='ban', | ||||
|                                                   **{'@click': "$emit('ignore-product')"})) | ||||
| 
 | ||||
|         if (self.has_perm('resolve_product') | ||||
|             and status in (self.enum.PENDING_PRODUCT_STATUS_PENDING, | ||||
|                            self.enum.PENDING_PRODUCT_STATUS_READY, | ||||
|                            self.enum.PENDING_PRODUCT_STATUS_IGNORED)): | ||||
|             buttons.append(self.make_buefy_button("Resolve Product", | ||||
|                                                   is_primary=True, | ||||
|                                                   icon_left='object-ungroup', | ||||
|                                                   **{'@click': "$emit('resolve-product')"})) | ||||
| 
 | ||||
|         if buttons: | ||||
|             text = HTML.tag('span', class_='control', c=[text]) | ||||
|             buttons = HTML.tag('div', class_='buttons', c=buttons) | ||||
|             html = HTML.tag('b-field', grouped='grouped', c=[text, buttons]) | ||||
| 
 | ||||
|         return html | ||||
| 
 | ||||
|     def editable_instance(self, pending): | ||||
|         if self.request.is_root: | ||||
|             return True | ||||
|  | @ -2487,6 +2541,12 @@ class PendingProductView(MasterView): | |||
|     def get_resolve_product_kwargs(self, **kwargs): | ||||
|         return kwargs | ||||
| 
 | ||||
|     def ignore_product(self): | ||||
|         model = self.model | ||||
|         pending = self.get_instance() | ||||
|         pending.status_code = self.enum.PENDING_PRODUCT_STATUS_IGNORED | ||||
|         return self.redirect(self.get_action_url('view', pending)) | ||||
| 
 | ||||
|     def get_row_data(self, pending): | ||||
|         model = self.model | ||||
|         return self.Session.query(model.CustomerOrderItem)\ | ||||
|  | @ -2554,6 +2614,17 @@ class PendingProductView(MasterView): | |||
|                         route_name='{}.resolve_product'.format(route_prefix), | ||||
|                         permission='{}.resolve_product'.format(permission_prefix)) | ||||
| 
 | ||||
|         # ignore product | ||||
|         config.add_tailbone_permission(permission_prefix, | ||||
|                                        f'{permission_prefix}.ignore_product', | ||||
|                                        f"Mark {model_title} as ignored") | ||||
|         config.add_route(f'{route_prefix}.ignore_product', | ||||
|                          f'{instance_url_prefix}/ignore-product', | ||||
|                          request_method='POST') | ||||
|         config.add_view(cls, attr='ignore_product', | ||||
|                         route_name=f'{route_prefix}.ignore_product', | ||||
|                         permission=f'{permission_prefix}.ignore_product') | ||||
| 
 | ||||
| 
 | ||||
| def defaults(config, **kwargs): | ||||
|     base = globals() | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lance Edgar
						Lance Edgar