Improve default behavior for receiving a purchase batch
only targeting desktop so far, mobile is next...
This commit is contained in:
		
							parent
							
								
									e6144ea08b
								
							
						
					
					
						commit
						a5d1eece71
					
				
					 3 changed files with 151 additions and 42 deletions
				
			
		|  | @ -310,6 +310,17 @@ class PurchaseView(MasterView): | |||
|         # department | ||||
|         f.set_renderer('department', self.render_row_department) | ||||
| 
 | ||||
|         # product | ||||
|         f.set_renderer('product', self.render_row_product) | ||||
| 
 | ||||
|     def render_row_product(self, row, field): | ||||
|         product = row.product | ||||
|         if not product: | ||||
|             return "" | ||||
|         text = six.text_type(product) | ||||
|         url = self.request.route_url('products.view', uuid=product.uuid) | ||||
|         return tags.link_to(text, url) | ||||
| 
 | ||||
|     def render_row_department(self, row, field): | ||||
|         return "{} {}".format(row.department_number, row.department_name) | ||||
| 
 | ||||
|  |  | |||
|  | @ -221,15 +221,24 @@ class PurchasingBatchView(BatchMasterView): | |||
|         # mode | ||||
|         f.set_enum('mode', self.enum.PURCHASE_BATCH_MODE) | ||||
| 
 | ||||
|         # TODO: this hardly seems complete... | ||||
|         # store | ||||
|         single_store = self.rattail_config.single_store() | ||||
|         if self.creating: | ||||
|             f.replace('store', 'store_uuid') | ||||
|             f.set_widget('store_uuid', dfwidget.SelectWidget(values=self.get_store_values())) | ||||
|             f.set_label('store_uuid', "Store") | ||||
|             if single_store: | ||||
|                 store = self.rattail_config.get_store(self.Session()) | ||||
|                 f.set_widget('store_uuid', forms.widgets.ReadonlyWidget()) | ||||
|                 f.set_default('store_uuid', store.uuid) | ||||
|                 f.set_hidden('store_uuid') | ||||
|             else: | ||||
|                 f.set_widget('store_uuid', dfwidget.SelectWidget(values=self.get_store_values())) | ||||
|                 f.set_label('store_uuid', "Store") | ||||
|         else: | ||||
|             f.set_readonly('store') | ||||
|             f.set_renderer('store', self.render_store) | ||||
|             if single_store: | ||||
|                 f.remove_field('store') | ||||
|             else: | ||||
|                 f.set_readonly('store') | ||||
|                 f.set_renderer('store', self.render_store) | ||||
| 
 | ||||
|         # purchase | ||||
|         f.set_renderer('purchase', self.render_purchase) | ||||
|  | @ -243,17 +252,27 @@ class PurchasingBatchView(BatchMasterView): | |||
|         f.set_renderer('vendor', self.render_vendor) | ||||
|         if self.creating: | ||||
|             f.replace('vendor', 'vendor_uuid') | ||||
|             f.set_node('vendor_uuid', colander.String()) | ||||
|             vendor_display = "" | ||||
|             if self.request.method == 'POST': | ||||
|                 if self.request.POST.get('vendor_uuid'): | ||||
|                     vendor = self.Session.query(model.Vendor).get(self.request.POST['vendor_uuid']) | ||||
|                     if vendor: | ||||
|                         vendor_display = six.text_type(vendor) | ||||
|             vendors_url = self.request.route_url('vendors.autocomplete') | ||||
|             f.set_widget('vendor_uuid', forms.widgets.JQueryAutocompleteWidget( | ||||
|                 field_display=vendor_display, service_url=vendors_url)) | ||||
|             f.set_label('vendor_uuid', "Vendor") | ||||
|             widget_type = self.rattail_config.get('tailbone', 'default_widget.vendor', | ||||
|                                                   default='autocomplete') | ||||
|             if widget_type == 'autocomplete': | ||||
|                 vendor_display = "" | ||||
|                 if self.request.method == 'POST': | ||||
|                     if self.request.POST.get('vendor_uuid'): | ||||
|                         vendor = self.Session.query(model.Vendor).get(self.request.POST['vendor_uuid']) | ||||
|                         if vendor: | ||||
|                             vendor_display = six.text_type(vendor) | ||||
|                 vendors_url = self.request.route_url('vendors.autocomplete') | ||||
|                 f.set_widget('vendor_uuid', forms.widgets.JQueryAutocompleteWidget( | ||||
|                     field_display=vendor_display, service_url=vendors_url)) | ||||
|             elif widget_type == 'dropdown': | ||||
|                 vendors = self.Session.query(model.Vendor)\ | ||||
|                                       .order_by(model.Vendor.id) | ||||
|                 vendor_values = [(vendor.uuid, "({}) {}".format(vendor.id, vendor.name)) | ||||
|                                  for vendor in vendors] | ||||
|                 f.set_widget('vendor_uuid', dfwidget.SelectWidget(values=vendor_values)) | ||||
|             else: | ||||
|                 raise NotImplementedError("Unsupported vendor widget type: {}".format(widget_type)) | ||||
|         elif self.editing: | ||||
|             f.set_readonly('vendor') | ||||
| 
 | ||||
