Beispiel #1
0
    def test_apply_discount(self, run_dialog):
        sellable = self.create_sellable(price=100, product=True)
        sellable.barcode = u'123'

        wizard = SaleQuoteWizard(self.store)

        self.click(wizard.next_button)
        step = wizard.get_current_step()
        step.barcode.set_text(u'123')
        self.activate(step.barcode)
        self.click(step.add_sellable_button)

        label = step.summary.get_value_widget()
        self.assertEqual(label.get_text(), '$100.00')

        # 10% of discount
        step.model.set_items_discount(decimal.Decimal(10))
        run_dialog.return_value = True
        self.click(step.discount_btn)
        run_dialog.assert_called_once_with(
            DiscountEditor, step.parent, step.store, step.model,
            user=api.get_current_user(step.store))
        self.assertEqual(label.get_text(), '$90.00')

        # Cancelling the dialog this time
        run_dialog.reset_mock()
        run_dialog.return_value = None
        self.click(step.discount_btn)
        run_dialog.assert_called_once_with(
            DiscountEditor, step.parent, step.store, step.model,
            user=api.get_current_user(step.store))
        self.assertEqual(label.get_text(), '$90.00')
Beispiel #2
0
 def create_model(self, store):
     return Calls(date=datetime.date.today(),
                  description=u'',
                  message=u'',
                  person=self.person,
                  attendant=api.get_current_user(self.store),
                  store=store)
Beispiel #3
0
    def on_confirm(self):
        till = self.model.till
        removed = abs(self.model.value)
        if removed:
            # We need to do this inside a new transaction, because if the
            # till closing fails further on, this still needs to be recorded
            # in the database
            store = api.new_store()
            t_till = store.fetch(till)
            TillRemoveCashEvent.emit(till=t_till, value=removed)

            reason = _('Amount removed from Till by %s') % (
                api.get_current_user(self.store).get_description(), )
            till_entry = t_till.add_debit_entry(removed, reason)

            # Financial transaction
            _create_transaction(store, till_entry)
            # DB transaction
            store.confirm(True)
            store.close()

        if self._close_ecf:
            try:
                retval = TillCloseEvent.emit(till=till,
                                             previous_day=self._previous_day)
            except (TillError, DeviceError), e:
                warning(str(e))
                return None

            # If the event was captured and its return value is False, then we
            # should not close the till.
            if retval is False:
                return False
Beispiel #4
0
    def on_ManageStock__activate(self, action):
        user = api.get_current_user(self.store)
        if not user.profile.check_app_permission(u'inventory'):
            return warning(_('Only users with access to the inventory app can'
                             ' change the stock quantity'))

        product = self.results.get_selected().product
        if product.storable and product.storable.is_batch:
            return warning(_("It's not possible to change the stock quantity of"
                             " a batch product"))

        branch = self.branch_filter.combo.get_selected()
        if not branch:
            return warning(_('You must select a branch first'))

        if (api.sysparam.get_bool('SYNCHRONIZED_MODE')
                and branch != api.get_current_branch(self.store)):
            return warning(_('You can only change the stock of your current branch'))

        with api.new_store() as store:
            self.run_dialog(ProductStockQuantityEditor, store,
                            store.fetch(product), branch=branch)

        if store.committed:
            self.refresh()
Beispiel #5
0
    def on_cost__validate(self, widget, value):
        sellable = self.proxy.model.sellable
        if not sellable:
            return

        # Dont allow numbers bigger than MAX_INT (see stoqlib.lib.defaults)
        if value > MAX_INT:
            return ValidationError(_("Price cannot be bigger than %s") % MAX_INT)

        if value <= 0:
            return ValidationError(_(u"Cost must be greater than zero."))

        if self.validate_price:
            category = getattr(self.model, "client_category", None)
            default_price = sellable.get_price_for_category(category)
            if not sysparam.get_bool("ALLOW_HIGHER_SALE_PRICE") and value > default_price:
                return ValidationError(_(u"The sell price cannot be greater " "than %s.") % default_price)

            manager = self.manager or api.get_current_user(self.store)
            client = getattr(self.model, "client", None)
            category = client and client.category
            extra_discount = self.get_extra_discount(sellable)
            valid_data = sellable.is_valid_price(value, category, manager, extra_discount=extra_discount)

            if not valid_data["is_valid"]:
                return ValidationError((_(u"Max discount for this product is %.2f%%.") % valid_data["max_discount"]))
