def test_create(self):
        storable = self.create_storable(is_batch=True)
        batch = self.create_storable_batch(storable=storable,
                                           batch_number=u'1')
        batch.create_date = datetime.date(2010, 10, 10)
        batch = self.create_storable_batch(storable=storable,
                                           batch_number=u'2')
        batch.create_date = datetime.date(2011, 11, 11)
        batch = self.create_storable_batch(storable=storable,
                                           batch_number=u'3')
        batch.create_date = datetime.date(2012, 12, 12)

        storable.register_initial_stock(10, api.get_current_branch(self.store),
                                        1, u'1')
        storable.register_initial_stock(15, api.get_current_branch(self.store),
                                        1, u'2')
        storable.register_initial_stock(8, api.get_current_branch(self.store),
                                        1, u'3')

        dialog = BatchSelectionDialog(self.store, storable, 33)
        for entry in dialog._spins.keys():
            entry.update(1)
            dialog._spins[entry].update(12)

        for entry in dialog._spins.keys()[1:]:
            entry.update(2)
            dialog._spins[entry].update(7)

        for entry in dialog._spins.keys()[2:]:
            entry.update(3)
            dialog._spins[entry].update(8)

        dialog.existing_batches_expander.set_expanded(True)

        self.check_dialog(dialog, 'dialog-batch-selection-dialog-create')
    def test_auto_reserve(self, yesno):
        # Data setup
        client = self.create_client()
        medic = self.create_optical_medic(crm_number=u'999')

        auto = self.create_storable(
            branch=api.get_current_branch(self.store),
            stock=10)
        auto.product.sellable.barcode = u'auto_reserve'
        OpticalProduct(store=self.store, product=auto.product,
                       auto_reserve=True)

        not_auto = self.create_storable(
            branch=api.get_current_branch(self.store),
            stock=10)
        not_auto.product.sellable.barcode = u'not_auto_reserve'
        OpticalProduct(store=self.store, product=not_auto.product,
                       auto_reserve=False)

        wizard = OpticalSaleQuoteWizard(self.store)
        # First step: Client
        step = wizard.get_current_step()
        step.client_gadget.set_value(client)
        self.click(wizard.next_button)

        # Second Step: optical data
        step = wizard.get_current_step()
        slave = step.slaves['WO 1']
        slave.patient.update('Patient')
        slave.medic_gadget.set_value(medic)
        slave.estimated_finish.update(localdate(2020, 1, 5))

        # Third Step: Products
        self.click(wizard.next_button)
        step = wizard.get_current_step()

        # Add two items: One auto reserved and another not. Both with initially
        # 10 items on stock
        for barcode in ['auto_reserve', 'not_auto_reserve']:
            step.barcode.set_text(barcode)
            self.activate(step.barcode)
            step.quantity.update(5)
            self.click(step.add_sellable_button)

        # Finish the wizard
        yesno.return_value = False
        with mock.patch.object(self.store, 'commit'):
            self.click(wizard.next_button)

        # Now check the stock for the two items. The auto reverd should have the
        # stock decreased to 5. The one that not auto reserves should still be
        # at 10
        self.assertEqual(auto.get_total_balance(), 5)
        self.assertEqual(not_auto.get_total_balance(), 10)
    def test_get(self):
        with self.sysparam(DEMO_MODE=True):
            with self.fake_store():
                api.get_current_branch(self.store)
                s = self.login()

                sellable = self.create_sellable()
                img = self.create_image()
                img.image = b'foobar'
                img.sellable_id = sellable.id

                rv = self.client.get('/image/' + sellable.id, headers={'stoq-session': s})
                self.assertEqual(rv.status_code, 200)
                self.assertEqual(rv.data, b'foobar')
Exemple #4
0
    def _check_user(self, username, password):
        username = unicode(username)
        password = unicode(password)
        # This function is really just a post-validation item.
        default_store = api.get_default_store()
        user = default_store.find(LoginUser, username=username).one()
        if not user:
            raise LoginError(_("Invalid user or password"))

        if not user.is_active:
            raise LoginError(_('This user is inactive'))

        branch = api.get_current_branch(default_store)
        # current_branch may not be set if we are registering a new station
        if branch and not user.has_access_to(branch):
            raise LoginError(_('This user does not have access to this branch'))

        if user.pw_hash != password:
            raise LoginError(_("Invalid user or password"))

        # Dont know why, but some users have this empty. Prevent user from
        # login in, since it will break later
        if not user.profile:
            msg = (_("User '%s' has no profile set, "
                     "but this should not happen.") % user.username + '\n\n' +
                   _("Please contact your system administrator or Stoq team."))
            warning(msg)
            raise LoginError(_("User does not have a profile"))

        user.login()

        # ICurrentUser might already be provided which is the case when
        # creating a new database, thus we need to replace it.
        provide_utility(ICurrentUser, user, replace=True)
        return user
    def _get_next_batch_number(self):
        max_db = StorableBatch.get_max_value(self.store,
                                             StorableBatch.batch_number)
        max_used = max_value_for(self._get_used_batches() | set([max_db]))
        if not api.sysparam.get_bool('SYNCHRONIZED_MODE'):
            return next_value_for(max_used)

        # On synchronized mode we need to append the branch acronym
        # to avoid conflicts
        max_used_list = max_used.split('-')
        if len(max_used_list) == 1:
            # '123'
            max_used = max_used_list[0]
        elif len(max_used_list) == 2:
            # '123-AB'
            max_used = max_used_list[0]
        else:
            # '123-456-AB'
            max_used = ''.join(max_used_list[:-1])

        branch = api.get_current_branch(self.store)
        if not branch.acronym:
            raise ValueError("branch '%s' needs an acronym since we are on "
                             "synchronized mode" % (branch.get_description(),))
        return '-'.join([next_value_for(max_used), branch.acronym])
 def __init__(self, store):
     self.model = None
     self.sync_mode = api.sysparam.get_bool('SYNCHRONIZED_MODE')
     self.current_branch = api.get_current_branch(store)
     first_step = ReceivingSelectionStep(self, store)
     BaseWizard.__init__(self, store, first_step, self.model)
     self.next_button.set_sensitive(False)
Exemple #7
0
    def _check_user(self, username, pw_hash):
        username = unicode(username)
        pw_hash = unicode(pw_hash)
        # This function is really just a post-validation item.
        default_store = api.get_default_store()
        current_branch = api.get_current_branch(default_store)

        user = LoginUser.authenticate(default_store, username, pw_hash,
                                      current_branch)

        # Dont know why, but some users have this empty. Prevent user from
        # login in, since it will break later
        if not user.profile:
            msg = (_("User '%s' has no profile set, "
                     "but this should not happen.") % user.username + '\n\n' +
                   _("Please contact your system administrator or Stoq team."))
            warning(msg)
            raise LoginError(_("User does not have a profile"))

        user.login()

        # ICurrentUser might already be provided which is the case when
        # creating a new database, thus we need to replace it.
        provide_utility(ICurrentUser, user, replace=True)
        return user
