def test_get_plugin_manager(self):
        # PluginManager should be a singleton
        self.assertEqual(self._manager, get_plugin_manager())
        self.assertEqual(id(self._manager), id(get_plugin_manager()))

        # Just check if it really provides IPluginManager
        self.assertTrue(IPluginManager.providedBy(self._manager))
        self.assertTrue(isinstance(self._manager, PluginManager))
Exemple #2
0
    def test_get_plugin_manager(self):
        # PluginManager should be a singleton
        self.assertEqual(self._manager, get_plugin_manager())
        self.assertEqual(id(self._manager), id(get_plugin_manager()))

        # Just check if it really provides IPluginManager
        self.assertTrue(IPluginManager.providedBy(self._manager))
        self.assertTrue(isinstance(self._manager, PluginManager))
Exemple #3
0
def _enable_plugins():
    manager = get_plugin_manager()
    for plugin in [u'nfe', u'ecf']:
        if not manager.is_installed(plugin):
            # STOQLIB_TEST_QUICK won't let dropdb on testdb run. Just a
            # precaution to avoid trying to install it again
            manager.install_plugin(plugin)
Exemple #4
0
    def _start_tasks(self):
        tasks = [
            _Task(start_backup_scheduler),
            _Task(start_server),
            _Task(start_rtc),
        ]
        if start_xmlrpc_server not in [t.func for t in
                                       self._get_children()]:
            tasks.append(_Task(start_xmlrpc_server, self._xmlrpc_conn2))

        manager = get_plugin_manager()
        for plugin_name in manager.installed_plugins_names:
            plugin = manager.get_plugin(plugin_name)
            if not hasattr(plugin, 'get_server_tasks'):
                continue

            # FIXME: Check that the plugin implements IPluginTask when
            # we Stoq 1.11 is released
            for plugin_task in plugin.get_server_tasks():
                task_name = plugin_task.name
                kwargs = {}
                if plugin_task.handle_actions:
                    conn1, conn2 = multiprocessing.Pipe(True)
                    self._plugins_pipes[(plugin_name, task_name)] = conn1
                    kwargs['pipe_connection'] = conn2

                tasks.append(_Task(plugin_task.start, **kwargs))

        for t in tasks:
            t.start()
Exemple #5
0
    def checkout(self, cancel_clear=False):
        """Initiates the sale wizard to confirm sale.

        :param cancel_clear: If cancel_clear is true, the sale will be cancelled
          if the checkout is cancelled.
        """
        assert len(self.sale_items) >= 1

        if self._current_store:
            store = self._current_store
            savepoint = 'before_run_fiscalprinter_confirm'
            store.savepoint(savepoint)
        else:
            store = api.new_store()
            savepoint = None

        if self._trade:
            if self._get_subtotal() < self._trade.returned_total:
                info(_("Traded value is greater than the new sale's value. "
                       "Please add more items or return it in Sales app, "
                       "then make a new sale"))
                return

            sale = self._create_sale(store)
            self._trade.new_sale = sale
            self._trade.trade()
        else:
            sale = self._create_sale(store)

        if sysparam.get_bool('CONFIRM_SALES_ON_TILL'):
            sale.order()
            store.commit()
        else:
            assert self._coupon

            ordered = self._coupon.confirm(sale, store, savepoint,
                                           subtotal=self._get_subtotal())
            # Dont call store.confirm() here, since coupon.confirm()
            # above already did it
            if not ordered:
                # FIXME: Move to TEF plugin
                manager = get_plugin_manager()
                if manager.is_active('tef') or cancel_clear:
                    self._cancel_order(show_confirmation=False)
                elif not self._current_store:
                    # Just do that if a store was created above and
                    # if _cancel_order wasn't called (it closes the connection)
                    store.rollback(close=True)
                return

            log.info("Checking out")

        self._coupon = None
        POSConfirmSaleEvent.emit(sale, self.sale_items[:])

        # We must close the connection only after the event is emmited, since it
        # may use value from the sale that will become invalid after it is
        # closed
        store.close()
        self._clear_order()
Exemple #6
0
    def _check_online_plugins(self):
        # For each online plugin, try to download and install it.
        # Otherwise warn him
        online_plugins = InstalledPlugin.get_pre_plugin_names(self.store)
        if not online_plugins:
            return

        successes = []
        manager = get_plugin_manager()
        for plugin_name in online_plugins:
            success, msg = manager.download_plugin(plugin_name)
            successes.append(success)
            if success:
                manager.install_plugin(self.store, plugin_name)
                online_plugins.remove(plugin_name)

        if all(successes):
            return

        # Title
        title = _('You have pending plugins.')

        # Description
        url = 'https://stoq.link/?source=stoq-plugin-alert&amp;hash={}'.format(
            api.sysparam.get_string('USER_HASH'))
        desc = _('The following plugins need to be enabled: <b>{}</b>.\n\n'
                 'You can do it by registering on <a href="{}">Stoq.link</a>.'
                 ).format(', '.join(online_plugins), url)
        msg = '<b>%s</b>\n%s' % (title, desc)
        self.add_info_bar(Gtk.MessageType.WARNING, msg)
Exemple #7
0
def _setup_test_environment(request):
    plugin_config = _get_plugin_configs(request.config)
    if plugin_config['skip_env_setup']:
        return

    stoq_config = StoqConfig()
    stoq_config.load_default()
    register_config(stoq_config)

    quick = plugin_config['quick_mode'] or _to_falsy(
        os.environ.get("STOQLIB_TEST_QUICK", None))
    bootstrap_suite(
        address=os.environ.get("STOQLIB_TEST_HOSTNAME"),
        dbname=os.environ.get("STOQLIB_TEST_DBNAME"),
        port=int(os.environ.get("STOQLIB_TEST_PORT") or 0),
        username=os.environ.get("STOQLIB_TEST_USERNAME"),
        password=os.environ.get("STOQLIB_TEST_PASSWORD"),
        quick=quick,
    )

    manager = get_plugin_manager()
    for plugin_name in plugin_config['extra_plugins']:
        _register_plugin(plugin_name)
        with stoqlib.api.new_store() as store:
            manager.install_plugin(store, plugin_name)
        manager.activate_plugin(plugin_name)

    plugin_cls = plugin_config['plugin_cls']
    if plugin_cls:
        _install_plugin(plugin_cls)
