new release version add option debug
This commit is contained in:
parent
c9b2f22b29
commit
543385d0fa
|
@ -21,6 +21,7 @@
|
|||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
*.log*
|
||||
|
||||
package-lock*
|
||||
|
||||
|
|
|
@ -63,12 +63,15 @@ class StartButtons(QVBoxLayout):
|
|||
values_extend([
|
||||
['button_control_panel', 'PANEL DE CONTROL', 'action_control_panel', 'settings'],
|
||||
['button_reports', 'REPORTES', 'action_reports', 'reports'],
|
||||
['button_historic_sales', 'HISTORIAL', 'action_historic_sales', 'sales_history'],
|
||||
])
|
||||
if parent.environment == 'retail':
|
||||
values_extend([
|
||||
['button_collection', 'RECAUDO', 'action_collection', 'collection']
|
||||
])
|
||||
else:
|
||||
values_extend([
|
||||
['button_historic_sales', 'HISTORIAL', 'action_historic_sales', 'sales_history'],
|
||||
])
|
||||
|
||||
values_extend([
|
||||
['button_help', 'AYUDA', 'action_help', 'help'],
|
||||
|
@ -156,7 +159,7 @@ class ButtonsFunction(QGridLayout):
|
|||
['button_change_salesman', 'CAMBIO VENDEDOR', 'action_change_salesman'],
|
||||
])
|
||||
pos_user = self.parent.type_pos_user
|
||||
if pos_user in ('order' ,'salesman'):
|
||||
if pos_user in ('order', 'salesman'):
|
||||
self.values.extend([
|
||||
['button_to_draft', 'BORRADOR', 'button_to_draft_pressed'],
|
||||
['button_to_quote', 'COTIZAR', 'button_to_quote_pressed'],
|
||||
|
|
|
@ -6,9 +6,8 @@ import gettext
|
|||
import logging
|
||||
import time
|
||||
import ssl
|
||||
from collections import OrderedDict
|
||||
from pathlib import Path
|
||||
from PySide6.QtWidgets import (QMainWindow, QDialog)
|
||||
from PySide6.QtWidgets import QDialog
|
||||
from PySide6.QtCore import Qt, QTimer
|
||||
from PySide6.QtGui import QPixmap
|
||||
from http.client import HTTPConnection, HTTPSConnection
|
||||
|
@ -16,6 +15,7 @@ import orjson as json
|
|||
from app.threads import VerifyConn
|
||||
from app.commons.config import Params
|
||||
from app.commons.ui_login import Ui_Login
|
||||
from logger_config import logger
|
||||
context_http = ssl._create_unverified_context()
|
||||
|
||||
_ = gettext.gettext
|
||||
|
@ -57,8 +57,7 @@ class Login(QDialog):
|
|||
conn.close()
|
||||
option = u"online"
|
||||
icon_conn = path_circle_green
|
||||
except Exception as e:
|
||||
print(e, 'error')
|
||||
except Exception:
|
||||
icon_conn = path_circle_red
|
||||
option = u"offline"
|
||||
self.ui.label_conn.setText(option)
|
||||
|
@ -135,7 +134,8 @@ class Login(QDialog):
|
|||
msg = 'Error: conexion del servidor'
|
||||
elif result['status'] == 500:
|
||||
msg = 'Error: interno del servidor \n' + result['message']
|
||||
print(msg, 'msg ,,,,', result['status'])
|
||||
logger.error(result)
|
||||
logger.info(msg)
|
||||
self.ui.label_error.setText(msg)
|
||||
self.error_message()
|
||||
else:
|
||||
|
|
|
@ -7,7 +7,6 @@ from collections import OrderedDict
|
|||
# )
|
||||
# from PyQt5.QtGui import QStandardItem, QStandardItemModel, QPixmap
|
||||
# from PyQt5.QtCore import Qt, pyqtSlot, QModelIndex
|
||||
from operator import methodcaller
|
||||
from PySide6.QtWidgets import (
|
||||
QDialog, QAbstractItemView, QVBoxLayout, QHBoxLayout, QLabel, QWidget,
|
||||
QTreeView, QLineEdit, QTableView, QCompleter
|
||||
|
@ -179,7 +178,7 @@ class QuickDialog(QDialog):
|
|||
print('cancell quitdialog')
|
||||
try:
|
||||
self.parent.label_input.setFocus()
|
||||
except:
|
||||
except Exception:
|
||||
pass
|
||||
self.setResult(0)
|
||||
self.hide()
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
from decimal import Decimal
|
||||
from datetime import datetime
|
||||
from operator import itemgetter, attrgetter
|
||||
from operator import itemgetter
|
||||
from .commons.dialogs import HelpDialog, QuickDialog
|
||||
# from PyQt5.QtCore import Qt, QSize
|
||||
# from PyQt5.QtWidgets import (
|
||||
# QCheckBox, QTextEdit, QVBoxLayout, QGridLayout, QLineEdit, QPlainTextEdit,
|
||||
# QScrollArea, QHBoxLayout, QDoubleSpinBox, QLabel, QMessageBox
|
||||
# )
|
||||
from PySide6.QtCore import Qt, QSize
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtWidgets import (
|
||||
QCheckBox, QTextEdit, QVBoxLayout, QGridLayout, QLineEdit, QPlainTextEdit,
|
||||
QScrollArea, QHBoxLayout, QDoubleSpinBox, QLabel, QMessageBox, QWidget
|
||||
QScrollArea, QHBoxLayout, QDoubleSpinBox, QLabel, QWidget
|
||||
)
|
||||
|
||||
from .proxy import Report
|
||||
|
@ -287,8 +287,8 @@ class SearchParty(SearchWindow):
|
|||
# 'street': parent.on_selected_street_party
|
||||
}
|
||||
super(SearchParty, self).__init__(parent, headers, None, methods,
|
||||
filter_column=[], cols_width=[60, 120, 270, 190, 90],
|
||||
title=title, fill=True)
|
||||
filter_column=[], cols_width=[60, 120, 270, 190, 90],
|
||||
title=title, fill=True)
|
||||
|
||||
|
||||
class SearchProduct(SearchWindow):
|
||||
|
@ -350,7 +350,7 @@ class SearchProduct(SearchWindow):
|
|||
fields_names = list(headers.keys())
|
||||
try:
|
||||
fields_names.remove('image')
|
||||
except:
|
||||
except Exception:
|
||||
pass
|
||||
self.fields_names = fields_names
|
||||
super(SearchProduct, self).__init__(parent, headers, None, methods,
|
||||
|
@ -594,7 +594,7 @@ class DialogSaleForm(QuickDialog):
|
|||
elements = (
|
||||
'id', 'party.', 'number', 'sale_date',
|
||||
'total_amount_cache', 'invoice_number', 'lines.'
|
||||
)
|
||||
)
|
||||
id, party, number, sale_date, total_amount_cache, invoice_number, lines = itemgetter(*elements)(data)
|
||||
self.sale_customer_selected = id
|
||||
self.field_party.setText(party['name'])
|
||||
|
@ -887,7 +887,7 @@ class DialogTableDeliveryParty(QuickDialog):
|
|||
method_selected_row=parent.delivery_party_selected
|
||||
)
|
||||
width, height = get_screen()
|
||||
table.setFixedSize(int(width/2.2), int(height/2.2))
|
||||
table.setFixedSize(int(width / 2.2), int(height / 2.2))
|
||||
vbox_ = QVBoxLayout()
|
||||
|
||||
grid = QGridLayout()
|
||||
|
@ -923,7 +923,7 @@ class DialogMoneyCount(QuickDialog):
|
|||
grid = QGridLayout()
|
||||
_sizes = (160, 120, 240)
|
||||
fields = (
|
||||
{'label': 'MONEDA', 'type': 'integer', 'readonly': True},
|
||||
{'label': 'MONEDA', 'type': 'integer', 'readonly': True},
|
||||
{'label': 'CANTIDAD', 'type': 'integer', 'change': 'set_total'},
|
||||
{'label': 'SUBTOTAL', 'type': 'integer', 'readonly': True},
|
||||
)
|
||||
|
@ -1029,8 +1029,8 @@ class DialogExpenses(QuickDialog):
|
|||
|
||||
_sizes = (140, 290, 210, 150)
|
||||
fields = (
|
||||
{'name': 'id', 'label': 'ID', 'type': 'integer', 'invisible': True},
|
||||
{'name': 'invoice_number', 'label': 'FACTURA', 'type': 'char'},
|
||||
{'name': 'id', 'label': 'ID', 'type': 'integer', 'invisible': True},
|
||||
{'name': 'invoice_number', 'label': 'FACTURA', 'type': 'char'},
|
||||
{'name': 'description', 'label': 'DESCRIPCION', 'type': 'char'},
|
||||
{'name': 'reference', 'label': 'REFERENCIA', 'type': 'char'},
|
||||
{'name': 'amount', 'label': 'VALOR', 'type': 'float', 'change': 'set_total'},
|
||||
|
@ -1126,7 +1126,7 @@ class DialogTaxes(QuickDialog):
|
|||
'heads': ['ID', 'VALOR'],
|
||||
}
|
||||
string = 'ESCOJA EL IMPUESTO'
|
||||
super(DialogTaxes, self).__init__(parent, 'selection', string, data)
|
||||
super(DialogTaxes, self).__init__(parent, 'selection', string, data)
|
||||
|
||||
|
||||
class DialogSource(QuickDialog):
|
||||
|
@ -1485,7 +1485,7 @@ class DialogComboProduct(QuickDialog):
|
|||
self.label_qty_min = QLabel('CANT. MIN.')
|
||||
self.label_qty_min.setObjectName('label_qty_min')
|
||||
self.hbox.addWidget(self.label_qty_min)
|
||||
|
||||
|
||||
self.label_qty_min_req = QLabel("")
|
||||
self.label_qty_min_req.setObjectName('label_qty_min_req')
|
||||
self.hbox.addWidget(self.label_qty_min_req)
|
||||
|
@ -1609,7 +1609,8 @@ class Help(HelpDialog):
|
|||
('DOMICILIARIO', 'F12'),
|
||||
('POSICION', 'Insert'),
|
||||
('FACTURAR', 'End'),
|
||||
('COMENTARIO', 'Quotation Marks'),
|
||||
('COMENTARIO', 'COMILLAS DOBLE (")'),
|
||||
('AGENTE', 'PUNTO Y COMA (;)'),
|
||||
)
|
||||
|
||||
self.set_shortcuts(shortcuts)
|
||||
|
@ -1618,7 +1619,6 @@ class Help(HelpDialog):
|
|||
class DialogListProduct(QuickDialog):
|
||||
def __init__(self, parent):
|
||||
self._parent = parent
|
||||
vbox = QVBoxLayout()
|
||||
grid = QGridLayout()
|
||||
label_code = QLabel('CODIGO:')
|
||||
label_code.setObjectName('label_info_product_code')
|
||||
|
@ -1806,7 +1806,7 @@ class DialogCollection(QuickDialog):
|
|||
self.input_filter.setObjectName('input_collection_filter')
|
||||
self.input_filter.editingFinished.connect(lambda: self.search())
|
||||
self.input_filter.returnPressed.connect(lambda: self.search())
|
||||
|
||||
|
||||
grid.addWidget(self.input_filter, 1, 2)
|
||||
|
||||
label_id_number = QLabel('DOCUMENTO:')
|
||||
|
@ -1836,8 +1836,8 @@ class DialogCollection(QuickDialog):
|
|||
label_payment_method.setObjectName('label_collection_payment_method')
|
||||
grid.addWidget(label_payment_method, 5, 1)
|
||||
self.combobox_payment_method = ComboBox(
|
||||
parent, 'payment_method_collection', {'values': self.get_payment_methods()}
|
||||
)
|
||||
parent, 'payment_method_collection', {'values': self.get_payment_methods()}
|
||||
)
|
||||
grid.addWidget(self.combobox_payment_method, 5, 2)
|
||||
|
||||
label_voucher_number = QLabel('NUMERO COMPROBANTE:')
|
||||
|
@ -1862,8 +1862,8 @@ class DialogCollection(QuickDialog):
|
|||
|
||||
def get_payment_methods(self):
|
||||
domain = [
|
||||
["sale_device", "=", self._parent.device['id']],
|
||||
["state", "=", "draft"]
|
||||
["sale_device", "=", self._parent.device['id']],
|
||||
["state", "=", "draft"]
|
||||
]
|
||||
statements = self._parent.Statement.find(domain,
|
||||
fields=['rec_name', 'journal.require_voucher'])
|
||||
|
|
|
@ -3,10 +3,7 @@ import time
|
|||
from datetime import date
|
||||
import logging
|
||||
from pathlib import Path
|
||||
# from PyQt5.QtWidgets import QMainWindow, QDesktopWidget, QLineEdit
|
||||
# from PyQt5.QtCore import QTimer, QThread, pyqtSignal
|
||||
from PySide6.QtWidgets import QMainWindow, QLineEdit
|
||||
from PySide6.QtCore import QTimer, QThread, Signal
|
||||
from PySide6.QtGui import QGuiApplication
|
||||
from .commons.dialogs import QuickDialog
|
||||
# from .commons.dblogin import safe_reconnect
|
||||
|
@ -29,11 +26,12 @@ from .constants import DIALOG_REPLY_YES
|
|||
from .version import __version__
|
||||
|
||||
|
||||
__all__ = ['FrontWindow', 'ClearUi']
|
||||
__all__ = ['FrontWindow']
|
||||
parent = Path(__file__).parent
|
||||
|
||||
file_base_css = os.path.join(str(parent), 'css', 'base.css')
|
||||
_DEFAULT_TIMEOUT = 60000 # on ms (100 minutes)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class FrontWindow(QMainWindow):
|
||||
|
@ -50,7 +48,6 @@ class FrontWindow(QMainWindow):
|
|||
# self.conn = connection
|
||||
self.version = __version__
|
||||
self.set_params(params)
|
||||
self.logger = logging.getLogger('app_logger')
|
||||
|
||||
"""
|
||||
We need get the size of screen (display)
|
||||
|
@ -201,6 +198,14 @@ class FrontWindow(QMainWindow):
|
|||
self._sale_pos_restaurant = None
|
||||
time1 = time.time()
|
||||
self.Module = Model('ir.module', self.ctx, main_window=self)
|
||||
module_names = [
|
||||
'sale_pos_frontend_rest', 'sale_pos',
|
||||
'sale_pos_frontend', 'account_credit_limit']
|
||||
modules = self.Module.find([
|
||||
('name', 'in', module_names),
|
||||
('state', '=', 'activated'),
|
||||
])
|
||||
self.modules = {m['name']: m for m in modules}
|
||||
print(time.time() - time1, 'final')
|
||||
self.Config = Model('sale.configuration', self.ctx, main_window=self)
|
||||
self.Sale = Model('sale.sale', self.ctx, main_window=self)
|
||||
|
@ -228,10 +233,7 @@ class FrontWindow(QMainWindow):
|
|||
self.sale_automatic = True
|
||||
res = self.Sale.fields_get(['commission'])
|
||||
self._commission_activated = True if res.get('commission') else False
|
||||
self._credit_limit_activated = self.Module.find([
|
||||
('name', '=', 'account_credit_limit'),
|
||||
('state', '=', 'activated'),
|
||||
])
|
||||
self._credit_limit_activated = 'account_credit_limit' in self.modules
|
||||
|
||||
# _product = {
|
||||
# 'name': 'product.product',
|
||||
|
@ -340,20 +342,13 @@ class FrontWindow(QMainWindow):
|
|||
self._password_admin = self._config.get('password_admin_pos')
|
||||
self._password_force_assign = self._config.get('password_force_assign')
|
||||
if self.environment == 'restaurant':
|
||||
self._sale_pos_restaurant = self.Module.find([
|
||||
('name', '=', 'sale_pos_frontend_rest'),
|
||||
('state', '=', 'activated'),
|
||||
])
|
||||
self._sale_pos_restaurant = 'sale_pos_frontend_rest' in self.modules
|
||||
print(self._sale_pos_restaurant, 'validate rest')
|
||||
if self._sale_pos_restaurant:
|
||||
self.RestTables = Model('sale.shop.table', self.ctx, main_window=self)
|
||||
self.Consumer = Model('party.consumer', self.ctx, main_window=self)
|
||||
# TODO get product and printers
|
||||
self.printers_shop, self.products_printers = None, None
|
||||
try:
|
||||
self.printers_shop, self.products_printers = self.Sale.get_product_printers(
|
||||
self.shop['id'])
|
||||
except Exception:
|
||||
pass
|
||||
self.printers_shop, self.products_printers = self.Sale.get_product_printers(
|
||||
self.shop['id'])
|
||||
|
||||
self._action_report_invoice, = self.ActionReport.find([
|
||||
('report_name', '=', 'account.invoice'),
|
||||
|
@ -374,17 +369,3 @@ class FrontWindow(QMainWindow):
|
|||
self.Source = Model('sale.source', self.ctx, main_window=self)
|
||||
self.Pricelist = Model('product.price_list', self.ctx, main_window=self)
|
||||
return True
|
||||
|
||||
|
||||
class ClearUi(QThread):
|
||||
# sigActionClear = pyqtSignal()
|
||||
sigActionClear = Signal()
|
||||
state = None
|
||||
|
||||
def __init__(self, wait_time):
|
||||
QThread.__init__(self)
|
||||
self.wait_time = wait_time
|
||||
|
||||
def run(self):
|
||||
time.sleep(self.wait_time)
|
||||
self.sigActionClear.emit()
|
||||
|
|
238
app/main.py
238
app/main.py
|
@ -7,7 +7,7 @@ import base64
|
|||
import time
|
||||
import traceback
|
||||
from decimal import Decimal
|
||||
from datetime import datetime, timedelta, date
|
||||
from datetime import datetime, timedelta
|
||||
from collections import OrderedDict
|
||||
from PySide6 import QtGui
|
||||
from PySide6.QtCore import Qt, QTimer
|
||||
|
@ -16,7 +16,7 @@ from PySide6.QtWidgets import (
|
|||
QWidget)
|
||||
from app.commons.image import Image
|
||||
from .frontwindow import FrontWindow
|
||||
from .tools import get_icon, to_float, to_numeric
|
||||
from .tools import get_icon, to_float, to_numeric, compare_versions
|
||||
from .status_bar import StatusBar
|
||||
from .stack_messages import StackMessages
|
||||
# from app.commons.action import Action
|
||||
|
@ -31,7 +31,7 @@ from .proxy import Report
|
|||
from .buttonpad import ButtonsStacked, ButtonsFunction, StartButtons
|
||||
from .states import STATES, RE_SIGN
|
||||
from .commons.custom_button import CustomButton
|
||||
from .threads import DoInvoice, VerifyOrderCommand
|
||||
from .threads import DoInvoice
|
||||
from .store import StoreView
|
||||
from .constants import (
|
||||
PATH_PRINTERS, DELTA_LOCALE, STRETCH, alignRight, alignLeft, alignCenter,
|
||||
|
@ -76,7 +76,8 @@ class AppWindow(FrontWindow):
|
|||
return
|
||||
self.setup_sale_line()
|
||||
self.setup_delivery_party()
|
||||
self.setup_sale_consumer()
|
||||
if self.environment == 'restaurant':
|
||||
self.setup_sale_consumer()
|
||||
self.setup_payment()
|
||||
# self.set_domains()
|
||||
print(time.time() - time1, 'set domains')
|
||||
|
@ -106,19 +107,16 @@ class AppWindow(FrontWindow):
|
|||
self.reader_thread = ScaleReader()
|
||||
self.reader_thread.sigSetWeight.connect(self.set_weight_readed)
|
||||
|
||||
if self.server_printer:
|
||||
self.verify_command_order_th = VerifyOrderCommand(self)
|
||||
self.verify_command_order_th.sigVerifyOrderCommand.connect(self.verify_print_order_automatic)
|
||||
self.verify_command_order_th.start()
|
||||
if self.server_printer and self.environment == 'restaurant':
|
||||
timer = QTimer()
|
||||
timer.timeout.connect(self.verify_print_order_automatic)
|
||||
timer.start(30000)
|
||||
|
||||
self.do_invoice = DoInvoice(self, self.ctx)
|
||||
self.do_invoice.sigDoInvoice.connect(self.__do_invoice_thread)
|
||||
self.set_state('disabled')
|
||||
self.change_view_to('start_front')
|
||||
|
||||
# if self.cache_local:
|
||||
# self.set_cache_company()
|
||||
# self.set_cache_products()
|
||||
matching_journal = next((j for j in self._journals if j['id'] == self.default_journal['id']), None)
|
||||
if matching_journal:
|
||||
self.default_journal = matching_journal
|
||||
|
@ -136,24 +134,45 @@ class AppWindow(FrontWindow):
|
|||
self.field_agent = None
|
||||
|
||||
def verify_print_order_automatic(self):
|
||||
records = self.Sale.get_orders_to_command({'shop': self.shop['id']})
|
||||
for record in records:
|
||||
orders = record['orders']
|
||||
tasks = record['tasks']
|
||||
try:
|
||||
result = self.receipt_order.print_orders(orders.values())
|
||||
if result:
|
||||
self.Sale.mark_commanded({'sale_id': record['id'], 'lines_ids': result})
|
||||
receipt = Receipt(context={}, environment='restaurant')
|
||||
receipt.print_tasks(tasks)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
traceback.print_exc()
|
||||
args = {'shop': self.shop['id']}
|
||||
orders = []
|
||||
tasks = []
|
||||
version = compare_versions(self.modules['sale_pos_frontend_rest']['version'], '6.0.7')
|
||||
if version in ('equal', 'higher'):
|
||||
print('pasa por esta new query')
|
||||
if not self.tasks_station:
|
||||
orders = self.SaleLine.get_data_command(args)
|
||||
else:
|
||||
result = self.SaleLine.get_data_command_and_task(args)
|
||||
orders = result['orders']
|
||||
tasks = result['tasks']
|
||||
|
||||
timer = QTimer()
|
||||
timer.timeout.connect(self.verify_print_order_automatic)
|
||||
timer.start(30000)
|
||||
self.verify_command_order_th.exit(0)
|
||||
# TODO: for remove this option
|
||||
else:
|
||||
records = self.Sale.get_orders_to_command(args)
|
||||
for record in records:
|
||||
orders += record['orders'].values()
|
||||
tasks += record['tasks'].values()
|
||||
print('ingresa a impresion', orders)
|
||||
print('ingresa a impresion tasks', tasks)
|
||||
try:
|
||||
result = self.receipt_order.print_orders(orders)
|
||||
if result:
|
||||
self.Sale.mark_commanded({'lines_ids': result})
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
|
||||
try:
|
||||
receipt = Receipt(context={}, environment='restaurant')
|
||||
result_print = receipt.print_tasks(tasks)
|
||||
if any(result_print):
|
||||
print(result_print, 'validate print')
|
||||
self.SaleLine.mark_tasks_printed({'task_ids': result_print})
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
# timer = QTimer()
|
||||
# timer.singleShot(30000, self.verify_print_order_automatic)
|
||||
# self.verify_command_order_th.exit(0)
|
||||
|
||||
# def set_domains(self):
|
||||
# self.domain_search_product = [
|
||||
|
@ -1745,7 +1764,7 @@ class AppWindow(FrontWindow):
|
|||
}
|
||||
orders, sale_number = self.Sale.get_reversion(args)
|
||||
self.receipt_order.print_orders(orders.values(), reversion=True)
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
print(self.print_order, 'validar variable en opcion print_order=True en config_pos.ini')
|
||||
logging.error('Printing order reversion fail!')
|
||||
|
||||
|
@ -1823,10 +1842,11 @@ class AppWindow(FrontWindow):
|
|||
if res == DIALOG_REPLY_NO:
|
||||
return False
|
||||
result = None
|
||||
if not sale.get('number'):
|
||||
result_set = self.Sale.set_sale_number({'sale_id': sale_id})
|
||||
self.store.set({'number': result_set})
|
||||
self.order_number.setText(result_set)
|
||||
number = sale.get('number')
|
||||
if not number:
|
||||
number = self.Sale.set_sale_number({'sale_id': sale_id})
|
||||
self.store.set({'number': number})
|
||||
self.order_number.setText(number)
|
||||
if self.environment == 'restaurant':
|
||||
if self.print_order:
|
||||
result = self.print_command(sale)
|
||||
|
@ -1842,6 +1862,7 @@ class AppWindow(FrontWindow):
|
|||
|
||||
def get_header_sale(self, sale):
|
||||
order = {
|
||||
'id': self.sale_id,
|
||||
'sale_number': sale['number'],
|
||||
'number': sale.get('invoice_number'),
|
||||
'turn': sale.get('turn'),
|
||||
|
@ -1875,65 +1896,87 @@ class AppWindow(FrontWindow):
|
|||
return result
|
||||
|
||||
def print_command(self, sale, line_reversion=None):
|
||||
order = self.get_header_sale(sale)
|
||||
version = compare_versions(self.modules['sale_pos_frontend_rest']['version'], '6.0.7')
|
||||
reversion = False if not line_reversion else True
|
||||
lines = [line_reversion] if reversion else self.model_sale_lines._data
|
||||
orders = {}
|
||||
lines_ids = []
|
||||
for ln in lines:
|
||||
if not reversion and ln['order_sended'] in (True, '✔'):
|
||||
continue
|
||||
pd_id = ln['product.']['id']
|
||||
try:
|
||||
printers, cat_id = self.products_printers.get(str(pd_id))
|
||||
cat_id = str(cat_id[0])
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
printers, cat_id = None, None
|
||||
if printers:
|
||||
for printer_id in printers:
|
||||
printer = self.printers_shop.get(str(printer_id))
|
||||
if printer_id not in orders.keys():
|
||||
orders[printer_id] = {
|
||||
**order,
|
||||
**printer,
|
||||
'lines_ids': []
|
||||
lines = [line_reversion] if reversion else self.model_sale_lines._data
|
||||
if version in ('equal', 'higher'):
|
||||
order = self.get_header_sale(sale)
|
||||
for ln in lines:
|
||||
if not reversion and ln['order_sended'] in (True, '✔'):
|
||||
continue
|
||||
pd_id = ln['product.']['id']
|
||||
try:
|
||||
printers, cat_id = self.products_printers.get(str(pd_id))
|
||||
cat_id = str(cat_id[0])
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
printers, cat_id = None, None
|
||||
if printers:
|
||||
for printer_id in printers:
|
||||
printer = self.printers_shop.get(str(printer_id))
|
||||
if printer_id not in orders.keys():
|
||||
orders[printer_id] = {
|
||||
**order,
|
||||
**printer,
|
||||
'lines_ids': []
|
||||
}
|
||||
if printer.get('categories'):
|
||||
orders[printer_id]['lines'] = {**printer['lines']}
|
||||
orders[printer_id]['categories'] = {**printer['categories']}
|
||||
else:
|
||||
orders[printer_id]['lines'] = []
|
||||
value_line = {
|
||||
'name': ln['product.']['name'],
|
||||
'quantity': str(ln['quantity']),
|
||||
'sale_price_taxed': '',
|
||||
'amount_w_tax': ln['amount_w_tax'],
|
||||
'note': ln['note']
|
||||
}
|
||||
if printer.get('categories'):
|
||||
orders[printer_id]['lines'] = {**printer['lines']}
|
||||
orders[printer_id]['categories'] = {**printer['categories']}
|
||||
if isinstance(orders[printer_id]['lines'], list):
|
||||
orders[printer_id]['lines'].append(value_line)
|
||||
orders[printer_id]['lines_ids'].append(ln['id'])
|
||||
else:
|
||||
orders[printer_id]['lines'] = []
|
||||
value_line = {
|
||||
'name': ln['product.']['name'],
|
||||
'quantity': str(ln['quantity']),
|
||||
'sale_price_taxed': '',
|
||||
'amount_w_tax': ln['amount_w_tax'],
|
||||
'note': ln['note']
|
||||
}
|
||||
if isinstance(orders[printer_id]['lines'], list):
|
||||
orders[printer_id]['lines'].append(value_line)
|
||||
orders[printer_id]['lines_ids'].append(ln['id'])
|
||||
else:
|
||||
try:
|
||||
key_id = orders[printer_id]['categories'][cat_id]
|
||||
except Exception:
|
||||
if 'others' not in orders[printer_id]['lines'].keys():
|
||||
orders[printer_id]['lines']['others'] = {'name': 'OTROS', 'lines':[]}
|
||||
key_id = 'others'
|
||||
try:
|
||||
orders[printer_id]['lines'][key_id]['lines'].append(value_line)
|
||||
orders[printer_id]['lines_ids'].append(ln['id'])
|
||||
except Exception:
|
||||
orders[printer_id]['lines'][key_id]['lines'] = [value_line]
|
||||
orders[printer_id]['lines_ids'].append(ln['id'])
|
||||
try:
|
||||
key_id = orders[printer_id]['categories'][cat_id]
|
||||
except Exception:
|
||||
if 'others' not in orders[printer_id]['lines'].keys():
|
||||
orders[printer_id]['lines']['others'] = {'name': 'OTROS', 'lines': []}
|
||||
key_id = 'others'
|
||||
try:
|
||||
orders[printer_id]['lines'][key_id]['lines'].append(value_line)
|
||||
orders[printer_id]['lines_ids'].append(ln['id'])
|
||||
except Exception:
|
||||
orders[printer_id]['lines'][key_id]['lines'] = [value_line]
|
||||
orders[printer_id]['lines_ids'].append(ln['id'])
|
||||
else:
|
||||
lines_ids.append(ln['id'])
|
||||
else:
|
||||
# for remove this code
|
||||
if reversion:
|
||||
args = {'sale_id': self.sale_id, 'sale_line_id': line_reversion['id']}
|
||||
orders, sale_number = self.Sale.get_reversion(args)
|
||||
else:
|
||||
lines_ids.append(ln['id'])
|
||||
args = {'sale_id': self.sale_id}
|
||||
orders, sale_number = self.Sale.get_order2print(args)
|
||||
|
||||
if self.environment == 'restaurant' and self.tasks_station:
|
||||
data_station = self.Sale.method_instance('get_data_for_stations', self.sale_id)
|
||||
receipt = Receipt(context={}, environment='restaurant')
|
||||
receipt.print_tasks(data_station)
|
||||
if version in ('equal', 'higher'):
|
||||
args = {
|
||||
'shop': self.shop['id'],
|
||||
'sale_id': self.sale_id
|
||||
}
|
||||
tasks = self.SaleLine.get_data_tasks(args)
|
||||
receipt = Receipt(context={}, environment='restaurant')
|
||||
result_print = receipt.print_tasks(tasks)
|
||||
if any(result_print):
|
||||
self.SaleLine.mark_tasks_printed(result_print)
|
||||
else:
|
||||
data_station = self.Sale.method_instance('get_data_for_stations', self.sale_id)
|
||||
receipt = Receipt(context={}, environment='restaurant')
|
||||
receipt.print_tasks(data_station.values())
|
||||
|
||||
result = self.receipt_order.print_orders(orders.values(), reversion)
|
||||
lines_sended = result + lines_ids
|
||||
if not reversion and lines_sended:
|
||||
|
@ -1960,11 +2003,12 @@ class AppWindow(FrontWindow):
|
|||
if self._ask_new_sale():
|
||||
self.create_new_sale()
|
||||
|
||||
def numpad_price_clicked(self):
|
||||
code = self.label_input.text()
|
||||
product = self._search_product(code)
|
||||
if not product:
|
||||
return
|
||||
# for remove
|
||||
# def numpad_price_clicked(self):
|
||||
# code = self.label_input.text()
|
||||
# product = self._search_product(code)
|
||||
# if not product:
|
||||
# return
|
||||
|
||||
def _ask_new_sale(self):
|
||||
dialog = self.dialog('new_sale', response=True)
|
||||
|
@ -2235,7 +2279,7 @@ class AppWindow(FrontWindow):
|
|||
if sale.get('payments'):
|
||||
for payment in sale['payments']:
|
||||
# FIXME
|
||||
#self.table_payment_lines.record_add(payment)
|
||||
# self.table_payment_lines.record_add(payment)
|
||||
pass
|
||||
|
||||
self.party_id = sale['party.']['id']
|
||||
|
@ -2431,7 +2475,7 @@ class AppWindow(FrontWindow):
|
|||
qty_text = self.dialog_combo_product.label_qty_add.text()
|
||||
try:
|
||||
qty = int(qty_text) + 1
|
||||
except:
|
||||
except Exception:
|
||||
qty = 1
|
||||
self.dialog_combo_product.label_qty_add.setText(str(qty))
|
||||
self.on_selected_item(record, list_price)
|
||||
|
@ -2557,7 +2601,7 @@ class AppWindow(FrontWindow):
|
|||
|
||||
ctx = self.stock_context
|
||||
if not self.stock_context:
|
||||
ctx = {'price_list': self.shop['price_list.']['id']}
|
||||
ctx = {'price_list': self.shop['price_list.']['id']}
|
||||
else:
|
||||
ctx['price_list'] = self.shop['price_list.']['id']
|
||||
fields = self.dialog_search_products.fields_names
|
||||
|
@ -2795,14 +2839,14 @@ class AppWindow(FrontWindow):
|
|||
('barcode', '=', code),
|
||||
('code', '=', code)
|
||||
])
|
||||
# 'image', 'image_icon', 'write_date' fields remove from domain
|
||||
products = self.Product.find(
|
||||
domain,
|
||||
fields=[
|
||||
'name', 'code', 'categories', 'description',
|
||||
'id', 'image', 'image_icon', 'list_price',
|
||||
'quantity', 'rec_name', 'template',
|
||||
'id', 'list_price', 'quantity', 'rec_name', 'template',
|
||||
'extra_tax', 'template.sale_price_w_tax',
|
||||
'template.default_uom', 'write_date'])
|
||||
'template.default_uom'])
|
||||
|
||||
if not products or len(products) > 1:
|
||||
self.message_bar.set('product_not_found')
|
||||
|
@ -2856,6 +2900,7 @@ class AppWindow(FrontWindow):
|
|||
product_id = record['id'] if record else None
|
||||
if not product_id and code:
|
||||
# REMOVE ME THIS OPTION IS FOR BARCODE
|
||||
# product = self._search_product(code)
|
||||
product = self._search_product(code)
|
||||
if product:
|
||||
product_id = product['id']
|
||||
|
@ -3282,7 +3327,8 @@ class AppWindow(FrontWindow):
|
|||
if note:
|
||||
self.SaleLine.write([removed_item['id']], {'note': note})
|
||||
prd_code = removed_item['product.']['code']
|
||||
if prd_code and self._config['tip_product.']['code'] == prd_code:
|
||||
tip_product = self._config.get('tip_product.')
|
||||
if prd_code and tip_product and tip_product['code'] == prd_code:
|
||||
self.Sale.write([self.sale_id], {'tip': None})
|
||||
self.SaleLine.delete([removed_item['id']])
|
||||
self.set_amounts()
|
||||
|
|
|
@ -388,7 +388,6 @@ MODELS_RETAIL = {
|
|||
'new_sale_automatic', 'show_product_image', 'delivery_product.code',
|
||||
'encoded_sale_price', 'delivery_product.list_price',
|
||||
'delivery_product.name', 'allow_discount_handle',
|
||||
'no_remove_commanded',
|
||||
'cache_products_local', 'show_party_categories',
|
||||
'print_lines_product', 'uvt_pos'
|
||||
]
|
||||
|
|
134
app/reporting.py
134
app/reporting.py
|
@ -8,7 +8,6 @@ from datetime import datetime
|
|||
from decimal import Decimal
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
from .printing.protocols import FileSSH
|
||||
|
||||
try:
|
||||
|
@ -77,7 +76,6 @@ class Receipt(object):
|
|||
__name__ = 'frontend_pos.ticket'
|
||||
|
||||
def __init__(self, context={}, row_characters=None, logo=None, environment='retail'):
|
||||
self.logger = logging.getLogger('reporting')
|
||||
self._company = context.get('company')
|
||||
self._sale_device = context.get('sale_device')
|
||||
self._shop = context.get('shop')
|
||||
|
@ -217,18 +215,16 @@ class Receipt(object):
|
|||
except Exception:
|
||||
host, port = self._device, None
|
||||
if port:
|
||||
self._printer = printer.Network(host, port=int(port), timeout=15)
|
||||
self._printer = printer.Network(host, port=int(port), timeout=5)
|
||||
else:
|
||||
self._printer = printer.Network(host, timeout=15)
|
||||
self._printer = printer.Network(host, timeout=5)
|
||||
if not self._printer:
|
||||
msg = "Warning: Can not found Printer!"
|
||||
self.logger.info("Warning: Can not found Printer!")
|
||||
logging.info("Warning: Can not found Printer!")
|
||||
return msg
|
||||
self.logger.info("Info: Printer is OK!")
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
self.logger.info(
|
||||
"Warning: Printer error or device not found!", str(e))
|
||||
except Exception:
|
||||
logging.exception(
|
||||
"Warning: Printer error or device not found!")
|
||||
|
||||
def print_sale(self, sale, type_doc=None, open_box=False):
|
||||
try:
|
||||
|
@ -236,33 +232,6 @@ class Receipt(object):
|
|||
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)
|
||||
|
@ -271,9 +240,8 @@ class Receipt(object):
|
|||
except Exception:
|
||||
pass
|
||||
self._printer.close()
|
||||
except Exception as e:
|
||||
print(str(e))
|
||||
self.logger.info("Warning: Printer error or device not found!")
|
||||
except Exception:
|
||||
logging.exception("Warning: Printer error or device not found!")
|
||||
|
||||
def _print_sale(self, sale, type_doc=None, open_box=False):
|
||||
short = sale['short_invoice']
|
||||
|
@ -432,7 +400,7 @@ class Receipt(object):
|
|||
self._printer.set(align='center')
|
||||
self._printer.image(self._img_logo, center=True)
|
||||
self.print_enter()
|
||||
except:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def print_qrcode(self, qrcode):
|
||||
|
@ -440,11 +408,15 @@ class Receipt(object):
|
|||
self.print_enter()
|
||||
|
||||
def print_tasks(self, data):
|
||||
for value in data.values():
|
||||
tasks_printed = []
|
||||
for value in data:
|
||||
try:
|
||||
self._printer = None
|
||||
self.config_printer(value['printer'])
|
||||
self.set_printer()
|
||||
if not self._printer:
|
||||
logging.error('impresora no disponible error impresion tarea %s', str(value['printer']))
|
||||
continue
|
||||
title = value['sale'] + ' - ' + value['work_station']
|
||||
self._printer.set(custom_size=True, width=2,
|
||||
height=2, align='center')
|
||||
|
@ -453,17 +425,18 @@ class Receipt(object):
|
|||
height=2, align='left')
|
||||
self._printer.ln(2)
|
||||
for ln in value['lines']:
|
||||
line_ = str(int(ln['qty'])) + ' ' + ln['name']
|
||||
line_ = str(int(ln['quantity'])) + ' ' + ln['name']
|
||||
self._printer.textln(line_)
|
||||
if ln.get('note'):
|
||||
self._printer.textln('NOTA:' + ln.get('note'))
|
||||
self._printer.ln(2)
|
||||
tasks_printed.append(ln['task'])
|
||||
self._printer.cut()
|
||||
self._printer.close()
|
||||
except Exception as e:
|
||||
print(e)
|
||||
traceback.print_exc()
|
||||
except Exception:
|
||||
logging.exception('error tarea')
|
||||
time.sleep(1)
|
||||
return tasks_printed
|
||||
|
||||
def print_header(self, short=False):
|
||||
if not short:
|
||||
|
@ -508,9 +481,9 @@ class Receipt(object):
|
|||
def print_split(self, left, right):
|
||||
len_left = self._row_characters - len(right) - 1
|
||||
left = left[:len_left]
|
||||
if type(left) == bytes:
|
||||
if isinstance(left, bytes):
|
||||
left = left.decode("utf-8")
|
||||
if type(right) == bytes:
|
||||
if isinstance(right, bytes):
|
||||
right = right.decode("utf-8")
|
||||
left += (len_left - len(left) + 1) * ' '
|
||||
self._printer.text(left)
|
||||
|
@ -534,11 +507,11 @@ class Receipt(object):
|
|||
if self._show_discount and discount and Decimal(discount) > 0:
|
||||
amount_w_tax = Decimal(line['amount_w_tax'])
|
||||
discount = Decimal(discount)
|
||||
initial = 'DCTO - ' + str(round(discount*100, 0)) + '%'
|
||||
initial = 'DCTO - ' + str(round(discount * 100, 0)) + '%'
|
||||
if discount == 1:
|
||||
line_total = 0
|
||||
else:
|
||||
line_total = amount_w_tax/(1-discount)
|
||||
line_total = amount_w_tax / (1 - discount)
|
||||
discount = '-' + money(line_total - amount_w_tax)
|
||||
line_total = money(line_total)
|
||||
|
||||
|
@ -547,7 +520,7 @@ class Receipt(object):
|
|||
length_name = self._row_characters - 11
|
||||
first_line = code + ' ' + line['name'][:length_name]
|
||||
|
||||
if type(first_line) == bytes:
|
||||
if isinstance(first_line, bytes):
|
||||
first_line = first_line.decode('utf-8')
|
||||
|
||||
self._printer.text(first_line + '\n')
|
||||
|
@ -866,38 +839,40 @@ class Receipt(object):
|
|||
if not hasattr(self, '_printer') or not self._printer and self._environment != 'restaurant':
|
||||
self.set_printer()
|
||||
if not self._printer:
|
||||
self.logger.info(
|
||||
logging.info(
|
||||
"Warning: Interface not found for printer!")
|
||||
# res.append(None)
|
||||
return False
|
||||
|
||||
self.logger.info("Info: Printer is OK!")
|
||||
logging.info("Info: Printer is OK!")
|
||||
try:
|
||||
self._print_order(order, reversion)
|
||||
res = self._print_order(order, reversion)
|
||||
# if True:
|
||||
res.extend(order['lines_ids'])
|
||||
except Exception as e:
|
||||
print(e)
|
||||
traceback.print_exc()
|
||||
if res:
|
||||
res.extend(res)
|
||||
elif order.get('lines_ids') and True:
|
||||
res.extend(order['lines_ids'])
|
||||
except Exception:
|
||||
logging.exception('error de impresora')
|
||||
self._printer.close()
|
||||
time.sleep(1)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
traceback.print_exc()
|
||||
self.logger.info("Warning: Can not found Printer!")
|
||||
except Exception:
|
||||
logging.exception('Can not found Printer!')
|
||||
return res
|
||||
|
||||
def _print_order(self, order, reversion):
|
||||
lines_printed = []
|
||||
for copie in range(self.order_copies):
|
||||
self.print_body_order(order, reversion)
|
||||
lines_printed = self.print_body_order(order, reversion)
|
||||
self._print_info_consumer(order)
|
||||
self._printer.cut()
|
||||
return True
|
||||
return lines_printed
|
||||
|
||||
def print_body_order(self, order, reversion):
|
||||
# Exists 2 types of order:
|
||||
# command => For restaurants kitchens
|
||||
# dispatch => For external dispatch
|
||||
lines_printed = []
|
||||
self._printer.set(font=_FONT_B)
|
||||
self._printer.set(align='center')
|
||||
turn = order.get('turn')
|
||||
|
@ -994,21 +969,25 @@ class Receipt(object):
|
|||
|
||||
def print_lines_order(lines, group=False):
|
||||
for line in lines:
|
||||
if self.order_kind == 'command':
|
||||
self._printer.set(custom_size=True, width=1, height=2)
|
||||
qty = ' ' + str(int(Decimal(line['quantity'])))
|
||||
name = line['name']
|
||||
if group:
|
||||
name = ' ' + name
|
||||
self.print_col(qty, self.order_col_1)
|
||||
self.print_col(name, col_width_name)
|
||||
if line['note']:
|
||||
self.print_enter()
|
||||
for msg_note in line['note'].split('\n'):
|
||||
self._printer.text(f' NOTA -> {msg_note}')
|
||||
try:
|
||||
if self.order_kind == 'command':
|
||||
self._printer.set(custom_size=True, width=1, height=2)
|
||||
qty = ' ' + str(int(Decimal(line['quantity'])))
|
||||
name = line['name']
|
||||
if group:
|
||||
name = ' ' + name
|
||||
self.print_col(qty, self.order_col_1)
|
||||
self.print_col(name, col_width_name)
|
||||
if line['note']:
|
||||
self.print_enter()
|
||||
for msg_note in line['note'].split('\n'):
|
||||
self._printer.text(f' NOTA -> {msg_note}')
|
||||
self.print_enter()
|
||||
if line.get('id'):
|
||||
lines_printed.append(line['id'])
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
self.print_enter()
|
||||
print('este es el camino de la comanda')
|
||||
self.print_enter()
|
||||
if isinstance(order['lines'], list):
|
||||
print_lines_order(order['lines'])
|
||||
|
@ -1031,6 +1010,7 @@ class Receipt(object):
|
|||
self._printer.text(str(order['comment']))
|
||||
self.print_enter()
|
||||
self._printer.ln(2)
|
||||
return lines_printed
|
||||
# if self._environment != 'retail':
|
||||
# self._printer.set(custom_size=True, width=2, height=2, align='center')
|
||||
# title = f'+ + + {_kind} + + +'
|
||||
|
|
14
app/tools.py
14
app/tools.py
|
@ -27,3 +27,17 @@ def get_screen():
|
|||
width = screen.width()
|
||||
height = screen.height()
|
||||
return width, height
|
||||
|
||||
def compare_versions(version_validate, version_required):
|
||||
v1_parts = version_validate.split('.')
|
||||
v2_parts = version_required.split('.')
|
||||
|
||||
for i in range(max(len(v1_parts), len(v2_parts))):
|
||||
v1_num = int(v1_parts[i]) if i < len(v1_parts) else 0
|
||||
v2_num = int(v2_parts[i]) if i < len(v2_parts) else 0
|
||||
|
||||
if v1_num < v2_num:
|
||||
return "lower"
|
||||
elif v1_num > v2_num:
|
||||
return "higher"
|
||||
return 'equal'
|
||||
|
|
|
@ -1 +1 @@
|
|||
__version__ = "6.0.24"
|
||||
__version__ = "6.0.25"
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
import os
|
||||
import logging
|
||||
|
||||
|
||||
log_file_path = os.path.dirname(os.path.abspath(__file__)) + '/presik_pos.log'
|
||||
log_formater = logging.Formatter(
|
||||
'%(asctime)s - %(levelname)s - %(funcName)s - %(name)s - %(message)s',
|
||||
datefmt='%Y-%m-%d %H:%M:%S', style="%")
|
||||
|
||||
|
||||
handlerConsole = logging.StreamHandler()
|
||||
handlerConsole.setFormatter(log_formater)
|
||||
|
||||
handlerFile = logging.FileHandler(log_file_path, mode='a', encoding='utf-8')
|
||||
handlerFile.setFormatter(log_formater)
|
||||
|
||||
logger = logging.getLogger()
|
||||
logger.setLevel(logging.DEBUG)
|
||||
logger.addHandler(handlerConsole)
|
||||
logger.addHandler(handlerFile)
|
Loading…
Reference in New Issue