Beispiel #6
0
    def on_cost__validate(self, widget, value):
        sellable = self.proxy.model.sellable
        if not sellable:
            return

        if value <= 0:
            return ValidationError(_(u'Cost must be greater than zero.'))

        if self.validate_price:
            category = getattr(self.model, 'client_category', None)
            default_price = sellable.get_price_for_category(category)
            if (not sysparam.get_bool('ALLOW_HIGHER_SALE_PRICE') and
                value > default_price):
                return ValidationError(_(u'The sell price cannot be greater '
                                         'than %s.') % default_price)

            manager = self.manager or api.get_current_user(self.store)
            client = getattr(self.model, 'client', None)
            category = client and client.category
            extra_discount = self.get_extra_discount(sellable)
            valid_data = sellable.is_valid_price(value, category, manager,
                                                 extra_discount=extra_discount)

            if not valid_data['is_valid']:
                return ValidationError(
                    (_(u'Max discount for this product is %.2f%%.') %
                     valid_data['max_discount']))
Beispiel #7
0
    def on_SalesCancel__activate(self, action):
        sale_view = self.results.get_selected()
        can_cancel = api.sysparam.get_bool('ALLOW_CANCEL_LAST_COUPON')
        if can_cancel and ECFIsLastSaleEvent.emit(sale_view.sale):
            info(_("That is last sale in ECF. Return using the menu "
                   "ECF - Cancel Last Document"))
            return

        store = api.new_store()
        sale = store.fetch(sale_view.sale)
        msg_text = _(u"This will cancel the sale, Are you sure?")
        model = SaleComment(store=store, sale=sale,
                            author=api.get_current_user(store))

        retval = self.run_dialog(
            NoteEditor, store, model=model, attr_name='comment',
            message_text=msg_text, label_text=_(u"Reason"),
            mandatory=True, ok_button_label=_(u"Cancel sale"),
            cancel_button_label=_(u"Don't cancel"))

        if not retval:
            store.rollback()
            return

        sale.cancel()
        store.commit(close=True)
        self.refresh()
Beispiel #8
0
    def on_price__validate(self, widget, value):
        if value <= 0:
            return ValidationError(_(u"The price must be greater than zero."))

        if (not sysparam.get_bool('ALLOW_HIGHER_SALE_PRICE') and
            value > self.model.base_price):
            return ValidationError(_(u'The sell price cannot be greater '
                                   'than %s.') % self.model.base_price)

        sellable = self.model.sellable
        manager = self.manager or api.get_current_user(self.store)

        if api.sysparam.get_bool('REUTILIZE_DISCOUNT'):
            extra_discount = self.model.sale.get_available_discount_for_items(
                user=manager, exclude_item=self.model)
        else:
            extra_discount = None

        valid_data = sellable.is_valid_price(
            value, category=self.model.sale.client_category,
            user=manager, extra_discount=extra_discount)

        if not valid_data['is_valid']:
            return ValidationError(
                (_(u'Max discount for this product is %.2f%%.') %
                 valid_data['max_discount']))
Beispiel #9
0
    def _create_receiving_order(self):
        # since we will create a new receiving order, we should confirm the
        # purchase first. Note that the purchase may already be confirmed
        if self.model.status in [PurchaseOrder.ORDER_PENDING,
                                 PurchaseOrder.ORDER_CONSIGNED]:
            self.model.confirm()

        temporary_identifier = None
        if self.wizard.is_for_another_branch():
            temporary_identifier = ReceivingOrder.get_temporary_identifier(self.store)

        receiving_invoice = ReceivingInvoice(
            store=self.store,
            supplier=self.model.supplier,
            branch=self.model.branch,
            responsible=api.get_current_user(self.store))
        receiving_model = ReceivingOrder(
            identifier=temporary_identifier,
            receiving_invoice=receiving_invoice,
            responsible=receiving_invoice.responsible,
            branch=self.model.branch,
            invoice_number=None,
            store=self.store)
        receiving_model.add_purchase(self.model)

        # Creates ReceivingOrderItem's
        for item in self.model.get_pending_items():
            receiving_model.add_purchase_item(item)

        self.wizard.receiving_model = receiving_model
Beispiel #10
0
    def test_price_validation(self):
        user = api.get_current_user(self.store)
        user.profile.max_discount = 2
        editor = self._create_editor()

        with self.sysparam(ALLOW_HIGHER_SALE_PRICE=True):
            editor.price.update(101)
            self.assertValid(editor, ['price'])
            editor.price.update(98)
            self.assertValid(editor, ['price'])
            editor.price.update(97)
            self.assertInvalid(editor, ['price'])
            editor.price.update(-1)
            self.assertInvalid(editor, ['price'])

        with self.sysparam(ALLOW_HIGHER_SALE_PRICE=False):
            editor.price.update(101)
            self.assertInvalid(editor, ['price'])
            editor.price.update(98)
            self.assertValid(editor, ['price'])
            editor.price.update(97)
            self.assertInvalid(editor, ['price'])
            editor.price.update(-1)
            self.assertInvalid(editor, ['price'])

        with self.sysparam(REUTILIZE_DISCOUNT=True):
            editor.price.update(10)
            self.assertInvalid(editor, ['price'])

        with self.sysparam(REUTILIZE_DISCOUNT=False):
            editor.price.update(10)
            self.assertInvalid(editor, ['price'])