Exemple #8
0
 def get_sellable_view_query(self):
     branch = api.get_current_branch(self.store)
     branch_query = Or(Field('_stock_summary', 'branch_id') == branch.id,
                       Eq(Field('_stock_summary', 'branch_id'), None))
     query = And(branch_query,
                 Sellable.get_available_sellables_query(self.store))
     return self.sellable_view, query
    def test_batch_number_suggestion_synchronized_mode(self):
        branch = api.get_current_branch(self.store)
        branch.acronym = u'AB'

        storable = self.create_storable(is_batch=True)
        storable2 = self.create_storable(is_batch=True)

        dialog = BatchIncreaseSelectionDialog(self.store, storable, 10)
        self.assertEqual(dialog._last_entry.get_text(), '')

        with self.sysparam(SUGGEST_BATCH_NUMBER=True, SYNCHRONIZED_MODE=True):
            storable.register_initial_stock(1, self.create_branch(), 0,
                                            batch_number=u'130')
            dialog = BatchIncreaseSelectionDialog(self.store, storable, 10)
            # Make sure it suggested right
            self.assertEqual(dialog._last_entry.get_text(), '131-AB')

            spinbutton = dialog.get_spin_by_entry(dialog._last_entry)
            spinbutton.update(5)
            # Updating the spinbutton should append a new entry with the suggestion
            self.assertEqual(dialog._last_entry.get_text(), '132-AB')
            self.click(dialog.main_dialog.ok_button)

            dialog = BatchIncreaseSelectionDialog(self.store, storable2, 10)
            # Since the dialog above was confirmed on the same store this one is,
            # it should consider it's batch numbers for the next suggestion
            self.assertEqual(dialog._last_entry.get_text(), '133-AB')

            branch.acronym = None
            spinbutton = dialog.get_spin_by_entry(dialog._last_entry)
    def test_existing_batches(self):
        branch = api.get_current_branch(self.store)
        storable = self.create_storable(is_batch=True)
        batch1 = self.create_storable_batch(storable=storable,
                                            batch_number=u'1')
        batch2 = self.create_storable_batch(storable=storable,
                                            batch_number=u'2')
        self.create_storable_batch(storable=storable, batch_number=u'3')

        storable.increase_stock(10, branch, 0, None, batch=batch1)
        storable.increase_stock(10, branch, 0, None, batch=batch2)

        dialog = BatchSelectionDialog(self.store, storable, 5)
        # The last batch should not appear since it doesn't have a storable
        self.assertEqual(set([view.batch for view in dialog.existing_batches]),
                         set([batch1, batch2]))

        last_spin = dialog.get_spin_by_entry(dialog._last_entry)
        # The spin (at the moment, the only one appended) should be filled
        # with the total value (100, passed on the constructor)
        self.assertEqual(last_spin.read(), 5)
        view1 = self.store.find(StorableBatchView,
                                StorableBatchView.id == batch1.id).one()
        dialog.existing_batches.emit('row-activated', view1)
        self.assertEqual(last_spin.read(), 5)
Exemple #11
0
 def _get_or_create_quote_group(self, order, store):
     if order is not None:
         quotation = store.find(Quotation, purchase=order).one()
         return quotation.group
     else:
         return QuoteGroup(branch=api.get_current_branch(store),
                           store=store)
Exemple #12
0
 def create_filters(self):
     self.executer.set_query(self._query)
     self.set_text_field_columns(['description'])
     self.branch_filter = ComboSearchFilter(
         _('Show by:'), self._get_branches())
     self.branch_filter.select(api.get_current_branch(self.store))
     self.add_filter(self.branch_filter, position=SearchFilterPosition.TOP)
Exemple #13
0
    def _update_widgets(self):
        branch = api.get_current_branch(self.store)

        is_main_branch = self.branch_filter.get_state().value is branch
        item = self.results.get_selected()

        sellable = item and item.product.sellable
        if sellable:
            if sellable.has_image:
                thumbnail = sellable.image.thumbnail
                pixbuf = self.pixbuf_converter.from_string(thumbnail)
            else:
                pixbuf = None

            self._update_edit_image(pixbuf)
            if self.image_viewer:
                self.image_viewer.set_sellable(sellable)
        else:
            self._update_edit_image()

        self.set_sensitive([self.EditProduct], bool(item))
        self.set_sensitive([self.ProductStockHistory],
                           bool(item) and is_main_branch)
        # We need more than one branch to be able to do transfers
        # Note that 'all branches' is not a real branch
        has_branches = len(self.branch_filter.combo) > 2

        transfer_active = self.NewTransfer.get_sensitive()
        self.set_sensitive([self.NewTransfer],
                           transfer_active and has_branches)
        self.set_sensitive([self.SearchTransfer], has_branches)
Exemple #14
0
    def test_confirm(self, yesno, print_report):
        client = self.create_client()
        branch = api.get_current_branch(self.store)
        storable = self.create_storable(branch=branch, stock=1)
        sellable = storable.product.sellable
        wizard = NewLoanWizard(self.store)

        step = wizard.get_current_step()
        step.client.update(client)
        step.expire_date.update(localtoday().date())
        self.check_wizard(wizard, 'new-loan-wizard-start-step')
        self.click(wizard.next_button)

        step = wizard.get_current_step()
        step.barcode.set_text(sellable.barcode)
        step.sellable_selected(sellable)
        step.quantity.update(1)
        self.click(step.add_sellable_button)
        loan_item = self.store.find(LoanItem, sellable=sellable).one()
        module = 'stoqlib.gui.events.NewLoanWizardFinishEvent.emit'
        with mock.patch(module) as emit:
            self.click(wizard.next_button)
            self.assertEquals(emit.call_count, 1)
            args, kwargs = emit.call_args
            self.assertTrue(isinstance(args[0], Loan))
        self.check_wizard(wizard, 'new-loan-wizard-item-step',
                          [wizard.retval, loan_item])

        yesno.assert_called_once_with(_('Would you like to print the receipt now?'),
                                      gtk.RESPONSE_YES, 'Print receipt', "Don't print")
        self.assertEquals(print_report.call_count, 1)

        # verifies if stock was decreased correctly
        self.assertEquals(storable.get_balance_for_branch(branch), 0)
Exemple #15
0
    def test_search(self):
        self._create_domain()
        search = self._show_search()

        search.date_filter.select(Any)
        self.check_search(search, 'product-sold-no-filter')

        search.set_searchbar_search_string('bot')
        search.search.refresh()
        self.check_search(search, 'product-sold-string-filter')

        search.set_searchbar_search_string('')
        search.branch_filter.set_state(api.get_current_branch(self.store).id)
        search.search.refresh()
        self.check_search(search, 'product-sold-branch-filter')

        search.branch_filter.set_state(None)
        search.date_filter.select(DateSearchFilter.Type.USER_DAY)
        search.date_filter.start_date.update(datetime.date.today())
        search.search.refresh()
        self.check_search(search, 'product-sold-date-today-filter')

        search.date_filter.select(DateSearchFilter.Type.USER_INTERVAL)
        search.date_filter.start_date.update(datetime.date(2012, 1, 1))
        search.date_filter.end_date.update(datetime.date(2012, 2, 2))
        search.search.refresh()
        self.check_search(search, 'product-sold-date-day-filter')
Exemple #16
0
    def _create_payment(self):
        group = PaymentGroup()
        group.payer = self.client.person

        method = PaymentMethod.get_by_name(self.store, u'credit')
        branch = api.get_current_branch(self.store)

        if self.model.value < 0:
            payment_type = Payment.TYPE_IN
        else:
            payment_type = Payment.TYPE_OUT

        # Set status to PENDING now, to avoid calling set_pending on
        # on_confirm for payments that shoud not have its status changed.
        payment = Payment(open_date=localtoday(),
                          branch=branch,
                          status=Payment.STATUS_PENDING,
                          description=self.model.description,
                          value=abs(self.model.value),
                          base_value=abs(self.model.value),
                          due_date=localtoday(),
                          method=method,
                          group=group,
                          till=None,
                          category=None,
                          payment_type=payment_type,
                          bill_received=False)
        payment.pay()

        return payment
