Allow pending product fields to be required, for new custorder
This commit is contained in:
		
							parent
							
								
									e308108bf7
								
							
						
					
					
						commit
						4247804707
					
				
					 3 changed files with 167 additions and 57 deletions
				
			
		|  | @ -79,15 +79,6 @@ | |||
|       </b-checkbox> | ||||
|     </b-field> | ||||
| 
 | ||||
|     <b-field message="If set, user can enter details of an arbitrary new "pending" product."> | ||||
|       <b-checkbox name="rattail.custorders.allow_unknown_product" | ||||
|                   v-model="simpleSettings['rattail.custorders.allow_unknown_product']" | ||||
|                   native-value="true" | ||||
|                   @input="settingsNeedSaved = true"> | ||||
|         Allow creating orders for "unknown" products | ||||
|       </b-checkbox> | ||||
|     </b-field> | ||||
| 
 | ||||
|     <b-field> | ||||
|       <b-checkbox name="rattail.custorders.allow_item_discounts" | ||||
|                   v-model="simpleSettings['rattail.custorders.allow_item_discounts']" | ||||
|  | @ -130,6 +121,41 @@ | |||
|     </b-field> | ||||
| 
 | ||||
|   </div> | ||||
| 
 | ||||
|   <h3 class="block is-size-3">Unknown Products</h3> | ||||
|   <div class="block" style="padding-left: 2rem;"> | ||||
| 
 | ||||
|     <b-field message="If set, user can enter details of an arbitrary new "pending" product."> | ||||
|       <b-checkbox name="rattail.custorders.allow_unknown_product" | ||||
|                   v-model="simpleSettings['rattail.custorders.allow_unknown_product']" | ||||
|                   native-value="true" | ||||
|                   @input="settingsNeedSaved = true"> | ||||
|         Allow creating orders for "unknown" products | ||||
|       </b-checkbox> | ||||
|     </b-field> | ||||
| 
 | ||||
|     <div v-if="simpleSettings['rattail.custorders.allow_unknown_product']"> | ||||
| 
 | ||||
|       <p class="block"> | ||||
|         Require these fields for new product: | ||||
|       </p> | ||||
| 
 | ||||
|       <div style="margin-left: 2rem;"> | ||||
|         % for field in pending_product_fields: | ||||
|             <b-field> | ||||
|               <b-checkbox name="rattail.custorders.unknown_product.fields.${field}.required" | ||||
|                           v-model="simpleSettings['rattail.custorders.unknown_product.fields.${field}.required']" | ||||
|                           native-value="true" | ||||
|                           @input="settingsNeedSaved = true"> | ||||
|                 ${field} | ||||
|               </b-checkbox> | ||||
|             </b-field> | ||||
|         % endfor | ||||
|       </div> | ||||
| 
 | ||||
|     </div> | ||||
| 
 | ||||
|   </div> | ||||
| </%def> | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ | |||
|                     :disabled="submittingOrder" | ||||
|                     icon-pack="fas" | ||||
|                     icon-left="fas fa-upload"> | ||||
|             {{ submitOrderButtonText }} | ||||
|             {{ submittingOrder ? "Working, please wait..." : "Submit this Order" }} | ||||
|           </b-button> | ||||
|           <b-button @click="startOverEntirely()" | ||||
|                     icon-pack="fas" | ||||
|  | @ -644,18 +644,29 @@ | |||
| 
 | ||||
|                         <b-field grouped> | ||||
| 
 | ||||
|                           <b-field label="Brand"> | ||||
|                           <b-field label="Brand" | ||||
|                                    % if 'brand_name' in pending_product_required_fields: | ||||
|                                    :type="pendingProduct.brand_name ? null : 'is-danger'" | ||||
|                                    % endif | ||||
|                                    > | ||||
|                             <b-input v-model="pendingProduct.brand_name"> | ||||
|                             </b-input> | ||||
|                           </b-field> | ||||
| 
 | ||||
|                           <b-field label="Description" | ||||
|                                    :type="pendingProduct.description ? null : 'is-danger'"> | ||||
|                                    % if 'description' in pending_product_required_fields: | ||||
|                                    :type="pendingProduct.description ? null : 'is-danger'" | ||||
|                                    % endif | ||||
|                                    > | ||||
|                             <b-input v-model="pendingProduct.description"> | ||||
|                             </b-input> | ||||
|                           </b-field> | ||||
| 
 | ||||