Exemple #8
0
    def run_command(self, options, cmd, args):
        func = getattr(self, 'cmd_' + cmd, None)
        if func is None:
            self._read_config(options,
                              load_plugins=False,
                              register_station=False)
            from stoqlib.lib.pluginmanager import get_plugin_manager
            manager = get_plugin_manager()
            if cmd in manager.installed_plugins_names:
                if not len(args):
                    raise SystemExit("%s: %s requires at least 2 argument(s)" %
                                     (self.prog_name, cmd))
                plugin = manager.get_plugin(cmd)
                return plugin.handle_dbadmin_command(args[0], options,
                                                     args[1:])
            else:
                print("%s: Invalid command: `%s' type `%s help' for usage." %
                      (self.prog_name, cmd, self.prog_name))
                return 1

        nargs = func.__code__.co_argcount - 2
        if len(args) < nargs:
            raise SystemExit("%s: %s requires at least %d argument(s)" %
                             (self.prog_name, cmd, nargs))
        self.args = args
        return func(options, *args)
Exemple #9
0
def _enable_plugins():
    manager = get_plugin_manager()
    for plugin in [u'nfe', u'ecf']:
        if not manager.is_installed(plugin):
            # STOQLIB_TEST_QUICK won't let dropdb on testdb run. Just a
            # precaution to avoid trying to install it again
            manager.install_plugin(plugin)
Exemple #10
0
    def cmd_help(self, options):
        """Show available commands help"""
        cmds = []
        max_len = 0

        for attr in dir(self):
            if not attr.startswith('cmd_'):
                continue

            name = attr[4:]
            doc = getattr(self, attr).__doc__ or ''
            max_len = max(max_len, len(name))
            cmds.append((name, doc.split(r'\n')[0]))

        max_len = max_len + 2

        print('Usage: stoqdbadmin [plugin] <command> [<args>]')
        print()
        print('Available commands:')

        for name, doc in cmds:
            print('  %s%s' % (name.ljust(max_len), doc))

        self._read_config(options, load_plugins=False,
                          register_station=False)

        from stoqlib.lib.pluginmanager import get_plugin_manager
        manager = get_plugin_manager()
        for plugin_name in manager.installed_plugins_names:
            plugin = manager.get_plugin(plugin_name)
            for command in plugin.get_dbadmin_commands():
                print('   %s %s' % (plugin_name, command))

        return 0
Exemple #11
0
    def run_embedded(self, appdesc, app_window, params=None):
        app = self._load_app(appdesc, app_window)
        app.launcher = app_window

        self._current_app = app
        self._appname = appdesc.name

        if appdesc.name in self._blocked_apps:
            app_window.show()
            return

        app.run(params)

        # Possibly correct window position (livecd workaround for small
        # screens)
        from stoqlib.lib.pluginmanager import get_plugin_manager
        manager = get_plugin_manager()
        from stoqlib.api import api
        if (api.sysparam(api.get_default_store()).DEMO_MODE
            and manager.is_active(u'ecf')):
            pos = app.main_window.toplevel.get_position()
            if pos[0] < 220:
                app.main_window.toplevel.move(220, pos[1])

        return app
Exemple #12
0
    def _setup_widgets(self):
        self._calc = CalculatorPopup(self.price, CalculatorPopup.MODE_SUB)

        self.sale.set_text(unicode(self.model.sale.identifier))
        self.description.set_text(self.model.sellable.get_description())
        self.original_price.update(self.model.base_price)

        self.price.set_adjustment(gtk.Adjustment(lower=0, upper=MAX_INT,
                                                 step_incr=1, page_incr=10))
        unit = self.model.sellable.unit
        digits = QUANTITY_PRECISION if unit and unit.allow_fraction else 0
        for widget in [self.quantity, self.reserved]:
            widget.set_digits(digits)
            widget.set_adjustment(gtk.Adjustment(lower=0, upper=MAX_INT,
                                                 step_incr=1, page_incr=10))

        manager = get_plugin_manager()
        self.nfe_is_active = manager.is_active('nfe')

        if not self.nfe_is_active:
            self.cfop_label.hide()
            self.cfop.hide()

        if not self._can_reserve():
            self.reserved.hide()
            self.reserved_lbl.hide()

        # We populate this even if it's hidden because we need a default value
        # selected to add to the sale item
        cfop_items = CfopData.get_for_sale(self.store)
        self.cfop.prefill(api.for_combo(cfop_items))

        self._update_total()
        self.reserved.get_adjustment().set_upper(self.quantity_model.quantity)
Exemple #13
0
    def cmd_help(self, options):
        """Show available commands help"""
        cmds = []
        max_len = 0

        for attr in dir(self):
            if not attr.startswith('cmd_'):
                continue

            name = attr[4:]
            doc = getattr(self, attr).__doc__ or ''
            max_len = max(max_len, len(name))
            cmds.append((name, doc.split(r'\n')[0]))

        max_len = max_len + 2

        print('Usage: stoqdbadmin [plugin] <command> [<args>]')
        print()
        print('Available commands:')

        for name, doc in cmds:
            print('  %s%s' % (name.ljust(max_len), doc))

        self._read_config(options, load_plugins=False, register_station=False)

        from stoqlib.lib.pluginmanager import get_plugin_manager
        manager = get_plugin_manager()
        for plugin_name in manager.installed_plugins_names:
            plugin = manager.get_plugin(plugin_name)
            for command in plugin.get_dbadmin_commands():
                print('   %s %s' % (plugin_name, command))

        return 0