Exemple #17
0
 def _collect_client_birthdays(self, start, end, day_events, store):
     branch = api.get_current_branch(store)
     for v in ClientWithSalesView.find_by_birth_date(
             store, (start, end), branch=branch):
         for year in xrange(start.year, end.year + 1):
             date, ev = self._create_client_birthday(v, year)
             self._append_event(day_events, date, 'client_birthdays', ev)
Exemple #18
0
    def _add_product_sellable(self, sellable, quantity, batch=None):
        product = sellable.product
        if product.storable and not batch and product.storable.is_batch:
            available_batches = list(
                product.storable.get_available_batches(
                    api.get_current_branch(self.store)))
            # The trivial case, where there's just one batch, use it directly
            if len(available_batches) == 1:
                batch = available_batches[0]
                sale_item = TemporarySaleItem(
                    sellable=sellable, quantity=quantity, batch=batch)
                self._update_added_item(sale_item)
                return

            rv = self.run_dialog(
                BatchDecreaseSelectionDialog,
                self.store,
                model=sellable.product_storable,
                quantity=quantity)
            if not rv:
                return

            for batch, b_quantity in rv.items():
                sale_item = TemporarySaleItem(
                    sellable=sellable, quantity=b_quantity, batch=batch)
                self._update_added_item(sale_item)
        else:
            sale_item = TemporarySaleItem(
                sellable=sellable, quantity=quantity, batch=batch)
            self._update_added_item(sale_item)
Exemple #19
0
    def _update_widgets(self):
        branch = api.get_current_branch(self.store)

        is_main_branch = self.branch_filter.get_state().value is branch
        item = self.results.get_selected()

        sellable = item and item.product.sellable
        if sellable:
            if item.has_image:
                thumbnail = sellable.image.thumbnail
                pixbuf = self.pixbuf_converter.from_string(thumbnail)
            else:
                pixbuf = None

            self._update_edit_image(pixbuf)
            if self.image_viewer:
                self.image_viewer.set_sellable(sellable)
        else:
            self._update_edit_image()

        self.set_sensitive([self.EditProduct, self.PrintLabels], bool(item))
        self.set_sensitive([self.ProductStockHistory],
                           bool(item) and is_main_branch)
        # We need more than one branch to be able to do transfers
        # Note that 'all branches' is not a real branch
        has_branches = len(self.branch_filter.combo) > 2

        transfer_active = self.NewTransfer.get_sensitive()
        self.set_sensitive([self.NewTransfer],
                           transfer_active and has_branches)
        # Building a list of searches that we must disable if there is no
        # branches other than the main company
        searches = [self.SearchTransfer, self.SearchTransferItems,
                    self.SearchPendingReturnedSales]
        self.set_sensitive(searches, has_branches)
    def test_wizard_create_payment(self, yesno):
        yesno.return_value = False

        sysparam.set_bool(self.store, 'CREATE_PAYMENTS_ON_STOCK_DECREASE', True)

        till = self.create_till()
        till.open_till()

        branch = api.get_current_branch(self.store)
        storable = self.create_storable(branch=branch, stock=1)
        sellable = storable.product.sellable
        wizard = StockDecreaseWizard(self.store)

        step = wizard.get_current_step()
        self.assertTrue(step.create_payments.get_visible())
        step.create_payments.update(True)
        step.reason.update('reason')
        self.check_wizard(wizard, 'start-stock-decrease-step-create-payments')
        self.assertSensitive(wizard, ['next_button'])
        self.click(wizard.next_button)

        step = wizard.get_current_step()
        step.barcode.set_text(sellable.barcode)
        step.sellable_selected(sellable)
        step.quantity.update(1)
        self.click(step.add_sellable_button)
        self.click(wizard.next_button)

        step = wizard.get_current_step()
        self.assertTrue(isinstance(step, PaymentMethodStep))
    def test_synchronized_mode(self):
        # This is a non editable parameter
        with self.sysparam(SYNCHRONIZED_MODE=True):
            current = api.get_current_branch(self.store)
            other_branch = self.create_branch()

            # One sale on one branch
            sale1 = self.create_sale(branch=current)
            self.add_product(sale1)
            sale1.order()
            self.add_payments(sale1, method_type=u'check')
            sale1.confirm()
            sale1.confirm_date = localdate(2011, 01, 01).date()
            sale1.salesperson.person.name = u'salesperson1'

            # And another one on a second branch
            sale2 = self.create_sale(branch=other_branch)
            sale2.salesperson = sale1.salesperson
            self.add_product(sale2)
            sale2.order()
            self.add_payments(sale2, method_type=u'money')
            sale2.confirm()
            sale2.confirm_date = sale1.confirm_date

            dialog = SalesPersonSalesSearch(self.store)
            dialog.date_filter.select(DateSearchFilter.Type.USER_INTERVAL)
            dialog.date_filter.start_date.update(sale1.confirm_date)
            dialog.date_filter.end_date.update(sale1.confirm_date)
            self.click(dialog.search.search_button)
            self.check_dialog(dialog, 'sales-person-sales-synchronized-show')
    def test_wizard_remove_delivery(self, yesno):
        yesno.return_value = True
        branch = api.get_current_branch(self.store)
        storable = self.create_storable(branch=branch, stock=1)
        sellable = storable.product.sellable
        # Run the wizard
        wizard = StockDecreaseWizard(self.store)
        step = wizard.get_current_step()
        step.reason.update('test')
        self.click(wizard.next_button)
        step = wizard.get_current_step()
        self.assertNotSensitive(step, ['delivery_button'])
        step.sellable_selected(sellable)
        step.quantity.update(1)
        self.click(step.add_sellable_button)
        self.assertSensitive(step, ['delivery_button'])

        delivery_sellable = sysparam.get_object(self.store, 'DELIVERY_SERVICE').sellable
        delivery = CreateDeliveryModel(price=delivery_sellable.price,
                                       recipient=wizard.model.person)

        module = 'stoqlib.gui.wizards.stockdecreasewizard.run_dialog'
        with mock.patch(module) as run_dialog:
            # Delivery set
            run_dialog.return_value = delivery
            self.click(step.delivery_button)
            self.assertEqual(step._delivery, delivery)
            self.assertTrue(isinstance(step._delivery_item, StockDecreaseItem))

            # Remove the delivery item
            run_dialog.return_value = delivery
            step.slave.klist.select(step.slave.klist[1])
            self.click(step.slave.delete_button)
            self.assertIsNone(step._delivery)
            self.assertIsNone(step._delivery_item)