|                           <b-field label="Unit Size"> | ||||
|                           <b-field label="Unit Size" | ||||
|                                    % if 'size' in pending_product_required_fields: | ||||
|                                    :type="pendingProduct.size ? null : 'is-danger'" | ||||
|                                    % endif | ||||
|                                    > | ||||
|                             <b-input v-model="pendingProduct.size"> | ||||
|                             </b-input> | ||||
|                           </b-field> | ||||
|  | @ -664,12 +675,20 @@ | |||
| 
 | ||||
|                         <b-field grouped> | ||||
| 
 | ||||
|                           <b-field :label="productKeyLabel"> | ||||
|                           <b-field :label="productKeyLabel" | ||||
|                                    % if 'key' in pending_product_required_fields: | ||||
|                                    :type="pendingProduct[productKeyField] ? null : 'is-danger'" | ||||
|                                    % endif | ||||
|                                    > | ||||
|                             <b-input v-model="pendingProduct[productKeyField]"> | ||||
|                             </b-input> | ||||
|                           </b-field> | ||||
| 
 | ||||
|                           <b-field label="Department"> | ||||
|                           <b-field label="Department" | ||||
|                                    % if 'department_uuid' in pending_product_required_fields: | ||||
|                                    :type="pendingProduct.department_uuid ? null : 'is-danger'" | ||||
|                                    % endif | ||||
|                                    > | ||||
|                             <b-select v-model="pendingProduct.department_uuid"> | ||||
|                               <option :value="null">(not known)</option> | ||||
|                               <option v-for="option in departmentOptions" | ||||
|  | @ -680,9 +699,36 @@ | |||
|                             </b-select> | ||||
|                           </b-field> | ||||
| 
 | ||||
|                           <b-field label="Unit Reg. Price"> | ||||
|                             <b-input v-model="pendingProduct.regular_price_amount" | ||||
|                                      type="number" step="0.01"> | ||||
|                         </b-field> | ||||
| 
 | ||||
|                         <b-field grouped> | ||||
| 
 | ||||
|                           <b-field label="Vendor" | ||||
|                                    % if 'vendor_name' in pending_product_required_fields: | ||||
|                                    :type="pendingProduct.vendor_name ? null : 'is-danger'" | ||||
|                                    % endif | ||||
|                                    > | ||||
|                             <b-input v-model="pendingProduct.vendor_name"> | ||||
|                             </b-input> | ||||
|                           </b-field> | ||||
| 
 | ||||
|                           <b-field label="Vendor Item Code" | ||||
|                                    % if 'vendor_item_code' in pending_product_required_fields: | ||||
|                                    :type="pendingProduct.vendor_item_code ? null : 'is-danger'" | ||||
|                                    % endif | ||||
|                                    > | ||||
|                             <b-input v-model="pendingProduct.vendor_item_code"> | ||||
|                             </b-input> | ||||
|                           </b-field> | ||||
| 
 | ||||
|                           <b-field label="Case Size" | ||||
|                                    % if 'case_size' in pending_product_required_fields: | ||||
|                                    :type="pendingProduct.case_size ? null : 'is-danger'" | ||||
|                                    % endif | ||||
|                                    > | ||||
|                             <b-input v-model="pendingProduct.case_size" | ||||
|                                      type="number" step="0.01" | ||||
|                                      style="width: 7rem;"> | ||||
|                             </b-input> | ||||
|                           </b-field> | ||||
| 
 | ||||
|  | @ -690,27 +736,24 @@ | |||
| 
 | ||||
|                         <b-field grouped> | ||||
| 
 | ||||
|                           <b-field label="Vendor"> | ||||
|                             <b-input v-model="pendingProduct.vendor_name"> | ||||
|                             </b-input> | ||||
|                           </b-field> | ||||
| 
 | ||||
|                           <b-field label="Vendor Item Code"> | ||||
|                             <b-input v-model="pendingProduct.vendor_item_code"> | ||||
|                             </b-input> | ||||
|                           </b-field> | ||||
| 
 | ||||
|                           <b-field label="Unit Cost"> | ||||
|                           <b-field label="Unit Cost" | ||||
|                                    % if 'unit_cost' in pending_product_required_fields: | ||||
|                                    :type="pendingProduct.unit_cost ? null : 'is-danger'" | ||||
|                                    % endif | ||||
|                                    > | ||||
|                             <b-input v-model="pendingProduct.unit_cost" | ||||
|                                      type="number" step="0.01" | ||||
|                                      style="width: 10rem;"> | ||||
|                             </b-input> | ||||
|                           </b-field> | ||||
| 
 | ||||
