configure dialogs for fast init pos
This commit is contained in:
parent
d01a27e103
commit
f792521158
13
INSTALL
13
INSTALL
|
@ -6,8 +6,7 @@ Prerequisites Client
|
|||
|
||||
* Python 3.7 or later (http://www.python.org/)
|
||||
* python-setuptools
|
||||
* python3-pyqt5
|
||||
* python3-pyqt5.qtsvg
|
||||
* python3-PySide6
|
||||
* python3-dateutil
|
||||
* python-pip
|
||||
* libusb-1.0-0
|
||||
|
@ -21,16 +20,12 @@ Prerequisites Client
|
|||
pip3 install pillow
|
||||
pip3 install qrcode
|
||||
pip3 install paramiko
|
||||
pip3 install pycups
|
||||
pip3 install requests
|
||||
pip3 install simplejson
|
||||
pip3 install orjson
|
||||
pip3 install escpos
|
||||
pip3 install packaging
|
||||
pip3 install PySide6>=6.4.1
|
||||
|
||||
|
||||
For Windows add:
|
||||
pip install pywin32
|
||||
pip install PyQt5==5.12.3
|
||||
pip install win32printing
|
||||
|
||||
|
||||
Prerequisites Server Modules
|
||||
|
|
11
INSTALL_es
11
INSTALL_es
|
@ -33,17 +33,10 @@ Los siguientes paquetes se deben instalar usando PIP
|
|||
pip3 install pillow
|
||||
pip3 install qrcode
|
||||
pip3 install paramiko
|
||||
pip3 install pycups
|
||||
pip3 install requests
|
||||
pip3 install simplejson
|
||||
pip3 install orjson
|
||||
pip3 install escpos
|
||||
pip3 install packaging
|
||||
|
||||
|
||||
Para Windows agregar:
|
||||
pip install pywin32
|
||||
pip install PyQt5==5.12.3
|
||||
pip install win32printing
|
||||
pip3 install PySide6>=6.4.1
|
||||
|
||||
|
||||
Tener en cuenta que algunos paquetes se deben instalar con pip para python3.
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -7,6 +7,7 @@ import logging
|
|||
from collections import OrderedDict
|
||||
from pathlib import Path
|
||||
from PySide6.QtWidgets import (QMainWindow, QDialog)
|
||||
from PySide6.QtCore import Qt
|
||||
# from PyQt5.QtWidgets import (QDialogButtonBox, QPushButton,
|
||||
# QLineEdit, QHBoxLayout, QFrame, QLabel,
|
||||
# QVBoxLayout, QStyle,)
|
||||
|
@ -64,6 +65,14 @@ class Login(QDialog):
|
|||
styles.append(infile.read())
|
||||
self.setStyleSheet(''.join(styles))
|
||||
|
||||
def keyPressEvent(self, event):
|
||||
print(event, 'this is event')
|
||||
if event.key() == Qt.Key_Escape:
|
||||
self.reject()
|
||||
elif event.key() == Qt.Key_Enter:
|
||||
self.accept()
|
||||
event.accept()
|
||||
|
||||
# def init_UI(self):
|
||||
# hbox_logo = QHBoxLayout()
|
||||
# label_logo = QLabel()
|
||||
|
@ -144,21 +153,11 @@ class Login(QDialog):
|
|||
self.error_msg.hide()
|
||||
|
||||
def run(self, profile=None):
|
||||
self.api_url = self.params['api_url']
|
||||
# self.api_url = self.params['api_url']
|
||||
if self.params['database']:
|
||||
self.ui.field_database.setText(self.params['database'])
|
||||
if self.params['user']:
|
||||
self.ui.field_user.setText(self.params['user'])
|
||||
# if self.params['server']:
|
||||
# self.ui.field_host.setText(self.params['server'])
|
||||
# if self.mode_conn == 'offline':
|
||||
# self.api_url = self.params['api_url_offline']
|
||||
# if self.params['database_offline']:
|
||||
# self.field_database.setText(self.params['database_offline'])
|
||||
# if self.params['user']:
|
||||
# self.field_user.setText(self.params['user'])
|
||||
# if self.params['server']:
|
||||
# self.field_host.setText(self.params['server_offline'])
|
||||
|
||||
def accept(self):
|
||||
self.validate_access()
|
||||
|
@ -188,9 +187,8 @@ class Login(QDialog):
|
|||
password = self.ui.field_password.text()
|
||||
server = self.params.get('server')
|
||||
database = self.ui.field_database.text()
|
||||
self.connection = xconnection(self.params['mode'],
|
||||
user, password, server, self.params['port'],
|
||||
database, self.params['protocol']
|
||||
self.connection = xconnection(
|
||||
self.params['mode'], user, password, server, database
|
||||
)
|
||||
if not self.connection:
|
||||
self.ui.field_password.setText('')
|
||||
|
@ -206,67 +204,46 @@ class Login(QDialog):
|
|||
self.ui.label_error.show()
|
||||
|
||||
|
||||
def xconnection(mode, user, password, host, port, database, protocol):
|
||||
def xconnection(mode, user, password, host, database):
|
||||
# Get user_id and session
|
||||
try:
|
||||
url = '%s://%s:%s@%s:%s/%s/' % (
|
||||
mode, user, password, host, port, database)
|
||||
print(url, 'url....')
|
||||
try:
|
||||
if not common.test_server_version(host, int(port)):
|
||||
print(u'Incompatible version of the server')
|
||||
return
|
||||
except:
|
||||
pass
|
||||
|
||||
if protocol == 'json':
|
||||
conn = connection.set_jsonrpc(url[:-1])
|
||||
elif protocol == 'local':
|
||||
conn = connection.set_trytond(
|
||||
database=database,
|
||||
user=user,
|
||||
)
|
||||
elif protocol == 'xml':
|
||||
conn = connection.set_xmlrpc(url)
|
||||
else:
|
||||
print("Protocol error...!")
|
||||
return None
|
||||
|
||||
return conn
|
||||
mode, user, password, host, 8000, database)
|
||||
return connection.set_xmlrpc(url)
|
||||
except:
|
||||
print('LOG: Data connection invalid!')
|
||||
return None
|
||||
|
||||
|
||||
def safe_reconnect(main):
|
||||
field_password = QLineEdit()
|
||||
field_password.setEchoMode(QLineEdit.Password)
|
||||
field_password.cursorPosition()
|
||||
field_password.cursor()
|
||||
dialog_password = QuickDialog(main, 'question',
|
||||
info=main.tr('Enter your password:'),
|
||||
widgets=[field_password],
|
||||
buttons=['ok'],
|
||||
response=True
|
||||
)
|
||||
field_password.setFocus()
|
||||
# def safe_reconnect(main):
|
||||
# field_password = QLineEdit()
|
||||
# field_password.setEchoMode(QLineEdit.Password)
|
||||
# field_password.cursorPosition()
|
||||
# field_password.cursor()
|
||||
# dialog_password = QuickDialog(main, 'question',
|
||||
# info=main.tr('Enter your password:'),
|
||||
# widgets=[field_password],
|
||||
# buttons=['ok'],
|
||||
# response=True
|
||||
# )
|
||||
# field_password.setFocus()
|
||||
|
||||
password = field_password.text()
|
||||
if not password or password == '':
|
||||
safe_reconnect(main)
|
||||
# password = field_password.text()
|
||||
# if not password or password == '':
|
||||
# safe_reconnect(main)
|
||||
|
||||
main.conn = xconnection(
|
||||
main.user,
|
||||
str(password),
|
||||
main.server,
|
||||
main.port,
|
||||
main.database,
|
||||
main.protocol,
|
||||
)
|
||||
# main.conn = xconnection(
|
||||
# main.user,
|
||||
# str(password),
|
||||
# main.server,
|
||||
# main.port,
|
||||
# main.database,
|
||||
# main.protocol,
|
||||
# )
|
||||
|
||||
if main.conn:
|
||||
field_password.setText('')
|
||||
dialog_password.hide()
|
||||
main.global_timer = 0
|
||||
else:
|
||||
safe_reconnect(main)
|
||||
# if main.conn:
|
||||
# field_password.setText('')
|
||||
# dialog_password.hide()
|
||||
# main.global_timer = 0
|
||||
# else:
|
||||
# safe_reconnect(main)
|
||||
|
|
|
@ -7,6 +7,7 @@ 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
|
||||
|
@ -221,18 +222,23 @@ class QuickDialog(QDialog):
|
|||
|
||||
def set_simple_model(self):
|
||||
self.data_model = QStandardItemModel(0, len(self.data['heads']), self)
|
||||
_horizontal = Qt.Horizontal
|
||||
for i, h in enumerate(self.data['heads'], 0):
|
||||
self.data_model.setHeaderData(i, _horizontal, h)
|
||||
# _horizontal = Qt.Horizontal
|
||||
# print('simple model')
|
||||
map(self.data_model.setHeaderData, enumerate(self.data['heads'], 0))
|
||||
# for i, h in enumerate(self.data['heads'], 0):
|
||||
# self.data_model.setHeaderData(i, _horizontal, h)
|
||||
|
||||
def _insert_items(self, model, values):
|
||||
ItemIsEnabled, ItemIsSelectable = Qt.ItemIsEnabled, Qt.ItemIsSelectable
|
||||
insertRow = self.data_model.insertRow
|
||||
for value in values:
|
||||
row = []
|
||||
row_append = row.append
|
||||
for v in value:
|
||||
itemx = QStandardItem(v)
|
||||
itemx.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
|
||||
row.append(itemx)
|
||||
self.data_model.insertRow(0, row)
|
||||
itemx.setFlags(ItemIsEnabled | ItemIsSelectable)
|
||||
row_append(itemx)
|
||||
insertRow(0, row)
|
||||
self.data_model.sort(0, Qt.AscendingOrder)
|
||||
|
||||
@Slot(QModelIndex)
|
||||
|
@ -293,7 +299,7 @@ class SearchDialog(QDialog):
|
|||
self.completer.activated.connect(on_activated)
|
||||
|
||||
def set_model(self):
|
||||
headers_name = [h[1] for h in self.headers]
|
||||
headers_name = (h[1] for h in self.headers)
|
||||
self.model = get_simple_model(self.parent, self.values, headers_name)
|
||||
self.completer.setModel(self.model)
|
||||
|
||||
|
|
|
@ -368,12 +368,12 @@ class ComboBox(QComboBox):
|
|||
self.setFrame(True)
|
||||
self.setObjectName('field_' + key)
|
||||
self.setFocusPolicy(Qt.StrongFocus)
|
||||
values = []
|
||||
if data.get('values'):
|
||||
values = data.get('values')
|
||||
heads = []
|
||||
if data.get('heads'):
|
||||
heads = data.get('heads')
|
||||
# values = []
|
||||
# if data.get('values'):
|
||||
values = data.get('values', [])
|
||||
# heads = []
|
||||
# if data.get('heads', []):
|
||||
heads = data.get('heads', [])
|
||||
selection_model = get_simple_model(obj, values, heads)
|
||||
self.setModel(selection_model)
|
||||
self.setModelColumn(1)
|
||||
|
@ -459,38 +459,65 @@ class GridForm(QGridLayout):
|
|||
if col == 0:
|
||||
align = 'left'
|
||||
|
||||
TYPES_ = {
|
||||
'selection': ComboBox,
|
||||
'checkbox': CheckBox,
|
||||
'money': FieldMoney,
|
||||
'text': TextField,
|
||||
'text_area': TextAreaField,
|
||||
'date': FieldDate,
|
||||
'editable': FieldInput,
|
||||
}
|
||||
|
||||
setted_focus = False
|
||||
addWidget = self.addWidget
|
||||
for key, value in values.items():
|
||||
type_ = value.get('type')
|
||||
expand = 0
|
||||
self.store[key] = None
|
||||
if value.get('editable'):
|
||||
_field = FieldInput(obj, key, value, form=self)
|
||||
elif value.get('type') == 'selection':
|
||||
_field = ComboBox(obj, key, value, form=self)
|
||||
elif value.get('type') == 'checkbox':
|
||||
_field = CheckBox(obj, key, value, form=self)
|
||||
expand = 1
|
||||
elif value.get('type') == 'money':
|
||||
_field = FieldMoney(obj, key, value, form=self)
|
||||
elif value.get('type') == 'text':
|
||||
_field = TextField(obj, key, value, form=self)
|
||||
setted_focus = True
|
||||
expand = 1
|
||||
align = 'left'
|
||||
elif value.get('type') == 'text_area':
|
||||
_field = TextAreaField(obj, key, value, form=self)
|
||||
# setted_focus = True
|
||||
expand = 1
|
||||
align = 'left'
|
||||
elif value.get('type') == 'date':
|
||||
_field = FieldDate(obj, key, value, form=self)
|
||||
else:
|
||||
_field = Field(obj, key, value, self)
|
||||
try:
|
||||
Field_ = TYPES_[type_]
|
||||
_field = Field_(obj, key, value, form=self)
|
||||
|
||||
if type_ in ('checkbox', 'text', 'text_area'):
|
||||
expand = 1
|
||||
if type_ == 'text':
|
||||
align = 'left'
|
||||
except:
|
||||
_field = Field(obj, key, value, form=self)
|
||||
if value.get('password') is True:
|
||||
_field.setEchoMode(QLineEdit.Password)
|
||||
if value.get('placeholder'):
|
||||
_field.setPlaceholderText(value['name'])
|
||||
|
||||
# if value.get('editable'):
|
||||
# _field = FieldInput(obj, key, value, form=self)
|
||||
# elif type_ == 'selection':
|
||||
# _field = ComboBox(obj, key, value, form=self)
|
||||
# elif type_ == 'checkbox':
|
||||
# _field = CheckBox(obj, key, value, form=self)
|
||||
# expand = 1
|
||||
# elif type_ == 'money':
|
||||
# _field = FieldMoney(obj, key, value, form=self)
|
||||
# elif type_ == 'text':
|
||||
# _field = TextField(obj, key, value, form=self)
|
||||
# setted_focus = True
|
||||
# expand = 1
|
||||
# align = 'left'
|
||||
# elif type_ == 'text_area':
|
||||
# _field = TextAreaField(obj, key, value, form=self)
|
||||
# # setted_focus = True
|
||||
# expand = 1
|
||||
# align = 'left'
|
||||
# elif type_ == 'date':
|
||||
# _field = FieldDate(obj, key, value, form=self)
|
||||
# else:
|
||||
# _field = Field(obj, key, value, self)
|
||||
# if value.get('password') is True:
|
||||
# _field.setEchoMode(QLineEdit.Password)
|
||||
# if value.get('placeholder'):
|
||||
# _field.setPlaceholderText(value['name'])
|
||||
|
||||
if not setted_focus:
|
||||
self.focus_widget = _field
|
||||
setted_focus = True
|
||||
|
@ -506,15 +533,15 @@ class GridForm(QGridLayout):
|
|||
continue
|
||||
if not expand:
|
||||
if not value.get('placeholder'):
|
||||
self.addWidget(_label, row, column1)
|
||||
addWidget(_label, row, column1)
|
||||
if col == 0:
|
||||
row = row + 1
|
||||
self.addWidget(_field, row, column1)
|
||||
addWidget(_field, row, column1)
|
||||
else:
|
||||
self.addWidget(_field, row, column2)
|
||||
addWidget(_field, row, column2)
|
||||
else:
|
||||
self.addWidget(_label, row, column1, row, column2)
|
||||
self.addWidget(_field, row + 1, column1, row + 1, column2)
|
||||
addWidget(_label, row, column1, row, column2)
|
||||
addWidget(_field, row + 1, column1, row + 1, column2)
|
||||
|
||||
if value.get('translate') is True:
|
||||
_field.translate = True
|
||||
|
|
|
@ -14,6 +14,7 @@ from PySide6.QtWidgets import (
|
|||
)
|
||||
|
||||
from .custom_button import CustomButton
|
||||
from ..tools import get_icon
|
||||
|
||||
pkg_dir = str(Path(os.path.dirname(__file__)).parents[0])
|
||||
file_back_icon = os.path.join(pkg_dir, 'share', 'back.svg')
|
||||
|
@ -29,7 +30,7 @@ def money(v):
|
|||
|
||||
class MenuDash(QWidget):
|
||||
|
||||
def __init__(self, parent, values, selected_method=None, title=None):
|
||||
def __init__(self, parent, values=[], selected_method=None, title=None):
|
||||
"""
|
||||
parent: parent window
|
||||
values: is to list of list/tuples values for data model
|
||||
|
@ -110,14 +111,14 @@ class MenuDash(QWidget):
|
|||
view_id = str(view_id)
|
||||
view = self.ctx_widgets[self.current_view]['items']
|
||||
view.hide()
|
||||
if not view_id:
|
||||
view_id = '0'
|
||||
|
||||
new_view = self.ctx_widgets[view_id]['items']
|
||||
if not new_view:
|
||||
# if not view_id:
|
||||
# view_id = '0'
|
||||
try:
|
||||
new_view = self.ctx_widgets[view_id]['items']
|
||||
new_view.show()
|
||||
except:
|
||||
return
|
||||
|
||||
new_view.show()
|
||||
self.main.addWidget(new_view)
|
||||
self.current_view = view_id
|
||||
self.setGeometry(self.rect_expanded)
|
||||
|
@ -135,10 +136,7 @@ class MenuDash(QWidget):
|
|||
self.main_categories.setSpacing(4)
|
||||
self.menu.setLayout(self.main_categories)
|
||||
|
||||
num_cat_cols = 3
|
||||
row_cat = 0
|
||||
col_cat = 0
|
||||
parent_id = '0'
|
||||
num_cat_cols, row_cat, col_cat, parent_id = 3, 0, 0, '0'
|
||||
self.ctx_widgets = {
|
||||
'0': {
|
||||
'items': self.menu_area,
|
||||
|
@ -147,9 +145,10 @@ class MenuDash(QWidget):
|
|||
}
|
||||
main_cat_addWidget = self.main_categories.addWidget
|
||||
for value in self.values:
|
||||
# print(value, type(value['id']))
|
||||
cat_id = str(value['id'])
|
||||
if not value:
|
||||
continue
|
||||
# if not value:
|
||||
# continue
|
||||
if col_cat > num_cat_cols - 1:
|
||||
col_cat = 0
|
||||
row_cat += 1
|
||||
|
@ -157,7 +156,7 @@ class MenuDash(QWidget):
|
|||
button = CustomButton(
|
||||
parent=self,
|
||||
id=value['id'],
|
||||
icon=value['icon'],
|
||||
icon=get_icon(value['name_icon']),
|
||||
method='selected_method',
|
||||
desc_extractor='name',
|
||||
record=value,
|
||||
|
@ -167,8 +166,8 @@ class MenuDash(QWidget):
|
|||
main_cat_addWidget(button, row_cat, col_cat)
|
||||
col_cat += 1
|
||||
|
||||
items = value.get('items')
|
||||
childs = value.get('childs', [])
|
||||
items = value.get('products.')
|
||||
childs = value.get('childs.', [])
|
||||
if items:
|
||||
products = self.get_products(items)
|
||||
self.ctx_widgets[cat_id] = {
|
||||
|
@ -176,8 +175,7 @@ class MenuDash(QWidget):
|
|||
'parent': parent_id,
|
||||
}
|
||||
if childs:
|
||||
subrow = 0
|
||||
subcol = 0
|
||||
subrow, subcol = 0, 0
|
||||
sub_categories = QGridLayout()
|
||||
sub_categories.setSpacing(4)
|
||||
scroll_subarea = QScrollArea()
|
||||
|
@ -196,7 +194,7 @@ class MenuDash(QWidget):
|
|||
button = CustomButton(
|
||||
parent=self,
|
||||
id=sub_id,
|
||||
icon=value['icon'],
|
||||
icon=get_icon(value['name_icon']),
|
||||
method='selected_method',
|
||||
desc_extractor='name',
|
||||
record=subcat,
|
||||
|
@ -205,7 +203,7 @@ class MenuDash(QWidget):
|
|||
)
|
||||
sub_cat_addWidget(button, subrow, subcol)
|
||||
subcol += 1
|
||||
products_list = subcat.get('items')
|
||||
products_list = subcat.get('products.')
|
||||
products_items = None
|
||||
if products_list:
|
||||
products_items = self.get_products(products_list)
|
||||
|
@ -215,6 +213,7 @@ class MenuDash(QWidget):
|
|||
'parent': cat_id,
|
||||
}
|
||||
sub_categories.setRowStretch(subrow + 1, 1)
|
||||
print('..... final')
|
||||
self.main_categories.setRowStretch(row_cat + 1, 1)
|
||||
|
||||
def action_back(self):
|
||||
|
@ -264,7 +263,7 @@ class GridButtons(QWidget):
|
|||
self.set_items()
|
||||
|
||||
def create_list_items(self):
|
||||
self.list_items = []
|
||||
self.list_items, button_size, style = [], self.button_size, self.style
|
||||
list_items_append = self.list_items.append
|
||||
for value in self.values:
|
||||
_button = CustomButton(
|
||||
|
@ -273,8 +272,8 @@ class GridButtons(QWidget):
|
|||
desc_extractor='name',
|
||||
method='action_selected',
|
||||
record=value,
|
||||
size=self.button_size,
|
||||
name_style=self.style,
|
||||
size=button_size,
|
||||
name_style=style,
|
||||
)
|
||||
list_items_append(_button)
|
||||
|
||||
|
@ -282,11 +281,10 @@ class GridButtons(QWidget):
|
|||
self.action(idx)
|
||||
|
||||
def set_items(self):
|
||||
colx = 0
|
||||
rowy = 0
|
||||
colx, rowy, num_cols = 0, 0, self.num_cols
|
||||
layout_addWidget = self.layout.addWidget
|
||||
for item_button in self.list_items:
|
||||
if colx >= self.num_cols:
|
||||
if colx >= num_cols:
|
||||
colx = 0
|
||||
rowy += 1
|
||||
layout_addWidget(item_button, rowy, colx)
|
||||
|
|
|
@ -39,7 +39,7 @@ class TLabel(QLabel):
|
|||
|
||||
|
||||
class RLabel(QLabel):
|
||||
#Item Label
|
||||
# Item Label
|
||||
|
||||
def __init__(self, name, idx):
|
||||
super(RLabel, self).__init__(name)
|
||||
|
@ -71,16 +71,17 @@ class List(QWidget):
|
|||
self.set_items(rows)
|
||||
|
||||
def action_selected(self, idx):
|
||||
self.action(idx) #.selected_method(idx)
|
||||
self.action(idx) # selected_method(idx)
|
||||
|
||||
def set_items(self, rows):
|
||||
self.rows = rows
|
||||
idx = 0
|
||||
self.layout_list.addWidget(Separator(), 0, 0, 1, self.num_cols)
|
||||
addWidget = self.layout_list.addWidget
|
||||
separator = Separator()
|
||||
addWidget(separator, 0, 0, 1, self.num_cols)
|
||||
|
||||
for row in rows:
|
||||
idx += 1
|
||||
separator = Separator()
|
||||
for col in range(self.num_cols):
|
||||
val = row[col]
|
||||
if isinstance(val, Decimal):
|
||||
|
@ -89,9 +90,9 @@ class List(QWidget):
|
|||
if col == 0:
|
||||
val = ''
|
||||
item = RLabel(val, idx=row[0])
|
||||
self.layout_list.addWidget(item, idx, col)
|
||||
addWidget(item, idx, col)
|
||||
idx += 1
|
||||
self.layout_list.addWidget(separator, idx, 0, 1, self.num_cols)
|
||||
addWidget(separator, idx, 0, 1, self.num_cols)
|
||||
self.layout_list.setRowStretch(idx + 1, 1)
|
||||
|
||||
|
||||
|
@ -154,12 +155,13 @@ class MenuWindow(QDialog):
|
|||
self.layout_category = QVBoxLayout()
|
||||
self.category.setLayout(self.layout_category)
|
||||
id_ = 1
|
||||
self.layout_category.addWidget(Separator())
|
||||
addWidget = self.layout_category.addWidget
|
||||
addWidget(Separator())
|
||||
separator = Separator()
|
||||
for k, values in self.values.items():
|
||||
separator = Separator()
|
||||
label = TLabel(k, id_, self)
|
||||
self.layout_category.addWidget(label)
|
||||
self.layout_category.addWidget(separator)
|
||||
addWidget(label)
|
||||
addWidget(separator)
|
||||
list_item = List(values, 3, self.show_code, self.selected_method)
|
||||
scroll_area = QScrollArea()
|
||||
scroll_area.setWidgetResizable(True)
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
# from PyQt5.QtCore import Qt, QAbstractTableModel, QModelIndex
|
||||
from PySide6.QtCore import Qt, QAbstractTableModel, QModelIndex
|
||||
import math
|
||||
from itertools import islice
|
||||
_horizontal = Qt.Horizontal
|
||||
|
||||
|
||||
__all__ = ['TableModel', 'TableEdit']
|
||||
|
||||
|
@ -63,11 +66,12 @@ class TableEdit(QAbstractTableModel):
|
|||
""" Set the headers to be displayed. """
|
||||
if role != Qt.DisplayRole:
|
||||
return None
|
||||
if orientation == Qt.Horizontal:
|
||||
for i in range(len(self._fields)):
|
||||
if section == i:
|
||||
return self._fields[i]['label']
|
||||
return None
|
||||
try:
|
||||
return next(islice(self._fields, section, None))['label']
|
||||
except:
|
||||
return None
|
||||
# if orientation == Qt.Horizontal:
|
||||
# return None
|
||||
|
||||
def add_record(self, rec):
|
||||
length = len(self._data)
|
||||
|
@ -77,7 +81,7 @@ class TableEdit(QAbstractTableModel):
|
|||
return rec
|
||||
|
||||
def get_sum(self, col):
|
||||
return sum([int(d[col]) for d in self._data])
|
||||
return sum(int(d[col]) for d in self._data)
|
||||
|
||||
|
||||
class TableModel(QAbstractTableModel):
|
||||
|
@ -126,11 +130,11 @@ class TableModel(QAbstractTableModel):
|
|||
def get_value(self, data, field):
|
||||
value = ''
|
||||
list_ = field.split('.')
|
||||
for l in list_:
|
||||
if not data.get(l):
|
||||
return None
|
||||
value = data[l]
|
||||
data = data[l]
|
||||
if len(list_) > 1:
|
||||
for l in list_[:-1]:
|
||||
l = l + '.'
|
||||
data = data[l]
|
||||
value = data[list_[-1]]
|
||||
return value
|
||||
|
||||
def data(self, index, role, field_name='name'):
|
||||
|
@ -188,7 +192,7 @@ class TableModel(QAbstractTableModel):
|
|||
return None
|
||||
|
||||
def get_sum(self, field_target):
|
||||
res = sum([d[field_target] for d in self._data])
|
||||
res = sum(d[field_target] for d in self._data)
|
||||
return res
|
||||
|
||||
def update_record(self, rec, pos=None):
|
||||
|
@ -205,13 +209,11 @@ class TableModel(QAbstractTableModel):
|
|||
self.dataChanged.emit(start_pos, end_pos)
|
||||
return rec
|
||||
|
||||
def headerData(self, section, orientation, role):
|
||||
def headerData(self, section, orientation=_horizontal, role=None):
|
||||
""" Set the headers to be displayed. """
|
||||
if role != Qt.DisplayRole:
|
||||
return None
|
||||
elements = [f['description'] for f in self._fields]
|
||||
if orientation == Qt.Horizontal:
|
||||
for i in range(len(elements)):
|
||||
if section == i:
|
||||
return elements[i]
|
||||
return None
|
||||
elements = (f['description'] for f in self._fields)
|
||||
return next(islice(elements, section, None))
|
||||
# if orientation == Qt.Horizontal:
|
||||
# return None
|
||||
|
|
|
@ -9,21 +9,24 @@ def get_simple_model(obj, data, header=[]):
|
|||
model = QStandardItemModel(0, len(header), obj)
|
||||
if header:
|
||||
i = 0
|
||||
setHeaderData = model.setHeaderData
|
||||
for head_name in header:
|
||||
model.setHeaderData(i, Qt.Horizontal, head_name)
|
||||
setHeaderData(i, Qt.Horizontal, head_name)
|
||||
i += 1
|
||||
_insert_items(model, data)
|
||||
return model
|
||||
|
||||
|
||||
def _insert_items(model, data):
|
||||
appendRow = model.appendRow
|
||||
for d in data:
|
||||
row = []
|
||||
row_append = row.append
|
||||
for val in d:
|
||||
itemx = QStandardItem(str(val))
|
||||
itemx.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
|
||||
row.append(itemx)
|
||||
model.appendRow(row)
|
||||
row_append(itemx)
|
||||
appendRow(row)
|
||||
model.sort(0, Qt.AscendingOrder)
|
||||
|
||||
|
||||
|
|
|
@ -10,8 +10,6 @@ from datetime import timedelta, datetime
|
|||
# QHBoxLayout, QItemDelegate, QMenu, QAction)
|
||||
# from PyQt5.QtGui import QPixmap, QIcon, QCursor
|
||||
from PySide6.QtWidgets import QApplication
|
||||
# from PySide6.Qt import QApplication, QClipboard
|
||||
from PyQt5.QtCore import (QVariant)
|
||||
from PySide6.QtCore import (
|
||||
Qt, QAbstractTableModel, Signal, QModelIndex
|
||||
)
|
||||
|
@ -20,9 +18,9 @@ from PySide6.QtWidgets import (
|
|||
QHBoxLayout, QItemDelegate, QMenu
|
||||
)
|
||||
from PySide6.QtGui import QPixmap, QIcon, QCursor, QAction
|
||||
|
||||
from .buttons import ActionButton
|
||||
from ..tools import get_screen
|
||||
_horizontal = Qt.Horizontal
|
||||
|
||||
__all__ = ['Item', 'SearchWindow', 'TableModel']
|
||||
|
||||
|
@ -138,8 +136,10 @@ class SearchWindow(QDialog):
|
|||
|
||||
def set_from_objects(self, objects):
|
||||
self.rows = []
|
||||
rows_append = self.rows.append
|
||||
for object_ in objects:
|
||||
row = []
|
||||
row_append = row.append
|
||||
for field, data in self.headers.items():
|
||||
val = getattr(object_, field)
|
||||
if hasattr(val, 'name'):
|
||||
|
@ -150,8 +150,8 @@ class SearchWindow(QDialog):
|
|||
val = str(val)
|
||||
elif data['type'] == 'date':
|
||||
val = val.strftime('%d/%m/%Y')
|
||||
row.append(val)
|
||||
self.rows.append(row)
|
||||
row_append(val)
|
||||
rows_append(row)
|
||||
self.table_model.set_rows(self.rows)
|
||||
|
||||
def create_table(self):
|
||||
|
@ -449,24 +449,29 @@ class TableModel(QAbstractTableModel):
|
|||
return item
|
||||
|
||||
def headerData(self, col, orientation, role):
|
||||
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
|
||||
return QVariant(self.header_name[col])
|
||||
return QVariant()
|
||||
if role != Qt.DisplayRole:
|
||||
return None
|
||||
try:
|
||||
return self.header_name[col]
|
||||
except:
|
||||
return None
|
||||
|
||||
def insertRows(self, item, row=0, column=1, index=QModelIndex()):
|
||||
self.beginInsertRows(index, row, row + 1)
|
||||
self.items.append(item)
|
||||
self.endInsertRows()
|
||||
|
||||
# def sort(self, column, order):
|
||||
# print(order, 'order....')
|
||||
# name_field = self.header_fields[column]
|
||||
# if 'icon-' in name_field:
|
||||
# return
|
||||
# data = [(str(value[name_field]), value) for value in self.items]
|
||||
# data.sort(key=itemgetter(0), reverse=order)
|
||||
# self.currentItems = [v for k, v in data]
|
||||
# self.layoutChanged.emit()
|
||||
def sort(self, column, order):
|
||||
name_field = self.header_fields[column]
|
||||
if 'icon-' in name_field or not self.items:
|
||||
return
|
||||
|
||||
if order == Qt.AscendingOrder:
|
||||
reverse = False
|
||||
else:
|
||||
reverse = True
|
||||
self.items.sort(key=lambda x: (x[name_field] is not None, x[name_field]), reverse=reverse)
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def setFilter(self, searchText=None, mainColumn=None, order=None):
|
||||
if not searchText:
|
||||
|
@ -479,7 +484,7 @@ class TableModel(QAbstractTableModel):
|
|||
self.currentItems = self.items
|
||||
|
||||
if searchText and self.filter_column:
|
||||
matchers = [t.lower() for t in searchText.split(' ')]
|
||||
matchers = (t.lower() for t in searchText.split(' '))
|
||||
self.filteredItems = []
|
||||
for item in self.currentItems:
|
||||
values = list(item.values())
|
||||
|
|
|
@ -106,6 +106,7 @@ class Ui_Login(object):
|
|||
self.field_password.setMinimumSize(QSize(0, 44))
|
||||
self.field_password.setMaximumSize(QSize(16777215, 44))
|
||||
self.field_password.setFont(font1)
|
||||
self.field_password.setFocus()
|
||||
self.field_password.setAutoFillBackground(False)
|
||||
self.field_password.setStyleSheet(u"border: 1.4px solid; border-radius:10%; background-color: palette(base); padding-top:8;padding-left:20;padding-bottom:0; padding-right:10;\n"
|
||||
"border-color: rgb(154, 153, 150);\n"
|
||||
|
@ -127,10 +128,6 @@ class Ui_Login(object):
|
|||
self.verticalLayout_2.setObjectName(u"verticalLayout_2")
|
||||
self.verticalLayout_2.setContentsMargins(-1, 10, -1, 20)
|
||||
|
||||
# self.box_buttons = QDialogButtonBox()
|
||||
# self.box_buttons.setOrientation(Qt.Vertical)
|
||||
# sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
||||
# self.box_buttons.setSizePolicy(sizePolicy)
|
||||
font2 = QFont()
|
||||
font2.setBold(True)
|
||||
self.pushButtonOk = QPushButton(self.gridGroupBoxMain)
|
||||
|
@ -155,11 +152,7 @@ class Ui_Login(object):
|
|||
self.pushButtonCancel.setStyleSheet(u"border: 1.4px solid; border-radius:10%; border-color: red;\n"
|
||||
"color: rgb(255, 255, 255);\n"
|
||||
"background-color: qlineargradient(spread:pad, x1:0.234, y1:0.448864, x2:0.78607, y2:0.449, stop:0.00995025 rgba(255, 20, 89, 252), stop:0.313433 rgba(252, 28, 86, 255), stop:0.666667 rgba(255, 58, 87, 255), stop:0.935323 rgba(246, 60, 60, 253));")
|
||||
# self.pushButtonCancel.setIconSize(QSize(20, 20))
|
||||
|
||||
# self.box_buttons.addButton(self.pushButtonOk, QDialogButtonBox.AcceptRole)
|
||||
# self.box_buttons.addButton(self.pushButtonCancel, QDialogButtonBox.RejectRole)
|
||||
# self.verticalLayout_2.addWidget(self.box_buttons)
|
||||
self.verticalLayout_2.addWidget(self.pushButtonOk)
|
||||
self.verticalLayout_2.addWidget(self.pushButtonCancel)
|
||||
self.gridLayout.addLayout(self.verticalLayout_2, 9, 0, 2, 1)
|
||||
|
@ -211,16 +204,10 @@ class Ui_Login(object):
|
|||
|
||||
self.gridLayout_2.addWidget(self.label_image, 0, 0, 3, 1)
|
||||
|
||||
# MainWindow.setCentralWidget(self.centralwidget)
|
||||
# MainWindow.setLayout(self.centralwidget)
|
||||
|
||||
# connect signals and slots
|
||||
# self.box_buttons.accepted.connect(MainWindow.accept)
|
||||
# self.box_buttons.rejected.connect(MainWindow.reject)
|
||||
self.pushButtonOk.clicked.connect(MainWindow.accept)
|
||||
self.pushButtonCancel.clicked.connect(MainWindow.reject)
|
||||
# self.field_user.textChanged.connect(MainWindow.update)
|
||||
# self.field_database.textChanged.connect(MainWindow.update)
|
||||
self.field_password.editingFinished.connect(MainWindow.accept)
|
||||
|
||||
# QMetaObject.connectSlotsByName(MainWindow)
|
||||
# setupUi
|
||||
|
|
144
app/dialogs.py
144
app/dialogs.py
|
@ -1,5 +1,6 @@
|
|||
from decimal import Decimal
|
||||
from datetime import datetime
|
||||
from operator import itemgetter
|
||||
from .commons.dialogs import HelpDialog, QuickDialog
|
||||
# from PyQt5.QtCore import Qt, QSize
|
||||
# from PyQt5.QtWidgets import (
|
||||
|
@ -104,13 +105,13 @@ class ControlPanel(QuickDialog):
|
|||
self.setWindowTitle('PANEL DE CONTROL')
|
||||
|
||||
def get_control_panel(self):
|
||||
menu_dash = [
|
||||
menu_dash = (
|
||||
('button_open', 'ABRIR ESTADOS DE CUENTA', 'action_open_statement'),
|
||||
('button_closed', 'CERRAR ESTADOS DE CUENTA', 'action_close_statement'),
|
||||
('button_expenses', 'GASTOS', 'action_expenses'),
|
||||
('button_discount', 'DESCUENTOS AUTORIZADOS', 'action_table_discount'),
|
||||
('button_delivery_party', 'CREAR DOMICILIARIO', 'action_delivery_party_panel'),
|
||||
]
|
||||
)
|
||||
return menu_dash
|
||||
|
||||
|
||||
|
@ -120,11 +121,11 @@ class DialogReports(QuickDialog):
|
|||
vbox = QVBoxLayout()
|
||||
grid = QGridLayout()
|
||||
scroll_area = QScrollArea()
|
||||
_reports = [
|
||||
_reports = (
|
||||
('button_square_box', 'CUADRE DE CAJA', 'action_square_box_report'),
|
||||
('button_terminal_journal', 'PAGOS ELECTRONICOS', 'action_terminal_journal_report'),
|
||||
('button_delivery_report', 'ENTREGA DOMICILIARIOS', 'action_delivery_report'),
|
||||
]
|
||||
)
|
||||
self.reports = ButtonsFunction(parent, values=_reports)
|
||||
self.parent = parent
|
||||
scroll_area.setLayout(self.reports)
|
||||
|
@ -179,28 +180,28 @@ class SearchSale(SearchWindow):
|
|||
headers['invoice_number'] = {'desc': 'FACTURA', 'type': 'char'}
|
||||
headers['salesman.rec_name'] = {'desc': 'VENDEDOR', 'type': 'char'}
|
||||
widths = [20, 115, 115, 160]
|
||||
|
||||
widths_append = widths.append
|
||||
if parent._sale_pos_restaurant:
|
||||
headers['kind'] = {'desc': 'CLASE', 'type': 'char'}
|
||||
widths.append(110)
|
||||
widths_append(110)
|
||||
headers['consumer.rec_name'] = {'desc': 'CONSUMIDOR', 'type': 'char'}
|
||||
widths.append(300)
|
||||
widths_append(300)
|
||||
headers['table_assigned.rec_name'] = {'desc': 'MESA', 'type': 'char'}
|
||||
widths.append(100)
|
||||
widths_append(100)
|
||||
headers['source.name'] = {'desc': 'FUENTE', 'type': 'char'}
|
||||
widths.append(150)
|
||||
widths_append(150)
|
||||
headers['create_date'] = {'desc': 'HORA', 'type': 'time'}
|
||||
widths.append(120)
|
||||
widths_append(120)
|
||||
else:
|
||||
headers['party.name'] = {'desc': 'CLIENTE', 'type': 'char'}
|
||||
widths.append(160)
|
||||
widths_append(160)
|
||||
headers['sale_date'] = {'desc': 'FECHA', 'type': 'char'}
|
||||
widths.append(80)
|
||||
widths_append(80)
|
||||
|
||||
headers['position'] = {'desc': 'POSICION', 'type': 'char'}
|
||||
widths.append(130)
|
||||
widths_append(130)
|
||||
headers['total_amount_cache'] = {'desc': 'VALOR TOTAL', 'type': 'number'}
|
||||
widths.append(90)
|
||||
widths_append(90)
|
||||
|
||||
title = ('BUSCAR PEDIDOS...')
|
||||
methods = {
|
||||
|
@ -245,7 +246,7 @@ class SearchSale(SearchWindow):
|
|||
self.buttons_layout_filter.addWidget(self.pushButtonReservation)
|
||||
widgets_to_create = self.buttons_layout_filter
|
||||
super(SearchSale, self).__init__(parent, headers, None, methods,
|
||||
filter_column=[2, 3, 4, 5, 6, 7], cols_width=widths,
|
||||
filter_column=(2, 3, 4, 5, 6, 7), cols_width=widths,
|
||||
title=title, fill=True, widgets=[widgets_to_create])
|
||||
|
||||
def action_search_sale(self, _type):
|
||||
|
@ -278,6 +279,7 @@ class SearchParty(SearchWindow):
|
|||
class SearchProduct(SearchWindow):
|
||||
def __init__(self, parent):
|
||||
_cols_width = [10, 80]
|
||||
_cols_width_append = _cols_width.append
|
||||
headers = OrderedDict()
|
||||
headers['id'] = {'desc': ('ID'), 'type': 'char'}
|
||||
headers['code'] = {'desc': ('COD'), 'type': 'char'}
|
||||
|
@ -286,22 +288,22 @@ class SearchProduct(SearchWindow):
|
|||
if parent._config['show_stock_pos'] == 'icon':
|
||||
headers['quantity']['icon'] = 'stock'
|
||||
headers['quantity']['type'] = 'icon'
|
||||
_cols_width.append(60)
|
||||
_cols_width_append(60)
|
||||
|
||||
if not parent.cache_local:
|
||||
headers['name'] = {'desc': 'NOMBRE', 'type': 'char'}
|
||||
else:
|
||||
headers['template.name'] = {'desc': 'NOMBRE', 'type': 'char'}
|
||||
|
||||
_cols_width.append(350)
|
||||
_cols_width_append(350)
|
||||
|
||||
if parent._config.get('show_description_pos'):
|
||||
headers['description'] = {'desc': 'DESCRIPCION', 'type': 'char'}
|
||||
_cols_width.append(300)
|
||||
_cols_width_append(300)
|
||||
|
||||
if parent._config.get('show_brand'):
|
||||
headers['template.brand'] = {'desc': 'BRAND', 'type': 'char'}
|
||||
_cols_width.append(100)
|
||||
_cols_width_append(100)
|
||||
|
||||
price = {'desc': ('PRICE'), 'type': 'number'}
|
||||
if not parent._config.get('encoded_sale_price'):
|
||||
|
@ -310,15 +312,15 @@ class SearchProduct(SearchWindow):
|
|||
price['type'] = 'char'
|
||||
headers['encoded_sale_price'] = price
|
||||
|
||||
_cols_width.append(100)
|
||||
_cols_width_append(100)
|
||||
|
||||
if parent._config.get('show_location_pos'):
|
||||
headers['location.name'] = {'desc': 'BODEGA', 'type': 'char'}
|
||||
_cols_width.append(100)
|
||||
_cols_width_append(100)
|
||||
|
||||
if parent._config['show_product_image']:
|
||||
headers['image'] = {'desc': 'IMAGEN', 'icon': 'image', 'type': 'icon'}
|
||||
_cols_width.append(30)
|
||||
_cols_width_append(30)
|
||||
|
||||
methods = {
|
||||
'on_selected_method': 'on_selected_product',
|
||||
|
@ -350,9 +352,9 @@ class DialogManageTables(QuickDialog):
|
|||
widgets=[self.manager])
|
||||
self.setFixedSize(int(width / 1.5), int(height / 1.5))
|
||||
|
||||
def exec_(self):
|
||||
def exec(self):
|
||||
self.open_tables()
|
||||
super(DialogManageTables, self).exec_()
|
||||
super(DialogManageTables, self).exec()
|
||||
|
||||
def open_tables(self):
|
||||
tables = self.parent.RestTables.find([
|
||||
|
@ -512,7 +514,7 @@ class DialogConsumer(QuickDialog):
|
|||
class DialogHistoricSales(QuickDialog):
|
||||
def __init__(self, parent):
|
||||
width, height = get_screen()
|
||||
col_sizes = [fd['width'] for fd in parent.fields_sales_query]
|
||||
col_sizes = (fd['width'] for fd in parent.fields_sales_query)
|
||||
vbox_ = QVBoxLayout()
|
||||
|
||||
table = TableView(
|
||||
|
@ -556,8 +558,9 @@ class DialogSaleForm(QuickDialog):
|
|||
]
|
||||
fields = OrderedDict(_fields)
|
||||
self.grid = GridForm(self, fields, col=2)
|
||||
col_sizes = [field['width'] for field in parent.fields_sale_line]
|
||||
self.table = TableView('model_sale_lines',
|
||||
col_sizes = (field['width'] for field in parent.fields_sale_line)
|
||||
self.table = TableView(
|
||||
'model_sale_lines',
|
||||
parent.model_sale_lines_simple, col_sizes
|
||||
)
|
||||
self.grid.addWidget(self.table, 4, 1, 1, 4)
|
||||
|
@ -569,16 +572,21 @@ class DialogSaleForm(QuickDialog):
|
|||
self.setFixedSize(int(width * 0.5), int(height * 0.6))
|
||||
|
||||
def start(self, data):
|
||||
self.sale_customer_selected = data['id']
|
||||
self.field_party.setText(data['party']['name'])
|
||||
self.field_number.setText(data['number'])
|
||||
self.field_sale_date.setText(data['sale_date'])
|
||||
self.field_total_amount_cache.setText(str(data['total_amount_cache']))
|
||||
self.field_invoice_number.setText(str(data['invoice_number']))
|
||||
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'])
|
||||
self.field_number.setText(number)
|
||||
self.field_sale_date.setText(sale_date)
|
||||
self.field_total_amount_cache.setText(str(total_amount_cache))
|
||||
self.field_invoice_number.setText(str(invoice_number))
|
||||
self.table.model.reset()
|
||||
for line in data['lines']:
|
||||
for line in lines:
|
||||
self.table.model.add_record(line)
|
||||
self.exec_()
|
||||
self.exec()
|
||||
|
||||
def get_button(self):
|
||||
button_duplicate_sale = CustomButton(
|
||||
|
@ -599,14 +607,12 @@ class DialogSaleForm(QuickDialog):
|
|||
self.dialog_search_consumer.close()
|
||||
self.dialog_table_sale_consumer.close()
|
||||
self.dialog_sale_consumer_selected.close()
|
||||
# FIXME
|
||||
# self.load_sale(res['sale_id'])
|
||||
return res
|
||||
|
||||
|
||||
class DialogAgent(QuickDialog):
|
||||
def __init__(self, parent):
|
||||
view = [
|
||||
view = (
|
||||
('agent_ask', {
|
||||
'name': 'AGENTE',
|
||||
'type': 'relation',
|
||||
|
@ -620,18 +626,18 @@ class DialogAgent(QuickDialog):
|
|||
}),
|
||||
('commission_ask', {'name': 'COMISION'}),
|
||||
('commission_amount', {'name': 'VALOR', 'readonly': True}),
|
||||
]
|
||||
)
|
||||
super(DialogAgent, self).__init__(parent, 'action', data=view)
|
||||
|
||||
|
||||
class DialogCancelInvoice(QuickDialog):
|
||||
def __init__(self, parent):
|
||||
view = [
|
||||
view = (
|
||||
('password_for_cancel_ask', {
|
||||
'name': 'INGRESE LA CONTRASEÑA',
|
||||
'password': True
|
||||
}),
|
||||
]
|
||||
)
|
||||
super(DialogCancelInvoice, self).__init__(parent, 'action', data=view)
|
||||
|
||||
|
||||
|
@ -653,7 +659,7 @@ class DialogStock(QuickDialog):
|
|||
data = {
|
||||
'name': 'stock',
|
||||
'values': [],
|
||||
'heads': ['BODEGA', 'CANTIDAD', 'POSICION'],
|
||||
'heads': ('BODEGA', 'CANTIDAD', 'POSICION'),
|
||||
}
|
||||
label = 'STOCK POR PRODUCTO:'
|
||||
width, height = get_screen()
|
||||
|
@ -671,7 +677,7 @@ class DialogGlobalDiscount(QuickDialog):
|
|||
|
||||
class DialogPrintInvoice(QuickDialog):
|
||||
def __init__(self, parent):
|
||||
view = [
|
||||
view = (
|
||||
('invoice_number_ask', {'name': 'ORDEN / FACTURA'}),
|
||||
('type_ask', {
|
||||
'name': 'TIPO',
|
||||
|
@ -695,20 +701,20 @@ class DialogPrintInvoice(QuickDialog):
|
|||
'type': 'checkbox',
|
||||
'placeholder': 'REENVIO DIAN',
|
||||
}),
|
||||
]
|
||||
)
|
||||
super(DialogPrintInvoice, self).__init__(parent, 'action', data=view)
|
||||
|
||||
|
||||
class DialogAdvance(QuickDialog):
|
||||
def __init__(self, parent):
|
||||
data = [
|
||||
data = (
|
||||
('amount_ask', {'name': 'VALOR'}),
|
||||
('reservation_ask', {
|
||||
'name': 'RESERVA',
|
||||
'type': 'checkbox',
|
||||
'placeholder': 'RESERVA',
|
||||
}),
|
||||
]
|
||||
)
|
||||
super(DialogAdvance, self).__init__(parent, 'action', data=data)
|
||||
|
||||
def clean(self):
|
||||
|
@ -853,10 +859,11 @@ class DeliveryPartySelected(QuickDialog):
|
|||
class DialogTableDeliveryParty(QuickDialog):
|
||||
def __init__(self, parent):
|
||||
self._parent = parent
|
||||
col_sizes_tlines = [field['width'] for field in parent.fields_delivery_party]
|
||||
table = TableView('model_delivery_party',
|
||||
parent.model_delivery_party, col_sizes_tlines,
|
||||
method_selected_row=parent.delivery_party_selected
|
||||
col_sizes_tlines = (field['width'] for field in parent.fields_delivery_party)
|
||||
table = TableView(
|
||||
'model_delivery_party',
|
||||
parent.model_delivery_party, col_sizes_tlines,
|
||||
method_selected_row=parent.delivery_party_selected
|
||||
)
|
||||
width, height = get_screen()
|
||||
table.setFixedSize(int(width/2.2), int(height/2.2))
|
||||
|
@ -893,12 +900,12 @@ class DialogMoneyCount(QuickDialog):
|
|||
self.kind = None
|
||||
width, height = get_screen()
|
||||
grid = QGridLayout()
|
||||
_sizes = [160, 120, 240]
|
||||
fields = [
|
||||
_sizes = (160, 120, 240)
|
||||
fields = (
|
||||
{'label': 'MONEDA', 'type': 'integer', 'readonly': True},
|
||||
{'label': 'CANTIDAD', 'type': 'integer', 'change': 'set_total'},
|
||||
{'label': 'SUBTOTAL', 'type': 'integer', 'readonly': True},
|
||||
]
|
||||
)
|
||||
self.model = TableEdit(self, MONEY, fields)
|
||||
table = TableView('model', self.model, _sizes, editable=True)
|
||||
table.setFixedSize(int(width * 0.35), int(height * 0.4))
|
||||
|
@ -958,7 +965,7 @@ class DialogMoneyCount(QuickDialog):
|
|||
if self.kind == 'open':
|
||||
kind = 'APERTURA'
|
||||
|
||||
_data = [(str(d[0]), str(d[1]), str(d[2])) for d in self.model._data]
|
||||
_data = ((str(d[0]), str(d[1]), str(d[2])) for d in self.model._data)
|
||||
data = {
|
||||
'type': kind,
|
||||
'total': self.field_total_money.text(),
|
||||
|
@ -995,14 +1002,14 @@ class DialogExpenses(QuickDialog):
|
|||
# )
|
||||
# grid.addWidget(self.button_test, 1, 1)
|
||||
|
||||
_sizes = [140, 290, 210, 150]
|
||||
fields = [
|
||||
_sizes = (140, 290, 210, 150)
|
||||
fields = (
|
||||
{'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': 'integer', 'change': 'set_total'},
|
||||
]
|
||||
)
|
||||
self.model = TableEdit(self, [], fields)
|
||||
self.table = TableView('model_expenses', self.model, _sizes, editable=True)
|
||||
self.table.hideColumn(0)
|
||||
|
@ -1028,15 +1035,16 @@ class DialogExpenses(QuickDialog):
|
|||
def load(self):
|
||||
if not self.parent.data_expenses:
|
||||
return
|
||||
model_add = self.model.add_record
|
||||
for rec in self.parent.data_expenses:
|
||||
data = [
|
||||
data = (
|
||||
rec['id'],
|
||||
rec['invoice_number'],
|
||||
rec['description'],
|
||||
rec['reference'],
|
||||
rec['amount']
|
||||
]
|
||||
self.model.add_record(data)
|
||||
)
|
||||
model_add(data)
|
||||
self.field_total.setText(str(self.model.get_sum(4)))
|
||||
|
||||
def set_total(self, args=None):
|
||||
|
@ -1079,7 +1087,7 @@ class DialogExpenses(QuickDialog):
|
|||
class DialogTaxes(QuickDialog):
|
||||
def __init__(self, parent):
|
||||
if parent.shop_taxes:
|
||||
taxes = [(str(e['id']), e['name']) for e in parent.shop_taxes]
|
||||
taxes = ((str(e['id']), e['name']) for e in parent.shop_taxes)
|
||||
else:
|
||||
taxes = []
|
||||
data = {
|
||||
|
@ -1506,7 +1514,7 @@ class Help(HelpDialog):
|
|||
|
||||
def __init__(self, parent):
|
||||
super(Help, self).__init__(parent)
|
||||
shortcuts = [
|
||||
shortcuts = (
|
||||
('PANEL DE CONTROL', 'F1'),
|
||||
('BUSCAR PRODUCTO', 'F2'),
|
||||
('MEDIO DE PAGO', 'F3'),
|
||||
|
@ -1522,7 +1530,7 @@ class Help(HelpDialog):
|
|||
('POSICION', 'Insert'),
|
||||
('FACTURAR', 'End'),
|
||||
('COMENTARIO', 'Quotation Marks'),
|
||||
]
|
||||
)
|
||||
|
||||
self.set_shortcuts(shortcuts)
|
||||
|
||||
|
@ -1633,10 +1641,10 @@ class DialogInfoProduct(QuickDialog):
|
|||
products = self._parent.local_db.find_product_elastic(domain, limit=100)
|
||||
else:
|
||||
products = self._parent.Product.find(domain, ctx=self._parent.stock_context,
|
||||
fields=['name', 'code', 'categories', 'description', 'encoded_sale_price'
|
||||
fields=['name', 'code', 'categories', 'description',
|
||||
'id', 'image', 'image_icon', 'list_price', 'location'
|
||||
'products_mix', 'quantity', 'rec_name', 'template',
|
||||
'extra_tax', 'template.sale_price_w_tax', 'uom',
|
||||
'extra_tax', 'template.sale_price_w_tax', 'sale_uom',
|
||||
'barcode', 'write_date'])
|
||||
|
||||
if not products:
|
||||
|
@ -1662,11 +1670,11 @@ class DialogInfoProduct(QuickDialog):
|
|||
parent = self._parent
|
||||
width, height = get_screen()
|
||||
grid = QGridLayout()
|
||||
_sizes = [160, 320]
|
||||
fields = [
|
||||
_sizes = (160, 320)
|
||||
fields = (
|
||||
{'label': 'CODIGO', 'type': 'integer', 'readonly': False},
|
||||
{'label': 'NOMBRE', 'type': 'char', 'readonly': False},
|
||||
]
|
||||
)
|
||||
self.model = TableEdit(self, [], fields)
|
||||
self.table = TableView('model_info_product', self.model, _sizes, editable=False, method_selected_row=self.on_selected_product)
|
||||
self.table.setFixedSize(int(width * 0.35), int(height * 0.4))
|
||||
|
|
|
@ -9,7 +9,8 @@ except:
|
|||
print('Warning: missing pyserial module!')
|
||||
|
||||
from decimal import Decimal
|
||||
from PyQt5.QtCore import QThread, pyqtSignal
|
||||
# from PyQt5.QtCore import QThread, pyqtSignal
|
||||
from PySide6.QtCore import QThread, Signal
|
||||
|
||||
ZERO_VALUES = [b'00.000\n', b'\r00.000\n']
|
||||
FAKE_WEIGHT = b'01.500\n'
|
||||
|
@ -20,9 +21,9 @@ class ScaleReader(QThread):
|
|||
"""
|
||||
Electronic Scale Reader Class
|
||||
"""
|
||||
sigSetDevice = pyqtSignal()
|
||||
sigSetWeight = pyqtSignal()
|
||||
sigCancelAction = pyqtSignal()
|
||||
sigSetDevice = Signal()
|
||||
sigSetWeight = Signal()
|
||||
sigCancelAction = Signal()
|
||||
|
||||
def __init__(self, device_path='/dev/ttyUSB0', fake=False):
|
||||
QThread.__init__(self)
|
||||
|
|
|
@ -9,8 +9,8 @@ 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
|
||||
from .proxy import FastModel, Model
|
||||
# from .commons.dblogin import safe_reconnect
|
||||
from .proxy import Model
|
||||
from .constants import SCREENS
|
||||
from .dialogs import (
|
||||
Help, ControlPanel, SearchSale, SearchParty, SearchProduct, Position,
|
||||
|
@ -124,7 +124,8 @@ class FrontWindow(QMainWindow):
|
|||
self.global_timer += 1
|
||||
if self.global_timer > self.timeout:
|
||||
self.global_timer = 0
|
||||
safe_reconnect()
|
||||
print('error esta linea no debia ejecutarse')
|
||||
# safe_reconnect()
|
||||
|
||||
def close(self):
|
||||
dialog = self.dialog('confirm_exit', response=True)
|
||||
|
@ -163,13 +164,16 @@ class FrontWindow(QMainWindow):
|
|||
self._keyStates[event.key()] = False
|
||||
|
||||
def create_dialogs(self):
|
||||
print('control panel')
|
||||
self.dialog_control_panel = ControlPanel(self)
|
||||
self.dialog_money_count = DialogMoneyCount(self)
|
||||
self.dialog_search_sales = SearchSale(self)
|
||||
print('control panel')
|
||||
self.dialog_search_parties = SearchParty(self)
|
||||
self.dialog_search_products = SearchProduct(self)
|
||||
self.dialog_position = Position(self)
|
||||
self.dialog_tip_amount = TipAmount(self)
|
||||
print('control panel')
|
||||
self.dialog_delivery_amount = DeliveryAmount(self)
|
||||
self.dialog_comment = Comment(self)
|
||||
self.dialog_payment = DialogPayment(self)
|
||||
|
@ -215,6 +219,15 @@ class FrontWindow(QMainWindow):
|
|||
def resize_window_tablet_dev(self):
|
||||
self.resize(690, self.get_geometry()[1])
|
||||
|
||||
def get_allow_categories_ids(self):
|
||||
allow_cat = []
|
||||
allow_cat_append = allow_cat.append
|
||||
allow_cat_extend = allow_cat.extend
|
||||
for pc in self.product_categories:
|
||||
allow_cat_append(pc['id'])
|
||||
allow_cat_extend(pc['childs'])
|
||||
return allow_cat
|
||||
|
||||
def load_modules(self):
|
||||
self._sale_pos_restaurant = None
|
||||
time1 = time.time()
|
||||
|
@ -270,7 +283,7 @@ class FrontWindow(QMainWindow):
|
|||
])
|
||||
if self._sale_pos_restaurant:
|
||||
self.PartyConsumer = Model('party.consumer', self.ctx)
|
||||
if self._config['delivery_product']:
|
||||
if self._config['delivery_product.']:
|
||||
self._delivery_product = 0
|
||||
|
||||
self.User = Model('res.user', self.ctx)
|
||||
|
@ -342,6 +355,7 @@ class FrontWindow(QMainWindow):
|
|||
self.user_can_delete = self.type_pos_user in ('frontend_admin', 'cashier')
|
||||
|
||||
self.product_categories = self.shop['product_categories.']
|
||||
self.allow_categories_ids = self.get_allow_categories_ids()
|
||||
self.salesman_required = self.shop['salesman_pos_required']
|
||||
|
||||
self.default_party = self.shop['party.']
|
||||
|
@ -362,12 +376,11 @@ class FrontWindow(QMainWindow):
|
|||
if self._config['show_stock_pos'] in ('value', 'icon'):
|
||||
self.stock_context = {
|
||||
'stock_date_end': date.today(),
|
||||
'locations': [self.shop['warehouse']['id']],
|
||||
'locations': [self.shop['warehouse']],
|
||||
}
|
||||
|
||||
self.Source = Model('sale.source', self.ctx)
|
||||
self.Pricelist = Model('product.price_list', self.ctx)
|
||||
print('finalice load')
|
||||
return True
|
||||
|
||||
|
||||
|
|
173
app/main.py
173
app/main.py
|
@ -10,8 +10,6 @@ from packaging.version import parse as parse_version
|
|||
from decimal import Decimal
|
||||
from datetime import datetime, timedelta, date
|
||||
from collections import OrderedDict
|
||||
# from PyQt5.QtCore import Qt
|
||||
# from PyQt5.QtWidgets import (QLabel, QHBoxLayout, QVBoxLayout, QWidget)
|
||||
from PySide6.QtCore import Qt
|
||||
from PySide6.QtWidgets import (QLabel, QHBoxLayout, QVBoxLayout, QWidget)
|
||||
from app.commons.image import Image
|
||||
|
@ -43,8 +41,10 @@ import time
|
|||
invoice_type = []
|
||||
|
||||
_SALE_HISTORIC = [
|
||||
'party', 'sale_date', 'number', 'invoice_number', 'consumer',
|
||||
'total_amount_cache', 'lines'
|
||||
'party.name', 'sale_date', 'number', 'invoice_number', 'consumer',
|
||||
'total_amount_cache', 'lines.quantity', 'lines.product.name', 'lines.unit.symbol',
|
||||
'lines.amount', 'lines.unit_price_w_tax', 'lines.amount_w_tax',
|
||||
'lines.product.template.name', 'lines.note'
|
||||
]
|
||||
|
||||
|
||||
|
@ -61,30 +61,25 @@ class AppWindow(FrontWindow):
|
|||
self.set_keys()
|
||||
time1 = time.time()
|
||||
StackMessages(self)
|
||||
print(time.time() - time1, 'load stack messages')
|
||||
self.stock_context = None
|
||||
self._sale = {}
|
||||
self.ctx = self._context
|
||||
self.ctx['params'] = params
|
||||
time2 = time.time()
|
||||
response = self.load_modules()
|
||||
print(time.time() - time2, 'load modules')
|
||||
if response is not True:
|
||||
d = self.dialog(response)
|
||||
d.exec_()
|
||||
super(AppWindow, self).close()
|
||||
return
|
||||
time3 = time.time()
|
||||
self.setup_sale_line()
|
||||
self.setup_delivery_party()
|
||||
self.setup_sale_consumer()
|
||||
self.setup_payment()
|
||||
self.set_domains()
|
||||
print(time.time() - time1, 'set domains')
|
||||
|
||||
print(time.time() - time3, 'load setups')
|
||||
time1 = time.time()
|
||||
self.create_gui()
|
||||
print(time.time() - time1, 'load gui')
|
||||
print(time.time() - time1, 'create gui')
|
||||
self.message_bar.load_stack(self.stack_msg)
|
||||
self.journal = {}
|
||||
if not hasattr(self, 'auto_print_commission'):
|
||||
|
@ -104,10 +99,8 @@ class AppWindow(FrontWindow):
|
|||
self._amount_text = ''
|
||||
self._input_text = ''
|
||||
self._sign = None
|
||||
time1 = time.time()
|
||||
self.create_dialogs()
|
||||
print(time.time() - time1, 'load dialogs')
|
||||
time1 = time.time()
|
||||
print(time.time() - time1, 'create dialogs')
|
||||
self.store = StoreView(self, SALE_FIELDS)
|
||||
if not hasattr(self, 'active_weighing'):
|
||||
self.active_weighing = False
|
||||
|
@ -127,7 +120,8 @@ class AppWindow(FrontWindow):
|
|||
for j in self._journals:
|
||||
if j['id'] == self.default_journal['id']:
|
||||
self.default_journal = j
|
||||
print(time.time() - time1, 'load final')
|
||||
time6 = time.time()
|
||||
print(time6 - time1, 'load final')
|
||||
|
||||
def set_domains(self):
|
||||
self.domain_search_product = [
|
||||
|
@ -336,23 +330,22 @@ class AppWindow(FrontWindow):
|
|||
|
||||
# CONFIGURE BOARD
|
||||
board.addWidget(self.start_front, 0)
|
||||
if self.mode_conn == 'offline':
|
||||
self.WidgetOffline = QWidget()
|
||||
self.WidgetOffline.setObjectName('label_offline')
|
||||
vbox_label = QVBoxLayout()
|
||||
vbox_label.setAlignment(Qt.AlignBottom)
|
||||
LabelOffline = QLabel(self.mode_conn)
|
||||
LabelOffline.setObjectName('LabelOffline')
|
||||
LabelOffline.setAlignment(Qt.AlignCenter)
|
||||
LabelOffline.setStyleSheet(
|
||||
"""background-color:red;
|
||||
font: 30px; color: white;
|
||||
font-weight: bold;
|
||||
min-height: 60px;
|
||||
max-height: 90px""")
|
||||
vbox_label.addWidget(LabelOffline)
|
||||
self.WidgetOffline.setLayout(vbox_label)
|
||||
board.addWidget(self.WidgetOffline, 2)
|
||||
self.WidgetShop = QWidget()
|
||||
self.WidgetShop.setObjectName('label_shop')
|
||||
vbox_label = QVBoxLayout()
|
||||
vbox_label.setAlignment(Qt.AlignBottom)
|
||||
LabelShop = QLabel(self.WidgetShop)
|
||||
LabelShop.setObjectName('LabelShop')
|
||||
LabelShop.setText(self.shop['name'])
|
||||
LabelShop.setStyleSheet(
|
||||
"""
|
||||
font: 30px; color: grey;
|
||||
font-weight: bold;
|
||||
min-height: 60px;
|
||||
max-height: 90px""")
|
||||
vbox_label.addWidget(LabelShop)
|
||||
self.WidgetShop.setLayout(vbox_label)
|
||||
board.addWidget(self.WidgetShop, 2)
|
||||
board.addWidget(self.order_front, 0)
|
||||
|
||||
# LEFT HEAD COMPONENTS
|
||||
|
@ -673,10 +666,12 @@ class AppWindow(FrontWindow):
|
|||
if self.enviroment == 'restaurant':
|
||||
self.panel_right_box = QWidget()
|
||||
time3 = time.time()
|
||||
values = self.get_product_by_categories_dash()
|
||||
# print(self.product_categories, 'product categories')
|
||||
# values = self.get_product_by_categories_dash()
|
||||
values = self.product_categories
|
||||
|
||||
print(time.time() - time3, 'load products categories dash')
|
||||
self.menu_dash = MenuDash(self, values, 'on_selected_item')
|
||||
print('final dash')
|
||||
self.order_front.hide()
|
||||
vbox_order_front.addLayout(self.buttons_function, 0)
|
||||
vbox_order_front.addLayout(self.grid_info, 0)
|
||||
|
@ -801,7 +796,7 @@ class AppWindow(FrontWindow):
|
|||
try:
|
||||
quantity = Decimal(eval_value)
|
||||
try:
|
||||
product_id = self._sale_line['product']['id']
|
||||
product_id = self._sale_line['product.']['id']
|
||||
except:
|
||||
product_id = self._sale_line['product']
|
||||
if product_id and self.stock_context:
|
||||
|
@ -855,7 +850,7 @@ class AppWindow(FrontWindow):
|
|||
sale_line, = self.SaleLine.find([
|
||||
('id', '=', line_id)
|
||||
])
|
||||
price_w_tax = float(str(round(sale_line['product']['sale_price_taxed'], 0)))
|
||||
price_w_tax = float(str(round(sale_line['product.']['sale_price_taxed'], 0)))
|
||||
if price_w_tax <= value:
|
||||
discount_valid = self.set_unit_price(value, discount=False)
|
||||
else:
|
||||
|
@ -901,9 +896,10 @@ class AppWindow(FrontWindow):
|
|||
return True
|
||||
|
||||
self.set_amounts()
|
||||
for j in self._journals:
|
||||
if j['id'] == self.default_journal['id']:
|
||||
self.journal = j
|
||||
print(self._journals, self.default_journal)
|
||||
# for j in self._journals:
|
||||
# if j['id'] == self.default_journal['id']:
|
||||
self.journal = self.default_journal
|
||||
|
||||
if res['msg'] == 'missing_money':
|
||||
self.message_bar.set('enter_payment', self.default_journal['name'])
|
||||
|
@ -1114,7 +1110,7 @@ class AppWindow(FrontWindow):
|
|||
self.set_amounts(res)
|
||||
self._sale['number'] = res['number']
|
||||
self.field_number.setText(self._sale['number'])
|
||||
|
||||
print(self.default_journal, 'defaut journal')
|
||||
self.field_invoice_number.setText(res['invoice_number'])
|
||||
self.field_amount.setText('')
|
||||
self.set_state('payment')
|
||||
|
@ -1614,7 +1610,7 @@ class AppWindow(FrontWindow):
|
|||
sale_line, = self.SaleLine.find([
|
||||
('id', '=', line_id)
|
||||
])
|
||||
price_w_tax = sale_line['product']['sale_price_taxed']
|
||||
price_w_tax = sale_line['product.']['sale_price_taxed']
|
||||
price = Decimal(price_w_tax) - (discount/Decimal(line['quantity']))
|
||||
if price < 0:
|
||||
price = 0
|
||||
|
@ -2042,34 +2038,25 @@ class AppWindow(FrontWindow):
|
|||
# return records
|
||||
|
||||
def get_product_by_categories_dash(self):
|
||||
allow_categories = [
|
||||
pc for pc in self.product_categories
|
||||
if not pc['parent'] and not pc['accounting']]
|
||||
get_products = self._get_products_by_category_dash
|
||||
find = self.Product.find
|
||||
for cat in allow_categories:
|
||||
cat['icon'] = get_icon(cat['name_icon'])
|
||||
if cat.get('childs.'):
|
||||
for child in cat.get('childs.'):
|
||||
get_products(child, find)
|
||||
else:
|
||||
get_products(cat, find)
|
||||
return allow_categories
|
||||
# self.allow_categories = {
|
||||
# pc['id']: pc for pc in self.product_categories \
|
||||
# if not pc['parent'] and not pc['accounting']
|
||||
# }
|
||||
|
||||
# def get_product_by_categories_dash(self):
|
||||
# self.allow_categories = [
|
||||
# pc for pc in self.product_categories
|
||||
# if not pc['parent'] and not pc['accounting']]
|
||||
# get_products = self._get_products_by_category_dash
|
||||
# find = self.Product.find
|
||||
# for cat in self.allow_categories:
|
||||
# cat['icon'] = get_icon(cat['name_icon'])
|
||||
# if cat.get('childs.'):
|
||||
# for child in cat.get('childs.'):
|
||||
# get_products(child, find)
|
||||
# else:
|
||||
# get_products(cat, find)
|
||||
# return self.allow_categories
|
||||
# get_products = self._get_products_by_category_dash
|
||||
# find = self.Product.find
|
||||
# for cat in self.allow_categories:
|
||||
# cat['icon'] = get_icon(cat['name_icon'])
|
||||
# if cat.get('childs.'):
|
||||
# for child in cat.get('childs.'):
|
||||
# get_products(child, find)
|
||||
# else:
|
||||
# get_products(cat, find)
|
||||
values = self.Sale.get_product_by_categories(
|
||||
{
|
||||
'categories': self.allow_categories_ids
|
||||
})
|
||||
return values
|
||||
|
||||
def action_square_box_report(self):
|
||||
try:
|
||||
|
@ -2190,7 +2177,10 @@ class AppWindow(FrontWindow):
|
|||
line = self.dialog_product_edit.get()
|
||||
self._current_line_id = line['id']
|
||||
# list_price = line['product'].get('list_price')
|
||||
code = line['product']['code']
|
||||
try:
|
||||
code = line['product.']['code']
|
||||
except:
|
||||
code = line['product']['code']
|
||||
product = self.Product.find([('code', '=', code)], fields=["list_price"])
|
||||
list_price = product[0].get('list_price')
|
||||
|
||||
|
@ -2200,7 +2190,7 @@ class AppWindow(FrontWindow):
|
|||
|
||||
if list_price < list_price_r:
|
||||
# Update price in selected_line
|
||||
self.set_unit_price(product_r[0]['template']['sale_price_w_tax'], discount=False)
|
||||
self.set_unit_price(product_r[0]['template.']['sale_price_w_tax'], discount=False)
|
||||
list_price = None
|
||||
self.on_selected_item(record, list_price)
|
||||
self.dialog_combine_product.close()
|
||||
|
@ -2265,7 +2255,7 @@ class AppWindow(FrontWindow):
|
|||
if journal.get('id'):
|
||||
self.field_journal_id = journal['id']
|
||||
self.dialog_payment.close()
|
||||
self.message_bar.set('enter_payment', journal['rec_name'])
|
||||
self.message_bar.set('enter_payment', journal['name'])
|
||||
|
||||
def on_search_product(self):
|
||||
target = self.dialog_search_products.filter_field.text()
|
||||
|
@ -2288,9 +2278,8 @@ class AppWindow(FrontWindow):
|
|||
]
|
||||
domain.append(clause)
|
||||
|
||||
if not self._sale_pos_restaurant and self.shop.get('product_categories'):
|
||||
categories_id = [ct['id']
|
||||
for ct in self.shop['product_categories']]
|
||||
if self.shop.get('product_categories'):
|
||||
categories_id = self.allow_categories_ids
|
||||
domain.append([
|
||||
'OR',
|
||||
('template.categories', 'in', categories_id),
|
||||
|
@ -2523,10 +2512,13 @@ class AppWindow(FrontWindow):
|
|||
return True
|
||||
for line in self.model_sale_lines._data:
|
||||
product_id = None
|
||||
if isinstance(line['product'], int):
|
||||
product_id = line['product']
|
||||
elif isinstance(line['product'], dict):
|
||||
product_id = line['product']['id']
|
||||
if line.get('product'):
|
||||
if isinstance(line['product'], dict):
|
||||
product_id = line['product']['id']
|
||||
else:
|
||||
product_id = line['product']
|
||||
elif line.get('product.'):
|
||||
product_id = line['product.']['id']
|
||||
if product_id:
|
||||
product, = self.Product.find(
|
||||
[('id', '=', product_id)],
|
||||
|
@ -2907,16 +2899,19 @@ class AppWindow(FrontWindow):
|
|||
|
||||
def action_combo(self):
|
||||
line = self.dialog_product_edit.get()
|
||||
code = line['product']['code']
|
||||
try:
|
||||
code = line['product.']['code']
|
||||
except:
|
||||
code = line['product']['code']
|
||||
product = self.Product.find(
|
||||
[('code', '=', code)],
|
||||
fields=[
|
||||
"barcode", "code", "description", "extra_tax", "name", "uom",
|
||||
"barcode", "code", "description", "extra_tax", "name", "sale_uom",
|
||||
"quantity", "sale_price_w_tax", "template.account_category",
|
||||
"template.sale_price_w_tax", "template.rec_name", "product_mix",
|
||||
'products_mix', 'products_mix.code', 'products_mix.name'
|
||||
"template.sale_price_w_tax", "template.rec_name",
|
||||
'products_mix.code', 'products_mix.name'
|
||||
])
|
||||
products_mix = product[0].get('products_mix')
|
||||
products_mix = product[0].get('products_mix.')
|
||||
if not products_mix:
|
||||
return
|
||||
self.dialog_combo_product.set_buttons(products_mix)
|
||||
|
@ -2925,14 +2920,17 @@ class AppWindow(FrontWindow):
|
|||
|
||||
def action_combine_line(self):
|
||||
line = self.dialog_product_edit.get()
|
||||
code = line['product']['code']
|
||||
try:
|
||||
code = line['product.']['code']
|
||||
except:
|
||||
code = line['product']['code']
|
||||
|
||||
product = self.Product.find([('code', '=', code)])
|
||||
categories = product[0].get('categories')
|
||||
if not categories:
|
||||
return
|
||||
categories_ids = [cat['id'] for cat in categories]
|
||||
mixables = self.Product.find([
|
||||
('categories', 'in', categories_ids),
|
||||
('categories', 'in', categories),
|
||||
], fields=['id', 'name', 'code', 'categories', 'rec_name', 'list_price'])
|
||||
self.dialog_combine_product.set_buttons(mixables)
|
||||
self.dialog_combine_product.exec_()
|
||||
|
@ -3131,7 +3129,6 @@ class AppWindow(FrontWindow):
|
|||
self.action_read_weight()
|
||||
|
||||
def key_special_pressed(self, value):
|
||||
print('especial presed2222')
|
||||
self.clear_amount_text()
|
||||
self.clear_input_text()
|
||||
if value not in ['-', '/', '*']:
|
||||
|
@ -3271,7 +3268,7 @@ class AppWindow(FrontWindow):
|
|||
sale_line, = self.SaleLine.find([
|
||||
('id', '=', line['id'])
|
||||
])
|
||||
base_price = float(str(round(sale_line['product']['sale_price_taxed'], 0)))
|
||||
base_price = float(str(round(sale_line['product.']['sale_price_taxed'], 0)))
|
||||
previous_qty = Decimal(line['quantity'])
|
||||
self._current_line_id = line['id']
|
||||
to_write = {}
|
||||
|
|
|
@ -96,16 +96,24 @@ MODELS = {
|
|||
'rec_name': 'name',
|
||||
'fields': [
|
||||
'name', 'shop.company', 'shop.name', 'shop.taxes', 'shop.taxes.name',
|
||||
'shop.party.name', 'journals.rec_name',
|
||||
'shop.party.name', 'journals.name',
|
||||
'shop.product_categories.accounting',
|
||||
'shop.product_categories.rec_name',
|
||||
'shop.product_categories.name',
|
||||
'shop.product_categories.name_icon',
|
||||
'shop.product_categories.parent',
|
||||
'shop.product_categories.childs.accounting',
|
||||
'shop.product_categories.childs.name_icon',
|
||||
'shop.product_categories.childs.parent',
|
||||
'shop.product_categories.childs.rec_name',
|
||||
'shop.product_categories.childs.name',
|
||||
'shop.product_categories.childs',
|
||||
'shop.product_categories.products.id',
|
||||
'shop.product_categories.products.name',
|
||||
'shop.product_categories.products.code',
|
||||
'shop.product_categories.childs.products.id',
|
||||
'shop.product_categories.childs.products.name',
|
||||
'shop.product_categories.childs.products.code',
|
||||
'journal.name',
|
||||
'journal.kind',
|
||||
'shop.payment_term.name', 'shop.warehouse', 'shop.discount_pos_method',
|
||||
'shop.salesman_pos_required', 'shop.electronic_authorization',
|
||||
'shop.invoice_copies', 'shop.pos_authorization', 'shop.discounts',
|
||||
|
@ -126,9 +134,10 @@ MODELS = {
|
|||
'fields': [
|
||||
'name', 'code', 'barcode', 'write_date', 'description',
|
||||
'template.sale_price_w_tax', 'template.account_category',
|
||||
'location.name', 'image', 'image_icon', 'quantity', 'list_price',
|
||||
'encoded_sale_price', 'location', 'uom', 'categories',
|
||||
'products_mix', 'products_mix.code', 'products_mix.name'
|
||||
'image', 'image_icon', 'quantity', 'list_price',
|
||||
'sale_uom.name', 'categories',
|
||||
'products_mix.code', 'products_mix.name'
|
||||
# 'location.name', 'encoded_sale_price',
|
||||
],
|
||||
'binaries': ['image']
|
||||
},
|
||||
|
@ -148,15 +157,17 @@ MODELS = {
|
|||
'sale.configuration': {
|
||||
'rec_name': 'id',
|
||||
'fields': [
|
||||
'tip_product', 'tip_product.code', 'show_description_pos',
|
||||
'tip_product.code', 'show_description_pos',
|
||||
'show_position_pos', 'show_stock_pos', 'password_force_assign',
|
||||
'tip_rate', 'show_agent_pos', 'discount_pos_method', 'show_brand',
|
||||
'show_location_pos', 'show_delivery_charge', 'use_price_list',
|
||||
'decimals_digits_quantity', 'password_admin_pos', 'show_fractions',
|
||||
'new_sale_automatic', 'show_product_image',
|
||||
'print_invoice_payment', 'delivery_product', 'encoded_sale_price',
|
||||
'delivery_product.list_price', 'delivery_product.code', 'allow_discount_handle',
|
||||
'cache_products_local', 'show_party_categories', 'print_lines_product',
|
||||
'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',
|
||||
'print_lines_product'
|
||||
]
|
||||
},
|
||||
'party.address': {
|
||||
|
|
231
app/proxy.py
231
app/proxy.py
|
@ -1,11 +1,12 @@
|
|||
import os
|
||||
import base64
|
||||
import requests
|
||||
import tempfile
|
||||
from datetime import date
|
||||
# import simplejson as json
|
||||
from decimal import Decimal
|
||||
from http.client import HTTPConnection, HTTPSConnection
|
||||
import orjson as json
|
||||
|
||||
# import simplejson as json
|
||||
# import requests
|
||||
try:
|
||||
from app.models import MODELS
|
||||
except:
|
||||
|
@ -17,6 +18,12 @@ except:
|
|||
from commons.common import slugify, file_open
|
||||
|
||||
|
||||
HEADERS = {
|
||||
"Content-type": "application/json",
|
||||
"Accept": "text/plain"
|
||||
}
|
||||
|
||||
|
||||
def encoder(obj):
|
||||
# FIXME: add datetime, buffer, bytes
|
||||
if isinstance(obj, date):
|
||||
|
@ -26,138 +33,24 @@ def encoder(obj):
|
|||
'month': obj.month,
|
||||
'day': obj.day,
|
||||
}
|
||||
elif isinstance(obj, Decimal):
|
||||
return str(obj)
|
||||
raise TypeError(repr(obj) + " is not JSON serializable")
|
||||
|
||||
|
||||
class FastModel(object):
|
||||
|
||||
def __init__(self, model, ctx, fields=None):
|
||||
self.model = model
|
||||
self.ctx = ctx
|
||||
api_url = ctx['params']['api_url']
|
||||
db = ctx['params']['database']
|
||||
self.api = '/'.join(['http:/', api_url, db])
|
||||
_model = MODELS.get(model)
|
||||
self.fields = None
|
||||
if fields:
|
||||
self.fields = fields
|
||||
elif _model.get('fields'):
|
||||
self.fields = _model['fields']
|
||||
|
||||
def __getattr__(self, name, *args):
|
||||
'Return attribute value'
|
||||
self.method = name
|
||||
return self
|
||||
|
||||
def find(self, domain, order=None, limit=1000, ctx=None, fields=None):
|
||||
if ctx:
|
||||
self.ctx.update(ctx)
|
||||
route = self.get_route('search')
|
||||
if not fields:
|
||||
fields = self.fields
|
||||
args_ = {
|
||||
'model': self.model,
|
||||
'domain': domain,
|
||||
'order': order,
|
||||
'limit': limit,
|
||||
'fields': fields,
|
||||
'context': self.ctx,
|
||||
}
|
||||
data = json.dumps(args_, default=encoder)
|
||||
res = requests.post(route, data=data)
|
||||
return res.json()
|
||||
|
||||
def write_many(self, ids, values, fields=None):
|
||||
route = self.get_route('save_many')
|
||||
if not fields:
|
||||
fields = self.fields
|
||||
args_ = {
|
||||
'model': self.model,
|
||||
'ids': ids,
|
||||
'values': values,
|
||||
'fields': fields,
|
||||
'context': self.ctx,
|
||||
}
|
||||
data = json.dumps(args_, default=encoder)
|
||||
res = requests.put(route, data=data)
|
||||
return res.json()
|
||||
|
||||
def write(self, ids, values, fields=None):
|
||||
route = self.get_route('save')
|
||||
|
||||
if not fields:
|
||||
fields = self.fields
|
||||
if values.get('rec_name'):
|
||||
_ = values.pop('rec_name')
|
||||
args_ = {
|
||||
'model': self.model,
|
||||
'id': ids[0],
|
||||
'ids': ids,
|
||||
'record_data': values,
|
||||
'fields': fields,
|
||||
'context': self.ctx,
|
||||
}
|
||||
data = json.dumps(args_, default=encoder)
|
||||
res = requests.put(route, data=data)
|
||||
return res.json()
|
||||
|
||||
def create(self, values):
|
||||
route = self.get_route('create')
|
||||
if values.get('rec_name'):
|
||||
_ = values.pop('rec_name')
|
||||
args_ = {
|
||||
'model': self.model,
|
||||
'record': values,
|
||||
'context': self.ctx,
|
||||
}
|
||||
data = json.dumps(args_, default=encoder)
|
||||
res = requests.post(route, data=data)
|
||||
return res.json()
|
||||
|
||||
def delete(self, ids):
|
||||
route = self.get_route('delete')
|
||||
args_ = {
|
||||
'model': self.model,
|
||||
'ids': ids,
|
||||
'context': self.ctx,
|
||||
}
|
||||
data = json.dumps(args_, default=encoder)
|
||||
res = requests.delete(route, data=data)
|
||||
return res.json()
|
||||
|
||||
def get_route(self, target):
|
||||
route = self.api + '/' + target
|
||||
return route
|
||||
|
||||
def __call__(self, values=None, ctx=None):
|
||||
if ctx:
|
||||
self.ctx.update(ctx)
|
||||
args_ = {
|
||||
'model': self.model,
|
||||
'method': self.method,
|
||||
'args': values,
|
||||
'context': self.ctx,
|
||||
}
|
||||
route = self.get_route('model_method')
|
||||
data = json.dumps(args_, default=encoder)
|
||||
res = requests.post(route, data=data)
|
||||
response = None
|
||||
try:
|
||||
response = res.json()
|
||||
except ValueError:
|
||||
pass
|
||||
return response
|
||||
|
||||
|
||||
class Model(object):
|
||||
|
||||
def __init__(self, model, ctx, fields=None):
|
||||
self.model = model
|
||||
self.ctx = ctx
|
||||
api_url = ctx['params']['api_url']
|
||||
mode = ctx['params']['mode']
|
||||
db = ctx['params']['database']
|
||||
self.api = '/'.join([mode + ':/', api_url, db])
|
||||
self.port = ctx['params']['port']
|
||||
self.host = ctx['params']['server']
|
||||
self.db = ctx['params']['database']
|
||||
self.api = 'http://localhost:8010/ZIRUS'
|
||||
if ctx['params']['mode'] == 'http':
|
||||
self.conn = HTTPConnection
|
||||
else:
|
||||
self.conn = HTTPSConnection
|
||||
_model = MODELS.get(model)
|
||||
self.fields = None
|
||||
if fields:
|
||||
|
@ -173,7 +66,6 @@ class Model(object):
|
|||
def find(self, domain, order=None, limit=1000, ctx=None, fields=None):
|
||||
if ctx:
|
||||
self.ctx.update(ctx)
|
||||
route = self.get_route('search')
|
||||
if not fields:
|
||||
fields = self.fields
|
||||
args_ = {
|
||||
|
@ -184,12 +76,14 @@ class Model(object):
|
|||
'fields_names': fields,
|
||||
'context': self.ctx,
|
||||
}
|
||||
data = json.dumps(args_, default=encoder)
|
||||
res = requests.post(route, data=data)
|
||||
return res.json()
|
||||
res = self.get_connection('POST', '/search', args_)
|
||||
return res
|
||||
# route = self.get_route('search')
|
||||
# data = json.dumps(args_, default=encoder)
|
||||
# res = requests.post(route, data=data)
|
||||
# return res.json()
|
||||
|
||||
def write_many(self, ids, values, fields=None):
|
||||
route = self.get_route('save_many')
|
||||
if not fields:
|
||||
fields = self.fields
|
||||
args_ = {
|
||||
|
@ -199,13 +93,14 @@ class Model(object):
|
|||
'fields': fields,
|
||||
'context': self.ctx,
|
||||
}
|
||||
data = json.dumps(args_, default=encoder)
|
||||
res = requests.put(route, data=data)
|
||||
return res.json()
|
||||
res = self.get_connection('POST', '/save_many', args_)
|
||||
return res
|
||||
# route = self.get_route('save_many')
|
||||
# data = json.dumps(args_, default=encoder)
|
||||
# res = requests.put(route, data=data)
|
||||
# return res.json()
|
||||
|
||||
def write(self, ids, values, fields=None):
|
||||
route = self.get_route('write')
|
||||
|
||||
if not fields:
|
||||
fields = self.fields
|
||||
if values.get('rec_name'):
|
||||
|
@ -217,12 +112,14 @@ class Model(object):
|
|||
'fields': fields,
|
||||
'context': self.ctx,
|
||||
}
|
||||
data = json.dumps(args_, default=encoder)
|
||||
res = requests.post(route, data=data)
|
||||
return res.json()
|
||||
res = self.get_connection('POST', '/write', args_)
|
||||
return res
|
||||
# route = self.get_route('write')
|
||||
# data = json.dumps(args_, default=encoder)
|
||||
# res = requests.post(route, data=data)
|
||||
# return res.json()
|
||||
|
||||
def create(self, values):
|
||||
route = self.get_route('create')
|
||||
if values.get('rec_name'):
|
||||
_ = values.pop('rec_name')
|
||||
args_ = {
|
||||
|
@ -230,25 +127,43 @@ class Model(object):
|
|||
'record': values,
|
||||
'context': self.ctx,
|
||||
}
|
||||
data = json.dumps(args_, default=encoder)
|
||||
res = requests.post(route, data=data)
|
||||
return res.json()
|
||||
res = self.get_connection('POST', '/create', args_)
|
||||
return res
|
||||
# route = self.get_route('create')
|
||||
# data = json.dumps(args_, default=encoder)
|
||||
# res = requests.post(route, data=data)
|
||||
# return res.json()
|
||||
|
||||
def delete(self, ids):
|
||||
route = self.get_route('delete')
|
||||
args_ = {
|
||||
'model': self.model,
|
||||
'ids': ids,
|
||||
'context': self.ctx,
|
||||
}
|
||||
data = json.dumps(args_, default=encoder)
|
||||
res = requests.post(route, data=data)
|
||||
return res.json()
|
||||
res = self.get_connection('POST', '/delete', args_)
|
||||
return res
|
||||
# route = self.get_route('delete')
|
||||
# data = json.dumps(args_, default=encoder)
|
||||
# res = requests.post(route, data=data)
|
||||
# return res.json()
|
||||
|
||||
def get_route(self, target):
|
||||
route = self.api + '/' + target
|
||||
return route
|
||||
|
||||
def get_connection(self, method, target, data=None):
|
||||
url = '/' + self.db + target
|
||||
if data:
|
||||
payload = json.dumps(data, default=encoder)
|
||||
else:
|
||||
payload = None
|
||||
conn = self.conn(self.host, port=self.port)
|
||||
conn.request(method, url, body=payload, headers=HEADERS)
|
||||
response = conn.getresponse()
|
||||
res = json.loads(response.read())
|
||||
conn.close()
|
||||
return res
|
||||
|
||||
def __call__(self, values=None, ctx=None):
|
||||
if ctx:
|
||||
self.ctx.update(ctx)
|
||||
|
@ -258,15 +173,17 @@ class Model(object):
|
|||
'args': values,
|
||||
'context': self.ctx,
|
||||
}
|
||||
route = self.get_route('method')
|
||||
data = json.dumps(args_, default=encoder)
|
||||
res = requests.post(route, data=data)
|
||||
response = None
|
||||
try:
|
||||
response = res.json()
|
||||
except ValueError:
|
||||
pass
|
||||
return response
|
||||
res = self.get_connection('POST', '/method', args_)
|
||||
return res
|
||||
# route = self.get_route('method')
|
||||
# data = json.dumps(args_, default=encoder)
|
||||
# res = requests.post(route, data=data)
|
||||
# response = None
|
||||
# try:
|
||||
# response = res.json()
|
||||
# except ValueError:
|
||||
# pass
|
||||
# return response
|
||||
|
||||
|
||||
class FastReport(object):
|
||||
|
|
6
pospro
6
pospro
|
@ -27,17 +27,13 @@ class Client(object):
|
|||
self.app = QApplication(sys.argv)
|
||||
|
||||
def init_login(self):
|
||||
_file_config = 'config_pos.ini'
|
||||
_file_config = 'config_pos_v2.ini'
|
||||
if args.o:
|
||||
_file_config = args.o
|
||||
login = Login(file_config=_file_config)
|
||||
while not login.connection:
|
||||
login.run()
|
||||
login.exec()
|
||||
# login.params['database'] = login.field_database.text()
|
||||
# login.params['user'] = login.field_user.text()
|
||||
# login.params['server'] = login.field_host.text()
|
||||
# login.params['api_url'] = login.api_url
|
||||
return login.connection, login.params, login.mode_conn
|
||||
|
||||
def main(self, conn, params, mode_conn):
|
||||
|
|
29
setup.py
29
setup.py
|
@ -1,11 +1,12 @@
|
|||
#!/usr/bin/env python
|
||||
# This file is part of Presik POS. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
from setuptools import setup
|
||||
from setuptools import setup, find_packages
|
||||
import os
|
||||
import glob
|
||||
import shutil
|
||||
from .app import __version__
|
||||
# from .app import __version__
|
||||
|
||||
|
||||
def read(fname):
|
||||
return open(os.path.join(os.path.dirname(__file__), fname)).read()
|
||||
|
@ -33,14 +34,21 @@ if os.name == 'posix':
|
|||
path_inifile = os.path.join(default_dir, 'config_pos.ini')
|
||||
|
||||
|
||||
setup(name='presik_pos',
|
||||
version=__version__,
|
||||
setup(
|
||||
name='presik_pos',
|
||||
# version=__version__,
|
||||
description='POS Client for Tryton',
|
||||
author='Oscar Alvarez',
|
||||
author_email='gerente@presik.com',
|
||||
url='www.presik.com',
|
||||
download_url="http://www.bitbucket.org",
|
||||
packages=['app/frontend', 'app/commons', 'client', 'app/css', 'app/locale'],
|
||||
packages=[
|
||||
'app',
|
||||
'app/printing',
|
||||
'app/commons',
|
||||
'app/css',
|
||||
'app/locale'
|
||||
],
|
||||
data_files=data_files,
|
||||
scripts=['pospro'],
|
||||
classifiers=[
|
||||
|
@ -55,5 +63,14 @@ setup(name='presik_pos',
|
|||
'Topic :: Office/Business',
|
||||
],
|
||||
license='GPL',
|
||||
install_requires=[]
|
||||
install_requires=[
|
||||
'pyusb',
|
||||
'pillow',
|
||||
'qrcode',
|
||||
'paramiko',
|
||||
'orjson',
|
||||
'escpos',
|
||||
'packaging',
|
||||
'PySide6>=6.4.1'
|
||||
]
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue