예제 #1
0
    def setup_slaves(self):
        self.opening_slave = WorkOrderOpeningSlave(
            self.store,
            self.model,
            visual_mode=self.visual_mode,
            edit_mode=self.edit_mode)
        self.attach_slave('opening_holder', self.opening_slave)

        self.quote_slave = WorkOrderQuoteSlave(self.store,
                                               self.model,
                                               visual_mode=self.visual_mode,
                                               edit_mode=self.edit_mode)
        self.attach_slave('quote_holder', self.quote_slave)

        self.execution_slave = WorkOrderExecutionSlave(
            self,
            self.store,
            self.model,
            visual_mode=self.visual_mode,
            edit_mode=self.edit_mode)
        self.attach_slave('execution_holder', self.execution_slave)

        self.history_slave = WorkOrderHistorySlave(
            self.store,
            self.model,
            visual_mode=self.visual_mode,
            edit_mode=self.edit_mode)
        self.attach_slave('history_holder', self.history_slave)

        self._update_view()
예제 #2
0
    def setup_slaves(self):
        self.opening_slave = WorkOrderOpeningSlave(
            self.store, self.model, visual_mode=self.visual_mode,
            edit_mode=self.edit_mode)
        self.attach_slave('opening_holder', self.opening_slave)

        self.quote_slave = WorkOrderQuoteSlave(
            self.store, self.model, visual_mode=self.visual_mode,
            edit_mode=self.edit_mode)
        self.attach_slave('quote_holder', self.quote_slave)

        self.execution_slave = WorkOrderExecutionSlave(
            self, self.store, self.model, visual_mode=self.visual_mode,
            edit_mode=self.edit_mode)
        self.attach_slave('execution_holder', self.execution_slave)

        self.history_slave = WorkOrderHistorySlave(
            self.store, self.model, visual_mode=self.visual_mode,
            edit_mode=self.edit_mode)
        self.attach_slave('history_holder', self.history_slave)

        if self.model.attachment:
            self.attachment_content.set_visible(True)
            self.attachment_content.set_label(self.model.attachment.name)
            self.attachment_chooser_delete.set_visible(True)

        self._update_view()
예제 #3
0
    def setup_slaves(self):
        self.opening_slave = WorkOrderOpeningSlave(self.store, self.model, visual_mode=self.visual_mode)
        self.attach_slave("opening_holder", self.opening_slave)

        self.quote_slave = WorkOrderQuoteSlave(self.store, self.model, visual_mode=self.visual_mode)
        self.attach_slave("quote_holder", self.quote_slave)

        self.execution_slave = WorkOrderExecutionSlave(self, self.store, self.model, visual_mode=self.visual_mode)
        self.attach_slave("execution_holder", self.execution_slave)

        self.history_slave = WorkOrderHistorySlave(self.store, self.model, visual_mode=self.visual_mode)
        self.attach_slave("history_holder", self.history_slave)

        self._update_view()
예제 #4
0
    def setup_slaves(self):
        self.opening_slave = WorkOrderOpeningSlave(
            self.store, self.model, visual_mode=self.visual_mode)
        self.attach_slave('opening_holder', self.opening_slave)

        self.quote_slave = WorkOrderQuoteSlave(
            self.store, self.model, visual_mode=self.visual_mode)
        self.attach_slave('quote_holder', self.quote_slave)

        self.execution_slave = WorkOrderExecutionSlave(
            self.store, self.model, visual_mode=self.visual_mode)
        self.attach_slave('execution_holder', self.execution_slave)
        # FIXME: It's strange to connect to the list on a slave on other slave
        # and other slave, but we need to update status_str proxy after.
        # Is there a way of doing this without having to create a gsinal
        # in each slave and propagate one to another?
        self.execution_slave.sellable_item_slave.slave.klist.connect(
            'has-rows', self._on_execution_slave__has_rows)

        self.history_slave = WorkOrderHistorySlave(
            self.store, self.model, visual_mode=self.visual_mode)
        self.attach_slave('history_holder', self.history_slave)

        self._update_view()
