Пример #1
0
 def validate_confirm(self):
     till = self.model.till
     removed = abs(self.model.value)
     if removed and removed > till.get_balance():
         warning(_("The amount that you want to remove is " "greater than the current balance."))
         return False
     return True
Пример #2
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()
Пример #3
0
    def _add_sellable(self, sellable, batch=None):
        quantity = self._read_quantity()
        if quantity == 0:
            return

        if not sellable.is_valid_quantity(quantity):
            warning(
                _(u"You cannot sell fractions of this product. "
                  u"The '%s' unit does not allow that") %
                sellable.unit_description)
            return

        if sellable.product:
            # If the sellable has a weight unit specified and we have a scale
            # configured for this station, go and check what the scale says.
            if (sellable and sellable.unit
                    and sellable.unit.unit_index == UnitType.WEIGHT
                    and self._scale_settings):
                self._read_scale(sellable)

        storable = sellable.product_storable
        if storable is not None:
            if not self._check_available_stock(storable, sellable):
                info(
                    _("You cannot sell more items of product %s. "
                      "The available quantity is not enough.") %
                    sellable.get_description())
                self.barcode.set_text('')
                self.barcode.grab_focus()
                return

        self._update_list(sellable, batch=batch)
        self.barcode.grab_focus()
Пример #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
Пример #5
0
    def finish(self):
        missing = get_missing_items(self.model, self.store)
        if missing:
            run_dialog(MissingItemsDialog, self, self.model, missing)
            return False

        invoice_ok = InvoiceSetupEvent.emit()
        if invoice_ok is False:
            # If there is any problem with the invoice, the event will display an error
            # message and the dialog is kept open so the user can fix whatever is wrong.
            return

        # FIXME: If any issue happen at any point of the "send process",
        # trying to issue it again would make some products have their stock
        # decreased twice. Make sure we undo it first.
        # The issue itself was related to missing stock. Why get_missing_items
        # failed above?
        self.store.savepoint('before_send_transfer')
        try:
            self.model.send()
        except Exception as e:
            warning(_("An error happened when trying to confirm the transfer"),
                    str(e))
            self.store.rollback_to_savepoint('before_send_transfer')
            raise

        self.retval = self.model
        self.close()

        StockTransferWizardFinishEvent.emit(self.model)
        # Commit before printing to avoid losing data if something breaks
        self.store.confirm(self.retval)
        self._receipt_dialog(self.model)
Пример #6
0
 def on_add_product_button__clicked(self, widget):
     if not self.model.description:
         warning(_('You should fill the description first'))
         return False
     self.model.add_grid_child(self._option_list.values())
     self.product_list.add_list(self.model.children)
     self.add_product_button.set_sensitive(False)
Пример #7
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
Пример #8
0
    def _cancel_last_document(self):
        try:
            self._validate_printer()
        except DeviceError as e:
            warning(str(e))
            return

        store = new_store()
        last_doc = self._get_last_document(store)
        if not self._confirm_last_document_cancel(last_doc):
            store.close()
            return

        if last_doc.last_till_entry:
            self._cancel_last_till_entry(last_doc, store)
        elif last_doc.last_sale:
            # Verify till balance before cancel the last sale.
            till = Till.get_current(store)
            if last_doc.last_sale.total_amount > till.get_balance():
                warning(_("You do not have this value on till."))
                store.close()
                return
            cancelled = self._printer.cancel()
            if not cancelled:
                info(_("Cancelling sale failed, nothing to cancel"))
                store.close()
                return
            else:
                self._cancel_last_sale(last_doc, store)
        store.commit()