|  | @ -271,26 +290,27 @@ class PurchasingBatchView(BatchMasterView): | |||
|             f.set_readonly('department') | ||||
| 
 | ||||
|         # buyer | ||||
|         f.set_renderer('buyer', self.render_buyer) | ||||
|         if self.creating or self.editing: | ||||
|             f.replace('buyer', 'buyer_uuid') | ||||
|             f.set_node('buyer_uuid', colander.String(), missing=colander.null) | ||||
|             buyer_display = "" | ||||
|             if self.request.method == 'POST': | ||||
|                 if self.request.POST.get('buyer_uuid'): | ||||
|                     buyer = self.Session.query(model.Employee).get(self.request.POST['buyer_uuid']) | ||||
|                     if buyer: | ||||
|                         buyer_display = six.text_type(buyer) | ||||
|             elif self.creating: | ||||
|                 buyer = self.request.user.employee | ||||
|                 buyer_display = six.text_type(buyer) | ||||
|                 f.set_default('buyer_uuid', buyer.uuid) | ||||
|             elif self.editing: | ||||
|                 buyer_display = six.text_type(batch.buyer or '') | ||||
|             buyers_url = self.request.route_url('employees.autocomplete') | ||||
|             f.set_widget('buyer_uuid', forms.widgets.JQueryAutocompleteWidget( | ||||
|                 field_display=buyer_display, service_url=buyers_url)) | ||||
|             f.set_label('buyer_uuid', "Buyer") | ||||
|         if 'buyer' in f: | ||||
|             f.set_renderer('buyer', self.render_buyer) | ||||
|             if self.creating or self.editing: | ||||
|                 f.replace('buyer', 'buyer_uuid') | ||||
|                 f.set_node('buyer_uuid', colander.String(), missing=colander.null) | ||||
|                 buyer_display = "" | ||||
|                 if self.request.method == 'POST': | ||||
|                     if self.request.POST.get('buyer_uuid'): | ||||
|                         buyer = self.Session.query(model.Employee).get(self.request.POST['buyer_uuid']) | ||||
|                         if buyer: | ||||
|                             buyer_display = six.text_type(buyer) | ||||
|                 elif self.creating: | ||||
|                     buyer = self.request.user.employee | ||||
|                     buyer_display = six.text_type(buyer) | ||||
|                     f.set_default('buyer_uuid', buyer.uuid) | ||||
|                 elif self.editing: | ||||
|                     buyer_display = six.text_type(batch.buyer or '') | ||||
|                 buyers_url = self.request.route_url('employees.autocomplete') | ||||
|                 f.set_widget('buyer_uuid', forms.widgets.JQueryAutocompleteWidget( | ||||
|                     field_display=buyer_display, service_url=buyers_url)) | ||||
|                 f.set_label('buyer_uuid', "Buyer") | ||||
| 
 | ||||
|         # date_ordered | ||||
|         f.set_type('date_ordered', 'date_jquery') | ||||
|  | @ -629,19 +649,33 @@ class PurchasingBatchView(BatchMasterView): | |||
| 
 | ||||
|         elif self.editing: | ||||
|             f.set_readonly('upc') | ||||
|             f.set_readonly('item_id') | ||||
|             f.set_readonly('product') | ||||
|             f.remove_fields('po_total', | ||||
|                             'invoice_total', | ||||
|                             'status_code') | ||||
|             f.set_renderer('product', self.render_product) | ||||
| 
 | ||||
|             # TODO: what's up with this again? | ||||
|             # f.remove_fields('po_total', | ||||
|             #                 'invoice_total', | ||||
|             #                 'status_code') | ||||
| 
 | ||||
|         elif self.viewing: | ||||
|             if row.product: | ||||
|                 f.remove_fields('brand_name', | ||||
|                                 'description', | ||||
|                                 'size') | ||||
|                 f.set_renderer('product', self.render_row_product) | ||||
|             else: | ||||
|                 f.remove_field('product') | ||||
| 
 | ||||
| 
 | ||||
|     def render_row_product(self, row, field): | ||||
|         product = row.product | ||||
|         if not product: | ||||
|             return "" | ||||
|         text = six.text_type(product) | ||||
|         url = self.request.route_url('products.view', uuid=product.uuid) | ||||
|         return tags.link_to(text, url) | ||||
| 
 | ||||
|     def configure_mobile_row_form(self, f): | ||||
|         super(PurchasingBatchView, self).configure_mobile_row_form(f) | ||||
|         # row = f.model_instance | ||||
|  | @ -786,6 +820,11 @@ class PurchasingBatchView(BatchMasterView): | |||
| #         self.request.session.flash("Added item: {} {}".format(row.upc.pretty(), row.product)) | ||||
| #         return self.redirect(self.request.current_route_url()) | ||||
| 
 | ||||