예제 #5
0
class WorkOrderEditor(BaseEditor):
    """An editor for working with |workorder| objects"""

    size = (800, -1)
    gladefile = 'WorkOrderEditor'
    model_type = WorkOrder
    model_name = _(u'Work order')
    help_section = 'workorder'
    need_cancel_confirmation = True
    proxy_widgets = [
        'category',
        'client',
        'description',
        'identifier',
        'status_str',
        'supplier_order',
        'quantity',
    ]

    def __init__(self, store, model=None, visual_mode=False, category=None,
                 available_categories=None):
        """
        @param category: The default category that should be already selected.
        @param available_categories: A list of categories names that should be
          available to the user. If None, all categoires will be available
        """
        self._default_category = category
        self.categories_for_combo = available_categories
        self.proxy = None
        super(WorkOrderEditor, self).__init__(store, model=model,
                                              visual_mode=visual_mode)
        self._setup_widgets()
        pm = PermissionManager.get_permission_manager()
        if not pm.can_create('WorkOrderCategory'):
            self.category_create.hide()
        if not pm.can_edit('WorkOrderCategory'):
            self.category_edit.hide()

    #
    #  BaseEditor
    #

    def create_model(self, store):
        defect_detected = api.sysparam.get_string('DEFECT_DETECTED_TEMPLATE')
        branch = api.get_current_branch(store)
        return WorkOrder(
            store=store,
            sellable=None,
            description=u'',
            branch=branch,
            category=self._default_category,
            defect_detected=defect_detected,
        )

    def setup_slaves(self):
        self.opening_slave = WorkOrderOpeningSlave(
            self.store, self.model, visual_mode=self.visual_mode,
            edit_mode=self.edit_mode)
        self.attach_slave('opening_holder', self.opening_slave)

        self.quote_slave = WorkOrderQuoteSlave(
            self.store, self.model, visual_mode=self.visual_mode,
            edit_mode=self.edit_mode)
        self.attach_slave('quote_holder', self.quote_slave)

        self.execution_slave = WorkOrderExecutionSlave(
            self, self.store, self.model, visual_mode=self.visual_mode,
            edit_mode=self.edit_mode)
        self.attach_slave('execution_holder', self.execution_slave)

        self.history_slave = WorkOrderHistorySlave(
            self.store, self.model, visual_mode=self.visual_mode,
            edit_mode=self.edit_mode)
        self.attach_slave('history_holder', self.history_slave)

        self._update_view()

    def setup_proxies(self):
        self._fill_categories_combo()
        self._setup_client_widget()
        if not self.model.sellable:
            self.quantity.set_sensitive(False)
        self.proxy = self.add_proxy(self.model, self.proxy_widgets)

    def update_visual_mode(self):
        for widget in [self.toggle_status_btn,
                       self.category_create, self.sellable_desc,
                       self.equip_search_button, self.quantity]:
            widget.set_sensitive(False)

    #
    #  Public API
    #

    def add_extra_tab(self, tab_label, slave):
        """Adds an extra tab to the editor

        :param tab_label: the label that will be display on the tab
        :param slave: the slave that will be attached to the new tab
        """
        event_box = gtk.EventBox()
        self.slaves_notebook.append_page(event_box, gtk.Label(tab_label))
        self.attach_slave(tab_label, slave, event_box)
        event_box.show()

    #
    #  Private
    #

    def _setup_widgets(self):
        # When editing an existing opened order, go to the quote tab.
        # But if the work is approved or in progress, go to execution tab.
        if self.model.status == WorkOrder.STATUS_OPENED and self.edit_mode:
            self._set_current_tab('quote_holder')
        elif self.model.status in [WorkOrder.STATUS_WORK_IN_PROGRESS,
                                   WorkOrder.STATUS_WORK_FINISHED,
                                   WorkOrder.STATUS_WORK_WAITING,
                                   WorkOrder.STATUS_DELIVERED]:
            self._set_current_tab('execution_holder')

        if self.edit_mode and self.model.sale:
            for widget in [self.client, self.category, self.category_create]:
                widget.set_sensitive(False)

        if self.model.sellable:
            self.sellable_desc.set_text(get_sellable_information(self.model.sellable))

    def _update_view(self):
        self.proxy.update('status_str')

        # Cache this to avoid multiple queries
        has_open_inventory = bool(Inventory.has_open(
            self.store, api.get_current_branch(self.store)))

        tab = self._get_tab('execution_holder')
        # If it's not opened, it's at least approved.
        # So, we can enable the execution slave
        tab.set_sensitive(
            self.model.status == WorkOrder.STATUS_WORK_IN_PROGRESS and
            not has_open_inventory and not self.visual_mode)

        has_items = bool(self.model.order_items.count())
        if self.model.can_approve():
            label = _("Approve")
        elif self.model.can_work() and not has_items:
            label = _("Start")
        elif self.model.can_work():
            label = _("Continue")
        elif self.model.can_pause():
            label = _("Pause")
        else:
            label = ''
        self.toggle_status_btn.set_label(label)
        self.toggle_status_btn.set_sensitive(not self.visual_mode and
                                             self.model.client is not None)
        self.toggle_status_btn.set_visible(bool(label))

        stock_id, tooltip = get_workorder_state_icon(self.model)
        if stock_id is not None:
            self.state_icon.set_from_stock(stock_id, gtk.ICON_SIZE_MENU)
            self.state_icon.set_visible(True)
            self.state_icon.set_tooltip_text(tooltip)
        else:
            self.state_icon.hide()

    def _get_tab_pagenum(self, holder_name):
        return self.slaves_notebook.page_num(getattr(self, holder_name))

    def _get_tab(self, holder_name):
        page_num = self._get_tab_pagenum(holder_name)
        return self.slaves_notebook.get_nth_page(page_num)

    def _set_current_tab(self, holder_name):
        page_num = self._get_tab_pagenum(holder_name)
        self.slaves_notebook.set_current_page(page_num)

    def _setup_client_widget(self):
        self.client_gadget = ClientEntryGadget(
            entry=self.client,
            store=self.store,
            initial_value=self.model.client,
            parent=self)

    def _fill_categories_combo(self):
        if self.categories_for_combo is not None:
            categories = self.store.find(WorkOrderCategory,
                                         In(WorkOrderCategory.name,
                                            self.categories_for_combo))
        else:
            categories = self.store.find(WorkOrderCategory)
        self.category.color_attribute = 'color'
        self.category.prefill(
            api.for_combo(categories, empty=_(u"No category")))

    def _run_category_editor(self, category=None):
        with api.new_store() as store:
            rv = run_dialog(WorkOrderCategoryEditor, self, store, category,
                            visual_mode=self.visual_mode)
        if rv:
            self._fill_categories_combo()
            self.category.select(self.store.fetch(rv))

    def _maybe_toggle_status(self):
        if self.model.can_approve():
            self.model.approve()
        elif self.model.can_work():
            self.model.work()
        elif self.model.can_pause():
            msg_text = _(u"This will pause the order. Are you sure?")
            rv = run_dialog(
                NoteEditor, self, self.store, model=Note(),
                message_text=msg_text, label_text=_(u"Reason"), mandatory=True)
            if not rv:
                return
            self.model.pause(reason=rv.notes)

        self._update_view()
        self.history_slave.update_items()

    #
    #  Callbacks
    #

    def after_client__content_changed(self, combo):
        if self.proxy:
            self._update_view()

    def on_category__content_changed(self, combo):
        has_category = bool(combo.read())
        self.category_edit.set_sensitive(has_category)

    def on_category_create__clicked(self, button):
        self._run_category_editor()

    def on_category_edit__clicked(self, button):
        self._run_category_editor(category=self.category.read())

    def on_toggle_status_btn__clicked(self, button):
        self._maybe_toggle_status()

    def on_equip_search_button__clicked(self, button):
        ret = run_dialog(SellableSearch, self, self.store, hide_footer=True,
                         hide_toolbar=True, double_click_confirm=True,
                         show_closed_items=True)
        if not ret:
            return

        sellable = ret.sellable
        self.sellable_desc.set_text(get_sellable_information(sellable))
        self.model.sellable = sellable
        self.quantity.set_sensitive(True)