Пример #9
0
 def _finish(self, returncode):
     logger.info('CreateDatabaseStep._finish (returncode=%s)' % returncode)
     if returncode:
         self.wizard.enable_back()
         # Failed to execute/create database
         if returncode == 30:
             # This probably happened because the user either;
             # - pressed cancel in the authentication popup
             # - user erred the password 3 times
             # Allow him to try again
             if yesno(_("Something went wrong while trying to create "
                        "the database. Try again?"),
                      gtk.RESPONSE_NO, _("Change settings"), _("Try again")):
                 return
             self._launch_stoqdbadmin()
             return
         elif returncode == 31:
             # Missing postgresql-contrib package
             self.expander.set_expanded(True)
             warning(_("Your database is missing the postgresql-contrib "
                       "package. Install it and try again"))
         else:
             # Unknown error, just inform user that something went wrong.
             self.expander.set_expanded(True)
             warning(_("Something went wrong while trying to create "
                       "the Stoq database"))
         return
     self.label.set_text("")
     self.wizard.load_config_and_call_setup()
     create_default_profile_settings()
     self.progressbar.set_text(_("Done."))
     self.progressbar.set_fraction(1.0)
     self.wizard.enable_next()
     self.done_label.set_markup(
         _("Installation successful, click <b>Forward</b> to continue."))
Пример #10
0
    def check_serial(self):
        driver_serial = self._driver.get_serial()
        if self._printer.device_serial != driver_serial:
            warning(_("Invalid serial number for fiscal printer connected to %s") % (self._printer.device_name))
            return False

        return True
Пример #11
0
def return_sale(parent, sale, store):
    from stoqlib.gui.wizards.salereturnwizard import SaleReturnWizard

    cancel_last_coupon = sysparam.get_bool('ALLOW_CANCEL_LAST_COUPON')
    if cancel_last_coupon and ECFIsLastSaleEvent.emit(sale):
        info(_("That is last sale in ECF. Return using the menu "
               "ECF - Cancel Last Document"))
        return

    if sale.can_return():
        need_document = not sysparam.get_bool('ACCEPT_SALE_RETURN_WITHOUT_DOCUMENT')
        if need_document and not sale.get_client_document():
            warning(_('It is not possible to accept a returned sale from clients '
                      'without document. Please edit the client document or change '
                      'the sale client'))
            return

        returned_sale = sale.create_sale_return_adapter()
        retval = run_dialog(SaleReturnWizard, parent, store, returned_sale)
    elif sale.can_cancel():
        retval = cancel_sale(sale)
    else:
        retval = False

    return retval
Пример #12
0
 def summarize(self):
     """sends a summarize (leituraX) command to the printer"""
     try:
         self._register_emitted_document(ECFDocumentHistory.TYPE_SUMMARY)
         self._driver.summarize()
     except DriverError as details:
         warning(_("Could not print summary"), str(details))
Пример #13
0
    def _read_import_file(self):
        data = {}
        not_found = set()
        with open(self.import_file.get_filename()) as fh:
            for line in fh:
                # The line should have 1 or 2 parts
                parts = line[:-1].split(',')
                assert 1 <= len(parts) <= 2

                if len(parts) == 2:
                    barcode, quantity = parts
                elif len(parts) == 1:
                    barcode = parts[0]
                    if not barcode:
                        continue
                    quantity = 1

                sellable = self.store.find(Sellable, barcode=str(barcode)).one()
                if not sellable:
                    sellable = self.store.find(Sellable, code=str(barcode)).one()

                if not sellable:
                    not_found.add(barcode)
                    continue

                data.setdefault(sellable, 0)
                data[sellable] += int(quantity)

        if not_found:
            warning(_('Some barcodes were not found'), ', '.join(not_found))

        self.wizard.imported_count = data
Пример #14
0
 def on_PrintProductListing__activate(self, button):
     selected = self.results.get_selected()
     sellables = list(self._get_sellables_by_inventory(selected))
     if not sellables:
         warning(_("No products found in the inventory."))
         return
     self.print_report(ProductCountingReport, sellables)
Пример #15
0
 def validate_confirm(self):
     if not self.model.change_reason:
         msg = self.get_validate_message()
         if bool(msg):
             warning(msg)
         return False
     return True
Пример #16
0
def return_sale(parent, sale, store):
    from stoqlib.gui.wizards.salereturnwizard import SaleReturnWizard

    # A plugin (e.g. ECF) can avoid the cancelation of a sale
    # because it wants it to be cancelled using another way
    if SaleAvoidCancelEvent.emit(sale, Sale.STATUS_RETURNED):
        return

    if sale.can_return():
        need_document = not sysparam.get_bool('ACCEPT_SALE_RETURN_WITHOUT_DOCUMENT')
        if need_document and not sale.get_client_document():
            warning(_('It is not possible to accept a returned sale from clients '
                      'without document. Please edit the client document or change '
                      'the sale client'))
            return

        returned_sale = sale.create_sale_return_adapter()
        retval = run_dialog(SaleReturnWizard, parent, store, returned_sale)
    elif sale.can_cancel():
        reason = _(u'Sale cancelled due to client return.')
        retval = cancel_sale(sale, reason)
    else:
        retval = False

    return retval