|     # TODO: seems like this should be master behavior, controlled by setting? | ||||
|     def redirect_after_edit_row(self, row, mobile=False): | ||||
|         parent = self.get_parent(row) | ||||
|         return self.redirect(self.get_action_url('view', parent, mobile=mobile)) | ||||
| 
 | ||||
|     def delete_row(self): | ||||
|         """ | ||||
|         Update the batch totals in addition to marking row as removed. | ||||
|  |  | |||
|  | @ -89,11 +89,38 @@ class ReceivingBatchView(PurchasingBatchView): | |||
|     model_title_plural = "Receiving Batches" | ||||
|     index_title = "Receiving" | ||||
|     creatable = False | ||||
|     rows_editable = True | ||||
|     rows_deletable = False | ||||
|     mobile_creatable = True | ||||
|     mobile_rows_filterable = True | ||||
|     mobile_rows_creatable = True | ||||
| 
 | ||||
|     form_fields = [ | ||||
|         'id', | ||||
|         'store', | ||||
|         'vendor', | ||||
|         'department', | ||||
|         'purchase', | ||||
|         'vendor_email', | ||||
|         'vendor_fax', | ||||
|         'vendor_contact', | ||||
|         'vendor_phone', | ||||
|         'date_ordered', | ||||
|         'date_received', | ||||
|         'po_number', | ||||
|         'po_total', | ||||
|         'invoice_date', | ||||
|         'invoice_number', | ||||
|         'invoice_total', | ||||
|         'notes', | ||||
|         'created', | ||||
|         'created_by', | ||||
|         'status_code', | ||||
|         'complete', | ||||
|         'executed', | ||||
|         'executed_by', | ||||
|     ] | ||||
| 
 | ||||
|     mobile_form_fields = [ | ||||
|         'vendor', | ||||
|         'department', | ||||
|  | @ -116,6 +143,34 @@ class ReceivingBatchView(PurchasingBatchView): | |||
|         'status_code', | ||||
|     ] | ||||
| 
 | ||||
|     row_form_fields = [ | ||||
|         'upc', | ||||
|         'item_id', | ||||
|         'product', | ||||
|         'brand_name', | ||||
|         'description', | ||||
|         'size', | ||||
|         'case_quantity', | ||||
|         'cases_ordered', | ||||
|         'units_ordered', | ||||
|         'cases_received', | ||||
|         'units_received', | ||||
|         'cases_damaged', | ||||
|         'units_damaged', | ||||
|         'cases_expired', | ||||
|         'units_expired', | ||||
|         'cases_mispick', | ||||
|         'units_mispick', | ||||
|         'po_line_number', | ||||
|         'po_unit_cost', | ||||
|         'po_total', | ||||
|         'invoice_line_number', | ||||
|         'invoice_unit_cost', | ||||
|         'invoice_total', | ||||
|         'status_code', | ||||
|         'credits', | ||||
|     ] | ||||
| 
 | ||||
|     @property | ||||
|     def batch_mode(self): | ||||
|         return self.enum.PURCHASE_BATCH_MODE_RECEIVING | ||||
|  | @ -177,8 +232,6 @@ class ReceivingBatchView(PurchasingBatchView): | |||
|         if mobile: | ||||
| 
 | ||||
|             purchase = self.get_purchase(self.request.POST['purchase']) | ||||
|             kwargs['sms_transaction_number'] = purchase.F1032 | ||||
| 
 | ||||
|             numbers = [d.F03 for d in purchase.details] | ||||
|             if numbers: | ||||
|                 number = max(set(numbers), key=numbers.count) | ||||
|  | @ -186,8 +239,6 @@ class ReceivingBatchView(PurchasingBatchView): | |||
|                                                    .filter(model.Department.number == number)\ | ||||
|                                                    .one() | ||||
| 
 | ||||
|         else: | ||||
|             kwargs['sms_transaction_number'] = batch.sms_transaction_number | ||||
|         return kwargs | ||||
| 
 | ||||
|     def configure_mobile_form(self, f): | ||||
|  | @ -199,6 +250,14 @@ class ReceivingBatchView(PurchasingBatchView): | |||
|         # department | ||||
|         # fs.department.with_renderer(fa.TextFieldRenderer), | ||||
| 
 | ||||
|     def configure_row_form(self, f): | ||||
|         super(ReceivingBatchView, self).configure_row_form(f) | ||||
|         f.set_readonly('cases_ordered') | ||||
|         f.set_readonly('units_ordered') | ||||
|         f.set_readonly('po_unit_cost') | ||||
|         f.set_readonly('po_total') | ||||
|         f.set_readonly('invoice_total') | ||||
| 
 | ||||
|     def render_mobile_row_listitem(self, row, i): | ||||
|         description = row.product.full_description if row.product else row.description | ||||
|         return "({}) {}".format(row.upc.pretty(), description) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lance Edgar
						Lance Edgar