예제 #6
0
class WorkOrderEditor(BaseEditor):
    """An editor for working with |workorder| objects"""

    size = (800, 500)
    gladefile = 'WorkOrderEditor'
    model_type = WorkOrder
    model_name = _(u'Work order')
    help_section = 'workorder'
    proxy_widgets = [
        'category',
        'client',
        'equipment',
        'identifier',
        'status_str',
    ]

    def __init__(self, store, model=None, visual_mode=False, category=None):
        self._default_category = category
        self.proxy = None
        # Force visual_mode if the order is not in the current branch
        if model and model.current_branch != api.get_current_branch(store):
            visual_mode = True

        super(WorkOrderEditor, self).__init__(store, model=model,
                                              visual_mode=visual_mode)
        self._setup_widgets()

    def _get_client(self):
        client_id = self.client.read()
        return self.store.get(Client, client_id)

    #
    #  BaseEditor
    #

    def create_model(self, store):
        branch = api.get_current_branch(store)
        return WorkOrder(
            store=store,
            equipment=u'',
            branch=branch,
            category=self._default_category,
        )

    def setup_slaves(self):
        self.opening_slave = WorkOrderOpeningSlave(
            self.store, self.model, visual_mode=self.visual_mode)
        self.attach_slave('opening_holder', self.opening_slave)

        self.quote_slave = WorkOrderQuoteSlave(
            self.store, self.model, visual_mode=self.visual_mode)
        self.attach_slave('quote_holder', self.quote_slave)

        self.execution_slave = WorkOrderExecutionSlave(
            self, self.store, self.model, visual_mode=self.visual_mode)
        self.attach_slave('execution_holder', self.execution_slave)

        self.history_slave = WorkOrderHistorySlave(
            self.store, self.model, visual_mode=self.visual_mode)
        self.attach_slave('history_holder', self.history_slave)

        self._update_view()

    def setup_proxies(self):
        self._fill_clients_combo()
        self._fill_categories_combo()
        self.proxy = self.add_proxy(self.model, self.proxy_widgets)

    def update_visual_mode(self):
        for widget in [self.toggle_status_btn, self.client_create,
                       self.category_create]:
            widget.set_sensitive(False)

    #
    #  Public API
    #

    def add_extra_tab(self, tab_label, slave):
        """Adds an extra tab to the editor

        :param tab_label: the label that will be display on the tab
        :param slave: the slave that will be attached to the new tab
        """
        event_box = gtk.EventBox()
        self.slaves_notebook.append_page(event_box, gtk.Label(tab_label))
        self.attach_slave(tab_label, slave, event_box)
        event_box.show()

    #
    #  Private
    #

    def _setup_widgets(self):
        for widget in [self.client_info, self.category_edit]:
            widget.set_sensitive(False)

        # When editing an existing opened order, go to the quote tab.
        # But if the work is approved or in progress, go to execution tab.
        if self.model.status == WorkOrder.STATUS_OPENED and self.edit_mode:
            self._set_current_tab('quote_holder')
        elif self.model.status in [WorkOrder.STATUS_WORK_IN_PROGRESS,
                                   WorkOrder.STATUS_WORK_FINISHED,
                                   WorkOrder.STATUS_WORK_WAITING,
                                   WorkOrder.STATUS_DELIVERED]:
            self._set_current_tab('execution_holder')

    def _update_view(self):
        self.proxy.update('status_str')

        has_open_inventory = bool(Inventory.has_open(
            self.store, api.get_current_branch(self.store)))

        tab = self._get_tab('execution_holder')
        # If it's not opened, it's at least approved.
        # So, we can enable the execution slave
        tab.set_sensitive(
            self.model.status == WorkOrder.STATUS_WORK_IN_PROGRESS and
            not has_open_inventory and not self.visual_mode)

        has_items = bool(self.model.order_items.count())
        if self.model.can_approve():
            label = _("Approve")
        elif self.model.can_work() and not has_items:
            label = _("Start")
        elif self.model.can_work():
            label = _("Continue")
        elif self.model.can_pause():
            label = _("Pause")
        else:
            label = ''
        self.toggle_status_btn.set_label(label)
        self.toggle_status_btn.set_sensitive(not self.visual_mode and
                                             self.model.client is not None)
        self.toggle_status_btn.set_visible(bool(label))

        stock_id, tooltip = get_workorder_state_icon(self.model)
        if stock_id is not None:
            self.state_icon.set_from_stock(stock_id, gtk.ICON_SIZE_MENU)
            self.state_icon.set_visible(True)
            self.state_icon.set_tooltip_text(tooltip)
        else:
            self.state_icon.hide()

    def _get_tab_pagenum(self, holder_name):
        return self.slaves_notebook.page_num(getattr(self, holder_name))

    def _get_tab(self, holder_name):
        page_num = self._get_tab_pagenum(holder_name)
        return self.slaves_notebook.get_nth_page(page_num)

    def _set_current_tab(self, holder_name):
        page_num = self._get_tab_pagenum(holder_name)
        self.slaves_notebook.set_current_page(page_num)

    def _fill_clients_combo(self):
        items = Client.get_active_items(self.store)
        self.client.prefill(items)

    def _fill_categories_combo(self):
        categories = self.store.find(WorkOrderCategory)
        self.category.color_attribute = 'color'
        self.category.prefill(
            api.for_combo(categories, empty=_(u"No category")))

    def _run_client_editor(self, client=None):
        with api.new_store() as store:
            rv = run_person_role_dialog(ClientEditor, self, store, client,
                                        visual_mode=self.visual_mode)
        if rv:
            self._fill_clients_combo()
            self.client.select(rv.id)

    def _run_category_editor(self, category=None):
        with api.new_store() as store:
            rv = run_dialog(WorkOrderCategoryEditor, self, store, category,
                            visual_mode=self.visual_mode)
        if rv:
            self._fill_categories_combo()
            self.category.select(self.store.fetch(rv))

    def _maybe_toggle_status(self):
        if self.model.can_approve():
            self.model.approve()
        elif self.model.can_work():
            self.model.work()
        elif self.model.can_pause():
            msg_text = _(u"This will pause the order. Are you sure?")
            rv = run_dialog(
                NoteEditor, self, self.store, model=Note(),
                message_text=msg_text, label_text=_(u"Reason"), mandatory=True)
            if not rv:
                return
            self.model.pause(reason=rv.notes)

        self._update_view()
        self.history_slave.update_items()

    #
    #  Callbacks
    #

    def on_client__content_changed(self, combo):
        has_client = bool(combo.read())
        self.client_info.set_sensitive(has_client)

    def after_client__content_changed(self, combo):
        if self.proxy:
            self._update_view()

    def on_category__content_changed(self, combo):
        has_category = bool(combo.read())
        self.category_edit.set_sensitive(has_category)

    def on_client_create__clicked(self, button):
        self._run_client_editor()

    def on_client_info__clicked(self, button):
        client = self._get_client()
        run_dialog(ClientDetailsDialog, self, self.store, client)

    def on_category_create__clicked(self, button):
        self._run_category_editor()

    def on_category_edit__clicked(self, button):
        self._run_category_editor(category=self.category.read())

    def on_toggle_status_btn__clicked(self, button):
        self._maybe_toggle_status()