Exemple #14
0
    def _start_tasks(self):
        tasks = [
            Task('_backup', start_backup_scheduler),
            Task('_server', start_server),
            Task('_rtc', start_rtc),
            Task('_xmlrpc', start_xmlrpc_server, self._xmlrpc_conn2),
            Task('_updater', start_plugins_update_scheduler,
                 self._updater_event),
        ]

        manager = get_plugin_manager()
        for plugin_name in manager.installed_plugins_names:
            plugin = manager.get_plugin(plugin_name)
            if not hasattr(plugin, 'get_server_tasks'):
                continue

            # FIXME: Check that the plugin implements IPluginTask when
            # we Stoq 1.11 is released
            for plugin_task in plugin.get_server_tasks():
                task_name = plugin_task.name
                name = _get_plugin_task_name(plugin_name, task_name)
                if self._manager.is_running(name):
                    continue

                kwargs = {}
                if plugin_task.handle_actions:
                    conn1, conn2 = multiprocessing.Pipe(True)
                    self._plugins_pipes[name] = conn1
                    kwargs['pipe_connection'] = conn2

                tasks.append(Task(name, plugin_task.start, **kwargs))

        for task in tasks:
            if not self._manager.is_running(task.name):
                self._manager.run_task(task)
Exemple #15
0
    def setUp(self):
        super(TestPluginManager, self).setUp()

        # Generate 2 instances of plugins that will be used for testing later.
        # '_dependent_plugin' will require 'independent_plugin' activation prior
        # to it's own.
        self._independent_plugin = _TestPlugin()
        self._dependent_plugin = _TestDependentPlugin()

        # Since the plugins are commited inside pluginmanager, try to remove
        # it first, or we will have problems if STOQLIB_TEST_QUICK is set.
        store = new_store()
        plugins = set(InstalledPlugin.get_plugin_names(store=self.store))
        expected = set([u'ecf', u'nfe', u'optical'])
        self.assertTrue(expected.issubset(plugins))

        ind_name = self._independent_plugin.name
        dep_name = self._dependent_plugin.name
        plugin_names = [ind_name, dep_name]

        test_plugins = store.find(InstalledPlugin,
                                  InstalledPlugin.plugin_name.is_in(plugin_names))
        for plugin in test_plugins:
            store.remove(plugin)
            store.commit()
        store.close()

        self._manager = get_plugin_manager()
        self._register_test_plugin()
Exemple #16
0
    def _setup_widgets(self):
        self._calc = CalculatorPopup(self.price, CalculatorPopup.MODE_SUB)

        self.sale.set_text(str(self.model.sale.identifier))
        self.description.set_text(self.model.sellable.get_description())
        self.original_price.update(self.model.base_price)

        self.price.set_adjustment(Gtk.Adjustment(lower=0, upper=MAX_INT,
                                                 step_increment=1, page_increment=10))
        unit = self.model.sellable.unit
        digits = QUANTITY_PRECISION if unit and unit.allow_fraction else 0
        for widget in [self.quantity, self.reserved]:
            widget.set_digits(digits)
            widget.set_adjustment(Gtk.Adjustment(lower=0, upper=MAX_INT,
                                                 step_increment=1, page_increment=10))

        manager = get_plugin_manager()
        self.nfe_is_active = manager.is_any_active(['nfe', 'nfce'])

        if not self.nfe_is_active:
            self.cfop_label.hide()
            self.cfop.hide()

        if not self._can_reserve():
            self.reserved.hide()
            self.reserved_lbl.hide()

        # We populate this even if it's hidden because we need a default value
        # selected to add to the sale item
        cfop_items = CfopData.get_for_sale(self.store)
        self.cfop.prefill(api.for_combo(cfop_items))

        self._update_total()
        self.reserved.get_adjustment().set_upper(self.quantity_model.quantity)
Exemple #17
0
    def _check_online_plugins(self):
        # For each online plugin, try to download and install it.
        # Otherwise warn him
        online_plugins = InstalledPlugin.get_pre_plugin_names(self.store)
        if not online_plugins:
            return

        successes = []
        manager = get_plugin_manager()
        for plugin_name in online_plugins:
            success, msg = manager.download_plugin(plugin_name)
            successes.append(success)
            if success:
                manager.install_plugin(self.store, plugin_name)
                online_plugins.remove(plugin_name)

        if all(successes):
            return

        # Title
        title = _('You have pending plugins.')

        # Description
        url = 'https://stoq.link/?source=stoq-plugin-alert&amp;hash={}'.format(
            api.sysparam.get_string('USER_HASH'))
        desc = _(
            'The following plugins need to be enabled: <b>{}</b>.\n\n'
            'You can do it by registering on <a href="{}">Stoq.link</a>.'
        ).format(', '.join(online_plugins), url)
        msg = '<b>%s</b>\n%s' % (title, desc)
        self.add_info_bar(gtk.MESSAGE_WARNING, msg)
Exemple #18
0
    def run_command(self, options, cmd, args):
        func = getattr(self, 'cmd_' + cmd, None)
        if func is None:
            self._read_config(options, load_plugins=False,
                              register_station=False)
            from stoqlib.lib.pluginmanager import get_plugin_manager
            manager = get_plugin_manager()
            if cmd in manager.installed_plugins_names:
                if not len(args):
                    raise SystemExit(
                        "%s: %s requires at least 2 argument(s)" % (
                        self.prog_name, cmd))
                plugin = manager.get_plugin(cmd)
                return plugin.handle_dbadmin_command(args[0], options, args[1:])
            else:
                print("%s: Invalid command: `%s' type `%s help' for usage." % (
                    self.prog_name, cmd, self.prog_name))
                return 1

        nargs = func.func_code.co_argcount - 2
        if len(args) < nargs:
            raise SystemExit(
                "%s: %s requires at least %d argument(s)" % (
                self.prog_name, cmd, nargs))
        self.args = args
        return func(options, *args)
