Fix get payment_term
This commit is contained in:
parent
4659847b00
commit
74120560c5
|
@ -1,459 +0,0 @@
|
|||
import os
|
||||
from operator import itemgetter
|
||||
from datetime import timedelta
|
||||
|
||||
from PyQt5.QtCore import Qt, QVariant, QAbstractTableModel, \
|
||||
pyqtSignal, QModelIndex, QSize
|
||||
from PyQt5.QtWidgets import QTableView, QVBoxLayout, \
|
||||
QAbstractItemView, QLineEdit, QDialog, QLabel, QScroller, \
|
||||
QHBoxLayout, QScrollArea, QItemDelegate
|
||||
from PyQt5.QtGui import QPixmap, QIcon
|
||||
|
||||
from neox.commons.buttons import ActionButton
|
||||
|
||||
__all__ = ['Item', 'SearchWindow', 'TableModel']
|
||||
|
||||
DELTA_LOCALE = -5 # deltatime col
|
||||
DIR = os.path.abspath(os.path.normpath(os.path.join(__file__,
|
||||
'..', '..')))
|
||||
|
||||
ICONS = {
|
||||
'image': os.path.join(DIR, 'share/icon-camera.svg'),
|
||||
'stock': os.path.join(DIR, 'share/icon-stock.svg'),
|
||||
}
|
||||
|
||||
|
||||
class Item(QItemDelegate):
|
||||
|
||||
def __init__(self, values, fields):
|
||||
super(Item, self).__init__()
|
||||
_ = [setattr(self, n, str(v)) for n, v in zip(fields, values)]
|
||||
|
||||
|
||||
class SearchWindow(QDialog):
|
||||
|
||||
def __init__(self, parent, headers, records, methods, filter_column=[],
|
||||
cols_width=[], title=None, fill=False):
|
||||
"""
|
||||
parent: parent window
|
||||
headers: is a ordered dict of data with name field-column as keys.
|
||||
records: is a tuple with two values: a key called 'objects' or 'values',
|
||||
and a list of instances values or plain values for build data model:
|
||||
[('a' 'b', 'c'), ('d', 'e', 'f')...]
|
||||
on_selected_method: method to call when triggered the selection
|
||||
filter_column: list of column to search values, eg: [0,2]
|
||||
title: title of window
|
||||
cols_width: list of width of columns, eg. [120, 60, 280]
|
||||
fill: Boolean that define if the table must be fill with all data and
|
||||
values and these are visibles
|
||||
"""
|
||||
super(SearchWindow, self).__init__(parent)
|
||||
|
||||
self.parent = parent
|
||||
self.headers = headers
|
||||
self.records = records
|
||||
self.fill = fill
|
||||
self.methods = methods
|
||||
self.on_selected_method = methods.get('on_selected_method')
|
||||
self.on_return_method = methods.get('on_return_method')
|
||||
self.filter_column = filter_column
|
||||
self.cols_width = cols_width
|
||||
self.rows = []
|
||||
self.current_row = None
|
||||
if not title:
|
||||
title = self.tr('SEARCH...')
|
||||
self.setWindowTitle(title)
|
||||
WIDTH = 550
|
||||
if cols_width:
|
||||
WIDTH = sum(cols_width) + 130
|
||||
|
||||
self.resize(QSize(WIDTH, 400))
|
||||
|
||||
self.create_table()
|
||||
self.create_widgets()
|
||||
self.create_layout()
|
||||
self.create_connections()
|
||||
if records:
|
||||
if records[0] == 'objects':
|
||||
self.set_from_objects(records[1])
|
||||
elif records[0] == 'values':
|
||||
self.set_from_values(records[1])
|
||||
elif records[0] == 'data':
|
||||
self.set_from_data(records[1])
|
||||
|
||||
def get_id(self):
|
||||
if self.current_row:
|
||||
return self.current_row['id']
|
||||
|
||||
def clear_rows(self):
|
||||
if self.fill:
|
||||
self.table_model.items = []
|
||||
self.table_model.currentItems = []
|
||||
self.table_model.layoutChanged.emit()
|
||||
|
||||
def clear_filter(self):
|
||||
self.filter_field.setText('')
|
||||
self.filter_field.setFocus()
|
||||
if self.fill:
|
||||
self.table_model.items = []
|
||||
self.table_view.selectRow(-1)
|
||||
self.table_model.currentItems = []
|
||||
self.table_model.layoutChanged.emit()
|
||||
|
||||
def set_from_data(self, values):
|
||||
if self.fill:
|
||||
self.clear_filter()
|
||||
self.table_model.set_rows(values, typedata='list')
|
||||
|
||||
def set_from_values(self, values):
|
||||
if self.fill:
|
||||
self.clear_rows()
|
||||
self.table_model.set_rows(values)
|
||||
self.update_count_field()
|
||||
|
||||
def update_count_field(self):
|
||||
values = self.table_model.currentItems
|
||||
self.label_count.setText(str(len(values)))
|
||||
|
||||
def activate_counter(self):
|
||||
self.label_control = QLabel('0')
|
||||
self.label_control.setObjectName('label_count')
|
||||
self.label_control.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
|
||||
self.filter_layout.addWidget(self.label_control)
|
||||
|
||||
def set_counter_control(self, val):
|
||||
self.label_control.setText(str(len(val)))
|
||||
|
||||
def set_from_objects(self, objects):
|
||||
self.rows = []
|
||||
for object_ in objects:
|
||||
row = []
|
||||
for field, data in self.headers.items():
|
||||
val = getattr(object_, field)
|
||||
if hasattr(val, 'name'):
|
||||
val = getattr(val, 'name')
|
||||
elif data['type'] == 'number':
|
||||
val = val
|
||||
elif data['type'] == 'int':
|
||||
val = str(val)
|
||||
elif data['type'] == 'date':
|
||||
val = val.strftime('%d/%m/%Y')
|
||||
row.append(val)
|
||||
self.rows.append(row)
|
||||
self.table_model.set_rows(self.rows)
|
||||
|
||||
def create_table(self):
|
||||
# set the table model
|
||||
self.table_model = TableModel(self, self.rows, self.headers,
|
||||
self.filter_column, fill=self.fill)
|
||||
|
||||
self.table_view = QTableView()
|
||||
self.table_view.setModel(self.table_model)
|
||||
self.table_view.setMinimumSize(450, 350)
|
||||
self.table_view.setColumnHidden(0, True)
|
||||
|
||||
self.table_view.setAlternatingRowColors(True)
|
||||
self.table_view.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||
self.table_view.setGridStyle(Qt.DotLine)
|
||||
for i in range(len(self.cols_width)):
|
||||
self.table_view.setColumnWidth(i, self.cols_width[i])
|
||||
|
||||
vh = self.table_view.verticalHeader()
|
||||
vh.setVisible(False)
|
||||
hh = self.table_view.horizontalHeader()
|
||||
hh.setStretchLastSection(True)
|
||||
|
||||
# enable sorting
|
||||
self.table_view.setSortingEnabled(True)
|
||||
|
||||
def create_widgets(self):
|
||||
self.filter_label = QLabel(self.tr("FILTER:"))
|
||||
self.filter_field = QLineEdit()
|
||||
self.label_count = QLabel('0')
|
||||
self.label_count.setObjectName('label_count')
|
||||
self.label_count.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
|
||||
self.pushButtonOk = ActionButton('ok', self.action_selection_changed)
|
||||
self.pushButtonCancel = ActionButton('cancel', self.action_close)
|
||||
|
||||
def create_layout(self):
|
||||
layout = QVBoxLayout()
|
||||
self.filter_layout = QHBoxLayout()
|
||||
self.filter_layout.addWidget(self.filter_label)
|
||||
self.filter_layout.addWidget(self.filter_field)
|
||||
self.filter_layout.addWidget(self.label_count)
|
||||
layout.addLayout(self.filter_layout)
|
||||
|
||||
scroll_area = QScrollArea()
|
||||
scroll_area.setWidgetResizable(True)
|
||||
scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
|
||||
scroll_area.setWidget(self.table_view)
|
||||
|
||||
layout.addWidget(scroll_area)
|
||||
buttons_layout = QHBoxLayout()
|
||||
buttons_layout.addWidget(self.pushButtonCancel)
|
||||
buttons_layout.addWidget(self.pushButtonOk)
|
||||
layout.addLayout(buttons_layout)
|
||||
|
||||
QScroller.grabGesture(scroll_area, QScroller.LeftMouseButtonGesture)
|
||||
|
||||
self.filter_field.setFocus()
|
||||
self.setLayout(layout)
|
||||
|
||||
def create_connections(self):
|
||||
self.filter_field.textChanged.connect(self.action_text_changed)
|
||||
self.filter_field.returnPressed.connect(self.action_filter_return_pressed)
|
||||
self.table_view.clicked.connect(self.action_selection_changed)
|
||||
self.table_view.activated.connect(self.action_table_activated)
|
||||
|
||||
def action_table_activated(self):
|
||||
pass
|
||||
|
||||
def execute(self):
|
||||
self.current_row = None
|
||||
self.parent.releaseKeyboard()
|
||||
self.filter_field.setFocus()
|
||||
return self.exec_()
|
||||
|
||||
def show(self):
|
||||
self.parent.releaseKeyboard()
|
||||
self.clear_filter()
|
||||
self.filter_field.setFocus()
|
||||
super(SearchWindow, self).show()
|
||||
|
||||
def hide(self):
|
||||
self.parent.grabKeyboard()
|
||||
self.parent.setFocus()
|
||||
super(SearchWindow, self).hide()
|
||||
|
||||
def action_close(self):
|
||||
self.close()
|
||||
|
||||
def action_selection_changed(self):
|
||||
selected = self.table_view.currentIndex()
|
||||
# current_row is a dict with values used on mainwindow
|
||||
self.current_row = self.table_model.getCurrentRow(selected)
|
||||
if selected.row() < 0:
|
||||
self.filter_field.setFocus()
|
||||
else:
|
||||
column = selected.column()
|
||||
name_field = self.table_model.header_fields[column]
|
||||
if self.methods.get(name_field):
|
||||
|
||||
parent_method = self.methods[name_field]
|
||||
parent_method()
|
||||
return
|
||||
self.hide()
|
||||
if self.parent:
|
||||
getattr(self.parent, self.on_selected_method)()
|
||||
self.filter_field.setText('')
|
||||
|
||||
def action_text_changed(self):
|
||||
self.table_model.setFilter(searchText=self.filter_field.text())
|
||||
self.update_count_field()
|
||||
self.table_model.layoutChanged.emit()
|
||||
|
||||
def action_filter_return_pressed(self):
|
||||
if hasattr(self.parent, self.on_return_method):
|
||||
method = getattr(self.parent, self.on_return_method)
|
||||
method()
|
||||
|
||||
def keyPressEvent(self, event):
|
||||
key = event.key()
|
||||
selected = self.table_view.currentIndex()
|
||||
if key == Qt.Key_Down:
|
||||
if not self.table_view.hasFocus():
|
||||
self.table_view.setFocus()
|
||||
self.table_view.selectRow(selected.row() + 1)
|
||||
elif key == Qt.Key_Up:
|
||||
if selected.row() == 0:
|
||||
self.filter_field.setFocus()
|
||||
else:
|
||||
self.table_view.selectRow(selected.row() - 1)
|
||||
elif key == Qt.Key_Return:
|
||||
if selected.row() < 0:
|
||||
self.filter_field.setFocus()
|
||||
else:
|
||||
self.action_selection_changed()
|
||||
elif key == Qt.Key_Escape:
|
||||
self.hide()
|
||||
else:
|
||||
pass
|
||||
super(SearchWindow, self).keyPressEvent(event)
|
||||
|
||||
|
||||
class TableModel(QAbstractTableModel):
|
||||
sigItem_selected = pyqtSignal(str)
|
||||
|
||||
def __init__(self, parent, rows, headers, filter_column=[], fill=False, *args):
|
||||
"""
|
||||
rows: a list of dicts with values
|
||||
headers: a list of strings
|
||||
filter_column: list of index of columns for use as filter
|
||||
fill: If is True ever the rows will be visible
|
||||
"""
|
||||
QAbstractTableModel.__init__(self, parent, *args)
|
||||
self.rows = rows
|
||||
self.fill = fill
|
||||
self.headers = headers
|
||||
self.header_fields = [h for h in headers.keys()]
|
||||
self.header_name = [h['desc'] for h in headers.values()]
|
||||
self.rows = []
|
||||
self.currentItems = []
|
||||
self.items = []
|
||||
self.searchField = None
|
||||
self.mainColumn = 2
|
||||
self.filter_column = filter_column
|
||||
self.create_icons()
|
||||
if rows and fill:
|
||||
self.set_rows(rows)
|
||||
|
||||
def create_icons(self):
|
||||
pix_camera = QPixmap()
|
||||
pix_camera.load(ICONS['image'])
|
||||
icon_camera = QIcon()
|
||||
icon_camera.addPixmap(pix_camera)
|
||||
|
||||
pix_stock = QPixmap()
|
||||
pix_stock.load(ICONS['stock'])
|
||||
icon_stock = QIcon()
|
||||
icon_stock.addPixmap(pix_stock)
|
||||
self.icons = {
|
||||
'icon_image': icon_camera,
|
||||
'icon_stock': icon_stock,
|
||||
}
|
||||
|
||||
def _get_item(self, values):
|
||||
res = {}
|
||||
for name, data in self.headers.items():
|
||||
if '.' in name:
|
||||
attrs = name.split('.')
|
||||
val = values.get(attrs[0])
|
||||
if val:
|
||||
val = val.get(attrs[1])
|
||||
else:
|
||||
val = values[name]
|
||||
|
||||
if val:
|
||||
if data['type'] == 'date':
|
||||
val = val.strftime('%d-%m-%Y')
|
||||
elif data['type'] == 'number':
|
||||
val = '{0:,}'.format(val)
|
||||
elif data['type'] == 'datetime':
|
||||
mod_hours = val + timedelta(hours=DELTA_LOCALE)
|
||||
val = mod_hours.strftime('%d/%m/%Y %I:%M %p')
|
||||
elif data['type'] == 'icon':
|
||||
val = self.icons['icon_' + data['icon']]
|
||||
|
||||
res[name] = val
|
||||
return res
|
||||
|
||||
def set_rows(self, rows):
|
||||
self.beginResetModel()
|
||||
self.endResetModel()
|
||||
self.rows = rows
|
||||
for values in rows:
|
||||
self.insertRows(self._get_item(values))
|
||||
|
||||
if self.fill is True:
|
||||
self.currentItems = self.items
|
||||
|
||||
def set_rows_list(self, rows):
|
||||
self.beginResetModel()
|
||||
self.endResetModel()
|
||||
for values in rows:
|
||||
self.insertRows(Item(values, self.header_fields))
|
||||
|
||||
if self.fill is True:
|
||||
self.currentItems = self.items
|
||||
|
||||
def rowCount(self, parent):
|
||||
return len(self.rows)
|
||||
|
||||
def columnCount(self, parent):
|
||||
return len(self.header_fields)
|
||||
|
||||
def getCurrentRow(self, index):
|
||||
row = index.row()
|
||||
if self.currentItems and row >= 0 and len(self.currentItems) > row:
|
||||
return self.currentItems[row]
|
||||
|
||||
def data(self, index, role, col=None):
|
||||
if not index.isValid():
|
||||
return
|
||||
|
||||
row = index.row()
|
||||
if col is None:
|
||||
column = index.column()
|
||||
else:
|
||||
column = col
|
||||
item = None
|
||||
if self.currentItems and len(self.currentItems) > row:
|
||||
item = self.currentItems[row]
|
||||
|
||||
name_field = self.header_fields[column]
|
||||
|
||||
data = self.headers[name_field]
|
||||
if role == Qt.DisplayRole and item:
|
||||
if column is not None:
|
||||
return item.get(name_field)
|
||||
elif role == Qt.DecorationRole:
|
||||
if item:
|
||||
return item[name_field]
|
||||
elif role == Qt.TextAlignmentRole:
|
||||
if item:
|
||||
align = Qt.AlignmentFlag(Qt.AlignLeft)
|
||||
if data['type'] == 'icon':
|
||||
align = Qt.AlignmentFlag(Qt.AlignHCenter)
|
||||
elif data['type'] == 'number':
|
||||
align = Qt.AlignmentFlag(Qt.AlignRight)
|
||||
return align
|
||||
elif role == Qt.UserRole:
|
||||
return item
|
||||
|
||||
def headerData(self, col, orientation, role):
|
||||
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
|
||||
return QVariant(self.header_name[col])
|
||||
return QVariant()
|
||||
|
||||
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):
|
||||
name_field = self.header_fields[column]
|
||||
if 'icon-' in name_field:
|
||||
return
|
||||
data = [(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 setFilter(self, searchText=None, mainColumn=None, order=None):
|
||||
if not searchText:
|
||||
return
|
||||
|
||||
if mainColumn is not None:
|
||||
self.mainColumn = mainColumn
|
||||
self.order = order
|
||||
|
||||
self.currentItems = self.items
|
||||
|
||||
if searchText and self.filter_column:
|
||||
matchers = [t.lower() for t in searchText.split(' ')]
|
||||
self.filteredItems = []
|
||||
for item in self.currentItems:
|
||||
values_clear = list(filter(None, item.values()))
|
||||
exists = all(mt in ''.join(values_clear).lower() for mt in matchers)
|
||||
if exists:
|
||||
self.filteredItems.append(item)
|
||||
|
||||
self.currentItems = self.filteredItems
|
||||
|
||||
self.layoutChanged.emit()
|
||||
|
||||
def clear_filter(self):
|
||||
if self.fill:
|
||||
self.items = []
|
||||
self.currentItems = []
|
||||
self.layoutChanged.emit()
|
|
@ -1416,16 +1416,16 @@ class MainWindow(FrontWindow):
|
|||
'shipment_address': party['addresses'][0]['id'],
|
||||
}
|
||||
|
||||
if party.get('customer_payment_term'):
|
||||
values['payment_term'] = party.get('customer_payment_term')
|
||||
self.field_payment_term.setText(str(party['customer_payment_term']['name']))
|
||||
self.field_payment_term_id = party.get('customer_payment_term')
|
||||
payment_term = party.get('customer_payment_term')
|
||||
if payment_term:
|
||||
values['payment_term'] = payment_term['id']
|
||||
self.field_payment_term.setText(str(payment_term['name']))
|
||||
self.field_payment_term_id = payment_term['id']
|
||||
else:
|
||||
values['payment_term'] = self.default_payment_term['id']
|
||||
self.field_payment_term_id = self.default_payment_term['id']
|
||||
self.field_payment_term.setText(self.default_payment_term['name'])
|
||||
print(self._sale['id'], values)
|
||||
values['payment_term'] = values['payment_term']['id']
|
||||
|
||||
self._PosSale.write([self._sale['id']], values)
|
||||
|
||||
self.party_id = party_id
|
||||
|
|
Loading…
Reference in New Issue