Beispiel #11
0
    def fields(self):
        # Only users with admin or purchase permission can modify transporters
        user = api.get_current_user(self.store)
        can_modify_transporter = any((
            user.profile.check_app_permission(u'admin'),
            user.profile.check_app_permission(u'purchase'),
        ))
        freight_types = [(v, k) for k, v in Delivery.freights.items()]
        states = [(v, v) for v in api.get_l10n_field('state').state_list]

        return collections.OrderedDict(
            recipient=PersonQueryField(_("Recipient"), proxy=True, mandatory=True,
                                       person_type=self.person_type),
            transporter_id=PersonField(_("Transporter"), proxy=True,
                                       person_type=Transporter,
                                       can_add=can_modify_transporter,
                                       can_edit=can_modify_transporter),
            address=AddressField(_("Address"), proxy=True, mandatory=True),
            freight_type=ChoiceField(_("Freight type"), proxy=True,
                                     values=freight_types),
            price=PriceField(_("Delivery cost"), proxy=True),
            estimated_fix_date=DateField(_("Estimated delivery date"), proxy=True),
            volumes_kind=TextField(_("Volumes kind"), proxy=True),
            volumes_quantity=IntegerField(_("Volumes quantity"), proxy=True),
            volumes_net_weight=NumericField(_("Volumes net weight"), proxy=True,
                                            digits=3),
            volumes_gross_weight=NumericField(_("Volumes gross weight"),
                                              proxy=True, digits=3),
            vehicle_license_plate=TextField(_("Vehicle license plate"), proxy=True),
            vehicle_state=ChoiceField(_("Vehicle state"), proxy=True, use_entry=True,
                                      values=states),
            vehicle_registration=TextField(_("Vehicle registration"), proxy=True),
        )
Beispiel #12
0
 def on_ChangePassword__activate(self, action):
     from stoqlib.gui.slaves.userslave import PasswordEditor
     store = api.new_store()
     user = api.get_current_user(store)
     retval = run_dialog(PasswordEditor, self, store, user)
     store.confirm(retval)
     store.close()
    def test_show(self):
        workorder = self.create_workorder(description=u'Test equipment')
        workorder.client = self.create_client()
        workorder.client.category = self.create_client_category()

        product = self.create_product(stock=10)
        sellable = product.sellable
        storable = product.storable

        item = workorder.add_sellable(sellable)
        editor = _WorkOrderItemEditor(self.store, model=item)
        self.check_editor(editor, 'editor-workorderitem-show')

        self.assertValid(editor, ['price'])
        editor.price.update(0)
        self.assertInvalid(editor, ['price'])
        editor.price.update(-1)
        self.assertInvalid(editor, ['price'])
        with mock.patch.object(sellable, 'is_valid_price') as ivp:
            ivp.return_value = {
                'is_valid': False,
                'min_price': decimal.Decimal('10.00'),
                'max_discount': decimal.Decimal('0.00'),
            }
            editor.price.update(1)
            ivp.assert_called_once_with(1, workorder.client.category,
                                        api.get_current_user(self.store))
            self.assertInvalid(editor, ['price'])

        self.assertValid(editor, ['quantity'])
        with mock.patch.object(storable, 'get_balance_for_branch') as gbfb:
            gbfb.return_value = 0
            editor.quantity.update(20)
            gbfb.assert_called_once_with(workorder.branch)
            self.assertInvalid(editor, ['quantity'])
Beispiel #14
0
    def get_columns(self):
        columns = [SearchColumn('code', title=_(u'Code'), data_type=str),
                   SearchColumn('barcode', title=_('Barcode'), data_type=str,
                                sort_func=sort_sellable_code, width=80),
                   SearchColumn('category_description', title=_('Category'),
                                data_type=str, width=120),
                   SearchColumn('description', title=_('Description'),
                                data_type=str, expand=True, sorted=True),
                   SearchColumn('location', title=_('Location'),
                                data_type=str, visible=False),
                   SearchColumn('manufacturer', title=_('Manufacturer'),
                                data_type=str, visible=False),
                   SearchColumn('model', title=_('Model'),
                                data_type=str, visible=False)]

        user = api.get_current_user(self.store)
        if user.profile.check_app_permission('purchase'):
            columns.append(SearchColumn('cost',
                                        title=_(u'Cost'),
                                        data_type=currency, visible=True))

        if hasattr(self.search_spec, 'price'):
            columns.append(SearchColumn('price',
                                        title=_(u'Price'),
                                        data_type=currency, visible=True))

        if hasattr(self.search_spec, 'minimum_quantity'):
            columns.append(SearchColumn('minimum_quantity',
                                        title=_(u'Minimum Qty'),
                                        data_type=Decimal, visible=False))

        if hasattr(self.search_spec, 'stock'):
            columns.append(QuantityColumn('stock', title=_(u'In Stock')))

        return columns