Exemple #19
0
    def checkout(self, cancel_clear=False):
        """Initiates the sale wizard to confirm sale.

        :param cancel_clear: If cancel_clear is true, the sale will be cancelled
          if the checkout is cancelled.
        """
        assert len(self.sale_items) >= 1

        if self._current_store:
            store = self._current_store
            savepoint = 'before_run_fiscalprinter_confirm'
            store.savepoint(savepoint)
        else:
            store = api.new_store()
            savepoint = None

        if self._trade:
            if self._get_subtotal() < self._trade.returned_total:
                info(
                    _("Traded value is greater than the new sale's value. "
                      "Please add more items or return it in Sales app, "
                      "then make a new sale"))
                return

            sale = self._create_sale(store)
            self._trade.new_sale = sale
            self._trade.trade()
        else:
            sale = self._create_sale(store)

        if self.param.CONFIRM_SALES_ON_TILL:
            sale.order()
            store.commit(close=True)
        else:
            assert self._coupon

            ordered = self._coupon.confirm(sale,
                                           store,
                                           savepoint,
                                           subtotal=self._get_subtotal())
            # Dont call store.confirm() here, since coupon.confirm()
            # above already did it
            if not ordered:
                # FIXME: Move to TEF plugin
                manager = get_plugin_manager()
                if manager.is_active('tef') or cancel_clear:
                    self._cancel_order(show_confirmation=False)
                elif not self._current_store:
                    # Just do that if a store was created above and
                    # if _cancel_order wasn't called (it closes the connection)
                    store.rollback(close=True)
                return

            log.info("Checking out")
            store.close()

        self._coupon = None
        POSConfirmSaleEvent.emit(sale, self.sale_items[:])
        self._clear_order()
Exemple #20
0
    def setup_widgets(self):
        marker('Setting up widgets')
        # Only quotes have expire date.
        self.expire_date.hide()
        self.expire_label.hide()

        # Hide client category widgets
        self.client_category_lbl.hide()
        self.client_category.hide()

        # if the NF-e plugin is active, the client is mandantory in this
        # wizard (in this situation, we have only quote sales).
        if self.model.status == Sale.STATUS_QUOTE:
            manager = get_plugin_manager()
            mandatory_client = manager.is_active('nfe')
            self.client.set_property('mandatory', mandatory_client)

        marker('Filling sales persons')
        salespersons = self.store.find(SalesPerson)
        self.salesperson.prefill(api.for_person_combo(salespersons))
        marker('Finished filling sales persons')

        marker('Read parameter')
        change_salesperson = sysparam.get_int('ACCEPT_CHANGE_SALESPERSON')
        if change_salesperson == ChangeSalespersonPolicy.ALLOW:
            self.salesperson.grab_focus()
        elif change_salesperson == ChangeSalespersonPolicy.DISALLOW:
            self.salesperson.set_sensitive(False)
        elif change_salesperson == ChangeSalespersonPolicy.FORCE_CHOOSE:
            self.model.salesperson = None
            self.salesperson.grab_focus()
        else:
            raise AssertionError
        marker('Finished reading parameter')
        self._setup_clients_widget()
        self._fill_transporter_combo()
        self._fill_cost_center_combo()

        if sysparam.get_bool('ASK_SALES_CFOP'):
            self._fill_cfop_combo()
        else:
            self.cfop_lbl.hide()
            self.cfop.hide()
            self.create_cfop.hide()

        # the maximum number allowed for an invoice is 999999999.
        self.invoice_number.set_adjustment(
            gtk.Adjustment(lower=1, upper=999999999, step_incr=1))

        if not self.model.invoice_number:
            new_invoice_number = Invoice.get_next_invoice_number(self.store)
            self.invoice_model.invoice_number = new_invoice_number
        else:
            new_invoice_number = self.model.invoice_number
            self.invoice_model.invoice_number = new_invoice_number
            self.invoice_number.set_sensitive(False)

        self.invoice_model.original_invoice = new_invoice_number
        marker('Finished setting up widgets')
Exemple #21
0
    def setup_widgets(self):
        marker('Setting up widgets')
        # Only quotes have expire date.
        self.expire_date.hide()
        self.expire_label.hide()

        # Hide client category widgets
        self.client_category_lbl.hide()
        self.client_category.hide()

        # if the NF-e plugin is active, the client is mandantory in this
        # wizard (in this situation, we have only quote sales).
        if self.model.status == Sale.STATUS_QUOTE:
            manager = get_plugin_manager()
            mandatory_client = manager.is_active('nfe')
            self.client.set_property('mandatory', mandatory_client)

        marker('Filling sales persons')
        salespersons = self.store.find(SalesPerson)
        self.salesperson.prefill(api.for_person_combo(salespersons))
        marker('Finished filling sales persons')

        marker('Read parameter')
        change_salesperson = sysparam.get_int('ACCEPT_CHANGE_SALESPERSON')
        if change_salesperson == ChangeSalespersonPolicy.ALLOW:
            self.salesperson.grab_focus()
        elif change_salesperson == ChangeSalespersonPolicy.DISALLOW:
            self.salesperson.set_sensitive(False)
        elif change_salesperson == ChangeSalespersonPolicy.FORCE_CHOOSE:
            self.model.salesperson = None
            self.salesperson.grab_focus()
        else:
            raise AssertionError
        marker('Finished reading parameter')
        self._setup_clients_widget()
        self._fill_transporter_combo()
        self._fill_cost_center_combo()

        if sysparam.get_bool('ASK_SALES_CFOP'):
            self._fill_cfop_combo()
        else:
            self.cfop_lbl.hide()
            self.cfop.hide()
            self.create_cfop.hide()

        # the maximum number allowed for an invoice is 999999999.
        self.invoice_number.set_adjustment(
            gtk.Adjustment(lower=1, upper=999999999, step_incr=1))

        if not self.model.invoice_number:
            new_invoice_number = Invoice.get_next_invoice_number(self.store)
            self.invoice_model.invoice_number = new_invoice_number
        else:
            new_invoice_number = self.model.invoice_number
            self.invoice_model.invoice_number = new_invoice_number
            self.invoice_number.set_sensitive(False)

        self.invoice_model.original_invoice = new_invoice_number
        marker('Finished setting up widgets')
