class ProductionDetailsDialog(BaseEditor): gladefile = "ProductionDetailsDialog" model_type = ProductionOrder title = _("Production Details") size = (750, 460) hide_footer = True proxy_widgets = ('branch', 'identifier', 'open_date', 'close_date', 'responsible_name', 'status_string', ) def _setup_widgets(self): self.production_items.set_columns(self._get_production_items_columns()) self.materials.set_columns(self._get_material_columns()) self.services.set_columns(self._get_service_columns()) self.produced_items.set_columns(self._get_produced_items_columns()) self.produced_items.set_selection_mode(Gtk.SelectionMode.MULTIPLE) def _setup_data(self): # FIXME: Improve this self.production_items.clear() self.materials.clear() self.services.clear() self.produced_items.clear() self.production_items.add_list(self.model.get_items()) self.materials.add_list(self.model.get_material_items()) self.services.add_list(self.model.get_service_items()) self.produced_items.add_list( self.model.produced_items.order_by(ProductionOrder.identifier)) self.proxy.update_many(['close_date', 'status_string']) def _get_production_items_columns(self): return [Column('description', title=_('Description'), data_type=str, expand=True, searchable=True, ellipsize=Pango.EllipsizeMode.END, sorted=True), Column('unit_description', _("Unit"), data_type=str, justify=Gtk.Justification.RIGHT), Column('quantity', title=_('Quantity'), data_type=Decimal, justify=Gtk.Justification.RIGHT), Column('produced', title=_('Produced'), data_type=Decimal, justify=Gtk.Justification.RIGHT), Column('lost', title=_('Lost'), data_type=Decimal, justify=Gtk.Justification.RIGHT)] def _get_material_columns(self): return [Column('description', title=_('Description'), data_type=str, expand=True, searchable=True, ellipsize=Pango.EllipsizeMode.END, sorted=True), Column('product.location', _("Location"), data_type=str), Column('unit_description', _("Unit"), data_type=str, justify=Gtk.Justification.RIGHT), Column('needed', title=_('Needed'), data_type=Decimal, justify=Gtk.Justification.RIGHT), Column('allocated', title=_('Allocated'), data_type=Decimal, justify=Gtk.Justification.RIGHT), Column('consumed', title=_('Consumed'), data_type=Decimal, justify=Gtk.Justification.RIGHT), Column('lost', title=_('Lost'), data_type=Decimal, justify=Gtk.Justification.RIGHT), Column('to_purchase', title=_('To Purchase'), data_type=Decimal, justify=Gtk.Justification.RIGHT, visible=False), Column('to_make', title=_('To Make'), data_type=Decimal, justify=Gtk.Justification.RIGHT, visible=False)] def _get_service_columns(self): return [Column('description', _("Description"), data_type=str, expand=True, ellipsize=Pango.EllipsizeMode.END), Column('quantity', _("Quantity"), data_type=Decimal, justify=Gtk.Justification.RIGHT), Column('unit_description', _("Unit"), data_type=str, justify=Gtk.Justification.RIGHT)] def _get_test_result(self, item, quality_test): """Gets test result from cache, or fetch from database. """ hit = self._test_result_cache.get((item.id, quality_test.id), -1) if hit != -1: return hit test_result = item.get_test_result(quality_test) self._test_result_cache[(item.id, quality_test.id)] = test_result return test_result def _format_func(self, item, test): """Format function for tests columns. test is the quality test associated with the column """ test_result = self._get_test_result(item, test) if not test_result: val = '' else: val = test_result.result_value return val def _colorize(self, item, test): """Set the color for this test result test is the quality test associated with the column """ test_result = self._get_test_result(item, test) if not test_result: return False return not test_result.test_passed def _get_produced_items_columns(self): # Create a cache for test results, to avoid quering the database for # every update. self._test_result_cache = dict() columns = [Column('serial_number', title=_('Serial Number'), data_type=str, expand=True)] # Add one column for each test from each product. products = dict() for item in self.model.get_items(): if item.product in products: continue products[item.product] = 1 for test in item.product.quality_tests: columns.append( # This wont just the serial number, since we use format_func # to change the displayed value, but we still need one # property to create the column ColoredColumn('serial_number', data_type=str, title=test.description, format_func=self._format_func, format_func_data=test, color='red', data_func=self._colorize, use_data_model=True)) columns.extend([ Column('test_passed', title=_('Tests Passed'), data_type=bool, visible=False), Column('entered_stock', title=_('Entered Stock'), data_type=bool, visible=False)]) return columns # # BaseEditor hooks # def setup_proxies(self): self._setup_widgets() self.proxy = self.add_proxy(self.model, ProductionDetailsDialog.proxy_widgets) self._setup_data() def setup_slaves(self): self.quality_slave = QualityTestResultSlave(self.store) self.quality_slave.connect('test-updated', self._on_quality__test_updated) self.attach_slave('quality_holder', self.quality_slave) def has_open_inventory(self): has_open = Inventory.has_open(self.store, api.get_current_branch(self.store)) return bool(has_open) # # Actions # def _run_editor(self, editor_class, item): self.store.savepoint('before_run_editor_production') retval = run_dialog(editor_class, self, self.store, item) if not retval: self.store.rollback_to_savepoint('before_run_editor_production') else: self.store.commit() self._setup_data() def _produce(self): production_item = self.production_items.get_selected() self._run_editor(ProductionItemProducedEditor, production_item) def _add_lost(self): item = self.materials.get_selected() self._run_editor(ProductionMaterialLostEditor, item) def _allocate(self): item = self.materials.get_selected() self._run_editor(ProductionMaterialAllocateEditor, item) # # Kiwi Callbacks # def _on_quality__test_updated(self, slave, produced_item, quality_test, test_result): self._test_result_cache[(produced_item.id, quality_test.id)] = test_result self.produced_items.update(produced_item) def on_print_button__clicked(self, widget): print_report(ProductionOrderReport, self.model) def on_production_items__selection_changed(self, widget, item): self.produce_button.set_sensitive(bool(item) and item.can_produce(Decimal('0.001')) and not self.has_open_inventory()) def on_materials__selection_changed(self, widget, item): self.lost_button.set_sensitive(bool(item) and item.product.manage_stock and item.can_add_lost(Decimal('0.001'))) self.allocate_button.set_sensitive(bool(item) and item.product.manage_stock and self.model.status == ProductionOrder.ORDER_PRODUCING and not self.has_open_inventory()) def on_produced_items__selection_changed(self, widget, items): products = set() for i in items: products.add(i.product) is_in_qa = self.model.status in (ProductionOrder.ORDER_PRODUCING, ProductionOrder.ORDER_QA) # We can only set test results if only one type of product is selected if len(products) == 1 and is_in_qa: self.quality_slave.set_item_tests(items, items[0].product) else: self.quality_slave.set_item_tests([], None) def on_lost_button__clicked(self, button): self._add_lost() def on_allocate_button__clicked(self, button): self._allocate() def on_produce_button__clicked(self, button): self._produce() def on_production_items__row_activated(self, list, row): if self.produce_button.get_sensitive(): self._produce()
class ProductionDetailsDialog(BaseEditor): gladefile = "ProductionDetailsDialog" model_type = ProductionOrder title = _("Production Details") size = (750, 460) hide_footer = True proxy_widgets = ( 'branch', 'identifier', 'open_date', 'close_date', 'responsible_name', 'status_string', ) def _setup_widgets(self): self.production_items.set_columns(self._get_production_items_columns()) self.materials.set_columns(self._get_material_columns()) self.services.set_columns(self._get_service_columns()) self.produced_items.set_columns(self._get_produced_items_columns()) self.produced_items.set_selection_mode(gtk.SELECTION_MULTIPLE) def _setup_data(self): # FIXME: Improve this self.production_items.clear() self.materials.clear() self.services.clear() self.produced_items.clear() self.production_items.add_list(self.model.get_items()) self.materials.add_list(self.model.get_material_items()) self.services.add_list(self.model.get_service_items()) self.produced_items.add_list( self.model.produced_items.order_by(ProductionOrder.identifier)) self.proxy.update_many(['close_date', 'status_string']) def _get_production_items_columns(self): return [ Column('description', title=_('Description'), data_type=str, expand=True, searchable=True, ellipsize=pango.ELLIPSIZE_END, sorted=True), Column('unit_description', _("Unit"), data_type=str, justify=gtk.JUSTIFY_RIGHT), Column('quantity', title=_('Quantity'), data_type=Decimal, justify=gtk.JUSTIFY_RIGHT), Column('produced', title=_('Produced'), data_type=Decimal, justify=gtk.JUSTIFY_RIGHT), Column('lost', title=_('Lost'), data_type=Decimal, justify=gtk.JUSTIFY_RIGHT) ] def _get_material_columns(self): return [ Column('description', title=_('Description'), data_type=str, expand=True, searchable=True, ellipsize=pango.ELLIPSIZE_END, sorted=True), Column('product.location', _("Location"), data_type=str), Column('unit_description', _("Unit"), data_type=str, justify=gtk.JUSTIFY_RIGHT), Column('needed', title=_('Needed'), data_type=Decimal, justify=gtk.JUSTIFY_RIGHT), Column('allocated', title=_('Allocated'), data_type=Decimal, justify=gtk.JUSTIFY_RIGHT), Column('consumed', title=_('Consumed'), data_type=Decimal, justify=gtk.JUSTIFY_RIGHT), Column('lost', title=_('Lost'), data_type=Decimal, justify=gtk.JUSTIFY_RIGHT), Column('to_purchase', title=_('To Purchase'), data_type=Decimal, justify=gtk.JUSTIFY_RIGHT, visible=False), Column('to_make', title=_('To Make'), data_type=Decimal, justify=gtk.JUSTIFY_RIGHT, visible=False) ] def _get_service_columns(self): return [ Column('description', _("Description"), data_type=str, expand=True, ellipsize=pango.ELLIPSIZE_END), Column('quantity', _("Quantity"), data_type=Decimal, justify=gtk.JUSTIFY_RIGHT), Column('unit_description', _("Unit"), data_type=str, justify=gtk.JUSTIFY_RIGHT) ] def _get_test_result(self, item, quality_test): """Gets test result from cache, or fetch from database. """ hit = self._test_result_cache.get((item.id, quality_test.id), -1) if hit != -1: return hit test_result = item.get_test_result(quality_test) self._test_result_cache[(item.id, quality_test.id)] = test_result return test_result def _format_func(self, item, test): """Format function for tests columns. test is the quality test associated with the column """ test_result = self._get_test_result(item, test) if not test_result: val = '' else: val = test_result.result_value return val def _colorize(self, item, test): """Set the color for this test result test is the quality test associated with the column """ test_result = self._get_test_result(item, test) if not test_result: return False return not test_result.test_passed def _get_produced_items_columns(self): # Create a cache for test results, to avoid quering the database for # every update. self._test_result_cache = dict() columns = [ Column('serial_number', title=_('Serial Number'), data_type=str, expand=True) ] # Add one column for each test from each product. products = dict() for item in self.model.get_items(): if item.product in products: continue products[item.product] = 1 for test in item.product.quality_tests: columns.append( # This wont just the serial number, since we use format_func # to change the displayed value, but we still need one # property to create the column ColoredColumn('serial_number', data_type=str, title=test.description, format_func=self._format_func, format_func_data=test, color='red', data_func=self._colorize, use_data_model=True)) columns.extend([ Column('test_passed', title=_('Tests Passed'), data_type=bool, visible=False), Column('entered_stock', title=_('Entered Stock'), data_type=bool, visible=False) ]) return columns # # BaseEditor hooks # def setup_proxies(self): self._setup_widgets() self.proxy = self.add_proxy(self.model, ProductionDetailsDialog.proxy_widgets) self._setup_data() def setup_slaves(self): self.quality_slave = QualityTestResultSlave(self.store) self.quality_slave.connect('test-updated', self._on_quality__test_updated) self.attach_slave('quality_holder', self.quality_slave) def has_open_inventory(self): has_open = Inventory.has_open(self.store, api.get_current_branch(self.store)) return bool(has_open) # # Actions # def _run_editor(self, editor_class, item): self.store.savepoint('before_run_editor_production') retval = run_dialog(editor_class, self, self.store, item) if not retval: self.store.rollback_to_savepoint('before_run_editor_production') else: self.store.commit() self._setup_data() def _produce(self): production_item = self.production_items.get_selected() self._run_editor(ProductionItemProducedEditor, production_item) def _add_lost(self): item = self.materials.get_selected() self._run_editor(ProductionMaterialLostEditor, item) def _allocate(self): item = self.materials.get_selected() self._run_editor(ProductionMaterialAllocateEditor, item) # # Kiwi Callbacks # def _on_quality__test_updated(self, slave, produced_item, quality_test, test_result): self._test_result_cache[(produced_item.id, quality_test.id)] = test_result self.produced_items.update(produced_item) def on_print_button__clicked(self, widget): print_report(ProductionOrderReport, self.model) def on_production_items__selection_changed(self, widget, item): self.produce_button.set_sensitive( bool(item) and item.can_produce(Decimal('0.001')) and not self.has_open_inventory()) def on_materials__selection_changed(self, widget, item): self.lost_button.set_sensitive( bool(item) and item.product.manage_stock and item.can_add_lost(Decimal('0.001'))) self.allocate_button.set_sensitive( bool(item) and item.product.manage_stock and self.model.status == ProductionOrder.ORDER_PRODUCING and not self.has_open_inventory()) def on_produced_items__selection_changed(self, widget, items): products = set() for i in items: products.add(i.product) is_in_qa = self.model.status in (ProductionOrder.ORDER_PRODUCING, ProductionOrder.ORDER_QA) # We can only set test results if only one type of product is selected if len(products) == 1 and is_in_qa: self.quality_slave.set_item_tests(items, items[0].product) else: self.quality_slave.set_item_tests([], None) def on_lost_button__clicked(self, button): self._add_lost() def on_allocate_button__clicked(self, button): self._allocate() def on_produce_button__clicked(self, button): self._produce() def on_production_items__row_activated(self, list, row): if self.produce_button.get_sensitive(): self._produce()
def setup_slaves(self): self.quality_slave = QualityTestResultSlave(self.store) self.quality_slave.connect('test-updated', self._on_quality__test_updated) self.attach_slave('quality_holder', self.quality_slave)