Beispiel #15
0
    def _create_receiving_order(self):
        supplier_id = self.purchases[0].supplier_id
        branch_id = self.purchases[0].branch_id

        # If the receiving is for another branch, we need a temporary identifier
        temporary_identifier = None
        if (api.sysparam.get_bool('SYNCHRONIZED_MODE') and
                api.get_current_branch(self.store).id != branch_id):
            temporary_identifier = ReceivingOrder.get_temporary_identifier(self.store)

        # We cannot create the model in the wizard since we haven't
        # selected a PurchaseOrder yet which ReceivingOrder depends on
        # Create the order here since this is the first place where we
        # actually have a purchase selected
        receiving_invoice = ReceivingInvoice(
            supplier=supplier_id, store=self.store, branch=branch_id,
            responsible=api.get_current_user(self.store))
        self.wizard.model = self.model = ReceivingOrder(
            identifier=temporary_identifier,
            receiving_invoice=receiving_invoice,
            responsible=receiving_invoice.responsible,
            invoice_number=None, branch=branch_id, store=self.store)

        for row in self.purchases:
            self.model.add_purchase(row.purchase)
Beispiel #16
0
    def __init__(self, resource, manager, compact=False):
        self._resource = resource
        self._compact = compact
        self._manager = manager
        user = api.get_current_user(api.get_default_store())
        self._is_admin = user.profile.check_app_permission(u'admin')

        super(ResourceStatusBox, self).__init__(spacing=6)
        if compact:
            self.props.margin = 6
        else:
            self.props.margin = 12

        self.img = Gtk.Image()
        self.pack_start(self.img, False, True, 0)
        self.lbl = Gtk.Label()
        self.lbl.set_xalign(0)
        self.lbl.set_line_wrap(True)
        self.pack_start(self.lbl, False, True, 0)

        self.buttonbox = Gtk.Box()
        self.buttonbox.set_valign(Gtk.Align.CENTER)
        self.buttonbox.get_style_context().add_class('linked')
        if not compact:
            self.pack_end(self.buttonbox, False, True, 0)
Beispiel #17
0
    def finish(self):
        for payment in self.model.group.payments:
            if payment.is_preview():
                # Set payments created on SaleReturnPaymentStep as pending
                payment.set_pending()

        total_amount = self.model.total_amount
        # If the user chose to create credit for the client instead of returning
        # money, there is no need to display this messages.
        if not self.credit:
            if total_amount == 0:
                info(_("The client does not have a debt to this sale anymore. "
                       "Any existing unpaid installment will be cancelled."))
            elif total_amount < 0:
                info(_("A reversal payment to the client will be created. "
                       "You can see it on the Payable Application."))

        login_user = api.get_current_user(self.store)
        self.model.return_(method_name=u'credit' if self.credit else u'money',
                           login_user=login_user)
        SaleReturnWizardFinishEvent.emit(self.model)
        self.retval = self.model
        self.close()

        # Commit before printing to avoid losing data if something breaks
        self.store.confirm(self.retval)
        if self.credit:
            if yesno(_(u'Would you like to print the credit letter?'),
                     gtk.RESPONSE_YES, _(u"Print Letter"), _(u"Don't print")):
                print_report(ClientCreditReport, self.model.client)
Beispiel #18
0
    def _check_client_birthdays(self):
        if not api.sysparam.get_bool('BIRTHDAY_NOTIFICATION'):
            return

        # Display the info bar once per day
        date = api.user_settings.get('last-birthday-check')
        last_check = date and datetime.datetime.strptime(date, '%Y-%m-%d').date()
        if last_check and last_check >= datetime.date.today():
            return

        # Only display the infobar if the user has access to calendar (because
        # clicking on the button will open it) and to sales (because it
        # requires that permission to be able to check client details)
        user = api.get_current_user(self.store)
        if not all([user.profile.check_app_permission(u'calendar'),
                    user.profile.check_app_permission(u'sales')]):
            return

        branch = api.get_current_branch(self.store)
        clients_count = ClientWithSalesView.find_by_birth_date(
            self.store, datetime.datetime.today(), branch=branch).count()

        if clients_count:
            msg = stoqlib_ngettext(
                _("There is %s client doing birthday today!"),
                _("There are %s clients doing birthday today!"),
                clients_count) % (clients_count, )
            button = gtk.Button(_("Check the calendar"))
            button.connect('clicked', self._on_check_calendar__clicked)

            self._birthdays_bar = self.add_info_bar(
                gtk.MESSAGE_INFO,
                "<b>%s</b>" % (glib.markup_escape_text(msg), ),
                action_widget=button)