Exemple #23
0
 def create_filters(self):
     self.search.set_query(self._query)
     self.set_text_field_columns(["description", "code", "barcode", "category_description", "manufacturer"])
     branches = Branch.get_active_branches(self.store)
     self.branch_filter = ComboSearchFilter(_("Show by:"), api.for_combo(branches, empty=_("All branches")))
     self.branch_filter.select(api.get_current_branch(self.store))
     self.add_filter(self.branch_filter, position=SearchFilterPosition.TOP)
 def _show_search(self):
     search = ProductionHistorySearch(self.store)
     search.branch_filter.set_state(api.get_current_branch(self.store).id)
     search.date_filter.select(Any)
     search.search.refresh()
     search.results.select(search.results[0])
     return search
    def test_confirm(self, save, generator, localtoday):
        save.return_value = True

        value = datetime.datetime(2012, 1, 31)
        localtoday.return_value = value

        # we need to create a system table because it is used by the sintegra
        # dialog to populate the date filter
        SystemTable(updated=datetime.datetime(2012, 1, 1),
                    patchlevel=0,
                    generation=1,
                    store=self.store)
        branch = api.get_current_branch(self.store)
        branch.manager = self.create_employee()

        dialog = SintegraDialog(self.store)
        with mock.patch.object(generator, 'write'):
            self.click(dialog.ok_button)
            self.check_dialog(dialog, 'dialog-sintegra-confirm', [dialog.retval])

            self.assertEquals(save.call_count, 1)
            args, kwargs = save.call_args
            label, toplevel, filename = args
            self.assertEquals(label, _("Save Sintegra file"))
            self.assertTrue(isinstance(toplevel, gtk.Dialog))
            self.assertEquals(filename, 'sintegra-2012-01.txt')
Exemple #26
0
    def test_save_new_sale(self, new_store):
        new_store.return_value = self.store

        with contextlib.nested(
                self.sysparam(USE_SALE_TOKEN=True),
                mock.patch.object(self.store, 'close'),
                mock.patch.object(self.store, 'commit')):
            pos = self.create_app(PosApp, u'pos')
            self._pos_open_till(pos)
            token = self.create_sale_token(
                u'foobar', branch=api.get_current_branch(self.store))
            self._open_token(pos, token)

            pos.barcode.set_text(u'1598756984265')
            self.activate(pos.barcode)

            _sale = []
            original_create_sale = pos._create_sale

            def _create_sale(*args, **kwargs):
                sale = original_create_sale(*args, **kwargs)
                _sale.append(sale)
                return sale

            with mock.patch.object(pos, '_create_sale') as create_sale:
                create_sale.side_effect = _create_sale
                self.click(pos.save_button)

            sale = _sale[0]
            self.assertEqual(sale.status, Sale.STATUS_ORDERED)
            self.assertEqual(sale.current_sale_token, token)
            items = list(sale.get_items())
            self.assertEqual(len(items), 1)
            self.assertEqual(items[0].sellable.barcode, u'1598756984265')
    def test_wizard(self, receipt_dialog):
        branch = api.get_current_branch(self.store)
        storable = self.create_storable(branch=branch, stock=1)
        sellable = storable.product.sellable
        wizard = StockDecreaseWizard(self.store)

        step = wizard.get_current_step()
        self.assertFalse(step.create_payments.get_visible())
        self.assertNotSensitive(wizard, ['next_button'])
        step.reason.update('text')
        self.assertSensitive(wizard, ['next_button'])
        self.check_wizard(wizard, 'start-stock-decrease-step')
        self.click(wizard.next_button)

        step = wizard.get_current_step()
        self.assertNotSensitive(wizard, ['next_button'])
        step.barcode.set_text(sellable.barcode)
        step.sellable_selected(sellable)
        step.quantity.update(1)
        self.click(step.add_sellable_button)
        self.check_wizard(wizard, 'decrease-item-step')

        self.assertSensitive(wizard, ['next_button'])
        module = 'stoqlib.gui.events.StockDecreaseWizardFinishEvent.emit'
        with mock.patch(module) as emit:
            with mock.patch.object(self.store, 'commit'):
                self.click(wizard.next_button)
            self.assertEqual(emit.call_count, 1)
            args, kwargs = emit.call_args
            self.assertTrue(isinstance(args[0], StockDecrease))

        self.assertEqual(receipt_dialog.call_count, 1)

        # Assert wizard decreased stock.
        self.assertEqual(storable.get_balance_for_branch(branch), 0)
Exemple #28
0
    def get_namespace(self):
        store = self.loan.store
        order_identifier = unicode(self.loan.identifier)
        print_promissory_note = api.sysparam.get_bool('PRINT_PROMISSORY_NOTE_ON_LOAN')
        branch = api.get_current_branch(store)
        drawer_person = self.loan.branch.person
        drawee_person = self.loan.client.person
        emission_address = branch.person.get_main_address()
        emission_location = emission_address.city_location

        promissory_data = Settable(
            order_identifier=order_identifier,
            payment_number=None,
            drawee=drawee_person.name,
            drawer=branch.get_description(),
            drawee_document=self._get_person_document(drawee_person),
            drawer_document=self._get_person_document(drawer_person),
            drawee_address=self._get_person_address(drawee_person),
            drawer_address=self._get_person_address(drawer_person),
            due_date=self.loan.expire_date,
            value=self.loan.get_total_amount(),
            emission_city=emission_location.city,
            emission_date=datetime.date.today(),
        )

        return dict(
            subtitle=_("Loan number: %s") % order_identifier,
            loan=self.loan,
            print_promissory_note=print_promissory_note,
            promissory_data=promissory_data,
        )
Exemple #29
0
    def _update_view(self):
        self.proxy.update("status_str")

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

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

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

        stock_id, tooltip = get_workorder_state_icon(self.model)
        if stock_id is not None:
            self.state_icon.set_from_stock(stock_id, gtk.ICON_SIZE_MENU)
            self.state_icon.set_visible(True)
            self.state_icon.set_tooltip_text(tooltip)
        else:
            self.state_icon.hide()
    def test_wizard_with_cost_center(self, yesno):
        sysparam.set_bool(self.store, 'CREATE_PAYMENTS_ON_STOCK_DECREASE', True)
        yesno.return_value = False

        branch = api.get_current_branch(self.store)
        storable = self.create_storable(branch=branch, stock=1)
        sellable = storable.product.sellable
        cost_center = self.create_cost_center()

        wizard = StockDecreaseWizard(self.store)

        entry = self.store.find(CostCenterEntry,
                                cost_center=wizard.model.cost_center)
        self.assertEqual(len(list(entry)), 0)

        step = wizard.get_current_step()
        step.reason.update('test')
        step.cost_center.select(cost_center)
        self.check_wizard(wizard, 'stock-decrease-with-cost-center')

        self.click(wizard.next_button)

        step = wizard.get_current_step()
        step.barcode.set_text(sellable.barcode)
        step.sellable_selected(sellable)
        step.quantity.update(1)
        self.click(step.add_sellable_button)
        with mock.patch.object(self.store, 'commit'):
            self.click(wizard.next_button)

        self.assertEqual(wizard.model.cost_center, cost_center)
        entry = self.store.find(CostCenterEntry,
                                cost_center=wizard.model.cost_center)
        self.assertEqual(len(list(entry)), 1)
Exemple #31
0
 def has_open_inventory(self):
     return Inventory.has_open(self.store,
                               api.get_current_branch(self.store))
Exemple #32
0
 def _has_open_inventory(self):
     store = self._parent.store
     has_open = Inventory.has_open(store, api.get_current_branch(store))
     return bool(has_open)
