def create_filters(self): self.set_text_field_columns( ['supplier_name', 'identifier_str', 'invoice_numbers']) self.status_filter = ComboSearchFilter(_('Show orders'), self._get_status_values()) self.add_filter(self.status_filter, SearchFilterPosition.TOP, ['status']) self.branch_filter = self.create_branch_filter( column=PurchaseOrderView.branch_id)
def create_filters(self): statuses = [(value, key) for key, value in Branch.statuses.items()] statuses.insert(0, (_('Any'), None)) status_filter = ComboSearchFilter(_('Show branches with status'), statuses) status_filter.select(None) executer = self.search.get_query_executer() executer.add_filter_query_callback(status_filter, self._get_status_query) self.search.add_filter(status_filter, SearchFilterPosition.TOP)
def create_filters(self): self.set_text_field_columns(['recipient_name', 'identifier_str']) self.main_filter = ComboSearchFilter(_('Show'), []) self.add_filter(self.main_filter, SearchFilterPosition.TOP, callback=self._get_main_query) self.create_branch_filter(column=[Invoice.branch_id]) self._update_filters()
def create_filters(self): self.search.set_query(self._query) self.set_text_field_columns([ 'description', 'code', 'barcode', 'category_description', 'manufacturer' ]) branches = Branch.get_active_branches(self.store) self.branch_filter = ComboSearchFilter( _('Show by:'), api.for_combo(branches, empty=_("All branches"))) self.branch_filter.select(api.get_current_branch(self.store)) self.add_filter(self.branch_filter, position=SearchFilterPosition.TOP)
def create_sellable_filter(self, label=None): from stoqlib.domain.sellable import Sellable items = [(desc, status) for status, desc in Sellable.statuses.items()] items.insert(0, (_(u"Any"), None)) if label is None: label = _('With status:') sellable_filter = ComboSearchFilter(label, items) # Select status available by default sellable_filter.select(Sellable.STATUS_AVAILABLE) return sellable_filter
def create_main_filter(self): self.main_filter = ComboSearchFilter(_('Show'), []) combo = self.main_filter.combo combo.color_attribute = 'color' combo.set_row_separator_func(self._on_main_filter__row_separator_func) self._update_filter_items() executer = self.search.get_query_executer() executer.add_filter_query_callback(self.main_filter, self._create_main_query) self.add_filter(self.main_filter, SearchFilterPosition.TOP) self.create_branch_filter(column=self.search_spec.branch_id)
def create_filters(self): # Disable string search right now, until we use a proper Viewable # for this application self.search.disable_search_entry() self.branch_filter = ComboSearchFilter(_('Show inventories at:'), self._get_branches_for_filter()) current = api.get_current_branch(self.store) self.branch_filter.select(current.id) self.add_filter(self.branch_filter, SearchFilterPosition.TOP, columns=["branch_id"])
def create_filters(self): self.set_text_field_columns([ 'tracking_code', 'transporter_name', 'recipient_name', 'identifier_str' ]) # Status statuses = [(desc, st) for st, desc in Delivery.statuses.items()] statuses.insert(0, (_('Any'), None)) self.status_filter = ComboSearchFilter(_('With status:'), statuses) self.status_filter.select(None) self.add_filter(self.status_filter, columns=['status'], position=SearchFilterPosition.TOP)
def create_filters(self): self.set_text_field_columns(['description', 'identifier_str']) executer = self.search.get_query_executer() executer.add_query_callback(self._get_query) # Status items = [(v, k) for k, v in Till.statuses.items() if k != Till.STATUS_PENDING] items.insert(0, (_(u'Any'), None)) status_filter = ComboSearchFilter(_(u'Show entries of type'), items) status_filter.select(Till.STATUS_OPEN) self.add_filter(status_filter, position=SearchFilterPosition.TOP, columns=['status'])
def create_payment_filter(self, label=None): from stoqlib.domain.payment.method import PaymentMethod methods = PaymentMethod.get_active_methods(self.store) items = [(_('Any'), None)] for method in methods: if method.method_name == 'multiple': continue items.append((method.description, method)) if not label: label = _('Method:') payment_filter = ComboSearchFilter(label, items) payment_filter.select(None) return payment_filter
def create_filters(self): # Category categories = self.store.find(SellableCategory) items = stoq_api.for_combo(categories, attr='full_description') items.insert(0, (_('Any'), None)) category_filter = ComboSearchFilter(_('Category'), items) self.add_filter(category_filter, columns=[Sellable.category])
def add_filter_by_attribute(self, attr, title, data_type, valid_values=None, callback=None, use_having=False, multiple_selection=False): """Add a filter accordingly to the attributes specified :param attr: attribute that will be filtered. This can be either the name of the attribute or the attribute itself. :param title: the title of the filter that will be visible in the interface :param data_type: the attribute type (str, bool, decimal, etc) :param callback: the callback function that will be triggered :param use_having: use having expression in the query """ if data_type is not bool: title += ':' if data_type == datetime.date: filter = DateSearchFilter(title) if valid_values: filter.clear_options() filter.add_custom_options() for opt in valid_values: filter.add_option(opt) filter.select(valid_values[0]) elif (data_type == decimal.Decimal or data_type == int or data_type == currency): filter = NumberSearchFilter(title) if data_type != int: filter.set_digits(2) elif data_type == str: if multiple_selection: filter = MultiSearchFilter(title, valid_values) elif valid_values: filter = ComboSearchFilter(title, valid_values) filter.enable_advanced() else: filter = StringSearchFilter(title) filter.enable_advanced() elif data_type == bool: filter = BoolSearchFilter(title) else: raise NotImplementedError(title, data_type) filter.set_removable() self.add_filter(filter, columns=[attr], callback=callback, use_having=use_having) if data_type is not bool: label = filter.get_title_label() label.set_alignment(1.0, 0.5) self.label_group.add_widget(label) combo = filter.get_mode_combo() if combo: self.combo_group.add_widget(combo) return filter
def create_filters(self): self.set_text_field_columns([ 'source_branch_name', 'destination_branch_name', 'identifier_str' ]) # Date self.date_filter = DateSearchFilter(_('Date:')) self.add_filter(self.date_filter, columns=['open_date', 'finish_date']) # Status self.status_filter = ComboSearchFilter(_('With status:'), self._get_status_options()) self.status_filter.select('pending') executer = self.search.get_query_executer() executer.add_filter_query_callback(self.status_filter, self._get_status_query) self.add_filter(self.status_filter, position=SearchFilterPosition.TOP)
def create_filters(self): self.set_text_field_columns([ 'sellable', 'description', 'client_name', 'identifier_str', 'sale_identifier_str' ]) self.main_filter = ComboSearchFilter(_('Show'), []) combo = self.main_filter.combo combo.color_attribute = 'color' combo.set_row_separator_func(self._on_main_filter__row_separator_func) self.add_filter(self.main_filter, SearchFilterPosition.TOP, callback=self._get_main_query) self.create_branch_filter( column=[WorkOrder.branch_id, WorkOrder.current_branch_id]) self._update_filters()
def create_salesperson_filter(self, label=None): from stoqlib.domain.person import SalesPerson items = SalesPerson.get_active_items( self.store, api.get_current_branch(self.store)) items.insert(0, (_("Any"), None)) if not label: label = _('Salesperson:') return ComboSearchFilter(label, items)
def create_filters(self): self.search.set_query(self._query_executer) self.set_text_field_columns(['client_name', 'salesperson_name', 'identifier_str', 'token_code', 'token_name']) self.status_filter = ComboSearchFilter(_(u"Show orders"), self._get_status_values()) self.add_filter(self.status_filter, position=SearchFilterPosition.TOP, columns=['status'])
def create_filters(self): self.search.set_query(self.executer_query) # Category categories = self.store.find(SellableCategory) items = stoq_api.for_combo(categories, attr='full_description') items.insert(0, (_('Any'), None)) category_filter = ComboSearchFilter(_('Category'), items) self.add_filter(category_filter, position=SearchFilterPosition.TOP) self.category_filter = category_filter
def create_filters(self): statuses = [(v, k) for k, v in Client.statuses.items()] statuses.insert(0, (_('Any'), None)) status_filter = ComboSearchFilter(_('Show clients with status'), statuses) status_filter.select(None) self.add_filter(status_filter, SearchFilterPosition.TOP, ['status']) if self._birth_date: birthday_filter = self.search.add_filter_by_attribute( 'birth_date', _('Birthday'), datetime.date, callback=self.birthday_search) # FIXME: The fifth position is a search by day. This is done # elsewhere too but we should not hardcode it. Try to # find a better solution in the future and fix everything birthday_filter.mode.select_item_by_position(5) birthday_filter.start_date.set_date(self._birth_date) self.search.refresh()
def create_provider_filter(self, label=None): from stoqlib.domain.payment.card import CreditProvider providers = CreditProvider.get_card_providers(self.store).order_by( CreditProvider.short_name) items = [(p.short_name, p) for p in providers] items.insert(0, (_("Any"), None)) if not label: label = _('Provider:') provider_filter = ComboSearchFilter(label, items) return provider_filter
class ProductionItemsSearch(ProductSearch): title = _(u'Production Items') search_spec = ProductionItemView report_class = ProductionItemReport csv_data = None has_print_price_button = False text_field_columns = [ProductionItemView.description, ProductionItemView.order_identifier_str] def __init__(self, store, hide_footer=True, hide_toolbar=True): ProductSearch.__init__(self, store, hide_footer=hide_footer, hide_toolbar=hide_toolbar) # # SearchDialog # def create_filters(self): statuses = [(desc, i) for i, desc in ProductionOrder.statuses.items()] statuses.insert(0, (_(u'Any'), None)) self.status_filter = ComboSearchFilter(_('order status:'), statuses) self.status_filter.select(ProductionOrder.ORDER_PRODUCING) self.add_filter(self.status_filter, columns=['order_status'], position=SearchFilterPosition.TOP) def get_columns(self): return [IdentifierColumn('order_identifier', title=_(u"Order #"), sorted=True), SearchColumn('category_description', title=_(u'Category'), data_type=str), SearchColumn('description', title=_(u'Description'), data_type=str, expand=True), SearchColumn('unit_description', title=_(u'Unit'), data_type=str), SearchColumn('quantity', title=_(u'To Produce'), data_type=Decimal), SearchColumn('produced', title=_(u'Produced'), data_type=Decimal), SearchColumn('lost', title=_(u'Lost'), data_type=Decimal, visible=False)]
def create_branch_filter(self, label=None, column=None): """Returns a new branch filter. :param label: The label to be used for the filter :param column: When provided, besides creating the filter, we will also add it to the interface, filtering by the informed column. """ items = api.get_branches_for_filter(self.store, use_id=True) if not label: label = _('Branch:') if column and not isinstance(column, list): column = [column] branch_filter = ComboSearchFilter(label, items) current = api.get_current_branch(self.store) branch_filter.select(current.id) if column: self.add_filter(branch_filter, columns=column, position=SearchFilterPosition.TOP) return branch_filter
def create_filters(self): self.set_text_field_columns(['client_name', 'salesperson_name', 'identifier_str', 'token_code', 'token_name']) status_filter = ComboSearchFilter(_('Show sales'), self._get_filter_options()) status_filter.combo.set_row_separator_func( lambda model, titer: model[titer][0] == 'sep') executer = self.search.get_query_executer() executer.add_filter_query_callback( status_filter, self._get_status_query) self.add_filter(status_filter, position=SearchFilterPosition.TOP) self.create_branch_filter(column=Sale.branch_id)
class DeliveryApp(ShellApp): """Delivery app""" app_title = _(u'Deliveries') gladefile = 'delivery' search_spec = DeliveryView search_label = _(u'matching:') # TODO: Create a report for the view here #report_table = DeliveriesReport # # Application # def create_actions(self): #group = get_accels('app.delivery') actions = [ # Search ( "Transporters", None, _("Transporters..."), # group.get("search_transporters")), None), ( "Clients", None, _("Clients..."), # group.get("search_clients")), None), ( "Products", None, _("Products..."), # group.get("search_products")), None), ( "Services", None, _("Services..."), # group.get("search_services")), None), # Delivery ( "Edit", Gtk.STOCK_EDIT, _("Edit..."), # group.get('delivery_pick'), None, _("Edit the selected delivery")), ( "Pick", None, _("Pick..."), # group.get('delivery_pick'), None, _("Pick the selected delivery")), ( "Pack", None, _("Pack..."), # group.get('delivery_pack'), None, _("Pack the selected delivery")), ( "Send", None, _("Send..."), # group.get('delivery_send'), None, _("Send the selected delivery to deliver")), ( "Receive", Gtk.STOCK_APPLY, _("Mark as received..."), # group.get('delivery_receive'), None, _("Mark the selected delivery as received by the recipient")), ( "Cancel", Gtk.STOCK_CANCEL, _("Cancel..."), # group.get('delivery_cancel'), None, _("Cancel the selected delivery")), ] self.delivery_ui = self.add_ui_actions(actions) self.set_help_section(_(u"Delivery help"), 'app-delivery') def get_domain_options(self): options = [ ('fa-edit-symbolic', _('Edit'), 'delivery.Edit', True), ('', _('Pick'), 'delivery.Cancel', False), ('', _('Pack'), 'delivery.Cancel', False), ('fa-share-square-symbolic', _('Send'), 'delivery.Send', True), ('fa-check-square-symbolic', _('Mark as received'), 'delivery.Receive', True), ('fa-ban-symbolic', _('Cancel'), 'delivery.Cancel', True), ] return options def create_ui(self): self.search.enable_lazy_search() # XXX: What should we put on new items? self.window.add_new_items([]) self.window.add_search_items([ self.Products, self.Services, self.Transporters, self.Clients, ]) # FIXME: identifier is here because it needs an integer column. # The lazy summary will actually be taken from the view's # post_search_callback self.search.set_summary_label( column='identifier', label=('<b>%s</b>' % api.escape(_('Number of deliveries:'))), format='<b>%s</b>', parent=self.get_statusbar_message_area()) self.results.set_cell_data_func(self._on_results__cell_data_func) def activate(self, refresh=True): self.check_open_inventory() if refresh: self._update_view() self.search.focus_search_entry() def search_completed(self, results, states): if len(results): return state = states[1] if state is None: return if state.value is None: # Base search with no filters base_msg = _("No deliveries could be found.") url_msg = '' elif state: base_msg = { Delivery.STATUS_INITIAL: _("No pending deliveries could be found"), Delivery.STATUS_CANCELLED: _("No cancelled deliveries could be found"), Delivery.STATUS_PICKED: _("No picked deliveries could be found"), Delivery.STATUS_PACKED: _("No packed deliveries could be found"), Delivery.STATUS_SENT: _("No sent deliveries could be found"), Delivery.STATUS_RECEIVED: _("No received deliveries could be found"), }[state.value] url_msg = '' msg = '\n\n'.join([base_msg, url_msg]) self.search.set_message(msg) def create_filters(self): self.set_text_field_columns(['recipient_name', 'identifier_str']) self.main_filter = ComboSearchFilter(_('Show'), []) self.add_filter(self.main_filter, SearchFilterPosition.TOP, callback=self._get_main_query) self.create_branch_filter(column=[Invoice.branch_id]) self._update_filters() def get_columns(self): return [ IdentifierColumn('identifier', title=_("Operation #"), sorted=True, width=110, format_func=self._format_identifier), SearchColumn('operation_nature', title=_('Operation Nature'), data_type=str), SearchColumn('status_str', title=_(u'Status'), search_attribute='status', data_type=str, valid_values=self._get_status_values()), SearchColumn('recipient_name', title=_(u'Recipient'), data_type=str, expand=True), Column('flag_icon', title=_(u'Status (Description)'), column='recipient_name', data_type=GdkPixbuf.Pixbuf, format_func=self._format_state_icon, format_func_data=True), SearchColumn('branch_name', title=_(u'Branch'), data_type=str, visible=False), SearchColumn('transporter_name', title=_(u'Transporter'), data_type=str), SearchColumn('open_date', title=_(u'Open date'), data_type=datetime.date), SearchColumn('cancel_date', title=_(u'Cancel date'), data_type=datetime.date, visible=False), SearchColumn('pick_date', title=_(u'Pick date'), data_type=datetime.date, visible=False), SearchColumn('pack_date', title=_(u'Pack date'), data_type=datetime.date, visible=False), SearchColumn('send_date', title=_(u'Send date'), data_type=datetime.date), SearchColumn('receive_date', title=_(u'Receive date'), data_type=datetime.date, visible=False), ] def set_open_inventory(self): pass # # Private # def _format_identifier(self, value): return str(value).zfill(5) def _edit(self): delivery = self.search.get_selected_item().delivery with api.new_store() as store: self.run_dialog(DeliveryEditor, store, model=store.fetch(delivery)) if store.committed: self._update_view() def _cancel(self): if not yesno(_("This will cancel the delivery. Are you sure?"), Gtk.ResponseType.NO, _(u"Cancel"), _(u"Don't cancel")): return selection = self.search.get_selected_item() with api.new_store() as store: delivery = store.fetch(selection.delivery) delivery.close() self._update_view(select_item=selection) def _pick(self): if not yesno(_("This will mark the delivery as picked. Are you sure?"), Gtk.ResponseType.NO, _(u"Mark as picked"), _(u"Don't mark")): return selection = self.search.get_selected_item() with api.new_store() as store: delivery = store.fetch(selection.delivery) delivery.pick(api.get_current_user(store)) self._update_view(select_item=selection) def _pack(self): if not yesno(_("This will mark the delivery as packed. Are you sure?"), Gtk.ResponseType.NO, _(u"Mark as packed"), _(u"Don't mark")): return selection = self.search.get_selected_item() with api.new_store() as store: delivery = store.fetch(selection.delivery) delivery.pack(api.get_current_user(store)) self._update_view(select_item=selection) def _send(self): if not yesno( _("This will mark the delivery as sent to the recipient. " "Are you sure?"), Gtk.ResponseType.NO, _(u"Mark as sent"), _(u"Don't mark")): return selection = self.search.get_selected_item() with api.new_store() as store: delivery = store.fetch(selection.delivery) delivery.send(api.get_current_user(store)) self._update_view(select_item=selection) def _receive(self): if not yesno( _("This will mark the delivery as received by the recipient. " "Are you sure?"), Gtk.ResponseType.NO, _(u"Mark as received"), _(u"Don't mark")): return selection = self.search.get_selected_item() with api.new_store() as store: delivery = store.fetch(selection.delivery) delivery.receive() self._update_view(select_item=selection) def _format_state_icon(self, item, data): # This happens with lazy object lists. Sometimes it calls this function # without actually having the real object. if not isinstance(item, DeliveryView): return stock_id, tooltip = get_delivery_state_icon(item.delivery) if stock_id is not None: return render_icon(stock_id, Gtk.IconSize.MENU) def _get_main_query(self, state): if state.value is None: return True return Delivery.status == state.value def _get_status_values(self): return ([(_('Any'), None)] + [(v, k) for k, v in Delivery.statuses.items()]) def _update_view(self, select_item=None): self.refresh() if select_item is not None: item = self.store.find(DeliveryView, id=select_item.id).one() self.select_result(item) self._update_list_aware_view() def _update_list_aware_view(self): selection = self.search.get_selected_item() has_selected = bool(selection) delivery = has_selected and selection.delivery self.set_sensitive([self.Edit], has_selected) self.set_sensitive([self.Pick], has_selected and delivery.can_pick()) self.set_sensitive([self.Pack], has_selected and delivery.can_pack()) self.set_sensitive([self.Send], has_selected and delivery.can_send()) self.set_sensitive([self.Receive], has_selected and delivery.can_receive()) self.set_sensitive([self.Cancel], has_selected and delivery.can_cancel()) def _update_filters(self): items = [(_("All Deliveries"), None)] items.extend((status_str, status) for status, status_str in Delivery.statuses.items()) self.main_filter.update_values(items) # # Callbacks # def _on_results__cell_data_func(self, column, renderer, item, text): if not isinstance(renderer, Gtk.CellRendererText): return text delivery = item.delivery is_finished = delivery.status in [ Delivery.STATUS_SENT, Delivery.STATUS_RECEIVED ] is_waiting = delivery.status == Delivery.STATUS_INITIAL is_picked = delivery.status == Delivery.STATUS_PICKED for prop, is_set, value in [('strikethrough', is_finished, True), ('style', is_picked, Pango.Style.ITALIC), ('weight', is_waiting, Pango.Weight.BOLD)]: renderer.set_property(prop + '-set', is_set) if is_set: renderer.set_property(prop, value) return text def on_search__result_selection_changed(self, search): self._update_list_aware_view() def on_search__result_item_activated(self, search, item): self._edit() def on_Edit__activate(self, action): self._edit() def on_Cancel__activate(self, action): self._cancel() def on_Pick__activate(self, action): self._pick() def on_Pack__activate(self, action): self._pack() def on_Send__activate(self, action): self._send() def on_Receive__activate(self, action): self._receive() def on_Products__activate(self, action): self.run_dialog(ProductSearch, self.store, hide_footer=True, hide_toolbar=True) def on_Transporters__activate(self, action): self.run_dialog(TransporterSearch, self.store) def on_Services__activate(self, action): self.run_dialog(ServiceSearch, self.store) def on_Clients__activate(self, button): self.run_dialog(ClientSearch, self.store, hide_footer=True)
def create_filters(self): items = [(v, k) for k, v in fiscal_book_entries.items()] self.entry_type = ComboSearchFilter(_('Show entries of type'), items) self.add_filter(self.entry_type, callback=self._get_entry_type_query, position=SearchFilterPosition.TOP)
class DeliverySearch(SearchEditor): """Delivery search implementation""" title = _('Delivery Search') search_spec = DeliveryView editor_class = DeliveryEditor has_new_button = False size = (750, 450) # # Private # def _get_status_values(self): items = [(value, key) for key, value in Delivery.statuses.items()] items.insert(0, (_('Any'), None)) return items # # SearchEditor # def create_filters(self): self.set_text_field_columns([ 'tracking_code', 'transporter_name', 'recipient_name', 'identifier_str' ]) # Status statuses = [(desc, st) for st, desc in Delivery.statuses.items()] statuses.insert(0, (_('Any'), None)) self.status_filter = ComboSearchFilter(_('With status:'), statuses) self.status_filter.select(None) self.add_filter(self.status_filter, columns=['status'], position=SearchFilterPosition.TOP) def get_editor_model(self, viewable): return viewable.delivery def get_columns(self): return [ IdentifierColumn('identifier', title=_('Sale #'), order=Gtk.SortType.DESCENDING, sorted=True), SearchColumn('status_str', title=_('Status'), data_type=str, search_attribute='status', valid_values=self._get_status_values()), Column('address_str', title=_('Address'), data_type=str, expand=True, ellipsize=Pango.EllipsizeMode.END), SearchColumn('tracking_code', title=_('Tracking code'), data_type=str), SearchColumn('transporter_name', title=_('Transporter'), data_type=str), SearchColumn('recipient_name', title=_('Recipient'), data_type=str), SearchColumn('open_date', title=_('Open date'), data_type=datetime.date, visible=False), SearchColumn('send_date', title=_('Sent date'), data_type=datetime.date, visible=False), SearchColumn('receive_date', title=_('Received date'), data_type=datetime.date, visible=False), ]
class TransferOrderSearch(SearchDialog): title = _(u"Transfer Order Search") size = (750, 500) search_spec = TransferOrderView report_class = TransferOrderReport selection_mode = Gtk.SelectionMode.MULTIPLE def __init__(self, store): SearchDialog.__init__(self, store) self._setup_widgets() def _show_transfer_order_details(self, order_view): transfer_order = order_view.transfer_order with api.new_store() as store: model = store.fetch(transfer_order) run_dialog(TransferOrderDetailsDialog, self, store, model) store.retval = store.get_pending_count() > 0 def _setup_widgets(self): self.results.connect('row_activated', self.on_row_activated) self.update_widgets() def _get_status_values(self): items = [(str(value), key) for key, value in TransferOrder.statuses.items()] items.insert(0, (_('Any'), None)) return items # # SearchDialog Hooks # def update_widgets(self): orders = self.results.get_selected_rows() has_one_selected = len(orders) == 1 self.set_details_button_sensitive(has_one_selected) self.set_print_button_sensitive(has_one_selected) def create_filters(self): self.set_text_field_columns([ 'source_branch_name', 'destination_branch_name', 'identifier_str' ]) # Date self.date_filter = DateSearchFilter(_('Date:')) self.add_filter(self.date_filter, columns=['open_date', 'finish_date']) # Status self.status_filter = ComboSearchFilter(_('With status:'), self._get_status_options()) self.status_filter.select('pending') executer = self.search.get_query_executer() executer.add_filter_query_callback(self.status_filter, self._get_status_query) self.add_filter(self.status_filter, position=SearchFilterPosition.TOP) def _get_status_options(self): return [ (_('All transfers'), None), (_('Pending receive'), 'pending'), (_('Received'), 'received'), (_('Sent'), 'sent'), (_('Cancelled'), 'cancelled'), ] def _get_status_query(self, state): current_branch = api.get_current_branch(self.store) if state.value == 'pending': return And( TransferOrder.status == TransferOrder.STATUS_SENT, TransferOrder.destination_branch_id == current_branch.id) elif state.value == 'received': return And( TransferOrder.status == TransferOrder.STATUS_RECEIVED, TransferOrder.destination_branch_id == current_branch.id) elif state.value == 'sent': return And( TransferOrder.source_branch_id == current_branch.id, Not(TransferOrder.status == TransferOrder.STATUS_CANCELLED)) elif state.value == 'cancelled': return And(TransferOrder.status == TransferOrder.STATUS_CANCELLED, TransferOrder.source_branch_id == current_branch.id) else: return Or(TransferOrder.source_branch_id == current_branch.id, TransferOrder.destination_branch_id == current_branch.id) def get_columns(self): return [ IdentifierColumn('identifier', title=_('Transfer #')), SearchColumn('transfer_order.status_str', _('Status'), data_type=str, valid_values=self._get_status_values(), search_attribute='status', width=100), SearchColumn('open_date', _('Open date'), data_type=datetime.date, sorted=True, width=100), SearchColumn('finish_date', _('Finish Date'), data_type=datetime.date, width=100, visible=False), SearchColumn('source_branch_name', _('Source'), data_type=str, expand=True), SearchColumn('destination_branch_name', _('Destination'), data_type=str, width=220), Column('total_items', _('Items'), data_type=Decimal, format_func=format_quantity, width=110) ] # # Callbacks # def on_row_activated(self, klist, view): self._show_transfer_order_details(view) def on_details_button_clicked(self, button): self._show_transfer_order_details(self.results.get_selected_rows()[0])
def create_filters(self): items = [(value, key) for key, value in Sale.statuses.items()] items.insert(0, (_('Any'), None)) status_filter = ComboSearchFilter(_('Show sales with status'), items) self.add_filter(status_filter, columns=[SaleView.status])
class ServicesApp(ShellApp): """Services app""" app_title = _(u'Services') gladefile = 'services' search_spec = WorkOrderView search_label = _(u'matching:') report_table = WorkOrdersReport _status_query_mapper = { 'pending': Or(WorkOrder.status == WorkOrder.STATUS_OPENED, WorkOrder.status == WorkOrder.STATUS_WORK_WAITING), 'in-progress': WorkOrder.status == WorkOrder.STATUS_WORK_IN_PROGRESS, 'finished': WorkOrder.status == WorkOrder.STATUS_WORK_FINISHED, 'delivered': WorkOrder.status == WorkOrder.STATUS_DELIVERED, 'cancelled': WorkOrder.status == WorkOrder.STATUS_CANCELLED, 'all-orders': None, 'not-delivered': And(WorkOrder.status != WorkOrder.STATUS_CANCELLED, WorkOrder.status != WorkOrder.STATUS_DELIVERED), } _flags_query_mapper = { 'approved': And(WorkOrder.status != WorkOrder.STATUS_OPENED, WorkOrder.status != WorkOrder.STATUS_CANCELLED), 'in-transport': Eq(WorkOrder.current_branch_id, None), 'rejected': Eq(WorkOrder.is_rejected, True), } def __init__(self, *args, **kwargs): self._other_kinds = {} self.actions = WorkOrderActions.get_instance() super(ServicesApp, self).__init__(*args, **kwargs) # # Application # def create_actions(self): group = get_accels('app.services') actions = [ # Search ("Products", None, _(u"Products..."), group.get("search_products") ), ("Services", None, _(u"Services..."), group.get("search_services")), ("Categories", None, _(u"Categories..."), group.get("search_categories")), ("Clients", None, _(u"Clients..."), group.get("search_clients")), ] self.services_ui = self.add_ui_actions(actions) radio_actions = [ ('ViewKanban', '', _("View as Kanban"), '', _("Show in Kanban mode")), ('ViewList', '', _("View as List"), '', _("Show in list mode")), ] self.add_ui_actions(radio_actions, 'RadioActions') self.set_help_section(_(u"Services help"), 'app-services') def get_domain_options(self): options = [ ('fa-info-circle-symbolic', _('Details'), 'work_order.Details', True), ('fa-edit-symbolic', _('Edit'), 'work_order.Edit', True), ('fa-check-symbolic', _('Finish'), 'work_order.FinishOrClose', True), ('fa-ban-symbolic', _('Cancel'), 'work_order.Cancel', True), ('', _('Deliver'), 'work_order.Close', False), # Separator ('', _('Approve'), 'work_order.Approve', False), ('', _('Pause the work'), 'work_order.Pause', False), ('', _('Start the work'), 'work_order.Work', False), ('', _('Reject order'), 'work_order.Reject', False), ('', _('Check order'), 'work_order.CheckOrder', False), ('', _('Inform client'), 'work_order.InformClient', False), ('', _('Undo order rejection'), 'work_order.UndoRejection', False), ('', _('Repoen order'), 'work_order.Reopen', False), # Separator ('', _('Print quote'), 'work_order.PrintQuote', False), ('', _('Print receipt'), 'work_order.PrintReceipt', False), ] return options def create_ui(self): if api.sysparam.get_bool('SMART_LIST_LOADING'): self.search.enable_lazy_search() self.window.add_print_items2([ (_("Print quote..."), 'work_order.PrintQuote'), (_("Print receipt..."), 'work_order.PrintReceipt'), ]) self.window.add_export_items() self.window.add_extra_items2([ (_("Send orders..."), 'work_order.SendOrders'), (_("Receive orders..."), 'work_order.ReceiveOrders'), ]) self.window.add_extra_items([self.ViewKanban, self.ViewList]) self.window.add_new_items2([ (_("Work order..."), 'work_order.NewOrder'), ]) self.window.add_search_items([ self.Products, self.Services, self.Categories, self.Clients, ]) self.search.set_summary_label(column='total', label=('<b>%s</b>' % api.escape(_('Total:'))), format='<b>%s</b>', parent=self.get_statusbar_message_area()) self.results.set_cell_data_func(self._on_results__cell_data_func) def activate(self, refresh=True): self.check_open_inventory() is_kanban = self.window._current_app_settings.get('show-kanban', False) if is_kanban: self.ViewKanban.set_state(GLib.Variant.new_boolean(True)) self.search.set_result_view(WorkOrderResultKanbanView, refresh=refresh) if refresh: self._update_view() self.search.focus_search_entry() def deactivate(self): # Reset actions to clean up connections self.actions = None def search_completed(self, results, states): if len(results): return base_msg = '' url_msg = '' state = states[1] if state and state.value is None: # Base search with no filters base_msg = _(u"No work orders could be found.") url = u"<a href='new_order'>%s</a>" % (api.escape( _(u"create a new work order")), ) url_msg = _(u"Would you like to %s ?") % (url, ) else: kind, value = state.value.value.split(':') # Search filtering by status if kind == 'status': if value == 'pending': base_msg = _(u"No pending work orders could be found.") elif value == 'in-progress': base_msg = _(u"No work orders in progress could be found.") elif value == 'finished': base_msg = _(u"No finished work orders could be found.") elif value == 'delivered': base_msg = _(u"No delivered or cancelled work " u"orders could be found.") # Search filtering by category elif kind == 'category': base_msg = _(u"No work orders in the category %s " u"could be found.") % ('<b>%s</b>' % (value, ), ) url = u"<a href='new_order?%s'>%s</a>" % ( urllib.parse.quote(value), api.escape(_(u"create a new work order")), ) url_msg = _(u"Would you like to %s ?") % (url, ) if not base_msg: return msg = '\n\n'.join([base_msg, url_msg]) self.search.set_message(msg) def create_filters(self): self.set_text_field_columns([ 'sellable', 'description', 'client_name', 'identifier_str', 'sale_identifier_str' ]) self.main_filter = ComboSearchFilter(_('Show'), []) combo = self.main_filter.combo combo.color_attribute = 'color' combo.set_row_separator_func(self._on_main_filter__row_separator_func) self.add_filter(self.main_filter, SearchFilterPosition.TOP, callback=self._get_main_query) self.create_branch_filter( column=[WorkOrder.branch_id, WorkOrder.current_branch_id]) self._update_filters() def get_columns(self): return [ IdentifierColumn('identifier', title=_('WO #'), sorted=True), IdentifierColumn('sale_identifier', title=_("Sale #"), visible=False), SearchColumn('status_str', title=_(u'Status'), search_attribute='status', data_type=str, valid_values=self._get_status_values(), visible=False), SearchColumn('category_name', title=_(u'Category'), data_type=str, visible=False, multiple_selection=True, search_attribute='category_id', valid_values=self._get_category_values()), Column('equipment', title=_(u'Equipment (Description)'), data_type=str, expand=True, pack_end=True), Column('category_color', title=_(u'Equipment (Description)'), column='equipment', data_type=GdkPixbuf.Pixbuf, format_func=render_pixbuf), Column('flag_icon', title=_(u'Equipment (Description)'), column='equipment', data_type=GdkPixbuf.Pixbuf, format_func=self._format_state_icon, format_func_data=True), SearchColumn('client_name', title=_(u'Client'), data_type=str), SearchColumn('branch_name', title=_(u'Branch'), data_type=str, visible=False), SearchColumn('current_branch_name', title=_(u'Current branch'), data_type=str, visible=False), SearchColumn('execution_branch_name', title=_(u'Execution branch'), data_type=str, visible=False), SearchColumn('supplier_order', title=_("Supplier Order #"), visible=False, data_type=str), SearchColumn('open_date', title=_(u'Open date'), data_type=datetime.date), SearchColumn('approve_date', title=_(u'Approval date'), data_type=datetime.date, visible=False), SearchColumn('estimated_start', title=_(u'Estimated start'), data_type=datetime.date, visible=False), SearchColumn('estimated_finish', title=_(u'Estimated finish'), data_type=datetime.date, visible=False), SearchColumn('finish_date', title=_(u'Finish date'), data_type=datetime.date, visible=False), SearchColumn('total', title=_(u'Total'), data_type=currency), ] def set_open_inventory(self): # This needs to be implemented because we are calling check_open_inventory. # We won't do anything here tough, WorkOrderEditor will, but we call # check_open_inventory to display the open inventory bar and make # it explicit for the user that there's an open inventory pass def search_for_date(self, date): self.main_filter.combo.select(self._not_delivered_filter_item) dfilter = DateSearchFilter(_("Estimated finish")) dfilter.set_removable() dfilter.select(data=DateSearchFilter.Type.USER_DAY) self.add_filter(dfilter, columns=["estimated_finish"]) dfilter.start_date.set_date(date) self.refresh() def add_filters(self, filter_items, kind, mapper): """Add additional filter option. :param filter_items: list of tuple (name, value, color) :param kind:the kind of filter :param mapper: a dictionary containing the query for each option """ for item in filter_items: option = _FilterItem(item[0], item[1], color=item[2]) self.main_filter.combo.append_item(option.name, option) self._other_kinds[kind] = mapper # # Private # def _format_state_icon(self, item, data): # This happens with lazy object lists. Sometimes it calls this function # without actually having the real object. if not isinstance(item, WorkOrderView): return stock_id, tooltip = get_workorder_state_icon(item.work_order) if stock_id is not None: return render_icon(stock_id, 16) def _get_main_query(self, state): item = state.value kind, value = item.value.split(':') if kind in self._other_kinds: return self._other_kinds[kind][value] elif kind == 'category': return WorkOrder.category_id == item.id elif kind == 'status': return self._status_query_mapper[value] elif kind == 'flag': return self._flags_query_mapper[value] else: raise AssertionError(kind, value) def _get_status_values(self): return ([(_('Any'), None)] + [(v, k) for k, v in WorkOrder.statuses.items()]) def _get_category_values(self): return [(category.name, category.id, render_pixbuf(category.color)) for category in self.store.find(WorkOrderCategory)] def _update_view(self, select_item=None): self.refresh() if select_item is not None: item = self.store.find(WorkOrderView, id=select_item.id).one() self.select_result(item) self._update_list_aware_view() def _update_list_aware_view(self): selection = self.search.get_selected_item() wo = selection and selection.work_order self.actions.set_model(wo) finish_btn = self.window.domain_header.get_children()[2] finish_btn.set_tooltip_text(_(u"Finish")) # If the selected work order is already finished, we change the finish # button's label. if wo and wo.status == WorkOrder.STATUS_WORK_FINISHED: finish_btn.set_tooltip_text(_(u"Deliver")) def _update_filters(self): self._not_delivered_filter_item = _FilterItem(_(u'Not delivered'), 'status:not-delivered') options = [ self._not_delivered_filter_item, _FilterItem(_(u'Pending'), 'status:pending'), _FilterItem(_(u'In progress'), 'status:in-progress'), _FilterItem(_(u'Finished'), 'status:finished'), _FilterItem(_(u'Delivered'), 'status:delivered'), _FilterItem(_(u'Cancelled'), 'status:cancelled'), _FilterItem(_(u'All work orders'), 'status:all-orders'), _FilterItem('sep', 'sep'), _FilterItem(_(u'Approved'), 'flag:approved'), _FilterItem(_(u'In transport'), 'flag:in-transport'), _FilterItem(_(u'Rejected'), 'flag:rejected'), ] categories = list(self.store.find(WorkOrderCategory)) if len(categories): options.append(_FilterItem('sep', 'sep')) for category in categories: value = 'category:%s' % (category.name, ) options.append( _FilterItem(category.name, value, color=category.color, obj_id=category.id)) self.main_filter.update_values([(item.name, item) for item in options]) def _run_order_category_dialog(self): with api.new_store() as store: self.run_dialog(WorkOrderCategoryDialog, store) self._update_view() self._update_filters() # # Kiwi Callbacks # def _on_main_filter__row_separator_func(self, model, titer): obj = model[titer][1] if obj and obj.value == 'sep': return True return False def _on_results__cell_data_func(self, column, renderer, wov, text): if not isinstance(renderer, Gtk.CellRendererText): return text work_order = wov.work_order is_finished = work_order.status == WorkOrder.STATUS_WORK_FINISHED is_delivered = work_order.status in [ WorkOrder.STATUS_CANCELLED, WorkOrder.STATUS_DELIVERED ] is_late = work_order.is_late() for prop, is_set, value in [('strikethrough', is_delivered, True), ('style', is_finished, Pango.Style.ITALIC), ('weight', is_late, Pango.Weight.BOLD)]: renderer.set_property(prop + '-set', is_set) if is_set: renderer.set_property(prop, value) return text def on_search__result_item_popup_menu(self, search, objectlist, item, event): self._popover.set_relative_to(objectlist) self.show_popover(event) def on_search__result_item_activated(self, search, item): self.actions.edit_or_details(item.work_order) def on_search__result_selection_changed(self, search): self._update_list_aware_view() def on_results__activate_link(self, results, uri): if not uri.startswith('new_order'): return if '?' in uri: category_name = str(urllib.parse.unquote(uri.split('?', 1)[1])) category = self.store.find(WorkOrderCategory, name=category_name).one() else: category = None self.actions.new_order(category=category) def on_actions__model_created(self, actions, order): self._update_view(select_item=order) # A category may have been created on the editor self._update_filters() def on_actions__model_edited(self, actions, order): self._update_view() # A category may have been created on the editor self._update_filters() def on_Products__activate(self, action): self.run_dialog(ProductSearch, self.store, hide_footer=True, hide_toolbar=True) def on_Services__activate(self, action): self.run_dialog(ServiceSearch, self.store) def on_Categories__activate(self, action): self._run_order_category_dialog() def on_Clients__activate(self, button): self.run_dialog(ClientSearch, self.store, hide_footer=True) def on_ViewList__change_state(self, action, value): action.set_state(value) if not value.get_boolean(): return self.ViewKanban.set_state( GLib.Variant.new_boolean(not value.get_boolean())) self.search.set_result_view(SearchResultListView, refresh=True) self._update_list_aware_view() def on_ViewKanban__change_state(self, action, value): action.set_state(value) self.ViewList.set_state( GLib.Variant.new_boolean(not value.get_boolean())) self.window._current_app_settings['show-kanban'] = value.get_boolean() if not value.get_boolean(): return self.search.set_result_view(WorkOrderResultKanbanView, refresh=True) self._update_list_aware_view()
class StockApp(ShellApp): app_title = _('Stock') gladefile = "stock" search_spec = ProductFullStockView search_labels = _('Matching:') report_table = SimpleProductReport pixbuf_converter = converter.get_converter(GdkPixbuf.Pixbuf) # # Application # def create_actions(self): group = get_accels('app.stock') actions = [ ("NewReceiving", None, _("Order _receival..."), group.get('new_receiving')), ('NewTransfer', Gtk.STOCK_CONVERT, _('Transfer...'), group.get('transfer_product')), ('NewStockDecrease', None, _('Stock decrease...'), group.get('stock_decrease')), ('StockInitial', Gtk.STOCK_GO_UP, _('Register initial stock...')), ("LoanNew", None, _("Loan...")), ("LoanClose", None, _("Close loan...")), ("SearchPurchaseReceiving", None, _("Received purchases..."), group.get('search_receiving'), _("Search for received purchase orders")), ("SearchProductHistory", None, _("Product history..."), group.get('search_product_history'), _("Search for product history")), ("SearchStockDecrease", None, _("Stock decreases..."), '', _("Search for manual stock decreases")), ("SearchPurchasedStockItems", None, _("Purchased items..."), group.get('search_purchased_stock_items'), _("Search for purchased items")), ("SearchBrandItems", None, _("Brand items..."), group.get('search_brand_items'), _("Search for brand items on stock")), ("SearchBrandItemsByBranch", None, _("Brand item by branch..."), group.get('search_brand_by_branch'), _("Search for brand items by branch on stock")), ("SearchBatchItems", None, _("Batch items..."), group.get('search_batch_items'), _("Search for batch items on stock")), ("SearchStockItems", None, _("Stock items..."), group.get('search_stock_items'), _("Search for items on stock")), ("SearchTransfer", None, _("Transfers..."), group.get('search_transfers'), _("Search for stock transfers")), ("SearchClosedStockItems", None, _("Closed stock Items..."), group.get('search_closed_stock_items'), _("Search for closed stock items")), ("LoanSearch", None, _("Loans...")), ("LoanSearchItems", None, _("Loan items...")), ("SearchTransferItems", None, _("Transfer items...")), ("SearchReturnedItems", None, _("Returned items...")), ("SearchPendingReturnedSales", None, _("Pending returned sales...")), ("ProductMenu", None, _("Product")), ("PrintLabels", None, _("Print labels...")), ("ManageStock", None, _("Manage stock...")), ("ProductStockHistory", Gtk.STOCK_INFO, _("History..."), group.get('history'), _('Show the stock history of the selected product')), ("EditProduct", Gtk.STOCK_EDIT, _("Edit..."), group.get('edit_product'), _("Edit the selected product, allowing you to change it's " "details")), ] self.stock_ui = self.add_ui_actions(actions) toggle_actions = [ ('StockPictureViewer', None, _('Picture viewer'), group.get('toggle_picture_viewer')), ] self.add_ui_actions(toggle_actions, 'ToggleActions') self.set_help_section(_("Stock help"), 'app-stock') def create_ui(self): if api.sysparam.get_bool('SMART_LIST_LOADING'): self.search.enable_lazy_search() self.window.add_print_items([self.PrintLabels]) self.window.add_export_items() self.window.add_extra_items( [self.StockInitial, self.LoanClose, self.StockPictureViewer]) self.window.add_new_items([ self.NewReceiving, self.NewTransfer, self.NewStockDecrease, self.LoanNew ]) self.window.add_search_items([ self.SearchPurchaseReceiving, self.SearchProductHistory, self.SearchTransfer, self.SearchTransferItems, self.SearchStockDecrease, self.SearchReturnedItems, self.SearchPurchasedStockItems, self.SearchStockItems, self.SearchBrandItems, self.SearchBrandItemsByBranch, self.SearchBatchItems, self.SearchClosedStockItems, self.SearchPendingReturnedSales, # Separator self.LoanSearch, self.LoanSearchItems, ]) self._inventory_widgets = [ self.NewTransfer, self.NewReceiving, self.StockInitial, self.NewStockDecrease, self.LoanNew, self.LoanClose ] self.register_sensitive_group(self._inventory_widgets, lambda: not self.has_open_inventory()) self.image_viewer = None self.image = Gtk.Image() # FIXME: How are we goint to display an image preview? #self.edit_button = self.uimanager.get_widget('/toolbar/AppToolbarPH/EditProduct') #self.edit_button.set_icon_widget(self.image) self.image.show() self.search.set_summary_label(column='stock', label=_('<b>Stock Total:</b>'), format='<b>%s</b>', parent=self.get_statusbar_message_area()) def get_domain_options(self): options = [ ('fa-info-circle-symbolic', _('History'), 'stock.ProductStockHistory', True), ('fa-edit-symbolic', _('Edit'), 'stock.EditProduct', True), ('', _('Print labels'), 'stock.PrintLabels', False), ('', _('Manage stock'), 'stock.ManageStock', False), ] return options def activate(self, refresh=True): if refresh: self.refresh() open_inventory = self.check_open_inventory() if not open_inventory: self.transfers_bar = self._create_pending_info_message() self.returned_bar = self._create_pending_returned_sale_message() else: self.transfers_bar = None self.returned_bar = None self._update_widgets() self.search.focus_search_entry() def deactivate(self): if self.transfers_bar: self.transfers_bar.hide() if self.returned_bar: self.returned_bar.hide() self._close_image_viewer() def set_open_inventory(self): self.set_sensitive(self._inventory_widgets, False) def create_filters(self): self.search.set_query(self._query) self.set_text_field_columns([ 'description', 'code', 'barcode', 'category_description', 'manufacturer' ]) branches = Branch.get_active_branches(self.store) self.branch_filter = ComboSearchFilter( _('Show by:'), api.for_combo(branches, empty=_("All branches"))) self.branch_filter.select(api.get_current_branch(self.store)) self.add_filter(self.branch_filter, position=SearchFilterPosition.TOP) def get_columns(self): return [ SearchColumn('code', title=_('Code'), sorted=True, sort_func=sort_sellable_code, data_type=str, width=130), SearchColumn('barcode', title=_("Barcode"), data_type=str, width=130), SearchColumn('category_description', title=_("Category"), data_type=str, width=100, visible=False), SearchColumn('description', title=_("Description"), data_type=str, expand=True, ellipsize=Pango.EllipsizeMode.END), SearchColumn('manufacturer', title=_("Manufacturer"), data_type=str, visible=False), SearchColumn('brand', title=_("Brand"), data_type=str, visible=False), SearchColumn('model', title=_("Model"), data_type=str, visible=False), SearchColumn('location', title=_("Location"), data_type=str, width=100, visible=False), QuantityColumn('stock', title=_('Quantity'), width=100, use_having=True), SearchColumn('has_image', title=_('Picture'), data_type=bool, width=80), ] # # Private API # def _open_image_viewer(self): assert self.image_viewer is None self.image_viewer = SellableImageViewer(size=(325, 325)) self.image_viewer.toplevel.connect('delete-event', self.on_image_viewer_closed) self.image_viewer.show_all() self._update_widgets() def _close_image_viewer(self): if self.image_viewer is None: return self.image_viewer.destroy() self.image_viewer = None def _query(self, store): branch = self.branch_filter.get_state().value return self.search_spec.find_by_branch(store, branch) def _update_widgets(self): branch = api.get_current_branch(self.store) is_main_branch = self.branch_filter.get_state().value is branch item = self.results.get_selected() sellable = item and item.product.sellable if sellable: if item.has_image: # XXX:Workaround for a bug caused by the image domain refactoring # which left some existent thumbnail as None thumbnail = sellable.image.thumbnail if thumbnail is None: # Create new store to create the thumbnail with api.new_store() as new_store: image = sellable.image image = new_store.fetch(image) size = (Image.THUMBNAIL_SIZE_WIDTH, Image.THUMBNAIL_SIZE_HEIGHT) image.thumbnail = get_thumbnail(image.image, size) thumbnail = image.thumbnail pixbuf = self.pixbuf_converter.from_string(thumbnail) else: pixbuf = None self._update_edit_image(pixbuf) if self.image_viewer: self.image_viewer.set_sellable(sellable) else: self._update_edit_image() # Always let the user choose the manage stock option and do a proper # check there (showing a warning if he can't) self.set_sensitive([self.ManageStock], bool(item)) self.set_sensitive([self.EditProduct, self.PrintLabels], bool(item)) self.set_sensitive([self.ProductStockHistory], bool(item) and is_main_branch) # We need more than one branch to be able to do transfers # Note that 'all branches' is not a real branch has_branches = len(self.branch_filter.combo) > 2 transfer_active = self.NewTransfer.get_enabled() self.set_sensitive([self.NewTransfer], transfer_active and has_branches) # Building a list of searches that we must disable if there is no # branches other than the main company searches = [ self.SearchTransfer, self.SearchTransferItems, self.SearchPendingReturnedSales ] self.set_sensitive(searches, has_branches) def _update_edit_image(self, pixbuf=None): if not pixbuf: self.image.set_from_stock(Gtk.STOCK_EDIT, Gtk.IconSize.LARGE_TOOLBAR) return # FIXME: get this icon size from settings icon_size = 24 pixbuf = pixbuf.scale_simple(icon_size, icon_size, GdkPixbuf.InterpType.BILINEAR) self.image.set_from_pixbuf(pixbuf) def _update_filter_slave(self, slave): self.refresh() def _transfer_stock(self): if self.check_open_inventory(): return store = api.new_store() model = self.run_dialog(StockTransferWizard, store) store.confirm(model) store.close() self.refresh() def _receive_purchase(self): if self.check_open_inventory(): return store = api.new_store() model = self.run_dialog(ReceivingOrderWizard, store) store.confirm(model) store.close() self.refresh() def _create_pending_info_message(self): branch = api.get_current_branch(self.store) n_transfers = TransferOrder.get_pending_transfers(self.store, branch).count() if not n_transfers: return None msg = stoqlib_ngettext(_(u"You have %s incoming transfer"), _(u"You have %s incoming transfers"), n_transfers) % n_transfers info_bar = self.window.add_info_bar(Gtk.MessageType.QUESTION, msg) button = info_bar.add_button(_(u"Receive"), Gtk.ResponseType.OK) button.connect('clicked', self._on_info_transfers__clicked) return info_bar def _create_pending_returned_sale_message(self): branch = api.get_current_branch(self.store) n_returned = ReturnedSale.get_pending_returned_sales( self.store, branch).count() if not n_returned: return None msg = stoqlib_ngettext(_(u"You have %s returned sale to receive"), _(u"You have %s returned sales to receive"), n_returned) % n_returned info_returned_bar = self.window.add_info_bar(Gtk.MessageType.QUESTION, msg) button = info_returned_bar.add_button(_(u"Returned sale"), Gtk.ResponseType.OK) button.connect('clicked', self._on_info_returned_sales__clicked) return info_returned_bar def _search_transfers(self): branch = api.get_current_branch(self.store) self.run_dialog(TransferOrderSearch, self.store) # After the search is closed we may want to update , or even hide the # message, if there is no pending transfer to receive if self.transfers_bar: n_transfers = TransferOrder.get_pending_transfers( self.store, branch).count() if n_transfers > 0: msg = stoqlib_ngettext(_(u"You have %s incoming transfer"), _(u"You have %s incoming transfers"), n_transfers) % n_transfers self.transfers_bar.set_message(msg) else: self.transfers_bar.hide() self.refresh() def _search_pending_returned_sales(self): with api.new_store() as store: self.run_dialog(PendingReturnedSaleSearch, store) branch = api.get_current_branch(self.store) # After the search is closed we may want to update , or even hide the # message, if there is no pending returned sale to receive if self.returned_bar: n_returned = ReturnedSale.get_pending_returned_sales( self.store, branch).count() if n_returned > 0: msg = stoqlib_ngettext( _(u"You have %s returned sale to receive"), _(u"You have %s returned sales to receive"), n_returned) % n_returned self.returned_bar.set_message(msg) else: self.returned_bar.hide() self.refresh() # # Callbacks # def on_image_viewer_closed(self, window, event): self.image_viewer = None self.StockPictureViewer.set_state(GLib.Variant.new_boolean(False)) def on_results__has_rows(self, results, product): self._update_widgets() def on_results__selection_changed(self, results, product): self._update_widgets() def on_ProductStockHistory__activate(self, button): selected = self.results.get_selected() sellable = selected.sellable self.run_dialog(ProductStockHistoryDialog, self.store, sellable, branch=self.branch_filter.combo.get_selected()) def on_ManageStock__activate(self, action): user = api.get_current_user(self.store) if not user.profile.check_app_permission(u'inventory'): return warning( _('Only users with access to the inventory app can' ' change the stock quantity')) product = self.results.get_selected().product if product.is_grid: return warning(_("Can't change stock quantity of a grid parent")) if product.storable and product.storable.is_batch: return warning( _("It's not possible to change the stock quantity of" " a batch product")) branch = self.branch_filter.combo.get_selected() if not branch: return warning(_('You must select a branch first')) with api.new_store() as store: self.run_dialog(ProductStockQuantityEditor, store, store.fetch(product), branch=branch) if store.committed: self.refresh() def on_PrintLabels__activate(self, button): selected = self.results.get_selected() sellable = selected.sellable label_data = self.run_dialog(PrintLabelEditor, None, self.store, sellable) if label_data: print_labels(label_data, self.store) def on_EditProduct__activate(self, button): selected = self.results.get_selected() assert selected store = api.new_store() product = store.fetch(selected.product) model = self.run_dialog(ProductStockEditor, store, product) store.confirm(model) store.close() if model: self.refresh() def _on_info_transfers__clicked(self, button): self._search_transfers() def _on_info_returned_sales__clicked(self, button): self._search_pending_returned_sales() # Stock def on_NewReceiving__activate(self, button): self._receive_purchase() def on_NewTransfer__activate(self, button): self._transfer_stock() def on_NewStockDecrease__activate(self, action): if self.check_open_inventory(): return store = api.new_store() model = self.run_dialog(StockDecreaseWizard, store) store.confirm(model) store.close() self.refresh() def on_StockInitial__activate(self, action): if self.check_open_inventory(): return with api.new_store() as store: self.run_dialog(InitialStockDialog, store) if store.committed: self.refresh() def on_StockPictureViewer__change_state(self, action, value): action.set_state(value) if value.get_boolean(): self._open_image_viewer() else: self._close_image_viewer() # Loan def on_LoanNew__activate(self, action): if self.check_open_inventory(): return store = api.new_store() model = self.run_dialog(NewLoanWizard, store) store.confirm(model) store.close() self.refresh() def on_LoanClose__activate(self, action): if self.check_open_inventory(): return store = api.new_store() model = self.run_dialog(CloseLoanWizard, store) store.confirm(model) store.close() self.refresh() def on_LoanSearch__activate(self, action): self.run_dialog(LoanSearch, self.store) def on_LoanSearchItems__activate(self, action): self.run_dialog(LoanItemSearch, self.store) # Search def on_SearchPurchaseReceiving__activate(self, button): self.run_dialog(PurchaseReceivingSearch, self.store) def on_SearchTransfer__activate(self, action): self._search_transfers() def on_SearchTransferItems__activate(self, action): self.run_dialog(TransferItemSearch, self.store) def on_SearchPendingReturnedSales__activate(self, action): self._search_pending_returned_sales() def on_SearchReturnedItems__activate(self, action): self.run_dialog(ReturnedItemSearch, self.store) def on_SearchPurchasedStockItems__activate(self, action): self.run_dialog(PurchasedItemsSearch, self.store) def on_SearchStockItems__activate(self, action): self.run_dialog(ProductStockSearch, self.store) def on_SearchBrandItems__activate(self, action): self.run_dialog(ProductBrandSearch, self.store) def on_SearchBrandItemsByBranch__activate(self, action): self.run_dialog(ProductBrandByBranchSearch, self.store) def on_SearchBatchItems__activate(self, action): self.run_dialog(ProductBatchSearch, self.store) def on_SearchClosedStockItems__activate(self, action): self.run_dialog(ProductClosedStockSearch, self.store) def on_SearchProductHistory__activate(self, action): self.run_dialog(ProductSearchQuantity, self.store) def on_SearchStockDecrease__activate(self, action): self.run_dialog(StockDecreaseSearch, self.store)
def create_filters(self): status_filter = ComboSearchFilter(_('Show employees with status'), self._get_status_values()) self.add_filter(status_filter, SearchFilterPosition.TOP, ['status'])