Exemple #22
0
    def close_till(self, close_db=True, close_ecf=True):
        """Closes the till

        There are 3 possibilities for parameters combination:
          * *total close*: Both *close_db* and *close_ecf* are ``True``.
            The till on both will be closed.
          * *partial close*: Both *close_db* and *close_ecf* are ``False``.
            It's more like a till verification. The actual user will do it
            to check and maybe remove money from till, leaving it ready
            for the next one. Note that this will not emit
            'till-status-changed' event, since the till will not
            really close.
          * *fix conflicting status*: *close_db* and *close_ecf* are
            different. Use this only if you need to fix a conflicting
            status, like if the DB is open but the ECF is closed, or
            the other way around.

        :param close_db: If the till in the DB should be closed
        :param close_ecf: If the till in the ECF should be closed
        :returns: True if the till was closed, otherwise False
        """
        is_partial = not close_db and not close_ecf
        manager = get_plugin_manager()

        # This behavior is only because of ECF
        if not is_partial and not self._previous_day:
            if (manager.is_active('ecf') and
                not yesno(_("You can only close the till once per day. "
                            "You won't be able to make any more sales today.\n\n"
                            "Close the till?"),
                          Gtk.ResponseType.NO, _("Close Till"), _("Not now"))):
                return
        elif not is_partial:
            # When closing from a previous day, close only what is needed.
            close_db = self._close_db
            close_ecf = self._close_ecf

        if close_db:
            till = Till.get_last_opened(self.store)
            assert till

        store = api.new_store()
        editor_class = TillVerifyEditor if is_partial else TillClosingEditor
        model = run_dialog(editor_class, self._parent, store,
                           previous_day=self._previous_day, close_db=close_db,
                           close_ecf=close_ecf)

        if not model:
            store.confirm(model)
            store.close()
            return

        # TillClosingEditor closes the till
        retval = store.confirm(model)
        store.close()
        if retval and not is_partial:
            self._till_status_changed(closed=True, blocked=False)

        return retval
Exemple #23
0
 def _on_EditorCreateEvent(self, editor, model, store, *args):
     from stoqlib.gui.dialogs.saledetails import SaleDetailsDialog
     manager = get_plugin_manager()
     nfe_active = manager.is_active('nfe')
     if not nfe_active and isinstance(editor, SaleDetailsDialog):
         # Only display the coupon number if the nfe is not active.
         editor.invoice_label.set_text(_('Coupon Number'))
         editor.invoice_number.update(model.coupon_id)
Exemple #24
0
 def _on_EditorCreateEvent(self, editor, model, store, *args):
     from stoqlib.gui.dialogs.saledetails import SaleDetailsDialog
     manager = get_plugin_manager()
     nfe_active = manager.is_active('nfe')
     if not nfe_active and isinstance(editor, SaleDetailsDialog):
         # Only display the coupon number if the nfe is not active.
         editor.invoice_label.set_text(_('Coupon Number'))
         editor.invoice_number.update(model.coupon_id)
Exemple #25
0
    def _register_plugins(self, plugin_names):
        from stoqlib.database.runtime import new_store
        from stoqlib.lib.pluginmanager import get_plugin_manager
        manager = get_plugin_manager()

        with new_store() as store:
            for name in plugin_names:
                manager.pre_install_plugin(store, name)
Exemple #26
0
def _register_plugin(plugin_name, plugin_module=None):
    manager = get_plugin_manager()

    if not plugin_module:
        plugin_module = importlib.import_module("stoq" + plugin_name)
    plugin_dir = os.path.dirname(plugin_module.__file__)
    desc_filename = os.path.join(plugin_dir, "{}.plugin".format(plugin_name))
    manager.register_plugin_description(desc_filename)
Exemple #27
0
    def _register_plugins(self, plugin_names):
        from stoqlib.database.runtime import new_store
        from stoqlib.lib.pluginmanager import get_plugin_manager
        manager = get_plugin_manager()

        with new_store() as store:
            for name in plugin_names:
                manager.pre_install_plugin(store, name)
Exemple #28
0
 def _on_EditorCreateEvent(self, editor, model, store, *args):
     from stoqlib.gui.dialogs.saledetails import SaleDetailsDialog
     manager = get_plugin_manager()
     nfe_active = any(manager.is_active(plugin) for plugin in ['nfe', 'nfce'])
     if not nfe_active and isinstance(editor, SaleDetailsDialog):
         # Only display the coupon number if the nfe is not active.
         editor.attach_slave('coupon_number_holder',
                             CouponNumberSlave(editor.store, model))
Exemple #29
0
    def __init__(self, store, model):
        manager = get_plugin_manager()
        self.nfe_is_active = manager.is_active('nfe')
        self.proxy = None
        self.icms_slave = None
        self.ipi_slave = None

        BaseEditor.__init__(self, store, model)
Exemple #30
0
 def _on_EditorCreateEvent(self, editor, model, store, *args):
     from stoqlib.gui.dialogs.saledetails import SaleDetailsDialog
     manager = get_plugin_manager()
     nfe_active = any(manager.is_active(plugin) for plugin in ['nfe', 'nfce'])
     if not nfe_active and isinstance(editor, SaleDetailsDialog):
         # Only display the coupon number if the nfe is not active.
         editor.attach_slave('coupon_number_holder',
                             CouponNumberSlave(editor.store, model))
    def _start_tasks(self):
        tasks = [
            Task('_xmlrpc', start_xmlrpc_server, self._xmlrpc_conn2),
            # This is not working nice when using NTK lib (maybe related to the multiprocess lib).
            # Must be executed as a separate process for now.
            #Task('_flask', start_flask_server),
            Task('_updater', start_plugins_update_scheduler,
                 self._updater_event, self._doing_backup),
            Task('_backup', start_backup_scheduler, self._doing_backup),
        ]
        # TODO: Make those work on windows
        if not _is_windows:
            tasks.extend([
                Task('_htsql', start_htsql, self._htsql_port),
                Task('_server', start_server),
                Task('_rtc', start_rtc),
            ])

        manager = get_plugin_manager()
        for plugin_name in manager.installed_plugins_names:
            plugin = manager.get_plugin(plugin_name)
            if not hasattr(plugin, 'get_server_tasks'):
                continue

            # FIXME: Check that the plugin implements IPluginTask when
            # we Stoq 1.11 is released
            for plugin_task in plugin.get_server_tasks():
                task_name = plugin_task.name
                name = _get_plugin_task_name(plugin_name, task_name)
                if self._manager.is_running(name):
                    continue

                kwargs = {}
                if plugin_task.handle_actions:
                    conn1, conn2 = multiprocessing.Pipe(True)
                    self._plugins_pipes[name] = conn1
                    kwargs['pipe_connection'] = conn2

                # Since Windows has no os.fork, multiprocessing will actually
                # run the process again and pass the required objects by
                # pickling them. For some reason, passing a plugin task will
                # break some places, since the it will make some objects
                # like PluginManager be pickled/unpicled, and when unlicking
                # it will run its contructor again, but it should wait
                # to do that until we have configured the database.
                func = (plugin_name, task_name)

                tasks.append(Task(name, func, **kwargs))

        for task in tasks:
            if not self._manager.is_running(task.name):
                self._manager.run_task(task)

        # Close the default store because it not functioning anymore since the
        # forked processes closed its "clone", but open a new one later
        # or else Stoq will not be able to find this instance
        set_default_store(None)
        get_default_store()