예제 #7
0
class WorkOrderEditor(BaseEditor):
    """An editor for working with |workorder| objects"""

    size = (800, -1)
    gladefile = 'WorkOrderEditor'
    model_type = WorkOrder
    model_name = _(u'Work order')
    help_section = 'workorder'
    need_cancel_confirmation = True
    proxy_widgets = [
        'category',
        'client',
        'description',
        'identifier',
        'status_str',
        'supplier_order',
        'quantity',
    ]

    def __init__(self,
                 store,
                 model=None,
                 visual_mode=False,
                 category=None,
                 available_categories=None):
        """
        @param category: The default category that should be already selected.
        @param available_categories: A list of categories names that should be
          available to the user. If None, all categoires will be available
        """
        self._default_category = category
        self.categories_for_combo = available_categories
        self.proxy = None
        super(WorkOrderEditor, self).__init__(store,
                                              model=model,
                                              visual_mode=visual_mode)
        self._setup_widgets()
        pm = PermissionManager.get_permission_manager()
        if not pm.can_create('WorkOrderCategory'):
            self.category_create.hide()
        if not pm.can_edit('WorkOrderCategory'):
            self.category_edit.hide()

    #
    #  BaseEditor
    #

    def create_model(self, store):
        defect_detected = api.sysparam.get_string('DEFECT_DETECTED_TEMPLATE')
        branch = api.get_current_branch(store)
        return WorkOrder(
            store=store,
            sellable=None,
            description=u'',
            branch=branch,
            category=self._default_category,
            defect_detected=defect_detected,
        )

    def setup_slaves(self):
        self.opening_slave = WorkOrderOpeningSlave(
            self.store,
            self.model,
            visual_mode=self.visual_mode,
            edit_mode=self.edit_mode)
        self.attach_slave('opening_holder', self.opening_slave)

        self.quote_slave = WorkOrderQuoteSlave(self.store,
                                               self.model,
                                               visual_mode=self.visual_mode,
                                               edit_mode=self.edit_mode)
        self.attach_slave('quote_holder', self.quote_slave)

        self.execution_slave = WorkOrderExecutionSlave(
            self,
            self.store,
            self.model,
            visual_mode=self.visual_mode,
            edit_mode=self.edit_mode)
        self.attach_slave('execution_holder', self.execution_slave)

        self.history_slave = WorkOrderHistorySlave(
            self.store,
            self.model,
            visual_mode=self.visual_mode,
            edit_mode=self.edit_mode)
        self.attach_slave('history_holder', self.history_slave)

        self._update_view()

    def setup_proxies(self):
        self._fill_categories_combo()
        self._setup_client_widget()
        if not self.model.sellable:
            self.quantity.set_sensitive(False)
        self.proxy = self.add_proxy(self.model, self.proxy_widgets)

    def update_visual_mode(self):
        for widget in [
                self.toggle_status_btn, self.category_create,
                self.sellable_desc, self.equip_search_button, self.quantity
        ]:
            widget.set_sensitive(False)

    #
    #  Public API
    #

    def add_extra_tab(self, tab_label, slave):
        """Adds an extra tab to the editor

        :param tab_label: the label that will be display on the tab
        :param slave: the slave that will be attached to the new tab
        """
        event_box = Gtk.EventBox()
        self.slaves_notebook.append_page(event_box, Gtk.Label(label=tab_label))
        self.attach_slave(tab_label, slave, event_box)
        event_box.show()

    #
    #  Private
    #

    def _setup_widgets(self):
        # When editing an existing opened order, go to the quote tab.
        # But if the work is approved or in progress, go to execution tab.
        if self.model.status == WorkOrder.STATUS_OPENED and self.edit_mode:
            self._set_current_tab('quote_holder')
        elif self.model.status in [
                WorkOrder.STATUS_WORK_IN_PROGRESS,
                WorkOrder.STATUS_WORK_FINISHED, WorkOrder.STATUS_WORK_WAITING,
                WorkOrder.STATUS_DELIVERED
        ]:
            self._set_current_tab('execution_holder')

        if self.edit_mode and self.model.sale:
            for widget in [self.client, self.category, self.category_create]:
                widget.set_sensitive(False)

        self._update_sellable_desc()

    def _update_sellable_desc(self):
        sellable = self.model.sellable
        if sellable is None:
            return

        if sellable.code:
            desc = "%s - %s" % (sellable.code, sellable.description)
        else:
            desc = sellable.description

        self.sellable_desc.set_text(desc)
        self.sellable_desc.set_tooltip_text(desc)

    def _update_view(self):
        self.proxy.update('status_str')

        # Cache this to avoid multiple queries
        has_open_inventory = bool(
            Inventory.has_open(self.store, api.get_current_branch(self.store)))

        tab = self._get_tab('execution_holder')
        # If it's not opened, it's at least approved.
        # So, we can enable the execution slave
        tab.set_sensitive(
            self.model.status == WorkOrder.STATUS_WORK_IN_PROGRESS
            and not has_open_inventory and not self.visual_mode)

        has_items = bool(self.model.order_items.count())
        if self.model.can_approve():
            label = _("Approve")
        elif self.model.can_work() and not has_items:
            label = _("Start")
        elif self.model.can_work():
            label = _("Continue")
        elif self.model.can_pause():
            label = _("Pause")
        else:
            label = ''
        self.toggle_status_btn.set_label(label)
        self.toggle_status_btn.set_sensitive(not self.visual_mode
                                             and self.model.client is not None)
        self.toggle_status_btn.set_visible(bool(label))

        stock_id, tooltip = get_workorder_state_icon(self.model)
        if stock_id is not None:
            self.state_icon.set_from_stock(stock_id, Gtk.IconSize.MENU)
            self.state_icon.set_visible(True)
            self.state_icon.set_tooltip_text(tooltip)
        else:
            self.state_icon.hide()

    def _get_tab_pagenum(self, holder_name):
        return self.slaves_notebook.page_num(getattr(self, holder_name))

    def _get_tab(self, holder_name):
        page_num = self._get_tab_pagenum(holder_name)
        return self.slaves_notebook.get_nth_page(page_num)

    def _set_current_tab(self, holder_name):
        page_num = self._get_tab_pagenum(holder_name)
        self.slaves_notebook.set_current_page(page_num)

    def _setup_client_widget(self):
        self.client_gadget = ClientEntryGadget(entry=self.client,
                                               store=self.store,
                                               initial_value=self.model.client,
                                               parent=self)

    def _fill_categories_combo(self):
        if self.categories_for_combo is not None:
            categories = self.store.find(
                WorkOrderCategory,
                In(WorkOrderCategory.name, self.categories_for_combo))
        else:
            categories = self.store.find(WorkOrderCategory)
        self.category.color_attribute = 'color'
        self.category.prefill(
            api.for_combo(categories, empty=_(u"No category")))

    def _run_category_editor(self, category=None):
        with api.new_store() as store:
            rv = run_dialog(WorkOrderCategoryEditor,
                            self,
                            store,
                            category,
                            visual_mode=self.visual_mode)
        if rv:
            self._fill_categories_combo()
            self.category.select(self.store.fetch(rv))

    def _maybe_toggle_status(self):
        if self.model.can_approve():
            self.model.approve()
        elif self.model.can_work():
            self.model.work()
        elif self.model.can_pause():
            msg_text = _(u"This will pause the order. Are you sure?")
            rv = run_dialog(NoteEditor,
                            self,
                            self.store,
                            model=Note(),
                            message_text=msg_text,
                            label_text=_(u"Reason"),
                            mandatory=True)
            if not rv:
                return
            self.model.pause(reason=rv.notes)

        self._update_view()
        self.history_slave.update_items()

    #
    #  Callbacks
    #

    def after_client__content_changed(self, combo):
        if self.proxy:
            self._update_view()

    def on_category__content_changed(self, combo):
        has_category = bool(combo.read())
        self.category_edit.set_sensitive(has_category)

    def on_category_create__clicked(self, button):
        self._run_category_editor()

    def on_category_edit__clicked(self, button):
        self._run_category_editor(category=self.category.read())

    def on_toggle_status_btn__clicked(self, button):
        self._maybe_toggle_status()

    def on_equip_search_button__clicked(self, button):
        ret = run_dialog(SellableSearch,
                         self,
                         self.store,
                         hide_footer=True,
                         hide_toolbar=True,
                         double_click_confirm=True,
                         show_closed_items=True)
        if not ret:
            return

        sellable = ret.sellable
        self.model.sellable = sellable
        self._update_sellable_desc()
        self.quantity.set_sensitive(True)