Пример #17
0
    def _remove_work_order(self, holder, name, work_order, work_order_id):
        if work_order.is_finished():
            warning(_("You cannot remove workorder with the status '%s'")
                    % work_order.status_str)
            return
        if not work_order.get_items().find().is_empty():
            warning(_("This workorder already has items and cannot be removed"))
            return

        # We cannot remove the WO from the database (since it already has some
        # history), but we can disassociate it from the sale, cancel and leave
        # a reason for it.
        reason = (_(u'Removed from sale %s') % work_order.sale.identifier)
        work_order.sale = None
        work_order.cancel(reason=reason)

        self._work_order_ids.remove(work_order_id)

        # Remove the tab
        self.detach_slave(name)
        pagenum = self.work_orders_nb.page_num(holder)
        self.work_orders_nb.remove_page(pagenum)

        # And remove the WO
        self.wizard.workorders.remove(work_order)

        self.force_validation()
Пример #18
0
    def _can_add_payment(self):
        if self.base_value.read() is ValueUnset:
            return False

        if self._outstanding_value <= 0:
            return False

        payments = self.model.group.get_valid_payments()
        payment_count = payments.find(
            Payment.method_id == self._method.id).count()
        if payment_count >= self._method.max_installments:
            info(_(u'You can not add more payments using the %s '
                   'payment method.') % self._method.description)
            return False

        # If we are creaing out payments (PurchaseOrder) or the Sale does not
        # have a client, assume all options available are creatable.
        if (isinstance(self.model, (PurchaseOrder, StockDecrease))
            or not self.model.client):
            return True

        method_values = {self._method: self._holder.value}
        for i, payment in enumerate(self.model.group.payments):
            method_values.setdefault(payment.method, 0)
            method_values[payment.method] += payment.value
        for method, value in method_values.items():
            try:
                self.model.client.can_purchase(method, value)
            except SellError as e:
                warning(str(e))
                return False

        return True
Пример #19
0
 def check_till(self):
     try:
         self._check_needs_closing()
         self.emit('ecf-changed', True)
     except (DeviceError, DriverError) as e:
         warning(str(e))
         self.emit('ecf-changed', False)
Пример #20
0
    def add_item(self, item):
        """
        @param item: A :class:`SellableItem` subclass
        @returns: id of the item.:
          0 >= if it was added successfully
          -1 if an error happend
          0 if added but not printed (gift certificates, free deliveries)
        """
        sellable = item.sellable
        max_len = self._get_capability("item_description").max_len
        description = sellable.description[:max_len]
        unit_desc = ''
        if not sellable.unit:
            unit = UnitType.EMPTY
        else:
            if sellable.unit.unit_index == UnitType.CUSTOM:
                unit_desc = sellable.unit.description
            unit = sellable.unit.unit_index or UnitType.EMPTY
        max_len = self._get_capability("item_code").max_len
        code = sellable.code[:max_len]

        try:
            tax_constant = self._printer.get_tax_constant_for_device(sellable)
        except DeviceError, e:
            warning(_("Could not print item"), str(e))
            return -1
Пример #21
0
    def validate_step(self):
        if any(i.need_adjust_batch for i in self.purchase_items):
            warning(_("Before proceeding you need to adjust quantities for "
                      "the batch products (highlighted in red)"))
            return False

        return True
Пример #22
0
    def validate_confirm(self):
        if self._get_diff_quantity() < 0:
            warning(_("There's some outstanding quantity. Adjust them "
                      "before you can confirm"))
            return False

        return True
