diff --git a/app/dialogs.py b/app/dialogs.py index 95aecab..21d8243 100644 --- a/app/dialogs.py +++ b/app/dialogs.py @@ -696,16 +696,18 @@ class DialogGlobalDiscount(QuickDialog): class DialogPrintInvoice(QuickDialog): def __init__(self, parent): + options_type = [ + ('invoice', 'FACTURA'), + ('order', 'ORDEN'), + ] + if parent.enviroment == 'restaurant': + options_type.append(('quotation', 'COTIZACION')) view = ( ('invoice_number_ask', {'name': 'ORDEN / FACTURA'}), ('type_ask', { 'name': 'TIPO', 'type': 'selection', - 'values': [ - ('invoice', 'FACTURA'), - ('order', 'ORDEN'), - ('quotation', 'COTIZACION') - ], + 'values': options_type, }), ('printer_ask', { 'name': 'IMPRESORA', diff --git a/app/frontwindow.py b/app/frontwindow.py index 5330dc3..678ede6 100644 --- a/app/frontwindow.py +++ b/app/frontwindow.py @@ -71,7 +71,6 @@ class FrontWindow(QMainWindow): self.screen_size = 'small' elif self.screen_width <= 1366: self.screen_size = 'medium' - print('self.screen_size > ', self.screen_size) self.timeout = _DEFAULT_TIMEOUT self.setFocus() @@ -96,7 +95,6 @@ class FrontWindow(QMainWindow): def get_geometry(self): screen = QGuiApplication.primaryScreen().size() - # screen = QDesktopWidget().screenGeometry() return screen.width(), screen.height() def set_style(self, file_css, theme_css=None): @@ -120,14 +118,10 @@ class FrontWindow(QMainWindow): else: event.ignore() - def dialog(self, name, response=False, widgets=None, extra_message=None): kind, msg = self.stack_msg[name] if extra_message: - print(extra_message) msg += '\n' + extra_message - # if args: - # msg = msg % args return QuickDialog(parent=self, kind=kind, string=msg, widgets=widgets) def set_params(self, values): diff --git a/app/main.py b/app/main.py index 3926ccc..57b1524 100644 --- a/app/main.py +++ b/app/main.py @@ -1065,7 +1065,10 @@ class AppWindow(FrontWindow): return # set type_doc for i in range(copies): - self.receipt_sale.print_sale(data, type_doc, open_box) + msg = self.receipt_sale.print_sale(data, type_doc, open_box) + if isinstance(msg, dict) and msg.get('error'): + self.dialog('print_error', extra_message=msg['error']) + break # def button_duplicate_sale(self): # if self.sale_customer_selected: @@ -2565,7 +2568,6 @@ class AppWindow(FrontWindow): print('res ....producto creado ...', res) _add_products() - def create_new_sale(self, kind='take_away'): if self.type_pos_user == 'cashier': self.message_bar.set('not_sale') @@ -3087,14 +3089,16 @@ class AppWindow(FrontWindow): line = self.dialog_product_edit.get() try: code = line['product.']['code'] - except: + except Exception: code = line['product']['code'] product = self.Product.find( [('code', '=', code)], - fields=["code", "description", "extra_tax", "name", "sale_uom", + fields=[ + "code", "description", "extra_tax", "name", "sale_uom", "quantity", "sale_price_w_tax", "template.account_category", "template.sale_price_w_tax", "template.rec_name", - 'products_mix.code', 'products_mix.name', "quantity_mix_required" + 'products_mix.code', 'products_mix.name', + "quantity_mix_required" ]) products_mix = product[0].get('products_mix.') if not products_mix: @@ -3110,7 +3114,7 @@ class AppWindow(FrontWindow): line = self.dialog_product_edit.get() try: code = line['product.']['code'] - except: + except Exception: code = line['product']['code'] product = self.Product.find([('code', '=', code)]) @@ -3128,7 +3132,7 @@ class AppWindow(FrontWindow): def action_print_count_money(self, data): try: self.receipt_sale.print_count_money(data) - except: + except Exception: pass def action_delete_line(self): @@ -3534,21 +3538,19 @@ class AppWindow(FrontWindow): self.dialog_delivery_party = DialogDeliveryParty(self).get() def update_delivery_party(self, field=''): + state_delivery = self.state_delivery_party if field == 'delivery_party': - self.state_delivery_party['party'] = self.row_delivery_party.text() - if field == 'row_phone': - self.state_delivery_party['phone'] = self.row_phone.text() - if field == 'id_number': - self.state_delivery_party['id_number'] = self.row_id_number.text() - if field == 'number_plate': - self.state_delivery_party['number_plate'] = self.row_number_plate.text( - ) - if field == 'type_vehicle': - self.state_delivery_party['type_vehicle'] = self.row_type_vehicle.get_id( - ) - if field == 'delivery_party_active': - self.state_delivery_party['active'] = self.row_delivery_party_active.isChecked( - ) + state_delivery['party'] = self.row_delivery_party.text() + elif field == 'delivery_party_active': + state_delivery['active'] = self.row_delivery_party_active.isChecked() + elif field == 'row_phone': + state_delivery['phone'] = self.row_phone.text() + elif field == 'id_number': + state_delivery['id_number'] = self.row_id_number.text() + elif field == 'number_plate': + state_delivery['number_plate'] = self.row_number_plate.text() + elif field == 'type_vehicle': + state_delivery['type_vehicle'] = self.row_type_vehicle.get_id() def search_consumer(self, phone): if phone: diff --git a/app/models.py b/app/models.py index 2f568ce..ad99a9f 100644 --- a/app/models.py +++ b/app/models.py @@ -31,10 +31,10 @@ MODELS_RESTAURANT = { 'payment_term.rec_name', 'payments', 'tip_amount', 'total_amount', 'residual_amount', 'paid_amount', 'untaxed_amount', 'tax_amount', 'delivery_charge', 'price_list', 'invoice_number', - 'shipment_address', 'kind', 'shop', 'order_status', + 'shipment_address', 'kind', 'shop', 'order_status', 'delivery_party', 'reference', 'comment', 'payment_method', - 'delivery_state', 'table_assigned.name', 'invoice_type', 'net_amount', - 'delivery_amount', + 'delivery_state', 'table_assigned.name', 'invoice_type', + 'net_amount', 'delivery_amount', 'source.rec_name', 'position', 'payment_term.payment_type', 'consumer.name', 'consumer.phone', 'consumer.rec_name', 'consumer.address', 'consumer.notes', 'consumer.delivery', @@ -82,7 +82,7 @@ MODELS_RESTAURANT = { 'fields': [ 'id', 'name', 'party', 'party.invoice_address', 'party.shipment_address' - ] + ] }, 'party.consumer': { 'rec_name': 'rec_name', @@ -97,8 +97,9 @@ MODELS_RESTAURANT = { 'sale.device': { 'rec_name': 'name', 'fields': [ - 'name', 'shop.company', 'shop.name', 'shop.taxes', 'shop.taxes.name', - 'shop.party.name', 'journals.name', 'journals.require_voucher', 'journals.kind', + 'name', 'shop.company', 'shop.name', 'shop.taxes', + 'shop.party.name', 'journals.name', 'journals.require_voucher', + 'journals.kind', 'shop.taxes.name', 'shop.product_categories.accounting', 'shop.product_categories.name', 'shop.product_categories.name_icon', @@ -116,16 +117,17 @@ MODELS_RESTAURANT = { 'shop.product_categories.childs.products.name', 'shop.product_categories.childs.products.code', 'shop.product_categories.childs.products.products_mix', - 'journal.name', - 'journal.kind', + 'journal.name', 'journal.kind', 'journal.require_voucher', - 'shop.payment_term.name', 'shop.warehouse', 'shop.discount_pos_method', + 'shop.payment_term.name', 'shop.warehouse', 'shop.salesman_pos_required', 'shop.electronic_authorization', 'shop.invoice_copies', 'shop.pos_authorization', 'shop.discounts', 'shop.computer_authorization', 'shop.manual_authorization', - 'shop.credit_note_electronic_authorization', 'shop.salesmans.rec_name', - 'shop.debit_note_electronic_authorization', 'shop.delivery_man.active', - 'shop.delivery_man.rec_name', 'shop.price_list.name', 'shop.order_copies' + 'shop.credit_note_electronic_authorization', + 'shop.salesmans.rec_name', 'shop.discount_pos_method', + 'shop.debit_note_electronic_authorization', + 'shop.delivery_man.rec_name', 'shop.price_list.name', + 'shop.order_copies', 'shop.delivery_man.active', ] }, 'sale.shop': { @@ -151,8 +153,8 @@ MODELS_RESTAURANT = { 'fields': [ 'name', 'id_number', 'addresses.street', 'phone', 'customer_payment_term.name', 'customer_payment_term.payment_type', - 'credit_limit_amount', 'receivable', - 'salesman', 'credit_amount', 'street', 'invoice_type' + 'credit_limit_amount', 'receivable', + 'salesman', 'credit_amount', 'street', 'invoice_type' ] }, 'ir.action.report': { @@ -171,7 +173,7 @@ MODELS_RESTAURANT = { 'print_invoice_payment', 'encoded_sale_price', 'delivery_product.list_price', 'delivery_product.code', 'delivery_product.name', 'allow_discount_handle', - 'cache_products_local', 'show_party_categories', + 'cache_products_local', 'show_party_categories', 'print_lines_product', 'uvt_pos' ] }, @@ -299,7 +301,7 @@ MODELS_RETAIL = { 'fields': [ 'id', 'name', 'party', 'party.invoice_address', 'party.shipment_address' - ] + ] }, 'party.consumer': { 'rec_name': 'rec_name', @@ -314,8 +316,9 @@ MODELS_RETAIL = { 'sale.device': { 'rec_name': 'name', 'fields': [ - 'name', 'shop.company', 'shop.name', 'shop.taxes', 'shop.taxes.name', - 'shop.party.name', 'journals.name', 'journals.require_voucher', 'journals.kind', + 'name', 'shop.company', 'shop.name', 'shop.taxes', + 'shop.party.name', 'journals.name', 'journals.require_voucher', + 'journals.kind', 'shop.taxes.name', 'shop.product_categories.accounting', 'shop.product_categories.name', 'shop.product_categories.name_icon', @@ -332,14 +335,16 @@ MODELS_RETAIL = { 'shop.product_categories.childs.products.name', 'shop.product_categories.childs.products.code', 'journal.name', 'journal.require_voucher', - 'journal.kind', - 'shop.payment_term.name', 'shop.warehouse', 'shop.discount_pos_method', + 'journal.kind', 'shop.discount_pos_method', + 'shop.payment_term.name', 'shop.warehouse', 'shop.salesman_pos_required', 'shop.electronic_authorization', 'shop.invoice_copies', 'shop.pos_authorization', 'shop.discounts', 'shop.computer_authorization', 'shop.manual_authorization', - 'shop.credit_note_electronic_authorization', 'shop.salesmans.rec_name', - 'shop.debit_note_electronic_authorization', 'shop.delivery_man.active', - 'shop.delivery_man.rec_name', 'shop.price_list.name', 'shop.order_copies' + 'shop.credit_note_electronic_authorization', + 'shop.salesmans.rec_name', 'shop.delivery_man.active', + 'shop.debit_note_electronic_authorization', + 'shop.delivery_man.rec_name', 'shop.price_list.name', + 'shop.order_copies' ] }, 'sale.shop': { @@ -364,8 +369,8 @@ MODELS_RETAIL = { 'fields': [ 'name', 'id_number', 'addresses.street', 'phone', 'customer_payment_term.name', 'customer_payment_term.payment_type', - 'credit_limit_amount', 'receivable', - 'salesman', 'credit_amount', 'street', 'invoice_type' + 'credit_limit_amount', 'receivable', + 'salesman', 'credit_amount', 'street', 'invoice_type' ] }, 'ir.action.report': { @@ -384,7 +389,7 @@ MODELS_RETAIL = { 'print_invoice_payment', 'encoded_sale_price', 'delivery_product.list_price', 'delivery_product.code', 'delivery_product.name', 'allow_discount_handle', - 'cache_products_local', 'show_party_categories', + 'cache_products_local', 'show_party_categories', 'print_lines_product', 'uvt_pos' ] }, diff --git a/app/proxy.py b/app/proxy.py index 778f084..6fa3928 100644 --- a/app/proxy.py +++ b/app/proxy.py @@ -1,19 +1,19 @@ +# import ssl import os import base64 import tempfile -import ssl from datetime import date from decimal import Decimal from http.client import HTTPConnection, HTTPSConnection import orjson as json try: from app.models import MODELS_RESTAURANT, MODELS_RETAIL -except: +except Exception: from models import MODELS_RESTAURANT, MODELS_RETAIL try: from app.commons.common import slugify, file_open -except: +except Exception: from commons.common import slugify, file_open from app.commons.dblogin import context_http @@ -37,6 +37,7 @@ def encoder(obj): return str(obj) raise TypeError(repr(obj) + " is not JSON serializable") + def logout(ctx): port = ctx['params']['port'] host = ctx['params']['server'] @@ -46,12 +47,11 @@ def logout(ctx): else: conn = HTTPSConnection(host, port=port, context=context_http) url = '/' + db + '/logout' - payload = json.dumps({'context': { - 'session':ctx.get('session'), - 'login': ctx.get('login') - }} - , - default=encoder) + payload = json.dumps({ + 'context': { + 'session': ctx.get('session'), + 'login': ctx.get('login')} + }, default=encoder) conn.request('POST', url, body=payload, headers=HEADERS) response = conn.getresponse() if response.status != 200: @@ -111,7 +111,7 @@ class Model(object): } res = self.get_connection('POST', '/search', args_) return res - + def fields_get(self, fields=[]): if not fields: fields = self.fields @@ -161,7 +161,7 @@ class Model(object): } res = self.get_connection('POST', '/create', args_) return res - + def method_instance(self, method, instance): args_ = { 'model': self.model, @@ -188,7 +188,10 @@ class Model(object): else: payload = None if self.context_http: - conn = self.conn(self.host, port=self.port, context=self.context_http) + conn = self.conn( + self.host, + port=self.port, + context=self.context_http) else: conn = self.conn(self.host, port=self.port) conn.request(method, url, body=payload, headers=HEADERS) @@ -197,7 +200,9 @@ class Model(object): if response.status != 200: if self.main_window: print(res, 'valida') - self.main_window.dialog('error_server', extra_message=res['detail']['error']) + self.main_window.dialog( + 'error_server', + extra_message=res['detail']['error']) res = res['detail'] conn.close() return res diff --git a/app/reporting.py b/app/reporting.py index 7e59b1d..578dff4 100755 --- a/app/reporting.py +++ b/app/reporting.py @@ -6,6 +6,7 @@ import logging import traceback from datetime import datetime from decimal import Decimal +import subprocess from .printing.protocols import FileSSH @@ -178,11 +179,33 @@ class Receipt(object): self._device = device self._profile = printer['profile'] + def check_status(self, interface, device): + status = False + if interface == "network": + command = "ping -c 1 " if OS_NAME == 'posix' else "ping -n 1" + response = subprocess.call(str(command + device).split(" ")) + if response == 0: + status = True + elif interface == "usb": + if OS_NAME == 'posix': + status = os.path.exists(device) + elif OS_NAME == 'nt': + status = True + return status + def set_printer(self): try: + status = self.check_status(self._interface, self._device) + if not status: + msg = f''' + Impresora no esta disponible; + revisa la configuracion o conexion de impresora + interface: {self._interface}, device: {self._device} + ''' + print(msg) + return msg if self._interface == 'usb': if OS_NAME == 'posix': - print() self._printer = printer.File( self._device, profile=self._profile) elif OS_NAME == 'nt': @@ -191,68 +214,68 @@ class Receipt(object): elif self._interface == 'network': try: host, port = self._device.split(":") - except: + except Exception: host, port = self._device, None if port: self._printer = printer.Network(host, port=int(port), timeout=15) else: self._printer = printer.Network(host, timeout=15) - elif self._interface == 'ssh': - self._printer = FileSSH(*self._device.split('@')) - self._printer.open() - elif self._interface == 'cups': - self.conn = cups.Connection() - self._file = open(TEMP_INVOICE_FILE, 'w') - self._printer = CupsPrinter(self._file, self._row_characters) + # elif self._interface == 'ssh': + # self._printer = FileSSH(*self._device.split('@')) + # self._printer.open() + # elif self._interface == 'cups': + # self.conn = cups.Connection() + # self._file = open(TEMP_INVOICE_FILE, 'w') + # self._printer = CupsPrinter(self._file, self._row_characters) if not self._printer: + msg = "Warning: Can not found Printer!" self.logger.info("Warning: Can not found Printer!") - return + return msg self.logger.info("Info: Printer is OK!") - except: + except Exception as e: traceback.print_exc() - self.logger.info("Warning: Printer error or device not found!") - - def validate_printer(self, _interface, ): - return - + self.logger.info( + "Warning: Printer error or device not found!", str(e)) def print_sale(self, sale, type_doc=None, open_box=False): try: # if call this function we can ommit line 216 to 238 - # self.set_printer() - if self._interface == 'usb': - if OS_NAME == 'posix': - self._printer = printer.File( - self._device, profile=self._profile) - elif OS_NAME == 'nt': - self._printer = printer.Win32Raw(self._device) - self._printer.open() - elif self._interface == 'network': - try: - host, port = self._device.split(":") - except: - host, port = self._device, None - if port: - self._printer = printer.Network(host, port=int(port), timeout=15) - else: - self._printer = printer.Network(host, timeout=15) - elif self._interface == 'ssh': - self._printer = FileSSH(*self._device.split('@')) - self._printer.open() - elif self._interface == 'cups': - self.conn = cups.Connection() - self._file = open(TEMP_INVOICE_FILE, 'w') - self._printer = CupsPrinter(self._file, self._row_characters) - if not self._printer: - self.logger.info("Warning: Can not found Printer!") - return - self.logger.info("Info: Printer is OK!") + msg = self.set_printer() + if msg: + return {"error": msg} + # if self._interface == 'usb': + # if OS_NAME == 'posix': + # self._printer = printer.File( + # self._device, profile=self._profile) + # elif OS_NAME == 'nt': + # self._printer = printer.Win32Raw(self._device) + # self._printer.open() + # elif self._interface == 'network': + # try: + # host, port = self._device.split(":") + # except: + # host, port = self._device, None + # if port: + # self._printer = printer.Network(host, port=int(port), timeout=15) + # else: + # self._printer = printer.Network(host, timeout=15) + # elif self._interface == 'ssh': + # self._printer = FileSSH(*self._device.split('@')) + # self._printer.open() + # elif self._interface == 'cups': + # self.conn = cups.Connection() + # self._file = open(TEMP_INVOICE_FILE, 'w') + # self._printer = CupsPrinter(self._file, self._row_characters) + # if not self._printer: + # self.logger.info("Warning: Can not found Printer!") + # return + # self.logger.info("Info: Printer is OK!") try: if type_doc in ('invoice', 'quotation') or self._environment == 'retail': self._print_sale(sale, type_doc, open_box) else: self._print_sale_verification(sale) - except: + except Exception: pass self._printer.close() except Exception as e: @@ -266,21 +289,18 @@ class Receipt(object): if not short: if sale.get('cufe'): self._printer.text('CUFE: ' + sale['cufe']) - try: - if sale.get('qr_code'): - self.print_qrcode(sale['qr_code']) - except: - pass + if sale.get('qr_code'): + self.print_qrcode(sale['qr_code']) self.print_footer(open_box, type_doc) else: self._printer.cut() # self.print_extra_info(sale) - if self._interface == 'cups': - self._file.close() - self.conn.printFile(self._printer_name, TEMP_INVOICE_FILE, - 'POS Invoice', {}) - else: - self._printer.close() + # if self._interface == 'cups': + # self._file.close() + # self.conn.printFile(self._printer_name, TEMP_INVOICE_FILE, + # 'POS Invoice', {}) + # else: + # self._printer.close() def _print_sale_verification(self, sale): self.print_header_sale_verification(sale) @@ -838,7 +858,7 @@ class Receipt(object): elif order['interface'] == 'network': try: host, port = host.split(":") - except: + except Exception: host, port = host, None if port: self._printer = printer.Network(host, port=int(port), timeout=15) @@ -862,10 +882,10 @@ class Receipt(object): self.logger.info("Info: Printer is OK!") try: res.append(self._print_order(order, reversion)) - except: + except Exception: pass self._printer.close() - except: + except Exception: self.logger.info("Warning: Can not found Printer!") res.append(None) return all(res) diff --git a/app/stack_messages.py b/app/stack_messages.py index cab4ee3..66a9a79 100644 --- a/app/stack_messages.py +++ b/app/stack_messages.py @@ -26,7 +26,7 @@ class StackMessages(QWidget): 'missing_agent': ('warning', 'FALTA EL AGENTE!'), 'missing_salesman': ('warning', 'NO HAY VENDEDOR EN LA VENTA!'), 'sale_without_products': ('warning', 'NO PUEDE CONFIRMAR VENTA SIN PRODUCTOS!'), - 'user_without_permission': ('error', 'USUARIO SIN PERMISOS DE VENTAS!'), + # 'user_without_permission': ('error', 'USUARIO SIN PERMISOS DE VENTAS!'), 'quantity_not_valid': ('error', 'LA CANTIDAD NO ES VALIDA...!'), 'user_not_permissions_device': ('error', 'EL USUARIO NO TIENE PERMISOS DE ACCESO!'), 'missing_party_configuration': ('warning', 'FALTA CONFIGURAR EL TERCERO POR DEFECTO!'), @@ -69,4 +69,5 @@ class StackMessages(QWidget): 'confirm_agent': ('question', 'Confirmar comision de agente'), 'qty_combo_min_req': ('error', 'Cantidad minima requerida!'), 'error_server': ('error', 'Error'), + 'print_error': ('error', 'Error de ImpresiĆ³n') } diff --git a/app/version.py b/app/version.py index 045fe8d..b329a7e 100644 --- a/app/version.py +++ b/app/version.py @@ -1 +1 @@ -__version__ = "6.0.17" +__version__ = "6.0.18" diff --git a/config_pos.ini b/config_pos.ini index 93bdf0d..c23f100 100644 --- a/config_pos.ini +++ b/config_pos.ini @@ -3,7 +3,7 @@ server=localhost port=8010 # options http or https mode=http -database=DEMO +database=DBNAME user=admin #########################################