Beispiel #19
0
    def create_actions(self):
        group = get_accels('app.financial')
        actions = [
            ('Import', Gtk.STOCK_ADD, _('Import...'),
             group.get('import'), _('Import a GnuCash or OFX file')),
            ('ConfigurePaymentMethods', None,
             _('Payment methods'),
             group.get('configure_payment_methods'),
             _('Select accounts for the payment methods on the system')),
            ('Delete', None, _('Delete...')),
            ("NewAccount", Gtk.STOCK_NEW, _("Account..."),
             group.get('new_account'),
             _("Add a new account")),
            ("NewTransaction", Gtk.STOCK_NEW, _("Transaction..."),
             group.get('new_store'),
             _("Add a new transaction")),
            ("Edit", Gtk.STOCK_EDIT, _("Edit..."),
             group.get('edit')),
        ]
        self.financial_ui = self.add_ui_actions(actions)
        self.set_help_section(_("Financial help"), 'app-financial')

        user = api.get_current_user(self.store)
        if not user.profile.check_app_permission(u'admin'):
            self.set_sensitive([self.ConfigurePaymentMethods], False)
Beispiel #20
0
    def on_SalesCancel__activate(self, action):
        sale_view = self.results.get_selected()
        can_cancel = api.sysparam.get_bool('ALLOW_CANCEL_LAST_COUPON')
        # A plugin (e.g. ECF) can avoid the cancelation of a sale
        # because it wants it to be cancelled using another way
        if can_cancel and SaleAvoidCancelEvent.emit(sale_view.sale):
            return

        store = api.new_store()
        sale = store.fetch(sale_view.sale)
        msg_text = _(u"This will cancel the sale, Are you sure?")
        model = SaleComment(store=store, sale=sale,
                            author=api.get_current_user(store))

        retval = self.run_dialog(
            NoteEditor, store, model=model, attr_name='comment',
            message_text=msg_text, label_text=_(u"Reason"),
            mandatory=True, ok_button_label=_(u"Cancel sale"),
            cancel_button_label=_(u"Don't cancel"))

        if not retval:
            store.rollback()
            return

        sale.cancel()
        store.commit(close=True)
        self.refresh()
    def test_create(self, set_message):
        sellable = self.create_sellable()
        self.create_storable(product=sellable.product)
        sale_item = TemporarySaleItem(sellable=sellable, quantity=1)

        user = api.get_current_user(self.store)
        with mock.patch.object(user.profile, 'check_app_permission') as has_acess:
            has_acess.side_effect = [False]
            search = SaleSellableSearch(self.store,
                                        sale_items=[sale_item], quantity=1)

            self.assertRaises(TypeError, SaleSellableSearch, self.store,
                              sale_items=[sale_item],
                              selection_mode=Gtk.SelectionMode.MULTIPLE)
            self.assertRaises(TypeError, SaleSellableSearch, self.store,
                              sale_items=[sale_item], quantity=None)

            search = SaleSellableSearch(self.store)
            search.search.refresh()
            self.check_search(search, 'sale-sellable-no-filter')

            search = SaleSellableSearch(self.store, info_message='test')
            set_message.assert_called_once_with('test')

            search = SaleSellableSearch(self.store, search_str='cal')
            self.check_search(search, 'sale-sellable-string-filter')
Beispiel #22
0
 def search_products(self):
     with api.new_store() as store:
         profile = api.get_current_user(store).profile
         can_create = (profile.check_app_permission('admin') or
                       profile.check_app_permission('purchase'))
         run_dialog(ProductSearch, None, store, hide_footer=True, hide_toolbar=not can_create,
                    hide_cost_column=not can_create)
 def _create_model(self, store):
     user = api.get_current_user(store)
     source_responsible = store.find(Employee, person=user.person).one()
     return TransferOrder(
         source_branch=api.get_current_branch(store),
         source_responsible=source_responsible,
         destination_branch=Branch.get_active_remote_branches(store)[0],
         store=store)
Beispiel #24
0
 def _create_model(self, store):
     loan = Loan(responsible=api.get_current_user(store),
                 branch=api.get_current_branch(store),
                 store=store)
     # Temporarily save the client_category, so it works fine with
     # SaleQuoteItemStep
     loan.client_category = None
     return loan
 def create_model(self, store):
     return CreditCheckHistory(check_date=localtoday().date(),
                               identifier=u'',
                               status=CreditCheckHistory.STATUS_NOT_INCLUDED,
                               client=self._client,
                               notes=u'',
                               user=api.get_current_user(self.store),
                               store=store)