|                           <b-field label="Case Size"> | ||||
|                             <b-input v-model="pendingProduct.case_size" | ||||
|                                      type="number" step="0.01" | ||||
|                                      style="width: 7rem;"> | ||||
|                           <b-field label="Unit Reg. Price" | ||||
|                                    % if 'regular_price_amount' in pending_product_required_fields: | ||||
|                                    :type="pendingProduct.regular_price_amount ? null : 'is-danger'" | ||||
|                                    % endif | ||||
|                                    > | ||||
|                             <b-input v-model="pendingProduct.regular_price_amount" | ||||
|                                      type="number" step="0.01"> | ||||
|                             </b-input> | ||||
|                           </b-field> | ||||
| 
 | ||||
|  | @ -854,7 +897,7 @@ | |||
|                               :disabled="itemDialogSaveDisabled" | ||||
|                               icon-pack="fas" | ||||
|                               icon-left="save"> | ||||
|                       {{ itemDialogSaveButtonText }} | ||||
|                       {{ itemDialogSaving ? "Working, please wait..." : (this.editingItem ? "Update Item" : "Add Item") }} | ||||
|                     </b-button> | ||||
|                   </div> | ||||
| 
 | ||||
|  | @ -1197,6 +1240,7 @@ | |||
|                 % endif | ||||
| 
 | ||||
|                 pendingProduct: {}, | ||||
|                 pendingProductRequiredFields: ${json.dumps(pending_product_required_fields)|n}, | ||||
|                 departmentOptions: ${json.dumps(department_options)|n}, | ||||
| 
 | ||||
|                 submittingOrder: false, | ||||
|  | @ -1385,37 +1429,30 @@ | |||
|             % endif | ||||
| 
 | ||||