예제 #8
0
class WorkOrderEditor(BaseEditor):
    """An editor for working with |workorder| objects"""

    size = (800, 500)
    gladefile = 'WorkOrderEditor'
    model_type = WorkOrder
    model_name = _(u'Work order')
    help_section = 'workorder'
    proxy_widgets = [
        'category',
        'client',
        'equipment',
        'identifier',
        'status_str',
    ]

    def __init__(self, store, model=None, visual_mode=False, category=None):
        self._default_category = category
        # Force visual_mode if the order is not in the current branch
        if model and model.current_branch != api.get_current_branch(store):
            visual_mode = True

        super(WorkOrderEditor, self).__init__(store,
                                              model=model,
                                              visual_mode=visual_mode)

    #
    #  BaseEditor
    #

    def create_model(self, store):
        branch = api.get_current_branch(store)
        return WorkOrder(
            store=store,
            equipment=u'',
            branch=branch,
            category=self._default_category,
        )

    def setup_slaves(self):
        self.opening_slave = WorkOrderOpeningSlave(
            self.store, self.model, visual_mode=self.visual_mode)
        self.attach_slave('opening_holder', self.opening_slave)

        self.quote_slave = WorkOrderQuoteSlave(self.store,
                                               self.model,
                                               visual_mode=self.visual_mode)
        self.attach_slave('quote_holder', self.quote_slave)

        self.execution_slave = WorkOrderExecutionSlave(
            self, self.store, self.model, visual_mode=self.visual_mode)
        self.attach_slave('execution_holder', self.execution_slave)

        self.history_slave = WorkOrderHistorySlave(
            self.store, self.model, visual_mode=self.visual_mode)
        self.attach_slave('history_holder', self.history_slave)

        self._update_view()

    def setup_proxies(self):
        self._setup_widgets()
        self.proxy = self.add_proxy(self.model, self.proxy_widgets)

    def update_visual_mode(self):
        for widget in [
                self.toggle_status_btn, self.client_create,
                self.category_create
        ]:
            widget.set_sensitive(False)

    #
    #  Public API
    #

    def add_extra_tab(self, tab_label, slave):
        """Adds an extra tab to the editor

        :param tab_label: the label that will be display on the tab
        :param slave: the slave that will be attached to the new tab
        """
        event_box = gtk.EventBox()
        self.slaves_notebook.append_page(event_box, gtk.Label(tab_label))
        self.attach_slave(tab_label, slave, event_box)
        event_box.show()

    #
    #  Private
    #

    def _setup_widgets(self):
        for widget in [self.client_info, self.category_edit]:
            widget.set_sensitive(False)
        self._fill_clients_combo()
        self._fill_categories_combo()

        # When editing an existing opened order, go to the quote tab.
        # But if the work is approved or in progress, go to execution tab.
        if self.model.status == WorkOrder.STATUS_OPENED and self.edit_mode:
            self._set_current_tab('quote_holder')
        elif self.model.status in [
                WorkOrder.STATUS_WORK_IN_PROGRESS,
                WorkOrder.STATUS_WORK_FINISHED, WorkOrder.STATUS_WORK_WAITING,
                WorkOrder.STATUS_DELIVERED
        ]:
            self._set_current_tab('execution_holder')

    def _update_view(self):
        self.proxy.update('status_str')

        # If it's not opened, it's at least approved.
        # So, we can enable the execution slave
        tab = self._get_tab('execution_holder')
        tab.set_sensitive(
            self.model.status == WorkOrder.STATUS_WORK_IN_PROGRESS)

        has_items = bool(self.model.order_items.count())
        if self.model.can_approve():
            label = _("Approve")
        elif self.model.can_work() and not has_items:
            label = _("Start")
        elif self.model.can_work():
            label = _("Continue")
        elif self.model.can_pause():
            label = _("Pause")
        else:
            label = ''
        self.toggle_status_btn.set_label(label)
        self.toggle_status_btn.set_sensitive(not self.visual_mode
                                             and self.model.client is not None)
        self.toggle_status_btn.set_visible(bool(label))

        stock_id, tooltip = get_workorder_state_icon(self.model)
        if stock_id is not None:
            self.state_icon.set_from_stock(stock_id, gtk.ICON_SIZE_MENU)
            self.state_icon.set_visible(True)
            self.state_icon.set_tooltip_text(tooltip)
        else:
            self.state_icon.hide()

    def _get_tab_pagenum(self, holder_name):
        return self.slaves_notebook.page_num(getattr(self, holder_name))

    def _get_tab(self, holder_name):
        page_num = self._get_tab_pagenum(holder_name)
        return self.slaves_notebook.get_nth_page(page_num)

    def _set_current_tab(self, holder_name):
        page_num = self._get_tab_pagenum(holder_name)
        self.slaves_notebook.set_current_page(page_num)

    def _fill_clients_combo(self):
        clients = Client.get_active_clients(self.store)
        self.client.prefill(api.for_person_combo(clients))

    def _fill_categories_combo(self):
        categories = self.store.find(WorkOrderCategory)
        self.category.color_attribute = 'color'
        self.category.prefill(
            api.for_combo(categories, empty=_(u"No category")))

    def _run_client_editor(self, client=None):
        with api.trans() as store:
            rv = run_person_role_dialog(ClientEditor,
                                        self,
                                        store,
                                        client,
                                        visual_mode=self.visual_mode)
        if rv:
            self._fill_clients_combo()
            self.client.select(self.store.fetch(rv))

    def _run_category_editor(self, category=None):
        with api.trans() as store:
            rv = run_dialog(WorkOrderCategoryEditor,
                            self,
                            store,
                            category,
                            visual_mode=self.visual_mode)
        if rv:
            self._fill_categories_combo()
            self.category.select(self.store.fetch(rv))

    def _maybe_toggle_status(self):
        if self.model.can_approve():
            self.model.approve()
        elif self.model.can_work():
            self.model.work()
        elif self.model.can_pause():
            msg_text = _(u"This will inform the order that we are waiting. "
                         u"Are you sure?")
            rv = run_dialog(NoteEditor,
                            self,
                            self.store,
                            model=Note(),
                            message_text=msg_text,
                            label_text=_(u"Reason"),
                            mandatory=True)
            if not rv:
                return
            self.model.pause(reason=rv.notes)

        self._update_view()
        self.history_slave.update_items()

    #
    #  Callbacks
    #

    def on_client__content_changed(self, combo):
        has_client = bool(combo.read())
        self.client_info.set_sensitive(has_client)

    def after_client__content_changed(self, combo):
        self._update_view()

    def on_category__content_changed(self, combo):
        has_category = bool(combo.read())
        self.category_edit.set_sensitive(has_category)

    def on_client_create__clicked(self, button):
        self._run_client_editor()

    def on_client_info__clicked(self, button):
        run_dialog(ClientDetailsDialog, self, self.store, self.client.read())

    def on_category_create__clicked(self, button):
        self._run_category_editor()

    def on_category_edit__clicked(self, button):
        self._run_category_editor(category=self.category.read())

    def on_toggle_status_btn__clicked(self, button):
        self._maybe_toggle_status()