Exemple #32
0
    def _start_tasks(self):
        tasks = [
            Task('_xmlrpc', start_xmlrpc_server, self._xmlrpc_conn2),
            # This is not working nice when using NTK lib (maybe related to the multiprocess lib).
            # Must be executed as a separate process for now.
            #Task('_flask', start_flask_server),
            Task('_updater', start_plugins_update_scheduler,
                 self._updater_event, self._doing_backup),
            Task('_backup', start_backup_scheduler, self._doing_backup),
        ]
        # TODO: Make those work on windows
        if not _is_windows:
            tasks.extend([
                Task('_htsql', start_htsql, self._htsql_port),
                Task('_server', start_server),
                Task('_rtc', start_rtc),
            ])

        manager = get_plugin_manager()
        for plugin_name in manager.installed_plugins_names:
            plugin = manager.get_plugin(plugin_name)
            if not hasattr(plugin, 'get_server_tasks'):
                continue

            # FIXME: Check that the plugin implements IPluginTask when
            # we Stoq 1.11 is released
            for plugin_task in plugin.get_server_tasks():
                task_name = plugin_task.name
                name = _get_plugin_task_name(plugin_name, task_name)
                if self._manager.is_running(name):
                    continue

                kwargs = {}
                if plugin_task.handle_actions:
                    conn1, conn2 = multiprocessing.Pipe(True)
                    self._plugins_pipes[name] = conn1
                    kwargs['pipe_connection'] = conn2

                # Since Windows has no os.fork, multiprocessing will actually
                # run the process again and pass the required objects by
                # pickling them. For some reason, passing a plugin task will
                # break some places, since the it will make some objects
                # like PluginManager be pickled/unpicled, and when unlicking
                # it will run its contructor again, but it should wait
                # to do that until we have configured the database.
                func = (plugin_name, task_name)

                tasks.append(Task(name, func, **kwargs))

        for task in tasks:
            if not self._manager.is_running(task.name):
                self._manager.run_task(task)

        # Close the default store because it not functioning anymore since the
        # forked processes closed its "clone", but open a new one later
        # or else Stoq will not be able to find this instance
        set_default_store(None)
        get_default_store()
Exemple #33
0
 def __init__(self, store):
     header = _(u'Select the plugin you want to activate and click in '
                 'the apply button.')
     BasicDialog.__init__(self, hide_footer=False,
                          size=PluginManagerDialog.size,
                          title=PluginManagerDialog.title,
                          header_text=header)
     self.store = store
     self._manager = get_plugin_manager()
     self._setup_widgets()
Exemple #34
0
 def _maybe_correct_demo_position(self, shell_window):
     # Possibly correct window position (livecd workaround for small
     # screens)
     from stoqlib.lib.parameters import sysparam
     from stoqlib.lib.pluginmanager import get_plugin_manager
     manager = get_plugin_manager()
     if (sysparam.get_bool('DEMO_MODE') and manager.is_active(u'ecf')):
         pos = shell_window.toplevel.get_position()
         if pos[0] < 220:
             shell_window.toplevel.move(220, pos[1])
Exemple #35
0
    def __init__(self, store, model):
        manager = get_plugin_manager()
        self.nfe_is_active = manager.is_any_active(['nfe', 'nfce'])
        self.proxy = None
        self.icms_slave = None
        self.ipi_slave = None
        self.pis_slave = None
        self.cofins_slave = None

        BaseEditor.__init__(self, store, model)
Exemple #36
0
 def __init__(self, store):
     header = _(u'Select the plugin you want to activate and click in '
                'the apply button.')
     BasicDialog.__init__(self,
                          hide_footer=False,
                          size=PluginManagerDialog.size,
                          title=PluginManagerDialog.title,
                          header_text=header)
     self.store = store
     self._manager = get_plugin_manager()
     self._setup_widgets()
Exemple #37
0
 def _maybe_correct_demo_position(self, shell_window):
     # Possibly correct window position (livecd workaround for small
     # screens)
     from stoqlib.lib.parameters import sysparam
     from stoqlib.lib.pluginmanager import get_plugin_manager
     manager = get_plugin_manager()
     if (sysparam.get_bool('DEMO_MODE') and
             manager.is_active(u'ecf')):
         pos = shell_window.toplevel.get_position()
         if pos[0] < 220:
             shell_window.toplevel.move(220, pos[1])