Пример #23
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
Пример #24
0
    def open(self):
        while True:
            log.info("opening coupon")
            try:
                self.emit('open')
                break
            except CouponOpenError:
                if not self.cancel():
                    return False
            except OutofPaperError:
                if not yesno(
                    _("The fiscal printer has run out of paper.\nAdd more paper "
                      "before continuing."),
                    gtk.RESPONSE_YES, _("Resume"), _("Confirm later")):
                    return False
                return self.open()
            except PrinterOfflineError:
                if not yesno(
                    (_(u"The fiscal printer is offline, turn it on and try "
                       "again")),
                    gtk.RESPONSE_YES, _(u"Resume"), _(u"Confirm later")):
                    return False
                return self.open()
            except (DriverError, DeviceError) as e:
                warning(_(u"It is not possible to emit the coupon"),
                        str(e))
                return False

        self._coo = self.emit('get-coo')
        self.totalized = False
        self.coupon_closed = False
        self.payments_setup = False
        return True
Пример #25
0
    def _receive(self):
        with api.new_store() as store:
            till = Till.get_current(store)
            assert till

            in_payment = self.results.get_selected()
            payment = store.fetch(in_payment.payment)
            assert self._can_receive(payment)

            retval = run_dialog(SalePaymentConfirmSlave, self, store,
                                payments=[payment], show_till_info=False)
            if not retval:
                return

            try:
                TillAddCashEvent.emit(till=till, value=payment.value)
            except (TillError, DeviceError, DriverError) as e:
                warning(str(e))
                return

            till_entry = till.add_credit_entry(payment.value,
                                               _(u'Received payment: %s') % payment.description)

            TillAddTillEntryEvent.emit(till_entry, store)

        if store.committed:
            self.search.refresh()