Exemple #33
0
    def test_complete_receiving(self, yesno, run_dialog, warning):
        yesno.return_value = True
        run_dialog.return_value = Settable(skip=Decimal('0'))
        branch = api.get_current_branch(self.store)

        order = self.create_purchase_order(branch=branch)
        order.identifier = 65432
        order.open_date = localdatetime(2012, 10, 9)
        order.expected_receival_date = localdatetime(2012, 9, 25)
        sellable = self.create_sellable()
        package = self.create_product(description=u'Package', is_package=True)
        component = self.create_product(description=u'Component', stock=2)
        self.create_product_component(product=package, component=component)

        order.add_item(sellable, 1)
        parent = order.add_item(package.sellable, 1)
        order.add_item(component.sellable, 1, parent=parent)
        order.status = PurchaseOrder.ORDER_PENDING
        order.confirm(self.current_user)
        wizard = ReceivingOrderWizard(self.store)

        step = wizard.get_current_step()
        self.assertNotSensitive(wizard, ['next_button'])
        self.click(step.search.search_button)
        order_view = step.search.results[0]
        step.search.results.select(order_view)
        self.assertSensitive(wizard, ['next_button'])
        self.check_wizard(wizard, 'purchase-selection-step')
        self.click(wizard.next_button)

        step = wizard.get_current_step()
        self.assertSensitive(wizard, ['next_button'])
        self.check_wizard(wizard, 'receiving-order-product-step')
        self.click(wizard.next_button)

        step = wizard.get_current_step()
        self.assertNotSensitive(wizard, ['next_button'])
        step.invoice_slave.invoice_number.update(1)
        self.assertSensitive(wizard, ['next_button'])
        self.check_wizard(wizard, 'receiving-invoice-step')

        module = 'stoq.lib.gui.events.ReceivingOrderWizardFinishEvent.emit'
        with contextlib.nested(mock.patch(module),
                               mock.patch.object(wizard.model, 'confirm'),
                               mock.patch.object(self.store,
                                                 'commit')) as (emit, confirm,
                                                                _):
            # When this parameter is empty, the user should not be asked
            # to print labels
            with self.sysparam(LABEL_TEMPLATE_PATH=u''):
                self.click(wizard.next_button)

            self.assertEqual(confirm.call_count, 1)
            self.assertEqual(yesno.call_count, 0)
            emit.assert_called_once_with(wizard.model)

            emit.reset_mock()
            confirm.reset_mock()

            # When the file exists, it should ask to print labels, although it
            # will fail as the file is not valid
            with self.sysparam(LABEL_TEMPLATE_PATH=u'non-existing-file'):
                self.click(wizard.next_button)

            self.assertEqual(emit.call_count, 1)
            self.assertEqual(confirm.call_count, 1)
            emit.assert_called_once_with(wizard.model)

            yesno.assert_called_once_with(
                "Do you want to print the labels for the received products?",
                Gtk.ResponseType.YES, "Print labels", "Don't print")

            run_dialog.assert_called_once_with(SkipLabelsEditor, wizard,
                                               self.store)

            warning.assert_called_once_with(
                "It was not possible to print the labels. The template "
                "file was not found.")
    def test_get(self):
        with self.fake_store():
            token = self.login()
            b = api.get_current_branch(self.store)

            s1 = self.create_sellable(description='s1')
            self.create_storable(product=s1.product, stock=10, branch=b)
            s2 = self.create_sellable(description='s2')
            s2.short_description = '2'
            self.create_storable(product=s2.product, stock=20, branch=b)
            s3 = self.create_sellable(description='s3')
            self.create_storable(product=s3.product, stock=30, branch=b)
            s4 = self.create_sellable(description='s4')

            c1 = self.create_sellable_category(description='c1')
            c2 = self.create_sellable_category(description='c2')
            c3 = self.create_sellable_category(description='c3')
            c4 = self.create_sellable_category(description='c4')

            c2.category = c1
            s1.category = c1
            s2.category = c2
            s3.category = c3
            s4.category = c2

            img = self.create_image()
            img.image = b'foobar'
            img.sellable_id = s1.id
            img.is_main = True

            c_ids = [c1.id, c2.id, c3.id, c4.id]

            def adjust_categories(obj):
                if isinstance(obj, dict):
                    del obj['id']
                    for c in obj['children']:
                        adjust_categories(c)
                    obj['products'].sort(key=lambda k: k['description'])
                    for p in obj['products']:
                        del p['id']
                elif isinstance(obj, list):
                    obj.sort(key=lambda k: k['description'])
                    for o in obj[:]:
                        if o['id'] not in c_ids:
                            obj.remove(o)
                        else:
                            adjust_categories(o)
                return obj

            rv = self.client.get('/data', headers={'Authorization': token})
            self.assertEqual(rv.status_code, 200)

            retval = json.loads(rv.data.decode())
            self.assertEqual(retval['branch'], b.id)
            self.assertEqual(
                retval['parameters'], {
                    'NFCE_CAN_SEND_DIGITAL_INVOICE': False,
                    'NFE_SEFAZ_TIMEOUT': 10,
                    'PASSBOOK_FIDELITY': None,
                    'SCALE_BARCODE_FORMAT': 0,
                    'INCLUDE_CASH_FUND_ON_TILL_CLOSING': False,
                    'AUTOMATIC_LOGOUT': 0,
                })
            # Those are the default payment methods created by example data
            self.assertEqual(retval['payment_methods'],
                             [{
                                 'name': 'bill',
                                 'max_installments': 12
                             }, {
                                 'name': 'card',
                                 'max_installments': 12,
                                 'card_types': ['credit', 'debit']
                             }, {
                                 'name': 'check',
                                 'max_installments': 12
                             }, {
                                 'name': 'credit',
                                 'max_installments': 1
                             }, {
                                 'name': 'money',
                                 'max_installments': 1
                             }, {
                                 'name': 'multiple',
                                 'max_installments': 12
                             }, {
                                 'name': 'store_credit',
                                 'max_installments': 1
                             }])

            self.assertTrue(isinstance(retval['categories'], list))
            self.assertEqual(adjust_categories(
                retval['categories']), [{
                    'children': [{
                        'children': [],
                        'description':
                        'c2',
                        'order':
                        0,
                        'products': [{
                            'availability': {
                                b.id: '20.000'
                            },
                            'order': '0',
                            'category_prices': {},
                            'color': '',
                            'description': 's2',
                            'short_description': '2',
                            'code': '',
                            'barcode': '',
                            'price': '10',
                            'requires_kitchen_production': False,
                            'has_image': False
                        }, {
                            'availability': None,
                            'order': '0',
                            'category_prices': {},
                            'color': '',
                            'code': '',
                            'barcode': '',
                            'description': 's4',
                            'short_description': '',
                            'price': '10',
                            'requires_kitchen_production': False,
                            'has_image': False
                        }]
                    }],
                    'description':
                    'c1',
                    'order':
                    0,
                    'products': [{
                        'availability': {
                            b.id: '10.000'
                        },
                        'order': '0',
                        'category_prices': {},
                        'color': '',
                        'description': 's1',
                        'short_description': '',
                        'code': '',
                        'barcode': '',
                        'price': '10',
                        'requires_kitchen_production': False,
                        'has_image': True
                    }]
                }, {
                    'children': [],
                    'description':
                    'c3',
                    'order':
                    0,
                    'products': [{
                        'availability': {
                            b.id: '30.000'
                        },
                        'order': '0',
                        'category_prices': {},
                        'color': '',
                        'description': 's3',
                        'short_description': '',
                        'code': '',
                        'barcode': '',
                        'price': '10',
                        'requires_kitchen_production': False,
                        'has_image': False
                    }]
                }, {
                    'children': [],
                    'description': 'c4',
                    'order': 0,
                    'products': []
                }])
Exemple #35
0
 def has_open_inventory(self):
     has_open = Inventory.has_open(self.store,
                                   api.get_current_branch(self.store))
     return bool(has_open)
Exemple #36
0
 def _fill_person_combo(self):
     items = Person.get_items(
         self.store, Person.branch != api.get_current_branch(self.store))
     self.person.prefill(items)
Exemple #37
0
 def create_model(self, store):
     self._current_branch = api.get_current_branch(store)
     return Settable(branch=self._current_branch)
