def before_start(self, store): till = Till.get_current(store) if till is None: till = Till(store=store, station=get_current_station(store)) till.open_till() assert till == Till.get_current(store)
def testGetCurrentTillClose(self): station = get_current_station(self.store) self.assertEqual(Till.get_current(self.store), None) till = Till(store=self.store, station=station) till.open_till() self.assertEqual(Till.get_current(self.store), till) till.close_till() self.assertEqual(Till.get_current(self.store), None)
def test_get_current_till_close(self): station = get_current_station(self.store) self.assertEqual(Till.get_current(self.store), None) till = Till(store=self.store, station=station) till.open_till() self.assertEqual(Till.get_current(self.store), till) till.close_till() self.assertEqual(Till.get_current(self.store), None)
def testGetCurrentTillOpen(self): self.assertEqual(Till.get_current(self.store), None) station = get_current_station(self.store) till = Till(store=self.store, station=station) self.assertEqual(Till.get_current(self.store), None) till.open_till() self.assertEqual(Till.get_current(self.store), till) self.assertEqual(till.opening_date.date(), localtoday().date()) self.assertEqual(till.status, Till.STATUS_OPEN) self.assertRaises(TillError, till.open_till)
def test_get_current_till_close(self): self.assertEqual(Till.get_current(self.store, self.current_station), None) till = Till(store=self.store, branch=self.current_branch, station=self.current_station) till.open_till(self.current_user) self.assertEqual(Till.get_current(self.store, self.current_station), till) till.close_till(self.current_user) self.assertEqual(Till.get_current(self.store, self.current_station), None)
def test_get_current_till_open(self): self.assertEqual(Till.get_current(self.store), None) station = get_current_station(self.store) till = Till(store=self.store, station=station) self.assertEqual(Till.get_current(self.store), None) till.open_till() self.assertEqual(Till.get_current(self.store), till) self.assertEqual(till.opening_date.date(), localtoday().date()) self.assertEqual(till.status, Till.STATUS_OPEN) self.assertRaises(TillError, till.open_till)
def on_Edit__activate(self, action): try: Till.get_current(self.store) except TillError as e: warning(str(e)) return store = api.new_store() views = self.results.get_selected_rows() sale = store.fetch(views[0].sale) retval = run_dialog(SalePaymentsEditor, self, store, sale) if store.confirm(retval): self.refresh() store.close()
def on_Edit__activate(self, action): try: Till.get_current(self.store, api.get_current_station(self.store)) except TillError as e: warning(str(e)) return store = api.new_store() views = self.results.get_selected_rows() sale = store.fetch(views[0].sale) retval = run_dialog(SalePaymentsEditor, self, store, sale) if store.confirm(retval): self.refresh() store.close()
def create_sale(self, id_=None, branch=None, client=None): from stoqlib.domain.sale import Sale from stoqlib.domain.till import Till till = Till.get_current(self.store) if till is None: till = self.create_till() till.open_till() salesperson = self.create_sales_person() group = self.create_payment_group() if client: group.payer = client.person sale = Sale( coupon_id=0, open_date=TransactionTimestamp(), salesperson=salesperson, branch=branch or get_current_branch(self.store), cfop=sysparam(self.store).DEFAULT_SALES_CFOP, group=group, client=client, store=self.store, ) if id_: sale.id = id_ sale.identifier = id_ return sale
def _open_till(self, store): till = Till(store=store, station=api.get_current_station(store)) till.open_till() TillOpenEvent.emit(till=till) self.assertEquals(till, Till.get_current(store)) return till
def open_till(self): """Opens the till """ try: current_till = Till.get_current(self.store) except TillError as e: warning(str(e)) return False if current_till is not None: warning(_("You already have a till operation opened. " "Close the current Till and open another one.")) return False store = api.new_store() try: model = run_dialog(TillOpeningEditor, self._parent, store) except TillError as e: warning(str(e)) model = None retval = store.confirm(model) store.close() if retval: self._till_status_changed(closed=False, blocked=False) return retval
def _update_till_status(self, closed, blocked): # Three different situations; # # - Till is closed # - Till is opened # - Till was not closed the previous fiscal day (blocked) self.set_sensitive([self.TillOpen], closed) self.set_sensitive([self.TillClose, self.PaymentReceive], not closed or blocked) widgets = [ self.TillVerify, self.TillAddCash, self.TillRemoveCash, self.SearchTillHistory, self.app_vbox ] self.set_sensitive(widgets, not closed and not blocked) if closed: text = _(u"Till closed") self.clear() self.setup_focus() elif blocked: text = _(u"Till blocked from previous day") else: till = Till.get_current(self.store) text = _(u"Till opened on %s") % till.opening_date.strftime('%x') self.till_status_label.set_text(text) self._update_toolbar_buttons() self._update_total()
def _update_till_status(self, closed, blocked): # Three different situations; # # - Till is closed # - Till is opened # - Till was not closed the previous fiscal day (blocked) self.set_sensitive([self.TillOpen], closed) self.set_sensitive([self.TillClose, self.PaymentReceive], not closed or blocked) widgets = [self.TillVerify, self.TillAddCash, self.TillRemoveCash, self.SearchTillHistory, self.app_vbox] self.set_sensitive(widgets, not closed and not blocked) if closed: text = _(u"Till closed") self.clear() self.setup_focus() elif blocked: text = _(u"Till blocked from previous day") else: till = Till.get_current(self.store) text = _(u"Till opened on %s") % till.opening_date.strftime('%x') self.till_status_label.set_text(text) self._update_toolbar_buttons() self._update_total()
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()
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()
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_last_coupon() if not cancelled: info(_("Cancelling sale failed, nothing to cancel")) store.close() return else: self._cancel_last_sale(last_doc, store) store.commit()
def open_till(self): """Opens the till """ try: current_till = Till.get_current( self.store, api.get_current_station(self.store)) except TillError as e: warning(str(e)) return False if current_till is not None: warning( _("You already have a till operation opened. " "Close the current Till and open another one.")) return False store = api.new_store() try: model = run_dialog(TillOpeningEditor, self._parent, store) except TillError as e: warning(str(e)) model = None retval = store.confirm(model) store.close() if retval: self._till_status_changed(closed=False, blocked=False) return retval
def _open_till(self, store): till = Till(store=store, station=api.get_current_station(store)) till.open_till() TillOpenEvent.emit(till=till) self.assertEqual(till, Till.get_current(store)) return till
def create_model(self, store): till = Till.get_current(self.store) return Settable(employee=None, payment=None, # FIXME: should send in consts.now() open_date=None, till=till, balance=till.get_balance(), value=currency(0))
def test_get_current_till_open(self): self.assertEqual(Till.get_current(self.store, self.current_station), None) till = Till(store=self.store, branch=self.current_branch, station=self.current_station) self.assertEqual(Till.get_current(self.store, self.current_station), None) till.open_till(self.current_user) self.assertEqual(Till.get_current(self.store, self.current_station), till) self.assertEqual(till.opening_date.date(), localtoday().date()) self.assertEqual(till.status, Till.STATUS_OPEN) with self.assertRaises(TillError): till.open_till(self.current_user)
def testCreateInPayment(self): payment = self.createInPayment() self.failUnless(isinstance(payment, Payment)) self.assertEqual(payment.value, Decimal(100)) self.assertEqual(payment.till, Till.get_current(self.store)) payment_without_till = self.createInPayment(till=None) self.failUnless(isinstance(payment, Payment)) self.assertEqual(payment_without_till.value, Decimal(100)) self.assertEqual(payment_without_till.till, None)
def when_done(self, store): # This is sort of hack, set the opening/closing dates to the date before # it's run, so we can open/close the till in the tests, which uses # the examples. till = Till.get_current(store) # Do not leave anything in the till. till.add_debit_entry(till.get_balance(), _(u"Amount removed from Till")) till.close_till() yesterday = localtoday() - datetime.timedelta(1) till.opening_date = yesterday till.closing_date = yesterday
def test_till_open_yesterday(self): yesterday = localnow() - datetime.timedelta(1) # Open a till, set the opening_date to yesterday till = Till(branch=self.current_branch, station=self.current_station, store=self.store) till.open_till(self.current_user) till.opening_date = yesterday with self.assertRaises(TillError): Till.get_current(self.store, self.current_station) # This is used to close a till self.assertEqual( Till.get_last_opened(self.store, self.current_station), till) till.close_till(self.current_user) self.assertEqual(Till.get_current(self.store, self.current_station), None)
def _get_till_balance(self): """Returns the balance of till operations""" try: till = Till.get_current(self.store) except TillError: till = None if till is None: return currency(0) return till.get_balance()
def on_Renegotiate__activate(self, action): try: Till.get_current(self.store) except TillError as e: warning(str(e)) return receivable_views = self.results.get_selected_rows() if not self._can_renegotiate(receivable_views): warning(_('Cannot renegotiate selected payments')) return store = api.new_store() groups = list(set([store.fetch(v.group) for v in receivable_views])) retval = run_dialog(PaymentRenegotiationWizard, self, store, groups) if store.confirm(retval): # FIXME: Storm is not expiring the groups correctly. # Figure out why. See bug 5087 self.refresh() self._update_widgets() store.close()
def when_done(self, store): # This is sort of hack, set the opening/closing dates to the date before # it's run, so we can open/close the till in the tests, which uses # the examples. till = Till.get_current(store) # Do not leave anything in the till. till.add_debit_entry(till.get_balance(), _(u'Amount removed from Till')) till.close_till() yesterday = localtoday() - datetime.timedelta(1) till.opening_date = yesterday till.closing_date = yesterday
def _cancel_last_sale(self, last_doc, store): if last_doc.last_sale.status == Sale.STATUS_RETURNED: return sale = store.fetch(last_doc.last_sale) value = sale.total_amount reason = _(u"Cancelling last document on ECF") sale.cancel(reason, force=True) till = Till.get_current(store) # TRANSLATORS: cash out = sangria till.add_debit_entry(value, _(u"Cash out: last sale cancelled")) last_doc.last_sale = None info(_("Document was cancelled"))
def _update_till_status(self, closed, blocked): # Three different situations: # # - Till is closed # - Till is opened # - Till was not closed the previous fiscal day (blocked) self.set_sensitive([self.TillOpen], closed) self.set_sensitive([self.TillClose], not closed or blocked) widgets = [ self.TillVerify, self.TillAddCash, self.TillRemoveCash, self.SearchTillHistory, self.search_holder, self.PaymentReceive ] self.set_sensitive(widgets, not closed and not blocked) def large(s): return '<span weight="bold" size="xx-large">%s</span>' % ( api.escape(s), ) if closed: text = large(_(u"Till closed")) self.search_holder.hide() self.footer_hbox.hide() self.large_status.show() self.clear() self.setup_focus() # Adding the label on footer without the link self.small_status.set_text(text) if not blocked: text += '\n\n<span size="large"><a href="open-till">%s</a></span>' % ( api.escape(_('Open till'))) self.status_link.set_markup(text) elif blocked: self.search_holder.hide() self.footer_hbox.hide() text = large(_(u"Till blocked")) self.status_link.set_markup(text) self.small_status.set_text(text) else: self.search_holder.show() self.footer_hbox.show() self.large_status.hide() till = Till.get_current(self.store, api.get_current_station(self.store)) text = _(u"Till opened on %s") % till.opening_date.strftime('%x') self.small_status.set_text(text) self._update_toolbar_buttons() self._update_total() if sysparam.get_bool('SHOW_TOTAL_PAYMENTS_ON_TILL'): self._update_payment_total()
def open_till(self): """Opens the till """ if Till.get_current(self.store) is not None: warning("You already have a till operation opened. " "Close the current Till and open another one.") return False store = api.new_store() try: model = run_dialog(TillOpeningEditor, self._parent, store) except TillError, e: warning(str(e)) model = None
def _cancel_last_sale(self, last_doc, store): if last_doc.last_sale.status == Sale.STATUS_RETURNED: return sale = store.fetch(last_doc.last_sale) value = sale.total_amount sale.cancel() comment = _(u"Cancelling last document on ECF") SaleComment(store=store, sale=sale, comment=comment, author=api.get_current_user(store)) till = Till.get_current(store) # TRANSLATORS: cash out = sangria till.add_debit_entry(value, _(u"Cash out: last sale cancelled")) last_doc.last_sale = None info(_("Document was cancelled"))
def test_till_open_yesterday(self): yesterday = localnow() - datetime.timedelta(1) # Open a till, set the opening_date to yesterday till = Till(station=get_current_station(self.store), store=self.store) till.open_till() till.opening_date = yesterday self.assertRaises(TillError, Till.get_current, self.store) # This is used to close a till self.assertEqual(Till.get_last_opened(self.store), till) till.close_till() self.assertEqual(Till.get_current(self.store), None)
def next_step(self): self.wizard.create_payments = self.create_payments.read() if self.wizard.create_payments: try: till = Till.get_current(self.store) except TillError as e: warning(str(e)) return self if not till: warning(_("You need to open the till before doing this operation.")) return self return DecreaseItemStep(self.wizard, self, self.store, self.model)
def _update_till_status(self, closed, blocked): # Three different situations: # # - Till is closed # - Till is opened # - Till was not closed the previous fiscal day (blocked) self.set_sensitive([self.TillOpen], closed) self.set_sensitive([self.TillClose], not closed or blocked) widgets = [self.TillVerify, self.TillAddCash, self.TillRemoveCash, self.SearchTillHistory, self.search_holder, self.PaymentReceive] self.set_sensitive(widgets, not closed and not blocked) def large(s): return '<span weight="bold" size="xx-large">%s</span>' % ( api.escape(s), ) if closed: text = large(_(u"Till closed")) self.search_holder.hide() self.footer_hbox.hide() self.large_status.show() self.clear() self.setup_focus() # Adding the label on footer without the link self.small_status.set_text(text) if not blocked: text += '\n\n<span size="large"><a href="open-till">%s</a></span>' % ( api.escape(_('Open till'))) self.status_link.set_markup(text) elif blocked: self.search_holder.hide() self.footer_hbox.hide() text = large(_(u"Till blocked")) self.status_link.set_markup(text) self.small_status.set_text(text) else: self.search_holder.show() self.footer_hbox.show() self.large_status.hide() till = Till.get_current(self.store) text = _(u"Till opened on %s") % till.opening_date.strftime('%x') self.small_status.set_text(text) self._update_toolbar_buttons() self._update_total() if sysparam.get_bool('SHOW_TOTAL_PAYMENTS_ON_TILL'): self._update_payment_total()
def _update_widgets(self, sale_view): sale = sale_view and sale_view.sale try: till = Till.get_current(self.store) except TillError: till = None can_edit = bool(sale and sale.can_edit()) # We need an open till to return sales if sale and till: can_return = sale.can_return() or sale.can_cancel() else: can_return = False self._sale_toolbar.return_sale_button.set_sensitive(can_return) self._sale_toolbar.edit_button.set_sensitive(can_edit)
def next_step(self): self.wizard.create_payments = self.create_payments.read() if self.wizard.create_payments: try: till = Till.get_current(self.store) except TillError as e: warning(str(e)) return self if not till: warning( _("You need to open the till before doing this operation.") ) return self return DecreaseItemStep(self.wizard, self, self.store, self.model)
def _cancel_last_till_entry(self, last_doc, store): last_till_entry = store.fetch(last_doc.last_till_entry) value = last_till_entry.value till = Till.get_current(store) try: self._printer.cancel_last_coupon() if last_till_entry.value > 0: till_entry = till.add_debit_entry( # TRANSLATORS: cash out = sangria, cash in = suprimento value, _(u"Cash out: last cash in cancelled")) self._set_last_till_entry(till_entry, store) else: till_entry = till.add_credit_entry( # TRANSLATORS: cash out = sangria, cash in = suprimento -value, _(u"Cash in: last cash out cancelled")) self._set_last_till_entry(till_entry, store) info(_("Document was cancelled")) except Exception: info(_("Cancelling failed, nothing to cancel")) return
def _check_needs_closing(self): needs_closing = self.needs_closing() # DB and ECF are ok if needs_closing is CLOSE_TILL_NONE: self._previous_day = False # We still need to check if the till is open or closed. till = Till.get_current(self.store, api.get_current_station(self.store)) self._till_status_changed(closed=not till, blocked=False) return True close_db = needs_closing in (CLOSE_TILL_DB, CLOSE_TILL_BOTH) close_ecf = needs_closing in (CLOSE_TILL_ECF, CLOSE_TILL_BOTH) # DB or ECF is open from a previous day self._till_status_changed(closed=False, blocked=True) self._previous_day = True # Save this statuses in case the user chooses not to close now. self._close_db = close_db self._close_ecf = close_ecf manager = get_plugin_manager() if close_db and (close_ecf or not manager.is_active('ecf')): msg = _("You need to close the till from the previous day before " "creating a new order.\n\nClose the Till?") elif close_db and not close_ecf: msg = _("The till in Stoq is opened, but in ECF " "is closed.\n\nClose the till in Stoq?") elif close_ecf and not close_db: msg = _("The till in stoq is closed, but in ECF " "is opened.\n\nClose the till in ECF?") if yesno(msg, Gtk.ResponseType.NO, _("Close Till"), _("Not now")): return self.close_till(close_db, close_ecf) return False
def _check_needs_closing(self): needs_closing = self.needs_closing() # DB and ECF are ok if needs_closing is CLOSE_TILL_NONE: self._previous_day = False # We still need to check if the till is open or closed. till = Till.get_current(self.store) self._till_status_changed(closed=not till, blocked=False) return True close_db = needs_closing in (CLOSE_TILL_DB, CLOSE_TILL_BOTH) close_ecf = needs_closing in (CLOSE_TILL_ECF, CLOSE_TILL_BOTH) # DB or ECF is open from a previous day self._till_status_changed(closed=False, blocked=True) self._previous_day = True # Save this statuses in case the user chooses not to close now. self._close_db = close_db self._close_ecf = close_ecf manager = get_plugin_manager() if close_db and (close_ecf or not manager.is_active('ecf')): msg = _("You need to close the till from the previous day before " "creating a new order.\n\nClose the Till?") elif close_db and not close_ecf: msg = _("The till in Stoq is opened, but in ECF " "is closed.\n\nClose the till in Stoq?") elif close_ecf and not close_db: msg = _("The till in stoq is closed, but in ECF " "is opened.\n\nClose the till in ECF?") if yesno(msg, gtk.RESPONSE_NO, _("Close Till"), _("Not now")): return self.close_till(close_db, close_ecf) return False
def create_sale(self, id_=None, branch=None, client=None): from stoqlib.domain.sale import Sale from stoqlib.domain.till import Till till = Till.get_current(self.store) if till is None: till = self.create_till() till.open_till() salesperson = self.create_sales_person() group = self.create_payment_group() if client: group.payer = client.person sale = Sale(coupon_id=0, open_date=TransactionTimestamp(), salesperson=salesperson, branch=branch or get_current_branch(self.store), cfop=sysparam(self.store).DEFAULT_SALES_CFOP, group=group, client=client, store=self.store) if id_: sale.id = id_ sale.identifier = id_ return sale
def create_model(self, store): till = Till.get_current(store) return Settable(value=currency(0), reason=u'', till=till, balance=till.get_balance())
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, current_document=self._current_document) 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) try: 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 if not self.print_receipts(sale): 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 sale.confirm(till=till) # Only finish the transaction after everything passed above. store.confirm(model) except Exception as e: warning(_("An error happened while trying to confirm the sale. " "Cancelling the coupon now..."), str(e)) self.cancel() store.rollback(name=savepoint, close=False) return False print_cheques_for_payment_group(store, sale.group) # 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
def on_Edit__activate(self, action): try: Till.get_current(self.store) except TillError, e: warning(str(e)) return
def current_till(store, example_creator, current_station): return Till.get_current(store, current_station) or example_creator.create_till()
def create_payment(self, payment_type, payment_group, branch, value, due_date=None, description=None, base_value=None, till=ValueUnset, payment_number=None): """Creates a new payment according to a payment method interface :param payment_type: the kind of payment, in or out :param payment_group: a :class:`PaymentGroup` subclass :param branch: the :class:`branch <stoqlib.domain.person.Branch>` associated with the payment, for incoming payments this is the branch receiving the payment and for outgoing payments this is the branch sending the payment. :param value: value of payment :param due_date: optional, due date of payment :param details: optional :param description: optional, description of the payment :param base_value: optional :param till: optional :param payment_number: optional :returns: a :class:`payment <stoqlib.domain.payment.Payment>` """ store = self.store if due_date is None: due_date = TransactionTimestamp() if payment_type == Payment.TYPE_IN: query = And(Payment.group_id == payment_group.id, Payment.method_id == self.id, Payment.payment_type == Payment.TYPE_IN, Payment.status != Payment.STATUS_CANCELLED) payment_count = store.find(Payment, query).count() if payment_count == self.max_installments: raise PaymentMethodError( _('You can not create more inpayments for this payment ' 'group since the maximum allowed for this payment ' 'method is %d') % self.max_installments) elif payment_count > self.max_installments: raise DatabaseInconsistency( _('You have more inpayments in database than the maximum ' 'allowed for this payment method')) if not description: description = self.describe_payment(payment_group) # If till is unset, do some clever guessing if till is ValueUnset: # We only need a till for inpayments if payment_type == Payment.TYPE_IN: till = Till.get_current(store) elif payment_type == Payment.TYPE_OUT: till = None else: raise AssertionError(payment_type) payment = Payment(store=store, branch=branch, payment_type=payment_type, due_date=due_date, value=value, base_value=base_value, group=payment_group, method=self, category=None, till=till, description=description, payment_number=payment_number) self.operation.payment_create(payment) return payment
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
self._validate_printer() except DeviceError, 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() def _till_summarize(self): try:
def create_model(self, store): till = Till.get_current(store, api.get_current_station(store)) return Settable(value=currency(0), reason=u'', till=till, balance=till.get_balance())