Beispiel #26
0
 def create_model(self, store):
     # TODO: Add a parameter for getting a default destination branch
     return WorkOrderPackage(
         store=store,
         identifier=u"",
         send_responsible=api.get_current_user(store),
         source_branch=api.get_current_branch(store),
     )
Beispiel #27
0
 def on_receive_button__clicked(self, event):
     if yesno(_(u'Receive pending returned sale?'), gtk.RESPONSE_NO,
              _(u'Receive'), _(u"Don't receive")):
         current_user = api.get_current_user(self.store)
         self.model.returned_sale.confirm(current_user)
         SaleReturnWizardFinishEvent.emit(self.model.returned_sale)
         self.store.commit(close=False)
         self._setup_status()
 def __init__(self, store):
     self.open_date = localnow()
     self.branch = api.get_current_branch(store)
     self.branch_name = self.branch.get_description()
     self.user = api.get_current_user(store)
     self.product_manufacturer = None
     self.product_brand = None
     self.product_family = None
Beispiel #29
0
    def test_apply_discount(self, run_dialog, run_person_role_dialog):
        client = self.create_client()
        self.create_address(person=client.person)
        run_person_role_dialog.return_value = client

        sellable = self.create_sellable(price=100, product=True)
        sellable.barcode = u'123'

        wizard = OpticalSaleQuoteWizard(self.store)

        step = wizard.get_current_step()
        self.click(step.create_client)
        self.click(wizard.next_button)

        step = wizard.get_current_step()
        slave = step.slaves['WO 1']
        slave.patient.update('Patient')
        slave.estimated_finish.update(localdate(2020, 1, 5))
        self.click(wizard.next_button)

        step = wizard.get_current_step()
        step.item_slave.barcode.set_text(u'123')
        self.activate(step.item_slave.barcode)
        self.click(step.item_slave.add_sellable_button)

        label = step.item_slave.summary.get_value_widget()
        self.assertEqual(label.get_text(), '$100.00')

        # 10% of discount
        step.model.set_items_discount(decimal.Decimal(10))
        run_dialog.return_value = True
        self.click(step.item_slave.discount_btn)
        run_dialog.assert_called_once_with(
            DiscountEditor, step.item_slave.parent, step.item_slave.store,
            step.item_slave.model, user=api.get_current_user(step.store))
        self.assertEqual(label.get_text(), '$90.00')

        # Cancelling the dialog this time
        run_dialog.reset_mock()
        run_dialog.return_value = None
        self.click(step.item_slave.discount_btn)
        run_dialog.assert_called_once_with(
            DiscountEditor, step.item_slave.parent, step.item_slave.store,
            step.item_slave.model, user=api.get_current_user(step.store))
        self.assertEqual(label.get_text(), '$90.00')
Beispiel #30
0
    def on_RemoveSettingsCache__activate(self, action):
        keys = ["app-ui", "launcher-geometry"]
        keys.append("search-columns-%s" % (api.get_current_user(api.get_default_store()).username,))

        for key in keys:
            try:
                api.user_settings.remove(key)
            except KeyError:
                pass