Exemple #38
0
 def testConfirm(self, create_main_branch):
     create_main_branch.return_value = api.get_current_branch(self.store)
     editor = BranchDialog(self.store)
     editor.name.set_text('minha empresa')
     editor.cnpj.set_text('00.000.000/0000-00')
     self.click(editor.main_dialog.ok_button)
Exemple #39
0
 def create_model(self, store):
     return SaleToken(store=self.store,
                      code=u'',
                      name=u'',
                      branch=api.get_current_branch(self.store))
Exemple #40
0
 def _query(self, store):
     branch = api.get_current_branch(self.store)
     return self.search_spec.find_by_branch(store, branch)
Exemple #41
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))
Exemple #42
0
 def _get_existing_batches(self):
     branch = api.get_current_branch(self.store)
     return StorableBatchView.find_available_by_storable(
         self.store, self.model, branch=branch)
Exemple #43
0
    def testCreate(self, create_main_branch):
        create_main_branch.return_value = api.get_current_branch(self.store)

        editor = BranchDialog(self.store)
        self.check_editor(editor, 'dialog-branch-create',
                          models=[editor.model])
Exemple #44
0
 def _create_model(self, store):
     branch = api.get_current_branch(store)
     return ProductionOrder(branch=branch,
                            station=api.get_current_station(store),
                            store=store)
Exemple #45
0
 def __init__(self, wizard, store, model):
     self.branch = api.get_current_branch(store)
     manager = get_plugin_manager()
     self._nfe_is_active = manager.is_active('nfe')
     WizardEditorStep.__init__(self, store, wizard, model)
Exemple #46
0
 def _get_query(self, state):
     branch = api.get_current_branch(self.store)
     return self.search_spec.branch_id == branch.id
Exemple #47
0
    def test_get(self):
        with self.fake_store():
            s = self.login()
            b = api.get_current_branch(self.store)

            s1 = self.create_sellable(description='s1')
            self.create_storable(product=s1.product, stock=10, branch=b)
            s2 = self.create_sellable(description='s2')
            self.create_storable(product=s2.product, stock=20, branch=b)
            s3 = self.create_sellable(description='s3')
            self.create_storable(product=s3.product, stock=30, branch=b)
            s4 = self.create_sellable(description='s4')

            c1 = self.create_sellable_category(description='c1')
            c2 = self.create_sellable_category(description='c2')
            c3 = self.create_sellable_category(description='c3')
            c4 = self.create_sellable_category(description='c4')

            c2.category = c1
            s1.category = c1
            s2.category = c2
            s3.category = c3
            s4.category = c2

            c_ids = [c1.id, c2.id, c3.id, c4.id]

            def adjust_categories(obj):
                if isinstance(obj, dict):
                    del obj['id']
                    for c in obj['children']:
                        adjust_categories(c)
                    obj['products'].sort(key=lambda k: k['description'])
                    for p in obj['products']:
                        del p['id']
                elif isinstance(obj, list):
                    obj.sort(key=lambda k: k['description'])
                    for o in obj[:]:
                        if o['id'] not in c_ids:
                            obj.remove(o)
                        else:
                            adjust_categories(o)
                return obj

            rv = self.client.get('/data', headers={'stoq-session': s})
            self.assertEqual(rv.status_code, 200)

            retval = json.loads(rv.data.decode())
            self.assertEqual(retval['branch'], b.id)
            # Those are the default payment methods created by example data
            self.assertEqual(retval['payment_methods'],
                             [{
                                 'name': 'bill',
                                 'max_installments': 12
                             }, {
                                 'name': 'card',
                                 'max_installments': 12,
                                 'card_types': ['credit', 'debit']
                             }, {
                                 'name': 'check',
                                 'max_installments': 12
                             }, {
                                 'name': 'credit',
                                 'max_installments': 1
                             }, {
                                 'name': 'money',
                                 'max_installments': 1
                             }, {
                                 'name': 'multiple',
                                 'max_installments': 12
                             }, {
                                 'name': 'store_credit',
                                 'max_installments': 1
                             }])
            self.assertEqual(adjust_categories(retval['categories']),
                             [{
                                 'children': [{
                                     'children': [],
                                     'description':
                                     'c2',
                                     'products': [{
                                         'availability': {
                                             b.id: '20.000'
                                         },
                                         'order': '0',
                                         'category_prices': {},
                                         'color': '',
                                         'description': 's2',
                                         'price': '10'
                                     }, {
                                         'availability': None,
                                         'order': '0',
                                         'category_prices': {},
                                         'color': '',
                                         'description': 's4',
                                         'price': '10'
                                     }]
                                 }],
                                 'description':
                                 'c1',
                                 'products': [{
                                     'availability': {
                                         b.id: '10.000'
                                     },
                                     'order': '0',
                                     'category_prices': {},
                                     'color': '',
                                     'description': 's1',
                                     'price': '10'
                                 }]
                             }, {
                                 'children': [],
                                 'description':
                                 'c3',
                                 'products': [{
                                     'availability': {
                                         b.id: '30.000'
                                     },
                                     'order': '0',
                                     'category_prices': {},
                                     'color': '',
                                     'description': 's3',
                                     'price': '10'
                                 }]
                             }, {
                                 'children': [],
                                 'description': 'c4',
                                 'products': []
                             }])
Exemple #48
0
    def test_post(self):
        with self.sysparam(DEMO_MODE=True):
            with self.fake_store() as es:
                b = api.get_current_branch(self.store)
                e = es.enter_context(
                    mock.patch('stoqserver.lib.restful.SaleConfirmedRemoteEvent.emit'))
                d = datetime.datetime(2018, 3, 6)
                now = es.enter_context(
                    mock.patch('stoqserver.lib.restful.localnow'))
                now.return_value = d
                tt = es.enter_context(
                    mock.patch('stoqlib.domain.sale.TransactionTimestamp'))
                tt.return_value = d
                s = self.login()

                p1 = self.create_product(price=10)
                p1.manage_stock = False
                s1 = p1.sellable

                p2 = self.create_product(price=currency('20.5'))
                p2.manage_stock = False
                s2 = p2.sellable

                c = self.create_client()
                c.person.individual.cpf = '333.341.828-27'

                rv = self.client.post(
                    '/sale',
                    headers={'stoq-session': s},
                    content_type='application/json',
                    data=json.dumps({
                        'client_document': '333.341.828-27',
                        'products': [
                            {'id': s1.id,
                             'price': str(s1.price),
                             'quantity': 2},
                            {'id': s2.id,
                             'price': str(s2.price),
                             'quantity': 1},
                        ],
                        'payments': [
                            {'method': 'money',
                             'installments': 1,
                             'value': '10.5'},
                            {'method': 'card',
                             'installments': 2,
                             'value': '30',
                             'card_type': 'credit'},
                        ],
                    }),
                )

                self.assertEqual(rv.status_code, 200)
                self.assertEqual(json.loads(rv.data.decode())['branch'], b.id)

                # This should be the sale made by the call above
                sale = self.store.find(Sale).order_by(Desc(Sale.open_date)).first()
                self.assertEqual(sale.get_total_sale_amount(), currency('40.5'))
                self.assertEqual(sale.open_date, d)
                self.assertEqual(sale.confirm_date, d)
                self.assertEqual(
                    {(i.sellable, i.quantity, i.price) for i in sale.get_items()},
                    {(s1, 2, s1.price),
                     (s2, 1, s2.price)})
                self.assertEqual(
                    {(p.method.method_name, p.due_date, p.value)
                     for p in sale.group.get_items()},
                    {('card', d, currency('15')),
                     ('card', datetime.datetime(2018, 4, 6), currency('15')),
                     ('money', d, currency('10.5'))}
                )

                self.assertEqual(e.call_count, 1)
                (sale, doc), _ = e.call_args_list[0]
                self.assertEqual(doc, '333.341.828-27')

                # Test the same sale again, but this time, lets mimic an exception
                # happening in SaleConfirmedRemoteEvent
                e.side_effect = Exception('foobar exception')
                # NOTE: This will print the original traceback to stdout, that
                # doesn't mean that the test is failing (unless it really fail)
                rv = self.client.post(
                    '/sale',
                    headers={'stoq-session': s},
                    content_type='application/json',
                    data=json.dumps({
                        'client_document': '333.341.828-27',
                        'products': [
                            {'id': s1.id,
                             'price': str(s1.price),
                             'quantity': 2},
                            {'id': s2.id,
                             'price': str(s2.price),
                             'quantity': 1},
                        ],
                        'payments': [
                            {'method': 'money',
                             'value': '40.5'},
                        ],
                    }),
                )
                self.assertEqual(rv.status_code, 500)
                self.assertEqual(json.loads(rv.data.decode()),
                                 {'message': 'foobar exception'})