Пример #26
0
    def _install_postgres(self):
        self.wizard.disable_back()
        self.wizard.disable_next()
        self.label.set_markup(
            _("Please wait while the package installation is completing."))

        packageinstaller = library.get_resource_filename(
            'stoq', 'scripts', 'packageinstaller.py')
        p = subprocess.Popen(
            [sys.executable, packageinstaller,
             'postgresql', 'postgresql-contrib', 'stoq-server'],
            stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stdout, stderr = p.communicate()

        self.wizard.enable_back()
        if p.returncode == 0:
            self.done = True
            self.wizard.enable_next()
            self.label.set_markup(
                _("Postgresql installation succeeded. You may now proceed "
                  "to the next step by clicking the <b>Forward</b> button"))
        elif p.returncode == 11:
            self.wizard.enable_next()
            self.label.set_markup(
                _("Authorization failed, try again or connect to "
                  "another database"))
        else:
            warning(_("Something went wrong while trying to install "
                      "the PostgreSQL server."))
            self.label.set_markup(
                _("Sorry, something went wrong while installing PostgreSQL, "
                  "try again manually or go back and configure Stoq to connect "
                  "to another."))
Пример #27
0
    def confirm(self, sale, store, savepoint=None, subtotal=None):
        """Confirms a |sale| on fiscalprinter and database

        If the sale is confirmed, the store will be committed for you.
        There's no need for the callsite to call store.confirm().
        If the sale is not confirmed, for instance the user cancelled the
        sale or there was a problem with the fiscal printer, then the
        store will be rolled back.

        :param sale: the |sale| to be confirmed
        :param trans: a store
        :param savepoint: if specified, a database savepoint name that
            will be used to rollback to if the sale was not confirmed.
        :param subtotal: the total value of all the items in the sale
        """
        # Actually, we are confirming the sale here, so the sale
        # confirmation process will be available to others applications
        # like Till and not only to the POS.
        total_paid = sale.group.get_total_confirmed_value()
        model = run_dialog(ConfirmSaleWizard, self._parent, store, sale,
                           subtotal=subtotal,
                           total_paid=total_paid)

        if not model:
            CancelPendingPaymentsEvent.emit()
            store.rollback(name=savepoint, close=False)
            return False

        if sale.client and not self.is_customer_identified():
            self.identify_customer(sale.client.person)

        if not self.totalize(sale):
            store.rollback(name=savepoint, close=False)
            return False

        if not self.setup_payments(sale):
            store.rollback(name=savepoint, close=False)
            return False

        if not self.close(sale, store):
            store.rollback(name=savepoint, close=False)
            return False

        try:
            sale.confirm()
        except SellError as err:
            warning(str(err))
            store.rollback(name=savepoint, close=False)
            return False

        if not self.print_receipts(sale):
            warning(_("The sale was cancelled"))
            sale.cancel()

        print_cheques_for_payment_group(store, sale.group)

        # Only finish the transaction after everything passed above.
        store.confirm(model)

        return True
Пример #28
0
Файл: pos.py Проект: romaia/stoq
    def _update_list(self, sellable):
        assert isinstance(sellable, Sellable)
        try:
            sellable.check_taxes_validity()
        except TaxError as strerr:
            # If the sellable icms taxes are not valid, we cannot sell it.
            warning(strerr)
            return

        quantity = self.sellableitem_proxy.model.quantity

        is_service = sellable.service
        if is_service and quantity > 1:
            # It's not a common operation to add more than one item at
            # a time, it's also problematic since you'd have to show
            # one dialog per service item. See #3092
            info(_("It's not possible to add more than one service "
                   "at a time to an order. So, only one was added."))

        sale_item = TemporarySaleItem(sellable=sellable,
                                      quantity=quantity)
        if is_service:
            with api.trans() as store:
                rv = self.run_dialog(ServiceItemEditor, store, sale_item)
            if not rv:
                return
        self._update_added_item(sale_item)
Пример #29
0
    def _send_selected_items_to_supplier(self):
        orders = self.results.get_selected_rows()
        valid_order_views = [
            order for order in orders
            if order.status == PurchaseOrder.ORDER_PENDING]

        if not valid_order_views:
            warning(_("There are no pending orders selected."))
            return

        msg = stoqlib_ngettext(
            _("The selected order will be marked as sent."),
            _("The %d selected orders will be marked as sent.")
            % len(valid_order_views),
            len(valid_order_views))
        confirm_label = stoqlib_ngettext(_("Confirm order"),
                                         _("Confirm orders"),
                                         len(valid_order_views))
        if not yesno(msg, gtk.RESPONSE_YES, confirm_label, _("Don't confirm")):
            return

        with api.new_store() as store:
            for order_view in valid_order_views:
                order = store.fetch(order_view.purchase)
                order.confirm()
        self.refresh()
        self.select_result(orders)
Пример #30
0
    def print_receipts(self, sale):
        # supports_duplicate = self.emit('get-supports-duplicate-receipt')
        # Vamos sempre imprimir sempre de uma vez, para simplificar
        supports_duplicate = False

        log.info('Printing payment receipts')

        # Merge card payments by nsu
        card_payments = {}
        for payment in sale.payments:
            if payment.method.method_name != 'card':
                continue
            operation = payment.method.operation
            card_data = operation.get_card_data_by_payment(payment)
            card_payments.setdefault(card_data.nsu, [])
            card_payments[card_data.nsu].append(payment)

        any_failed = False
        for nsu, payment_list in card_payments.items():
            receipt = CardPaymentReceiptPrepareEvent.emit(
                nsu, supports_duplicate)
            if receipt is None:
                continue

            value = sum([p.value for p in payment_list])

            # This is BS, but if any receipt failed to print, we must print
            # the remaining ones in Gerencial Rports
            if any_failed:
                retval = self.reprint_payment_receipt(receipt)
            else:
                retval = self.print_payment_receipt(payment_list[0], value,
                                                    receipt)
            while not retval:
                if not yesno(
                        _(u"An error occurred while trying to print. "
                          u"Would you like to try again?"), gtk.RESPONSE_YES,
                        _("Try again"), _(u"Don't try again")):
                    CancelPendingPaymentsEvent.emit()
                    try:
                        GerencialReportCancelEvent.emit()
                    except (DriverError, DeviceError) as details:
                        log.info('Error canceling last receipt: %s' % details)
                        warning(
                            _(u"It wasn't possible to cancel "
                              u"the last receipt"))

                    return False
                any_failed = True
                _flush_interface()
                retval = self.reprint_payment_receipt(
                    receipt, close_previous=True)

        # Only confirm payments receipt printed if *all* receipts wore
        # printed.
        for nsu in card_payments.keys():
            CardPaymentReceiptPrintedEvent.emit(nsu)

        return True
Пример #31
0
    def validate_step(self):
        if self.packages.get_selected() is None:
            warning(_(u"You need to select a package to receive first."))
            return False

        return True
Пример #32
0
 def _set_error(self, msg, long_msg=None):
     warning(msg, long_msg)
     self._set_processing(False)
Пример #33
0
    def confirm(self, sale, store, savepoint=None, subtotal=None):
        """Confirms a |sale| on fiscalprinter and database

        If the sale is confirmed, the store will be committed for you.
        There's no need for the callsite to call store.confirm().
        If the sale is not confirmed, for instance the user cancelled the
        sale or there was a problem with the fiscal printer, then the
        store will be rolled back.

        :param sale: the |sale| to be confirmed
        :param trans: a store
        :param savepoint: if specified, a database savepoint name that
            will be used to rollback to if the sale was not confirmed.
        :param subtotal: the total value of all the items in the sale
        """
        # Actually, we are confirming the sale here, so the sale
        # confirmation process will be available to others applications
        # like Till and not only to the POS.
        payments_total = sale.group.get_total_confirmed_value()
        sale_total = sale.get_total_sale_amount()

        payment = get_formatted_price(payments_total)
        amount = get_formatted_price(sale_total)
        msg = _(u"Payment value (%s) is greater than sale's total (%s). "
                "Do you want to confirm it anyway?") % (payment, amount)
        if (sale_total < payments_total
                and not yesno(msg, gtk.RESPONSE_NO, _(u"Confirm Sale"),
                              _(u"Don't Confirm"))):
            return False

        model = run_dialog(ConfirmSaleWizard,
                           self._parent,
                           store,
                           sale,
                           subtotal=subtotal,
                           total_paid=payments_total)

        if not model:
            CancelPendingPaymentsEvent.emit()
            store.rollback(name=savepoint, close=False)
            return False

        if sale.client and not self.is_customer_identified():
            self.identify_customer(sale.client.person)

        if not self.totalize(sale):
            store.rollback(name=savepoint, close=False)
            return False

        if not self.setup_payments(sale):
            store.rollback(name=savepoint, close=False)
            return False

        if not self.close(sale, store):
            store.rollback(name=savepoint, close=False)
            return False

        # FIXME: This used to be done inside sale.confirm. Maybe it would be
        # better to do a proper error handling
        till = Till.get_current(store)
        assert till

        try:
            sale.confirm(till=till)
        except SellError as err:
            warning(str(err))
            store.rollback(name=savepoint, close=False)
            return False

        if not self.print_receipts(sale):
            warning(_("The sale was cancelled"))
            sale.cancel(force=True)

        print_cheques_for_payment_group(store, sale.group)

        # Only finish the transaction after everything passed above.
        store.confirm(model)

        # Try to print only after the transaction is commited, to prevent
        # losing data if something fails while printing
        group = sale.group
        booklets = list(group.get_payments_by_method_name(u'store_credit'))
        bills = list(group.get_payments_by_method_name(u'bill'))

        if (booklets and yesno(
                _("Do you want to print the booklets for this sale?"),
                gtk.RESPONSE_YES, _("Print booklets"), _("Don't print"))):
            try:
                print_report(BookletReport, booklets)
            except ReportError:
                warning(_("Could not print booklets"))

        if (bills and BillReport.check_printable(bills) and yesno(
                _("Do you want to print the bills for this sale?"),
                gtk.RESPONSE_YES, _("Print bills"), _("Don't print"))):
            try:
                print_report(BillReport, bills)
            except ReportError:
                # TRANSLATORS: bills here refers to "boletos" in pt_BR
                warning(_("Could not print bills"))

        return True
Пример #34
0
 def validate_step(self):
     if len(self.slave.get_selected_attributes()) == 0:
         warning(_("You should select an attribute first"))
         return False
     return True
Пример #35
0
 def new_activate(self):
     if not self.NewInventory.get_sensitive():
         warning(_("You cannot open an inventory without having a "
                   "branch with stock in it."))
         return
     self._open_inventory()
Пример #36
0
    def next_step(self):
        if not self.wizard.need_create_payment():
            if self.cash_change_slave.credit_checkbutton.get_active():
                self._create_change_payment()
            return

        selected_method = self.get_selected_method()
        if selected_method.method_name == u'money':
            if not self.cash_change_slave.can_finish():
                warning(
                    _(u"Invalid value, please verify if it was "
                      "properly typed."))
                self.cash_change_slave.received_value.select_region(
                    0, len(self.cash_change_slave.received_value.get_text()))
                self.cash_change_slave.received_value.grab_focus()
                return self

            # We have to modify the payment, so the fiscal printer can
            # calculate and print the payback, if necessary.
            payment = self.setup_cash_payment()
            if payment is None:
                return

            total = self.cash_change_slave.get_received_value()
            payment.base_value = total

            # Return None here means call wizard.finish, which is exactly
            # what we need
            return None
        elif selected_method.method_name == u'credit':
            client = self.model.client
            total = self.wizard.get_total_to_pay()

            assert client.can_purchase(selected_method, total)

            try:
                payment = selected_method.create_payment(
                    Payment.TYPE_IN, self.model.group, self.model.branch,
                    total)
            except PaymentMethodError as err:
                warning(str(err))
                return self

            # Return None here means call wizard.finish, which is exactly
            # what we need
            return None
        elif selected_method.method_name == u'store_credit':
            client = self.model.client
            total = self.wizard.get_total_to_pay()

            assert client.can_purchase(selected_method, total)

            step_class = PaymentMethodStep
        elif selected_method.method_name == 'card':
            providers = CreditProvider.get_card_providers(self.store)
            if providers.is_empty():
                warning(
                    _("You need active credit providers to use the "
                      "card payment method."))
                return self
            step_class = PaymentMethodStep
        else:
            step_class = PaymentMethodStep

        retval = CreatePaymentEvent.emit(selected_method, self.model,
                                         self.store)

        # None means no one catched this event
        if retval is None or retval == CreatePaymentStatus.UNHANDLED:
            # FIXME: We cannot send outstanding_value to multiple editor
            # since if we have a trade going on, it will be calculated wrong
            if selected_method.method_name == 'multiple':
                outstanding_value = None
            else:
                outstanding_value = self.wizard.get_total_to_pay()

            manager = get_plugin_manager()
            return step_class(self.wizard,
                              self,
                              self.store,
                              self.model,
                              selected_method,
                              outstanding_value=outstanding_value,
                              finish_on_total=manager.is_active('tef'))

        # finish the wizard
        if retval == CreatePaymentStatus.SUCCESS:
            return None

        # returning self to stay on this step
        return self
Пример #37
0
    def validate_confirm(self):
        if not any(i.will_send for i in self.workorders):
            warning(_(u"You need to select at least one work order"))
            return False

        return True
Пример #38
0
    def _check_locale(self):
        if not self._locale_error:
            return

        from stoqlib.lib.message import warning
        warning(self._locale_error[0], str(self._locale_error[1]))
Пример #39
0
 def _on_manager__action_finished(self, manager, action, retval):
     if isinstance(retval, Exception):
         warning(_('An error happened when executing "%s"') % (action.label, ),
                 str(retval))
     self._update_ui()
Пример #40
0
 def _abort(self, msg=None, title=None):
     if msg:
         warning(msg)
     raise SystemExit
Пример #41
0
 def validate_step(self):
     if (self.wizard.product_type == Product.TYPE_GRID
             and not GridGroup.has_group(self.wizard.store)):
         warning(_("You need to register an attribute group first"))
         return False
     return True
Пример #42
0
 def _has_open_coupon(self):
     self._validate_printer()
     if self._printer.has_open_coupon():
         warning(_("The ECF has an open coupon. It will be canceled now."))
         self._printer.cancel()
Пример #43
0
    def _close_till(self, till, previous_day):
        log.info('ECFCouponPrinter.close_till(%r, %r)' % (till, previous_day))

        # XXX: this is so ugly, but the printer stops responding
        # if its printing something. We should wait a little bit...
        # This only happens if closing the till from the current day.
        if not previous_day:
            time.sleep(4)

        # Callsite catches DeviceError
        self._validate_printer()

        printer = self._printer.get_printer()

        if (sysparam.get_bool('ENABLE_DOCUMENT_ON_INVOICE') and not
            (printer.user_number and printer.register_date and
             printer.register_cro)):
            response = warning(
                short=_(u"You need to set some details about your ECF "
                        "if you want to save the paulista invoice file. "
                        "Go to the admin application and fill the "
                        "required information for the ECF."),
                buttons=((_(u"Cancel Close Till"), Gtk.ResponseType.CANCEL), ))
            return False

        retval = True
        while True:
            try:
                self._printer.close_till(previous_day=previous_day)
            except CouponOpenError:
                self._printer.cancel()
                retval = False
            except DriverError:
                response = warning(
                    short=_(u"It's not possible to emit a reduce Z for the "
                            "configured printer.\nWould you like to ignore "
                            "this error and continue?"),
                    buttons=((_(u"Cancel"), Gtk.ResponseType.CANCEL),
                             (_(u"Ignore"), Gtk.ResponseType.YES),
                             (_(u"Try Again"), Gtk.ResponseType.NONE)))
                if response == Gtk.ResponseType.NONE:
                    continue
                elif response == Gtk.ResponseType.CANCEL:
                    retval = False

            break

        if self._needs_cat52(printer):
            day = datetime.date.today()
            if previous_day:
                # XXX: Make sure this is tested
                day = till.opening_date

            dir = sysparam.get_string('CAT52_DEST_DIR')
            dir = os.path.expanduser(dir)
            if not os.path.exists(dir):
                os.mkdir(dir)

            generator = StoqlibCATGenerator(self.default_store, day, printer)
            generator.write(dir)

        self._reset_last_doc()

        return retval
Пример #44
0
 def new_activate(self):
     if not self.NewReceiving.get_sensitive():
         warning(_("You cannot receive a purchase with an open inventory."))
         return
     self._receive_purchase()
Пример #45
0
    def confirm(self, sale, store, savepoint=None, subtotal=None):
        """Confirms a |sale| on fiscalprinter and database

        If the sale is confirmed, the store will be committed for you.
        There's no need for the callsite to call store.confirm().
        If the sale is not confirmed, for instance the user cancelled the
        sale or there was a problem with the fiscal printer, then the
        store will be rolled back.

        :param sale: the |sale| to be confirmed
        :param trans: a store
        :param savepoint: if specified, a database savepoint name that
            will be used to rollback to if the sale was not confirmed.
        :param subtotal: the total value of all the items in the sale
        """
        # Actually, we are confirming the sale here, so the sale
        # confirmation process will be available to others applications
        # like Till and not only to the POS.
        total_paid = sale.group.get_total_confirmed_value()
        model = run_dialog(ConfirmSaleWizard,
                           self._parent,
                           store,
                           sale,
                           subtotal=subtotal,
                           total_paid=total_paid)

        if not model:
            CancelPendingPaymentsEvent.emit()
            store.rollback(name=savepoint, close=False)
            return False

        if sale.client and not self.is_customer_identified():
            self.identify_customer(sale.client.person)

        if not self.totalize(sale):
            store.rollback(name=savepoint, close=False)
            return False

        if not self.setup_payments(sale):
            store.rollback(name=savepoint, close=False)
            return False

        if not self.close(sale, store):
            store.rollback(name=savepoint, close=False)
            return False

        try:
            sale.confirm()
        except SellError as err:
            warning(str(err))
            store.rollback(name=savepoint, close=False)
            return False

        if not self.print_receipts(sale):
            warning(_("The sale was cancelled"))
            sale.cancel()

        print_cheques_for_payment_group(store, sale.group)

        # Only finish the transaction after everything passed above.
        store.confirm(model)

        return True
Пример #46
0
 def _on_toolbar__new(self, toolbar):
     if not self.store.find(GridGroup, is_active=True).any():
         warning(_("You need an active grid group."))
     else:
         self.run()
Пример #47
0
    def validate_confirm(self):
        if self.store.find(GridOption, attribute=self.model).is_empty():
            warning(_("You need to add at least one option"))
            return False

        return True
Пример #48
0
    def confirm(self):
        if len(self.notes.read()) < self.min_length:
            warning(_("The note must have at least %s characters.") % self.min_length)
            return

        BaseEditor.confirm(self)
Пример #49
0
    def validate_confirm(self):
        if self._user.get_associated_branches().count() <= 0:
            warning(_(u'User must be associated to at least one branch.'))
            return False

        return True