Beispiel #31
0
    def create_actions(self):
        group = get_accels('app.calendar')
        actions = [
            # File
            ('NewClientCall', None, _("Client call"),
             group.get('new_client_call'), _("Add a new client call")),
            ('NewPayable', None, _("Account payable"),
             group.get('new_payable'), _("Add a new account payable")),
            ('NewReceivable', None, _("Account receivable"),
             group.get('new_receivable'), _("Add a new account receivable")),
            ('NewWorkOrder', None, _("Work order"),
             group.get('new_work_order'), _("Add a new work order")),
            # View
            ('Back', gtk.STOCK_GO_BACK, _("Back"), group.get('go_back'),
             _("Go back")),
            ('Forward', gtk.STOCK_GO_FORWARD, _("Forward"),
             group.get('go_forward'), _("Go forward")),
            ('Today', STOQ_CALENDAR_TODAY, _("Show today"),
             group.get('show_today'), _("Show today")),
            ('CalendarEvents', None, _("Calendar events")),
            ('CurrentView', None, _("Display view as")),
        ]
        self.calendar_ui = self.add_ui_actions('',
                                               actions,
                                               filename='calendar.xml')
        self.set_help_section(_("Calendar help"), 'app-calendar')

        toggle_actions = [
            ('AccountsPayableEvents', None, _("Accounts payable"), None,
             _("Show accounts payable in the list")),
            ('AccountsReceivableEvents', None, _("Accounts receivable"), None,
             _("Show accounts receivable in the list")),
            ('PurchaseEvents', None, _("Purchases"), None,
             _("Show purchases in the list")),
            ('ClientCallEvents', None, _("Client Calls"), None,
             _("Show client calls in the list")),
            ('ClientBirthdaysEvents', None, _("Client Birthdays"), None,
             _("Show client birthdays in the list")),
            ('WorkOrderEvents', None, _("Work orders"), None,
             _("Show work orders in the list")),
        ]
        self.add_ui_actions('', toggle_actions, 'ToggleActions', 'toggle')

        events_info = dict(
            in_payments=(self.AccountsReceivableEvents, self.NewReceivable,
                         u'receivable'),
            out_payments=(self.AccountsPayableEvents, self.NewPayable,
                          u'payable'),
            purchase_orders=(self.PurchaseEvents, None, u'stock'),
            client_calls=(self.ClientCallEvents, self.NewClientCall, u'sales'),
            client_birthdays=(self.ClientBirthdaysEvents, None, u'sales'),
            work_orders=(self.WorkOrderEvents, self.NewWorkOrder, u'services'),
        )

        user = api.get_current_user(self.store)
        events = self._calendar.get_events()
        for event_name, value in events_info.items():
            view_action, new_action, app = value
            view_action.props.active = events[event_name]
            # Disable feature if user does not have acces to required
            # application
            if not user.profile.check_app_permission(app):
                view_action.props.active = False
                view_action.set_sensitive(False)
                if new_action:
                    new_action.set_sensitive(False)

            view_action.connect('notify::active', self._update_events)
        self._update_events()

        radio_actions = [
            ('ViewMonth', STOQ_CALENDAR_MONTH, _("View as month"), '',
             _("Show one month")),
            ('ViewWeek', STOQ_CALENDAR_WEEK, _("View as week"), '',
             _("Show one week")),
            ('ViewDay', STOQ_CALENDAR_LIST, _("View as day"), '',
             _("Show one day")),
        ]
        self.add_ui_actions('', radio_actions, 'RadioActions', 'radio')
        self.ViewMonth.set_short_label(_("Month"))
        self.ViewWeek.set_short_label(_("Week"))
        self.ViewDay.set_short_label(_("Day"))
        self.ViewMonth.props.is_important = True
        self.ViewWeek.props.is_important = True
        self.ViewDay.props.is_important = True

        view = api.user_settings.get('calendar-view', 'month')
        if view == 'month':
            self.ViewMonth.props.active = True
        elif view == 'basicWeek':
            self.ViewWeek.props.active = True
        else:
            self.ViewDay.props.active = True
Beispiel #32
0
 def create_model(self, store):
     return OpticalPatientVisualAcuity(client_id=self._client.id, store=store,
                                       responsible=api.get_current_user(store))
Beispiel #33
0
 def create_model(self, store):
     return OpticalPatientHistory(store=store, client_id=self._client.id,
                                  responsible=api.get_current_user(store))
 def finish(self):
     self.model.receive_responsible = get_current_user(self.store)
     self.model.receive(api.get_current_user(self.store))
     self.retval = self.model
     self.close()
Beispiel #35
0
 def on_confirm(self):
     if self.model.salary != self._original_salary:
         ClientSalaryHistory.add(self.store, self._original_salary,
                                 self.model, api.get_current_user(self.store))
Beispiel #36
0
 def _needs_password_confirmation(self):
     current_user = api.get_current_user(self.store)
     return not current_user.profile.check_app_permission(u'admin')
Beispiel #37
0
 def create_model(self, store):
     # TODO: Add a parameter for getting a default destination branch
     return WorkOrderPackage(store=store,
                             identifier=u'',
                             send_responsible=api.get_current_user(store),
                             source_branch=api.get_current_branch(store))