Exemple #49
0
    def test_confirm(self, run_dialog, yesno):
        WorkOrderCategory(store=self.store, name=u'Category', color=u'#ff0000')
        client = self.create_client()
        medic = self.create_optical_medic()
        self.create_address(person=client.person)

        yesno.return_value = False

        # Test for reserve without storable
        sellable = self.create_sellable()
        sellable.barcode = u'12345678'
        # Test for reserve with storable
        sellable2 = self.create_sellable()
        sellable2.barcode = u'12345679'
        self.create_storable(product=sellable2.product,
                             branch=api.get_current_branch(self.store),
                             stock=10)
        # Test for reserve for a batch with storable
        sellable3 = self.create_sellable()
        sellable3.barcode = u'12345680'
        storable, batch = self.create_storable(product=sellable3.product,
                                               branch=api.get_current_branch(
                                                   self.store),
                                               is_batch=True,
                                               stock=10)
        # Test for return_to_stock
        sellable4 = self.create_sellable()
        sellable4.barcode = u'12345681'
        self.create_storable(product=sellable4.product)

        wizard = OpticalSaleQuoteWizard(self.store)

        step = wizard.get_current_step()
        step.client_gadget.set_value(client)

        run_dialog.return_value = False
        self.click(step.notes_button)
        self.assertEquals(run_dialog.call_count, 1)
        args, kwargs = run_dialog.call_args
        editor, parent, store, model, comment = args
        self.assertEquals(editor, NoteEditor)
        self.assertEquals(parent, wizard)
        self.assertTrue(store is not None)
        self.assertTrue(isinstance(model, SaleComment))
        self.assertEquals(comment, 'comment')
        self.assertEquals(kwargs['title'], _("Additional Information"))

        self.check_wizard(wizard, 'wizard-optical-start-sale-quote-step')
        self.click(wizard.next_button)

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

        sale = wizard.model
        self.check_wizard(wizard, 'wizard-optical-work-order-step')

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

        for barcode in [
                batch.batch_number, sellable.barcode, sellable2.barcode,
                sellable4.barcode
        ]:
            step.barcode.set_text(barcode)
            self.activate(step.barcode)
            step.quantity.update(1)
            self.click(step.add_sellable_button)

        for item in step.slave.klist:
            if item.sellable == sellable4:
                wo_item = WorkOrderItem.get_from_sale_item(self.store, item)
                wo_item.quantity_decreased = 10

        self.check_wizard(wizard, 'wizard-optical-item-step', [sale, client] +
                          list(sale.get_items().order_by('te_id')))

        module = 'stoqlib.gui.events.SaleQuoteWizardFinishEvent.emit'
        with mock.patch(module) as emit:
            with mock.patch.object(self.store, 'commit'):
                self.click(wizard.next_button)
            self.assertEquals(emit.call_count, 1)
            args, kwargs = emit.call_args
            self.assertTrue(isinstance(args[0], Sale))

        self.assertEqual(wizard.model.payments.count(), 0)
        yesno.assert_called_once_with(
            _('Would you like to print the quote '
              'details now?'), gtk.RESPONSE_YES, _("Print quote details"),
            _("Don't print"))

        # Test get_saved_items, using the existing model here
        wizard2 = OpticalSaleQuoteWizard(self.store, model=wizard.model)
        self.click(wizard2.next_button)
        self.click(wizard2.next_button)
Exemple #50
0
 def __init__(self, wizard, previous, store, model):
     self.branch = api.get_current_branch(store)
     SellableItemStep.__init__(self, wizard, previous, store, model)
Exemple #51
0
 def __init__(self, wizard, store, model):
     self.branch = api.get_current_branch(store)
     WizardEditorStep.__init__(self, store, wizard, model)
Exemple #52
0
    def test_confirm(self, yesno, print_report):
        client = self.create_client()
        branch = api.get_current_branch(self.store)
        storable = self.create_storable(branch=branch, stock=1, unit_cost=10)
        sellable = storable.product.sellable
        wizard = NewLoanWizard(self.store)

        step = wizard.get_current_step()
        step.client_gadget.set_value(client)
        step.expire_date.update(localtoday().date())
        self.check_wizard(wizard, 'new-loan-wizard-start-step')
        self.click(wizard.next_button)

        step = wizard.get_current_step()
        step.barcode.set_text(sellable.barcode)
        step.sellable_selected(sellable)

        # This is a workaround to be able to set a value bigger than MAX_INT,
        # so we can get its validation
        step.quantity.get_adjustment().set_upper(MAX_INT + 1)
        # Checking values bigger than MAX_INT for quantity
        step.quantity.update(MAX_INT + 1)
        self.assertInvalid(step, ['quantity'])
        # Checking values bigger than we have on stock
        step.quantity.update(2)
        self.assertInvalid(step, ['quantity'])
        # Checking negative value
        step.quantity.update(-1)
        self.assertInvalid(step, ['quantity'])
        # Checking valid values
        step.quantity.update(1)
        self.assertValid(step, ['quantity'])

        # Checking negative value
        step.cost.update(-1)
        self.assertInvalid(step, ['cost'])
        # This is a workaround to be able to set a value bigger than MAX_INT,
        # so we can get its validation
        step.cost.get_adjustment().set_upper(MAX_INT + 1)
        # Checking values bigger than MAX_INT for cost
        step.cost.update(MAX_INT + 1)
        self.assertInvalid(step, ['cost'])
        # Checking valid value
        step.cost.update(10)
        self.assertValid(step, ['cost'])

        self.click(step.add_sellable_button)
        loan_item = self.store.find(LoanItem, sellable=sellable).one()
        module = 'stoq.lib.gui.events.NewLoanWizardFinishEvent.emit'
        with mock.patch(module) as emit:
            with mock.patch.object(self.store, 'commit'):
                self.click(wizard.next_button)
            self.assertEqual(emit.call_count, 1)
            args, kwargs = emit.call_args
            self.assertTrue(isinstance(args[0], Loan))
        self.check_wizard(wizard, 'new-loan-wizard-item-step',
                          [wizard.retval, loan_item])

        yesno.assert_called_once_with('Would you like to print the receipt now?',
                                      Gtk.ResponseType.YES, 'Print receipt', "Don't print")
        self.assertEqual(print_report.call_count, 1)

        # verifies if stock was decreased correctly
        self.assertEqual(storable.get_balance_for_branch(branch), 0)