Exemple #38
0
    def setup_proxies(self):
        manager = get_plugin_manager()
        nfe_is_active = manager.is_active('nfe')
        self.invoice_number.set_property('mandatory', nfe_is_active)

        # Set an initial invoice number.
        if not self.model.invoice_number:
            new_invoice_number = Invoice.get_next_invoice_number(self.store)
            self.model.invoice_number = new_invoice_number

        self.proxy = self.add_proxy(self.model, self.proxy_widgets)
    def setup_proxies(self):
        manager = get_plugin_manager()
        nfe_is_active = manager.is_active('nfe')
        self.invoice_number.set_property('mandatory', nfe_is_active)

        # Set an initial invoice number.
        if not self.model.invoice_number:
            new_invoice_number = Invoice.get_next_invoice_number(self.store)
            self.model.invoice_number = new_invoice_number

        self.proxy = self.add_proxy(self.model, self.proxy_widgets)
    def post_init(self):
        self.hide_add_button()
        manager = get_plugin_manager()
        nfe_is_active = manager.is_active("nfe")
        if not self.wizard.create_payments and not nfe_is_active:
            self.cost_label.hide()
            self.cost.hide()
            self.cost.update(0)

        self.slave.klist.connect("cell-editing-started", self._on_klist__cell_editing_started)

        super(DecreaseItemStep, self).post_init()
Exemple #41
0
 def __init__(self, **kw):
     if not 'branch' in kw:
         kw['branch'] = get_current_branch(kw.get('store'))
     super(Invoice, self).__init__(**kw)
     # The mode and series are only set if the nfce plugin is active, since
     # the invoice_number will be also set by it.
     if get_plugin_manager().is_active('nfce'):
         mode = InvoiceGetModeEvent.emit()
         assert mode
         self.mode = mode
         # TODO Handle series number
         self.series = 1
Exemple #42
0
    def run(self):
        # FIXME: parent pid is not supported on windows. Maybe we should
        # find a way for the task to check if the parent is alive in another
        # way in this case?
        if not _is_windows:
            os.setpgrp()
            self._ppid = os.getppid()
            t = threading.Thread(target=self._check_parent_running)
            t.daemon = True
            t.start()
        else:
            from stoqserver.main import setup_stoq, setup_logging
            from stoqserver.sentry import setup_excepthook

            # Do this as soon as possible so we can log any early traceback
            setup_excepthook()

            # Allow .pyd files to be imported from egg files
            from zipextimporter import ZipExtensionImporter
            sys.path_hooks.append(ZipExtensionImporter)
            sys.path_importer_cache.clear()

            cacerts_path = os.path.join(_root, 'cacert.pem')
            requests.utils.DEFAULT_CA_BUNDLE_PATH = cacerts_path
            requests.adapters.DEFAULT_CA_BUNDLE_PATH = cacerts_path

            setup_stoq()
            setup_logging()

        if isinstance(self.func, tuple):
            # Windows
            plugin_name, task_name = self.func

            manager = get_plugin_manager()
            plugin = manager.get_plugin(plugin_name)
            for task in plugin.get_server_tasks():
                if task.name == task_name:
                    break
            else:
                raise AssertionError

            func = task.start
        else:
            func = self.func

        # Workaround a python issue where multiprocessing/threading will not
        # use the modified sys.excepthook: https://bugs.python.org/issue1230540
        try:
            func(*self._func_args, **self._func_kwargs)
        except Exception:
            sys.excepthook(*sys.exc_info())
            self._error_queue.put(self.name)
Exemple #43
0
    def post_init(self):
        self.hide_add_button()
        manager = get_plugin_manager()
        nfe_is_active = manager.is_any_active(['nfce', 'nfe'])
        if not self.wizard.create_payments and not nfe_is_active:
            self.cost_label.hide()
            self.cost.hide()
            self.cost.update(0)

        self.slave.klist.connect('cell-editing-started',
                                 self._on_klist__cell_editing_started)

        super(DecreaseItemStep, self).post_init()
Exemple #44
0
    def cmd_update_plugins(self, options):
        """Update plugins on Stoq"""
        self._read_config(options, register_station=False,
                          check_schema=False,
                          load_plugins=False)
        self._provide_app_info()
        self._setup_logging()

        from stoqlib.lib.pluginmanager import get_plugin_manager
        manager = get_plugin_manager()

        for egg_plugin in manager.egg_plugins_names:
            manager.download_plugin(egg_plugin)
Exemple #45
0
    def _uifield__cell_data_func(self, column, renderer, obj, text):
        if isinstance(renderer, Gtk.CellRendererText):
            return text

        manager = get_plugin_manager()
        if manager.is_any_active(['nfe', 'nfce']):
            is_editable = obj.field_name not in [u'street', u'district',
                                                 u'city', u'state',
                                                 u'country', u'street_number']

            renderer.set_property('sensitive', is_editable)
            renderer.set_property('activatable', is_editable)
        return text
Exemple #46
0
def _enable_plugins():
    manager = get_plugin_manager()
    for plugin in [u'ecf', u'nfe', u'optical']:
        if not manager.is_installed(plugin):
            # STOQLIB_TEST_QUICK won't let dropdb on testdb run. Just a
            # precaution to avoid trying to install it again
            manager.install_plugin(plugin)

        else:
            # Make sure that the plugin is imported so sys.path is properly
            # setup
            plugin = manager.get_plugin(plugin)
            plugin  # pylint: disable=W0104
    def run(self):
        # FIXME: parent pid is not supported on windows. Maybe we should
        # find a way for the task to check if the parent is alive in another
        # way in this case?
        if not _is_windows:
            os.setpgrp()
            self._ppid = os.getppid()
            t = threading.Thread(target=self._check_parent_running)
            t.daemon = True
            t.start()
        else:
            from stoqserver.main import (setup_stoq, setup_logging,
                                         setup_excepthook)
            # Do this as soon as possible so we can log any early traceback
            setup_excepthook()

            # Allow .pyd files to be imported from egg files
            from zipextimporter import ZipExtensionImporter
            sys.path_hooks.append(ZipExtensionImporter)
            sys.path_importer_cache.clear()

            cacerts_path = os.path.join(_root, 'cacert.pem')
            requests.utils.DEFAULT_CA_BUNDLE_PATH = cacerts_path
            requests.adapters.DEFAULT_CA_BUNDLE_PATH = cacerts_path

            setup_stoq()
            setup_logging()

        if isinstance(self.func, tuple):
            # Windows
            plugin_name, task_name = self.func

            manager = get_plugin_manager()
            plugin = manager.get_plugin(plugin_name)
            for task in plugin.get_server_tasks():
                if task.name == task_name:
                    break
            else:
                raise AssertionError

            func = task.start
        else:
            func = self.func

        # Workaround a python issue where multiprocessing/threading will not
        # use the modified sys.excepthook: https://bugs.python.org/issue1230540
        try:
            func(*self._func_args, **self._func_kwargs)
        except Exception:
            sys.excepthook(*sys.exc_info())
            self._error_queue.put(self.name)