Beispiel #38
0
    def _create_headerbar(self):
        # User/help menu
        user = api.get_current_user(self.store)
        xml = MENU_XML.format(username=api.escape(user.get_description()),
                              preferences=_('Preferences...'),
                              password=_('Change password...'),
                              signout=_('Sign out...'),
                              help=_('Help'),
                              contents=_('Contents'),
                              translate=_('Translate Stoq...'),
                              get_support=_('Get support online...'),
                              chat=_('Online chat...'),
                              about=_('About'),
                              quit=_('Quit'))
        builder = Gtk.Builder.new_from_string(xml, -1)

        # Header bar
        self.header_bar = Gtk.HeaderBar()
        self.toplevel.set_titlebar(self.header_bar)

        # Right side
        self.close_btn = self.create_button('fa-power-off-symbolic',
                                            action='stoq.quit')
        self.close_btn.set_relief(Gtk.ReliefStyle.NONE)
        self.min_btn = self.create_button('fa-window-minimize-symbolic')
        self.min_btn.set_relief(Gtk.ReliefStyle.NONE)
        #self.header_bar.pack_end(self.close_btn)
        #self.header_bar.pack_end(self.min_btn)
        box = Gtk.Box.new(orientation=Gtk.Orientation.HORIZONTAL, spacing=0)
        box.pack_start(self.min_btn, False, False, 0)
        box.pack_start(self.close_btn, False, False, 0)
        self.header_bar.pack_end(box)

        self.user_menu = builder.get_object('app-menu')
        self.help_section = builder.get_object('help-section')
        self.user_button = self.create_button('fa-cog-symbolic',
                                              menu_model=self.user_menu)
        self.search_menu = Gio.Menu()
        self.search_button = self.create_button('fa-search-symbolic',
                                                _('Searches'),
                                                menu_model=self.search_menu)
        self.main_menu = Gio.Menu()
        self.menu_button = self.create_button('fa-bars-symbolic',
                                              _('Actions'),
                                              menu_model=self.main_menu)

        self.header_bar.pack_end(
            ButtonGroup(
                [self.menu_button, self.search_button, self.user_button]))

        self.sign_button = self.create_button('',
                                              _('Sign now'),
                                              style_class='suggested-action')
        #self.header_bar.pack_end(self.sign_button)

        # Left side
        self.home_button = self.create_button(STOQ_LAUNCHER,
                                              style_class='suggested-action')
        self.new_menu = Gio.Menu()
        self.new_button = self.create_button('fa-plus-symbolic',
                                             _('New'),
                                             menu_model=self.new_menu)

        self.header_bar.pack_start(
            ButtonGroup([
                self.home_button,
                self.new_button,
            ]))

        self.domain_header = None
        self.header_bar.show_all()

        self.notifications = NotificationCounter(self.home_button, blink=True)
 def on_confirm(self):
     self.model.adjust(api.get_current_user(self.store), self._invoice_number)
Beispiel #40
0
    def create_actions(self):
        group = get_accels('app.calendar')
        actions = [
            # File
            ('NewClientCall', None, _("Client call"),
             group.get('new_client_call'), _("Add a new client call")),
            ('NewPayable', None, _("Account payable"),
             group.get('new_payable'), _("Add a new account payable")),
            ('NewReceivable', None, _("Account receivable"),
             group.get('new_receivable'), _("Add a new account receivable")),
            ('NewWorkOrder', None, _("Work order"),
             group.get('new_work_order'), _("Add a new work order")),
            # View
            ('Back', Gtk.STOCK_GO_BACK, _("Back"),
             group.get('go_back'), _("Go back")),
            ('Forward', Gtk.STOCK_GO_FORWARD, _("Forward"),
             group.get('go_forward'), _("Go forward")),
            ('Today', None, _("Show today"),
             group.get('show_today'), _("Show today")),
        ]
        self.calendar_ui = self.add_ui_actions(actions)
        self.set_help_section(_("Calendar help"), 'app-calendar')

        toggle_actions = [
            ('AccountsPayableEvents', None, _("Accounts payable"),
             None, _("Show accounts payable in the list")),
            ('AccountsReceivableEvents', None, _("Accounts receivable"),
             None, _("Show accounts receivable in the list")),
            ('PurchaseEvents', None, _("Purchases"),
             None, _("Show purchases in the list")),
            ('ClientCallEvents', None, _("Client Calls"),
             None, _("Show client calls in the list")),
            ('ClientBirthdaysEvents', None, _("Client Birthdays"),
             None, _("Show client birthdays in the list")),
            ('WorkOrderEvents', None, _("Work orders"),
             None, _("Show work orders in the list")),
        ]
        self.add_ui_actions(toggle_actions, 'ToggleActions')

        events_info = dict(
            in_payments=(self.AccountsReceivableEvents, self.NewReceivable,
                         u'receivable'),
            out_payments=(self.AccountsPayableEvents, self.NewPayable,
                          u'payable'),
            purchase_orders=(self.PurchaseEvents, None, u'stock'),
            client_calls=(self.ClientCallEvents, self.NewClientCall, u'sales'),
            client_birthdays=(self.ClientBirthdaysEvents, None, u'sales'),
            work_orders=(self.WorkOrderEvents, self.NewWorkOrder, u'services'),
        )

        user = api.get_current_user(self.store)
        events = self._calendar.get_events()
        for event_name, value in events_info.items():
            view_action, new_action, app = value
            view_action.set_state(GLib.Variant.new_boolean(events[event_name]))

            # Disable feature if user does not have acces to required
            # application
            if not user.profile.check_app_permission(app):
                view_action.set_state(GLib.Variant.new_boolean(False))
                self.set_sensitive([view_action], False)
                if new_action:
                    self.set_sensitive([new_action], False)

            view_action.connect('change-state', self._view_option_state_changed)
        self._update_events()