Exemple #53
0
    def __init__(self, store, model=None, visual_mode=False):
        from stoq.lib.gui.slaves.sellableslave import CategoryPriceSlave
        is_new = not model
        self._sellable = None
        self._demo_mode = sysparam.get_bool('DEMO_MODE')
        self._requires_weighing_text = (
            "<b>%s</b>" % stoq_api.escape(_("This unit type requires weighing")))

        if self.ui_form_name:
            self.db_form = DatabaseForm(self.ui_form_name)
        else:
            self.db_form = None
        BaseEditor.__init__(self, store, model, visual_mode)
        self.enable_window_controls()
        if self._demo_mode:
            self._add_demo_warning()

        # Code suggestion. We need to do this before disabling sensitivity,
        # otherwise, the sellable will not be updated.
        if not self.code.read():
            self._update_default_sellable_code()
        edit_code_product = sysparam.get_bool('EDIT_CODE_PRODUCT')
        self.code.set_sensitive(not edit_code_product and not self.visual_mode)

        self.description.grab_focus()
        self.table.set_focus_chain([self.code,
                                    self.barcode,
                                    self.default_sale_cfop,
                                    self.description,
                                    self.cost_hbox,
                                    self.price_hbox,
                                    self.category_combo,
                                    self.tax_hbox,
                                    self.unit_combo,
                                    ])

        self._print_labels_btn = self.add_button('print_labels', Gtk.STOCK_PRINT)
        self._print_labels_btn.connect('clicked', self.on_print_labels_clicked,
                                       'print_labels')
        label = self._print_labels_btn.get_children()[0]
        label = label.get_children()[0].get_children()[1]
        label.set_label(_(u'Print labels'))

        self.setup_widgets()

        if not is_new and not self.visual_mode:
            # Although a sellable can be both removed/closed, we show only one,
            # to avoid having *lots* of buttons. If it's closed, provide a way
            # to reopen it, else, show a delete button if it can be removed
            # or a close button if it can be closed
            if self._sellable.is_closed(api.get_current_branch(self.store)):
                self._add_reopen_button()
            elif self._sellable.can_remove():
                self._add_delete_button()
            elif self._sellable.can_close():
                self._add_close_button()

        self.set_main_tab_label(self.model_name)
        image_gallery_slave = ImageGallerySlave(
            self.store, self.model.sellable, self.visual_mode)
        self.add_extra_tab(_(u'Images'), image_gallery_slave)
        price_slave = CategoryPriceSlave(self.store, self.model.sellable,
                                         self.visual_mode)
        self.add_extra_tab(_(u'Category Prices'), price_slave)
        self._setup_ui_forms()
        self._update_print_labels()
        self._update_price()
Exemple #54
0
 def __init__(self, store, wizard, transfer_order, previous):
     self.store = store
     self.transfer_order = transfer_order
     self.branch = api.get_current_branch(self.store)
     BaseWizardStep.__init__(self, self.store, wizard, previous)
     self.setup_proxies()
Exemple #55
0
 def _get_orders(self):
     branch = api.get_current_branch(self.store)
     query = Eq(WorkOrderView.branch_id, branch.id)
     result = WorkOrderView.find_pending(self.store).find(query)
     return result.order_by(WorkOrder.estimated_finish, WorkOrder.status)
Exemple #56
0
    def _setup_widgets(self):
        if self._is_batch:
            self._add_batches_tab()

        self.receiving_list.set_columns(self._get_receiving_columns())
        self.sales_list.set_columns(self._get_sale_columns())
        self.transfer_list.set_columns(self._get_transfer_columns())
        self.loan_list.set_columns(self._get_loan_columns())
        self.decrease_list.set_columns(self._get_decrease_columns())
        self.inventory_list.set_columns(self._get_inventory_columns())
        self.returned_list.set_columns(self._get_returned_columns())

        current_branch = api.get_current_branch(self.store)
        items = self.store.find(ReceivingItemView, sellable_id=self.model.id)
        if api.sysparam.get_bool('SYNCHRONIZED_MODE'):
            items = items.find(Branch.id == current_branch.id)
        self.receiving_list.add_list(list(items))

        items = SaleItemsView.find_confirmed(self.store, sellable=self.model)
        if api.sysparam.get_bool('SYNCHRONIZED_MODE'):
            items = items.find(Branch.id == current_branch.id)
        self.sales_list.add_list(list(items))

        items = TransferItemView.find_by_branch(self.store, self.model,
                                                current_branch)
        self.transfer_list.add_list(list(items))

        items = self.store.find(LoanItemView, sellable_id=self.model.id)
        if api.sysparam.get_bool('SYNCHRONIZED_MODE'):
            items = items.find(Branch.id == current_branch.id)
        self.loan_list.add_list(list(items))

        items = self.store.find(StockDecreaseItemsView, sellable=self.model.id)
        if api.sysparam.get_bool('SYNCHRONIZED_MODE'):
            items = items.find(Branch.id == current_branch.id)
        self.decrease_list.add_list(list(items))

        items = InventoryItemsView.find_by_product(self.store,
                                                   self.model.product)
        if api.sysparam.get_bool('SYNCHRONIZED_MODE'):
            items = items.find(Branch.id == current_branch.id)
        self.inventory_list.add_list(items)

        items = self.store.find(ReturnedSaleItemsView,
                                sellable_id=self.model.id)
        if api.sysparam.get_bool('SYNCHRONIZED_MODE'):
            items = items.find(Branch.id == current_branch.id)
        self.returned_list.add_list(items)

        value_format = '<b>%s</b>'
        total_label = "<b>%s</b>" % api.escape(_("Total:"))
        receiving_summary_label = SummaryLabel(klist=self.receiving_list,
                                               column='quantity',
                                               label=total_label,
                                               value_format=value_format)
        receiving_summary_label.show()
        self.receiving_vbox.pack_start(receiving_summary_label, False)

        sales_summary_label = SummaryLabel(klist=self.sales_list,
                                           column='quantity',
                                           label=total_label,
                                           value_format=value_format)
        sales_summary_label.show()
        self.sales_vbox.pack_start(sales_summary_label, False)

        transfer_summary_label = SummaryLabel(klist=self.transfer_list,
                                              column='item_quantity',
                                              label=total_label,
                                              value_format=value_format)
        transfer_summary_label.show()
        self.transfer_vbox.pack_start(transfer_summary_label, False)

        loan_summary_label = SummaryLabel(klist=self.loan_list,
                                          column='quantity',
                                          label=total_label,
                                          value_format=value_format)
        self.loan_vbox.pack_start(loan_summary_label, False)

        decrease_summary_label = SummaryLabel(klist=self.decrease_list,
                                              column='quantity',
                                              label=total_label,
                                              value_format=value_format)
        decrease_summary_label.show()
        self.decrease_vbox.pack_start(decrease_summary_label, False)
Exemple #57
0
 def get_title(self):
     # This method must be redefined in child when it's needed
     branch = api.get_current_branch(self.store)
     return _('[%s] - %s') % (branch.get_description(), self.app_title)
Exemple #58
0
 def get_title(self):
     return _('Stoq - Till for Branch %03d') % (api.get_current_branch(
         self.store).id, )
Exemple #59
0
 def get_title(self):
     return _('[%s] - Till') % (
         api.get_current_branch(self.store).get_description(), )