|             itemDialogSaveDisabled() { | ||||
| 
 | ||||
|                 if (this.itemDialogSaving) { | ||||
|                     return true | ||||
|                 } | ||||
| 
 | ||||
|                 if (this.productIsKnown) { | ||||
|                     if (!this.productUUID) { | ||||
|                         return true | ||||
|                     } | ||||
| 
 | ||||
|                 } else { | ||||
|                     if (!this.pendingProduct.description) { | ||||
|                         return true | ||||
|                     for (let field of this.pendingProductRequiredFields) { | ||||
|                         if (!this.pendingProduct[field]) { | ||||
|                             return true | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 if (!this.productUOM) { | ||||
|                     return true | ||||
|                 } | ||||
| 
 | ||||
|                 return false | ||||
|             }, | ||||
| 
 | ||||
|             itemDialogSaveButtonText() { | ||||
|                 if (this.itemDialogSaving) { | ||||
|                     return "Working, please wait..." | ||||
|                 } | ||||
|                 return this.editingItem ? "Update Item" : "Add Item" | ||||
|             }, | ||||
| 
 | ||||
|             submitOrderButtonText() { | ||||
|                 if (this.submittingOrder) { | ||||
|                     return "Working, please wait..." | ||||
|                 } | ||||
|                 return "Submit this Order" | ||||
|             }, | ||||
|         }, | ||||
|         mounted() { | ||||
|             if (this.customerStatusType) { | ||||
|  | @ -1925,11 +1962,14 @@ | |||
| 
 | ||||
|                 this.productIsKnown = !!row.product_uuid | ||||
|                 this.productUUID = row.product_uuid | ||||
|                 this.pendingProduct = {} | ||||
| 
 | ||||
|                 // nb. must construct new object before updating data | ||||
|                 // (otherwise vue does not notice the changes?) | ||||
|                 let pending = {} | ||||
|                 if (row.pending_product) { | ||||
|                     this.copyPendingProductAttrs(row.pending_product, | ||||
|                                                  this.pendingProduct) | ||||
|                     this.copyPendingProductAttrs(row.pending_product, pending) | ||||
|                 } | ||||
|                 this.pendingProduct = pending | ||||
| 
 | ||||
|                 this.productDisplay = row.product_full_description | ||||
|                 this.productKey = row.product_key | ||||
|  |  | |||
|  | @ -102,6 +102,19 @@ class CustomerOrderView(MasterView): | |||
|         'flagged', | ||||
|     ] | ||||
| 
 | ||||
|     PENDING_PRODUCT_ENTRY_FIELDS = [ | ||||
|         'key', | ||||
|         'department_uuid', | ||||
|         'brand_name', | ||||
|         'description', | ||||
|         'size', | ||||
|         'vendor_name', | ||||
|         'vendor_item_code', | ||||
|         'unit_cost', | ||||
|         'case_size', | ||||
|         'regular_price_amount', | ||||
|     ] | ||||
| 
 | ||||
|     def __init__(self, request): | ||||
|         super(CustomerOrderView, self).__init__(request) | ||||
|         self.batch_handler = self.get_batch_handler() | ||||
|  | @ -361,6 +374,7 @@ class CustomerOrderView(MasterView): | |||
|             'order_items': items, | ||||
|             'product_key_label': app.get_product_key_label(), | ||||
|             'allow_unknown_product': self.batch_handler.allow_unknown_product(), | ||||
|             'pending_product_required_fields': self.get_pending_product_required_fields(), | ||||
|             'department_options': self.get_department_options(), | ||||
|             'default_uom_choices': self.batch_handler.uom_choices_for_product(None), | ||||
|             'default_uom': None, | ||||
|  | @ -390,6 +404,17 @@ class CustomerOrderView(MasterView): | |||
|                             'value': department.uuid}) | ||||
|         return options | ||||
| 
 | ||||
|     def get_pending_product_required_fields(self): | ||||
|         required = [] | ||||
|         for field in self.PENDING_PRODUCT_ENTRY_FIELDS: | ||||
|             require = self.rattail_config.getbool('rattail.custorders', | ||||
|                                                   f'unknown_product.fields.{field}.required') | ||||
|             if require is None and field == 'description': | ||||
|                 require = True | ||||
|             if require: | ||||
|                 required.append(field) | ||||
|         return required | ||||
| 
 | ||||
|     def get_current_batch(self): | ||||
|         user = self.request.user | ||||
|         if not user: | ||||
|  | @ -1044,7 +1069,7 @@ class CustomerOrderView(MasterView): | |||
|         } | ||||
| 
 | ||||
|     def configure_get_simple_settings(self): | ||||
|         return [ | ||||
|         settings = [ | ||||
| 
 | ||||
|             # customer handling | ||||
|             {'section': 'rattail.custorders', | ||||
|  | @ -1067,9 +1092,6 @@ class CustomerOrderView(MasterView): | |||
|             {'section': 'rattail.custorders', | ||||
|              'option': 'product_price_may_be_questionable', | ||||
|              'type': bool}, | ||||
|             {'section': 'rattail.custorders', | ||||
|              'option': 'allow_unknown_product', | ||||
|              'type': bool}, | ||||
|             {'section': 'rattail.custorders', | ||||
|              'option': 'allow_item_discounts', | ||||
|              'type': bool}, | ||||
|  | @ -1082,8 +1104,30 @@ class CustomerOrderView(MasterView): | |||
|             {'section': 'rattail.custorders', | ||||
|              'option': 'allow_past_item_reorder', | ||||
|              'type': bool}, | ||||
| 
 | ||||
|             # unknown products | ||||
|             {'section': 'rattail.custorders', | ||||
|              'option': 'allow_unknown_product', | ||||
|              'type': bool}, | ||||
|         ] | ||||
| 
 | ||||
|         for field in self.PENDING_PRODUCT_ENTRY_FIELDS: | ||||
|             setting = {'section': 'rattail.custorders', | ||||
|                        'option': f'unknown_product.fields.{field}.required', | ||||
|                        'type': bool} | ||||
|             if field == 'description': | ||||
|                 setting['default'] = True | ||||
|             settings.append(setting) | ||||
| 
 | ||||
|         return settings | ||||
| 
 | ||||
|     def configure_get_context(self, **kwargs): | ||||
|         context = super().configure_get_context(**kwargs) | ||||
| 
 | ||||
|         context['pending_product_fields'] = self.PENDING_PRODUCT_ENTRY_FIELDS | ||||
| 
 | ||||
|         return context | ||||
| 
 | ||||
|     @classmethod | ||||
|     def defaults(cls, config): | ||||
|         cls._order_defaults(config) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lance Edgar
						Lance Edgar