Exemple #48
0
    def __init__(self, store, person, model=None, is_main_address=True,
                 visual_mode=False, db_form=None):
        self.person = person
        self.is_main_address = (model and model.is_main_address
                                or is_main_address)
        self.db_form = db_form
        if model is not None:
            model = store.fetch(model)
            model = _AddressModel(model, store)

        plugin = get_plugin_manager()
        self._nfe_active = plugin.is_any_active(['nfe', 'nfce'])

        BaseEditorSlave.__init__(self, store, model, visual_mode=visual_mode)
Exemple #49
0
def start_plugins_update_scheduler(event):
    _setup_signal_termination()

    if not api.sysparam.get_bool('ONLINE_SERVICES'):
        logger.info(
            "ONLINE_SERVICES not enabled. Not scheduling plugin updates...")
        return

    manager = get_plugin_manager()

    while True:
        last_check_str = UserSettings().get('last-plugins-update', None)
        last_check = (dateutil.parser.parse(last_check_str)
                      if last_check_str else datetime.datetime.min)

        # Check for updates once per day
        if last_check.date() == datetime.date.today():
            time.sleep(24 * 60 * 60)
            continue

        logger.info("Checking for plugins updates...")
        updated = False
        default_store = get_default_store()
        # TODO: atm we are only updating the conector plugin to avoid
        # problems with migrations. Let this update everything once we
        # find a solution for this problem
        for egg in default_store.find(PluginEgg, plugin_name=u'conector'):
            md5sum = egg.egg_md5sum
            manager.download_plugin(egg.plugin_name)

            # If download_plugin updated the plugin, autoreload will
            # make egg. be reloaded from the database
            if md5sum != egg.egg_md5sum:
                updated = True

        settings = UserSettings()
        settings.set('last-plugins-update',
                     datetime.datetime.now().isoformat())
        settings.flush()

        if updated:
            # Wait until any running backup is finished and restart
            while _doing_backup.value:
                time.sleep(60)

            logger.info("Some plugins were updated. Restarting now "
                        "to reflect the changes...")
            event.set()
        else:
            logger.info("No update was found...")
Exemple #50
0
    def _setup_widgets(self):
        self.confirm_date.set_sensitive(False)
        self._fill_employee_combo()
        self._fill_branch_combo()
        self._fill_cfop_combo()
        self._fill_cost_center_combo()
        self._fill_person_combo()

        manager = get_plugin_manager()
        nfe_is_active = manager.is_active('nfe')
        self.person.set_property('mandatory', nfe_is_active)

        if not sysparam.get_bool('CREATE_PAYMENTS_ON_STOCK_DECREASE'):
            self.create_payments.hide()
Exemple #51
0
    def _setup_widgets(self):
        self.confirm_date.set_sensitive(False)
        self._fill_employee_combo()
        self._fill_branch_combo()
        self._fill_cfop_combo()
        self._fill_cost_center_combo()
        self._fill_person_combo()

        manager = get_plugin_manager()
        nfe_is_active = manager.is_active('nfe')
        self.person.set_property('mandatory', nfe_is_active)

        if not sysparam.get_bool('CREATE_PAYMENTS_ON_STOCK_DECREASE'):
            self.create_payments.hide()
    def setUp(self):
        super(TestPluginManager, self).setUp()

        # Since the plugins are commited inside pluginmanager, try to remove
        # it first, or we will have problems if STOQLIB_TEST_QUICK is set.
        store = new_store()
        test_plugin = store.find(InstalledPlugin,
                                 plugin_name=_TestPlugin.name).one()
        if test_plugin:
            store.remove(test_plugin)
            store.commit()
        store.close()

        self._manager = get_plugin_manager()
        self._register_test_plugin()
Exemple #53
0
def _enable_plugins():
    manager = get_plugin_manager()
    for plugin in [u'ecf',
                   u'nfe',
                   u'optical']:
        if not manager.is_installed(plugin):
            # STOQLIB_TEST_QUICK won't let dropdb on testdb run. Just a
            # precaution to avoid trying to install it again
            manager.install_plugin(plugin)

        else:
            # Make sure that the plugin is imported so sys.path is properly
            # setup
            plugin = manager.get_plugin(plugin)
            plugin  # pylint: disable=W0104
Exemple #54
0
    def _setup_widgets(self):
        branches = Branch.get_active_remote_branches(self.store)
        self.destination_branch.prefill(api.for_person_combo(branches))
        self.source_branch.set_text(self.branch.get_description())

        employees = self.store.find(Employee)
        self.source_responsible.prefill(api.for_person_combo(employees))

        manager = get_plugin_manager()
        nfe_is_active = manager.is_active('nfe')
        self.invoice_number.set_property('mandatory', nfe_is_active)

        # Set an initial invoice number to TransferOrder and Invoice
        if not self.model.invoice_number:
            new_invoice_number = Invoice.get_next_invoice_number(self.store)
            self.model.invoice_number = new_invoice_number
    def action_install_plugin(self, plugin_name):
        manager = get_plugin_manager()
        if (plugin_name not in manager.available_plugins_names or
                plugin_name in manager.egg_plugins_names):
            rv, msg = manager.download_plugin(plugin_name)
            if not rv:
                return False, msg

        if plugin_name not in manager.installed_plugins_names:
            with api.new_store() as store:
                try:
                    manager.install_plugin(store, plugin_name)
                except PluginError as err:
                    return False, str(err)

        return True, "Plugin installed/updated sucessfully"