presik_pos/app/dialogs.py

2217 lines
80 KiB
Python

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 (
# QCheckBox, QTextEdit, QVBoxLayout, QGridLayout, QLineEdit, QPlainTextEdit,
# QScrollArea, QHBoxLayout, QDoubleSpinBox, QLabel, QMessageBox
# )
from PySide6.QtCore import Qt
from PySide6.QtWidgets import (
QCheckBox, QTextEdit, QVBoxLayout, QGridLayout, QLineEdit, QPlainTextEdit,
QScrollArea, QHBoxLayout, QDoubleSpinBox, QLabel, QWidget
)
from .proxy import Report
from .buttonpad import ButtonsFunction
from .constants import (alignCenter, alignLeft, FRACTIONS, TYPE_VEHICLE,
MONEY, TYPE_PRINTER, ROW_CHARACTERS)
from .constants import (alignCenter, alignLeft, FRACTIONS, TYPE_VEHICLE,
MONEY, TYPE_PRINTER, ROW_CHARACTERS)
from .commons.forms import FieldMoney, ComboBox, GridForm
from .commons.search_window import SearchWindow
from collections import OrderedDict
from .manage_tables import ManageTables
from app.commons.menu_buttons import GridButtons
from app.commons.table import TableView
from app.commons.model import TableEdit
from .commons.custom_button import CustomButton
from .tools import get_icon, get_screen
from .reporting import Receipt
from .reporting import Receipt
__all__ = [
'ControlPanel', 'SearchSale', 'SearchParty', 'SearchProduct', 'Position',
'DialogPayment', 'DialogSource', 'DialogSplitSale', 'DialogTaxes', 'Help',
'DialogMoneyCount', 'DialogTableDeliveryParty', 'DialogDeliveryParty',
'DeliveryPartySelected', 'DialogPrintInvoice', 'DialogStock', 'Comment',
'DialogAuthDiscounts', 'DialogSalesmanCode', 'DialogAgent', 'ProductEdit',
'DialogOrder', 'DialogGlobalDiscount', 'DialogVoucher', 'DialogConsumer',
'DialogManageTables', 'DialogHistoricSales', 'DialogSaleForm',
'DialogCancelInvoice', 'DialogForceAssign', 'CombineProduct',
'DialogReports', 'DialogFixedDiscounts', 'DialogFixedDiscountsManual',
'DialogExpenses', 'DialogInfoProduct', 'DialogAdvance',
'DialogDeleteProduct', 'DialogCollection', 'DialogTestPrinter'
]
WIZARDS = {
'square_box_report': {
'name': 'sale_pos_frontend.sale_square_box_report',
'fields': [
('date', {
'name': 'FECHA',
'type': 'date',
'default': datetime.now().strftime("%Y-%m-%d"),
}),
('turn', {
'name': 'TURNO',
'type': 'selection',
'values': [('', ''), ('1', '1'), ('2', '2'), ('3', '3')],
}),
],
},
'delivery_report': {
'fields': [
('date', {
'name': 'FECHA',
'type': 'date',
'default': datetime.now().strftime("%Y-%m-%d"),
}),
],
}
}
def create_vbox(parent, values, method, columns=4):
vbox_ = QVBoxLayout()
grid = QGridLayout()
grid.setSpacing(2)
if isinstance(method, str):
method = getattr(parent, method)
grid_buttons = GridButtons(parent, values, columns, action=method,
style='standard_button')
vbox_.setObjectName('grid_buttons')
scroll_area = QScrollArea()
scroll_area.setWidgetResizable(True)
scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
scroll_area.setWidget(grid_buttons)
grid.addWidget(scroll_area)
vbox_.addLayout(grid)
return vbox_
class ControlPanel(QuickDialog):
def __init__(self, parent):
vbox_ = QVBoxLayout()
grid = QGridLayout()
values = self.get_control_panel()
control_panel = ButtonsFunction(parent, values=values)
scroll_area = QScrollArea()
scroll_area.setLayout(control_panel)
grid.addWidget(scroll_area)
vbox_.addLayout(grid)
width, height = get_screen()
super(ControlPanel, self).__init__(parent, 'action', widgets=[vbox_])
self.setFixedSize(int(width * 0.5), int(height * 0.5))
self.setWindowTitle('PANEL DE CONTROL')
def get_control_panel(self):
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
class DialogReports(QuickDialog):
def __init__(self, parent):
super(DialogReports, self).__init__(parent, 'action')
vbox = QVBoxLayout()
grid = QGridLayout()
scroll_area = QScrollArea()
_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)
grid.addWidget(scroll_area)
vbox.addLayout(grid)
width, height = get_screen()
self.setFixedSize(int(width * 0.5), int(height * 0.5))
self.setWindowTitle('REPORTES')
self.add_widget(vbox)
def open_wizard(self, report, add_fields=None, open_print=True):
vbox = QVBoxLayout()
wiz_report = WIZARDS[report]
fields = wiz_report['fields']
if add_fields:
fields.append(add_fields)
fields = OrderedDict(fields)
self.form = GridForm(self, fields, col=2)
vbox.addLayout(self.form)
dialog = QuickDialog(self, 'action', widgets=[vbox])
result = dialog.exec()
store = self.form.getStore()
values = {}
values.update(store)
report_name = wiz_report.get('name')
if result == 1:
if not open_print:
return values, report_name
else:
self.open_report(report_name, values)
def open_report(self, report_name, data):
report = Report(self.parent.ctx)
values = {
'report_name': report_name,
'args': data,
}
result = report.get(values)
report.open(result)
class SearchSale(SearchWindow):
def __init__(self, parent):
self.parent = parent
self.screen_size = 'small'
headers = OrderedDict()
headers['id'] = {'desc': 'ID', 'type': 'char'}
headers['number'] = {'desc': 'NUMERO', 'type': 'char'}
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)
headers['consumer.rec_name'] = {'desc': 'CONSUMIDOR', 'type': 'char'}
widths_append(300)
headers['party.name'] = {'desc': 'CLIENTE', 'type': 'char'}
widths_append(300)
headers['table_assigned.rec_name'] = {'desc': 'MESA', 'type': 'char'}
widths_append(100)
headers['source.name'] = {'desc': 'FUENTE', 'type': 'char'}
widths_append(150)
headers['create_date'] = {'desc': 'HORA', 'type': 'time'}
widths_append(120)
else:
headers['party.name'] = {'desc': 'CLIENTE', 'type': 'char'}
widths_append(160)
headers['sale_date'] = {'desc': 'FECHA', 'type': 'char'}
widths_append(80)
headers['position'] = {'desc': 'POSICION', 'type': 'char'}
widths_append(130)
headers['total_amount'] = {'desc': 'VALOR TOTAL', 'type': 'number'}
widths_append(90)
title = ('BUSCAR PEDIDOS...')
self.methods = {
'on_selected_method': 'on_selected_sale',
'on_return_method': 'on_selected_sale'
}
self.buttons_layout_filter = QHBoxLayout()
self.pushButtonCash = CustomButton(
id='button_search_sale_cash',
parent=self,
# icon=get_icon('history'),
title='CONTADO',
name_style='start',
record='cash',
method='action_search_sale',
size='mini_button',
)
self.pushButtonCredit = CustomButton(
id='button_search_sale_credit',
parent=self,
# icon=get_icon('history'),
title='CREDITO',
name_style='start',
record='credit',
method='action_search_sale',
size='mini_button',
)
if self.parent.environment == 'restaurant':
self.pushButtonReservation = CustomButton(
id='button_search_sale_reservation',
parent=self,
# icon=get_icon('history'),
title='RESERVA',
name_style='start',
record='reservation',
method='action_search_sale',
size='mini_button',
)
else:
self.pushButtonReservation = CustomButton(
id='button_search_sale_quote',
parent=self,
title='COTIZACION',
name_style='start',
record='quotation',
method='action_search_sale',
size='mini_button',
)
self.buttons_layout_filter.addWidget(self.pushButtonCash)
self.buttons_layout_filter.addWidget(self.pushButtonCredit)
self.buttons_layout_filter.addWidget(self.pushButtonReservation)
widgets_to_create = self.buttons_layout_filter
super(SearchSale, self).__init__(parent, headers, None, self.methods,
filter_column=(1, 2, 3, 4, 5, 6, 7), cols_width=widths,
title=title, fill=True, widgets=[widgets_to_create])
def action_search_sale(self, _type):
if _type == 'quotation':
self.on_return_method = 'on_search_sale_by_number'
else:
self.on_return_method = 'on_selected_sale'
self.parent.search_sales_by_domain(_type)
class SearchParty(SearchWindow):
def __init__(self, parent):
headers = OrderedDict()
headers['id'] = {'desc': 'ID', 'type': 'char'}
headers['id_number'] = {'desc': 'NUMERO ID', 'type': 'char'}
headers['name'] = {'desc': 'NOMBRE', 'type': 'char'}
headers['phone'] = {'desc': 'TELEFONO', 'type': 'char'}
headers['street'] = {'desc': 'DIRECCION', 'type': 'char'}
show_party_cats = parent._config.get('show_party_categories', None)
if show_party_cats:
headers['categories_string'] = {'desc': 'CATEGORIA', 'type': 'char'}
title = 'BUSCAR CLIENTE'
methods = {
'on_selected_method': 'on_selected_party',
'on_return_method': 'on_search_party',
# 'street': parent.on_selected_street_party
}
super(SearchParty, self).__init__(parent, headers, None, methods,
filter_column=[], cols_width=[60, 120, 270, 190, 90],
title=title, fill=True)
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'}
if parent._config.get('show_stock_pos') in ['icon', 'value']:
headers['quantity'] = {'desc': ('STOCK'), 'type': 'char'}
if parent._config['show_stock_pos'] == 'icon':
headers['quantity']['icon'] = 'stock'
headers['quantity']['type'] = 'icon'
_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)
if parent._config.get('show_description_pos'):
headers['description'] = {'desc': 'DESCRIPCION', 'type': 'char'}
_cols_width_append(300)
if parent._config.get('show_brand'):
headers['template.brand.name'] = {'desc': 'MARCA', 'type': 'char'}
_cols_width_append(100)
if parent.environment == 'retail':
headers['template.reference'] = {'desc': 'REFERENCIA', 'type': 'char'}
_cols_width_append(200)
price = {'desc': ('PRICE'), 'type': 'number'}
if not parent._config.get('encoded_sale_price'):
headers['template.sale_price_w_tax'] = price
else:
price['type'] = 'char'
headers['encoded_sale_price'] = price
_cols_width_append(100)
# if parent._config.get('show_location_pos'):
# headers['positions.name'] = {'desc': 'BODEGA', 'type': 'char'}
_cols_width_append(100)
if parent._config['show_product_image']:
headers['image'] = {'desc': 'IMAGEN', 'icon': 'image', 'type': 'icon'}
_cols_width_append(30)
methods = {
'on_selected_method': 'on_selected_product',
'on_return_method': 'on_search_product',
'image': parent.on_selected_icon_product,
'quantity': parent.on_selected_stock_product
}
fields_names = list(headers.keys())
try:
fields_names.remove('image')
except Exception:
pass
self.fields_names = fields_names
super(SearchProduct, self).__init__(parent, headers, None, methods,
cols_width=_cols_width, fill=True)
class DialogManageTables(QuickDialog):
def __init__(self, parent):
self.parent = parent
if not parent._sale_pos_restaurant:
return
tables = parent.RestTables.find([
('shop', '=', parent.shop['id'])
])
self.manager = ManageTables(parent, tables)
width, height = get_screen()
super(DialogManageTables, self).__init__(parent, 'action',
widgets=[self.manager])
self.setFixedSize(int(width / 1.5), int(height / 1.2))
def exec(self):
self.open_tables()
super(DialogManageTables, self).exec()
def open_tables(self):
tables = self.parent.RestTables.find([
('shop', '=', self.parent.shop['id'])
])
self.manager.update_records(tables)
class DialogConsumer(QuickDialog):
def __init__(self, parent):
self._parent = parent
self._parent._consumer = None
vbox_consumer = QVBoxLayout()
grid = QGridLayout()
self.consumer = {}
label_phone = QLabel('TELEFONO:')
label_phone.setObjectName('label_phone')
grid.addWidget(label_phone, 1, 1)
self.form_phone = QLineEdit()
self.form_phone.setObjectName('form_consumer_phone')
self.form_phone.textChanged.connect(
lambda: self.update('phone'))
self.form_phone.editingFinished.connect(lambda: self.search())
self.form_phone.returnPressed.connect(lambda: self.search())
grid.addWidget(self.form_phone, 1, 2)
label_consumer = QLabel('CONSUMIDOR:')
label_consumer.setObjectName('label_consumer')
grid.addWidget(label_consumer, 2, 1)
self.form_name = QLineEdit()
self.form_name.setFocus()
self.form_name.setObjectName('form_consumer_name')
self.form_name.textChanged.connect(
lambda: self.update('name'))
grid.addWidget(self.form_name, 2, 2)
label_address = QLabel('DIRECCION:')
label_address.setObjectName('label_address')
grid.addWidget(label_address, 3, 1)
self.form_address = QLineEdit()
self.form_address.setObjectName('form_consumer_address')
self.form_address.textChanged.connect(
lambda: self.update('address'))
grid.addWidget(self.form_address, 3, 2)
label_id_number = QLabel('NUMERO ID:')
label_id_number.setObjectName('label_id_number')
grid.addWidget(label_id_number, 4, 1)
self.form_id_number = QLineEdit()
self.form_id_number.setObjectName('form_consumer_id_number')
self.form_id_number.textChanged.connect(
lambda: self.update('id_number'))
grid.addWidget(self.form_id_number, 4, 2)
label_delivery = QLabel('DOMICILO:')
label_delivery.setObjectName('label_delivery')
grid.addWidget(label_delivery, 5, 1)
self.form_delivery = QLineEdit()
self.form_delivery.setObjectName('form_consumer_delivery')
self.form_delivery.textChanged.connect(
lambda: self.update('delivery'))
grid.addWidget(self.form_delivery, 5, 2)
label_notes = QLabel('NOTAS:')
label_notes.setObjectName('label_notes')
grid.addWidget(label_notes, 6, 1)
self.form_notes = QPlainTextEdit()
self.form_notes.setObjectName('form_consumer_notes')
self.form_notes.textChanged.connect(
lambda: self.update('notes')
)
grid.addWidget(self.form_notes, 6, 2)
grid.setVerticalSpacing(15)
self.label_msg = QLabel('Faltan campos requeridos!')
grid.addWidget(self.label_msg, 7, 2)
self.label_msg.setVisible(False)
grid.addWidget(self.get_button(), 8, 1, 1, 2)
vbox_consumer.addLayout(grid)
super(DialogConsumer, self).__init__(parent, 'form', widgets=[
vbox_consumer])
self.setWindowTitle('CONSUMIDOR')
self.ok_button.setDefault(False)
width, height = get_screen()
self.setGeometry(0, 0, int(width * 0.4), int(height * 0.7))
def get_button(self):
self.button_history_customer = CustomButton(
id='button_history_customer',
parent=self._parent,
icon=get_icon('history'),
title='HISTORIAL DE VENTAS',
name_style='toolbar',
method='button_sale_consumer_history'
)
self.button_history_customer.setVisible(False)
return self.button_history_customer
def fill(self, values):
self.consumer = values
self.form_phone.setText(values['phone'])
self.form_name.setText(values['name'])
self.form_delivery.setText(values.get('delivery', None))
self.form_address.setText(values['address'])
id_number = values.get('id_number', None)
if id_number:
self.form_id_number.setText(id_number)
notes = values.get('notes', None)
if not notes:
notes = ''
self.form_notes.setPlainText(notes)
self.button_history_customer.setVisible(True)
def update(self, field):
self.label_msg.setVisible(False)
field_wid = getattr(self, 'form_' + field)
if hasattr(field_wid, 'text'):
value = field_wid.text()
else:
value = field_wid.toPlainText()
self.consumer[field] = value.upper()
def search(self):
self.ok_button.setDefault(False)
phone = self.form_phone.text()
res = self.parent.search_consumer(phone)
if res:
self.button_history_customer.setVisible(True)
def show(self):
super(DialogConsumer, self).show()
self.form_phone.setFocus()
def dialog_accepted(self):
if self.consumer and len(self.consumer['phone']) > 6:
if self.consumer.get('address') and self.consumer.get('name'):
self.parent.save_consumer(self.consumer)
else:
# Add dialog error missing required fields
self.label_msg.setVisible(True)
return
super(DialogConsumer, self).dialog_accepted()
def clear(self):
self.consumer = {}
self.form_phone.setText('')
self.form_name.setText('')
self.form_address.setText('')
self.form_id_number.setText('')
self.form_delivery.setText('')
self.form_notes.clear()
self.button_history_customer.setVisible(False)
self.ok_button.setDefault(False)
class DialogHistoricSales(QuickDialog):
def __init__(self, parent):
width, height = get_screen()
col_sizes = (fd['width'] for fd in parent.fields_sales_query)
vbox_ = QVBoxLayout()
table = TableView(
'model_sale_historic', parent.model_sale_historic,
col_sizes, method_selected_row=parent.sale_form_selected
)
vbox_.addWidget(table)
vbox_.addSpacing(10)
super(DialogHistoricSales, self).__init__(parent, 'action', widgets=[vbox_])
self.setWindowTitle('-- VENTA --')
self.setFixedSize(int(width * 0.8), int(height * 0.7))
class DialogSaleForm(QuickDialog):
def __init__(self, parent):
self._parent = parent
vbox_ = QVBoxLayout()
_fields = [
('party', {
'name': 'CLIENTE',
'readonly': True,
}),
('number', {
'name': 'NUMERO',
'readonly': True,
}),
('sale_date', {
'name': 'FECHA',
'readonly': True,
}),
('invoice_number', {
'name': 'FACTURA',
'readonly': True,
}),
('total_amount_cache', {
'name': 'TOTAL',
'readonly': True,
'type': 'money',
}),
]
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',
parent.model_sale_lines_simple, col_sizes
)
self.grid.addWidget(self.table, 4, 1, 1, 4)
vbox_.addLayout(self.grid)
super(DialogSaleForm, self).__init__(parent, 'action', widgets=[vbox_])
self.grid.addWidget(self.get_button(), 5, 3, 3, 4)
width, height = get_screen()
self.setFixedSize(int(width * 0.5), int(height * 0.6))
def start(self, data):
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 lines:
self.table.model.add_record(line)
self.exec()
def get_button(self):
button_duplicate_sale = CustomButton(
id='button_duplicate_sale',
parent=self,
icon=get_icon('duplicate_sale'),
title=('DUPLICAR VENTA'),
name_style='toolbar',
method='button_duplicate_sale'
)
return button_duplicate_sale
def button_duplicate_sale(self):
if self.sale_customer_selected:
res = self._parent.Sale.duplicate_sale({
'sale_id': self.sale_customer_selected,
})
self.parent.dialog_consumer.close()
self.parent.dialog_historic_sales.close()
self.close()
return res
class DialogAgent(QuickDialog):
def __init__(self, parent):
view = (
('agent_ask', {
'name': 'AGENTE',
'type': 'relation',
'model': parent.Agent,
'domain': [],
'fields': [
('id', 'ID'),
('party.name', 'NOMBRE'),
('party.id_number', 'NUMERO ID'),
]
}),
('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 = (
('password_for_cancel_ask', {
'name': 'INGRESE LA CONTRASEÑA',
'password': True
}),
)
super(DialogCancelInvoice, self).__init__(parent, 'action', data=view)
class DialogForceAssign(QuickDialog):
def __init__(self, parent):
field = 'password_force_assign_ask'
data = (field, {'name': 'CONTRASEÑA DE FORZAR ASIGNACION'})
super(DialogForceAssign, self).__init__(parent, 'action', data=[data])
class DialogOrder(QuickDialog):
def __init__(self, parent):
string = 'DESEA CONFIRMAR EL ENVIO DE LA ORDEN?'
super(DialogOrder, self).__init__(parent, 'action', string, data=[])
class DialogStock(QuickDialog):
def __init__(self, parent):
data = {
'name': 'stock',
'values': [],
'heads': ('BODEGA', 'CANTIDAD', 'POSICION'),
}
label = 'STOCK POR PRODUCTO:'
width, height = get_screen()
super(DialogStock, self).__init__(parent, 'selection', label,
data, readonly=True)
self.setFixedSize(int(width * 0.4), int(height * 0.3))
class DialogGlobalDiscount(QuickDialog):
def __init__(self, parent):
field = 'global_discount_ask'
data = (field, {'name': 'DESCUENTO GLOBAL'})
super(DialogGlobalDiscount, self).__init__(parent, 'action', data=[data])
class DialogPrintInvoice(QuickDialog):
def __init__(self, parent):
options_type = [
('invoice', 'FACTURA'),
('order', 'ORDEN'),
]
if parent.environment == 'restaurant':
options_type.append(('quotation', 'COTIZACION'))
view = (
('invoice_number_ask', {'name': 'ORDEN / FACTURA'}),
('type_ask', {
'name': 'TIPO',
'type': 'selection',
'values': options_type,
}),
('printer_ask', {
'name': 'IMPRESORA',
'type': 'selection',
'values': [
(1, 'POS'),
(2, 'LASER')
],
}),
('resend_dian_ask', {
'name': 'REENVIO DIAN',
'type': 'checkbox',
'placeholder': 'REENVIO DIAN',
}),
)
super(DialogPrintInvoice, self).__init__(parent, 'action', data=view)
class DialogAdvance(QuickDialog):
def __init__(self, parent):
data = (
('amount_ask', {'name': 'VALOR'}),
('reservation_ask', {
'name': 'RESERVA',
'type': 'checkbox',
'placeholder': 'RESERVA',
}),
)
super(DialogAdvance, self).__init__(parent, 'action', data=data)
def clean(self):
self.parent.field_amount_ask.clear()
self.parent.field_reservation_ask.setChecked(False)
class DialogVoucher(QuickDialog):
def __init__(self, parent):
data = ('voucher_ask', {'name': 'NUMERO DE COMPROBANTE'})
super(DialogVoucher, self).__init__(parent, 'action', data=[data])
class DialogDeleteProduct(QuickDialog):
def __init__(self, parent):
data = ('note_ask', {'name': 'OBSERVACION', 'type': 'text_area'})
super(DialogDeleteProduct, self).__init__(parent, 'action', data=[data])
class DialogAuthDiscounts(QuickDialog):
def __init__(self, parent):
vbox_discounts = create_vbox(
parent,
parent.discounts,
parent.on_selected_discount
)
width, height = get_screen()
super(DialogAuthDiscounts, self).__init__(parent, 'action',
size=(width * 0.8, height * 0.8), widgets=[vbox_discounts])
self.setWindowTitle('DESCUENTOS AUTORIZADOS')
class DialogFixedDiscounts(QuickDialog):
def __init__(self, parent):
widgets = create_vbox(
parent,
parent.discounts_fixed,
parent.on_selected_discount
)
width, height = get_screen()
super(DialogFixedDiscounts, self).__init__(parent, 'action',
widgets=[widgets])
self.setFixedSize(int(width * 0.8), int(height * 0.7))
self.setWindowTitle('DESCUENTO/BONO')
class DialogFixedDiscountsManual(QuickDialog):
def __init__(self, parent):
field = 'bono_discount_manual'
data = (field, {'name': 'BONO ABIERTO'})
super(DialogFixedDiscountsManual, self).__init__(parent, 'action', data=[data])
self.setWindowTitle('BONO ABIERTO')
class DialogDeliveryParty(QuickDialog):
def __init__(self, parent):
vbox_ = create_vbox(
parent,
parent.delivery_parties,
parent.on_selected_delivery_party,
)
width, height = get_screen()
super(DialogDeliveryParty, self).__init__(parent, 'action',
widgets=[vbox_])
self.setWindowTitle('ESCOJE EL DOMICILIARIO')
self.setFixedSize(int(width * 0.8), int(height * 0.7))
class DeliveryPartySelected(QuickDialog):
def __init__(self, parent):
parent.state_delivery_party = {}
vbox_ = QVBoxLayout()
grid = QGridLayout()
label_delivery_party = QLabel('DOMICILIARIO:')
label_delivery_party.setAlignment(alignCenter)
label_delivery_party.setObjectName('label_delivery_party')
grid.addWidget(label_delivery_party, 1, 1)
parent.row_delivery_party = QLineEdit()
parent.row_delivery_party.setObjectName('row_delivery_party')
parent.row_delivery_party.textChanged.connect(
lambda: parent.update_delivery_party('party'))
grid.addWidget(parent.row_delivery_party, 1, 2)
label_id_number = QLabel('NUMERO ID:')
label_id_number.setAlignment(alignCenter)
label_id_number.setObjectName('label_id_number')
grid.addWidget(label_id_number, 2, 1)
parent.row_id_number = QLineEdit()
parent.row_id_number.setObjectName('row_id_number')
parent.row_id_number.textChanged.connect(
lambda: parent.update_delivery_party('id_number'))
grid.addWidget(parent.row_id_number, 2, 2)
label_number_plate = QLabel('PLACA:')
label_number_plate.setAlignment(alignCenter)
label_number_plate.setObjectName('label_number_plate')
grid.addWidget(label_number_plate, 3, 1)
parent.row_number_plate = QLineEdit()
parent.row_number_plate.setObjectName('row_number_plate')
parent.row_number_plate.textChanged.connect(
lambda: parent.update_delivery_party('number_plate'))
grid.addWidget(parent.row_number_plate, 3, 2)
label_phone = QLabel('TELEFONO:')
label_phone.setAlignment(alignCenter)
label_phone.setObjectName('label_phone')
grid.addWidget(label_phone, 4, 1)
parent.row_phone = QLineEdit()
parent.row_phone.setObjectName('row_phone')
parent.row_phone.textChanged.connect(
lambda: parent.update_delivery_party('phone'))
grid.addWidget(parent.row_phone, 4, 2)
label_type_vehicle = QLabel('TIPO DE VEHICULO:')
label_type_vehicle.setAlignment(alignCenter)
label_type_vehicle.setObjectName('label_type_vehicle')
grid.addWidget(label_type_vehicle, 5, 1)
parent.row_type_vehicle = ComboBox(parent,
'TIPO DE VEHICULO', {'values': TYPE_VEHICLE})
parent.row_type_vehicle.setObjectName('row_type_vehicle')
parent.row_type_vehicle.currentIndexChanged.connect(
lambda: parent.update_delivery_party('type_vehicle'))
grid.addWidget(parent.row_type_vehicle, 5, 2)
label_delivery_party_active = QLabel('ACTIVO:')
label_delivery_party_active.setAlignment(alignCenter)
label_delivery_party_active.setObjectName('label_delivery_party_active')
grid.addWidget(label_delivery_party_active, 6, 1)
parent.row_delivery_party_active = QCheckBox()
parent.row_delivery_party_active.setObjectName('row_delivery_party_active')
parent.row_delivery_party_active.stateChanged.connect(
lambda: parent.update_delivery_party('active'))
grid.addWidget(parent.row_delivery_party_active, 6, 2)
vbox_.addLayout(grid)
super(DeliveryPartySelected, self).__init__(parent, 'action',
widgets=[vbox_])
self.accepted.connect(parent.dialog_delivery_party_accepted)
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
)
width, height = get_screen()
table.setFixedSize(int(width / 2.2), int(height / 2.2))
vbox_ = QVBoxLayout()
grid = QGridLayout()
grid.addWidget(table, 1, 1, 1, 2)
grid.setVerticalSpacing(20)
grid.addWidget(self.get_button(), 2, 1, 1, 2)
grid.setAlignment(alignCenter)
vbox_.addLayout(grid)
super(DialogTableDeliveryParty, self).__init__(parent, 'action',
widgets=[vbox_])
width, height = get_screen()
self.setGeometry(0, 0, int(width / 1.8), int(height / 1.5))
self.setWindowTitle('DOMICILIARIO')
def get_button(self):
self._parent.button_create_delivery_party = CustomButton(
id='button_create_delivery_party',
parent=self._parent,
icon=get_icon('delivery_party'),
title='NUEVO DOMICILIARIO',
name_style='toolbar',
method='button_create_delivery_party'
)
return self._parent.button_create_delivery_party
class DialogMoneyCount(QuickDialog):
def __init__(self, parent):
self._parent = parent
self.kind = None
width, height = get_screen()
grid = QGridLayout()
_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))
grid.addWidget(table, 1, 0, 1, 2)
label_total = QLabel('TOTAL DINERO:')
label_total.setObjectName('label_total_money')
grid.addWidget(label_total, 2, 0)
self.field_total_money = FieldMoney(self, 'field_total_money')
self.field_total_money.setObjectName('field_total_money')
self.field_total_money.setAlignment(alignLeft)
grid.addWidget(self.field_total_money, 2, 1)
self.screen_size = parent.screen_size
self.button_print = CustomButton(
self,
id='button_print_count_money',
size='small',
icon=get_icon('print_sale'),
title='IMPRIMIR',
method='action_print_count_money',
name_style='mini_button',
)
grid.addWidget(self.button_print, 3, 0)
parent.field_send_mail = QCheckBox()
parent.field_send_mail.setText('ENVIAR EMAIL')
grid.addWidget(parent.field_send_mail, 3, 1)
grid.setRowStretch(0, 1)
grid.setSpacing(10)
super(DialogMoneyCount, self).__init__(parent, 'action',
widgets=[grid])
self.setWindowTitle('CONTEO DE DINERO')
def exec(self, kind):
self.kind = kind
self.exec()
def set_total(self, row):
_row = self.model._data[row]
money, value = _row[0], _row[1]
_row[2] = int(value) * int(money)
self.field_total_money.setText(str(self.model.get_sum(2)))
def dialog_accepted(self):
super(DialogMoneyCount, self).dialog_accepted()
val = self.field_total_money.text().replace(',', '')
if self.kind == 'open':
self.parent.open_statement_accepted(val)
else:
values = self.model._data
self.parent.close_statement_accepted(values)
def clear(self):
self.field_total_money.setText('0')
def action_print_count_money(self):
kind = 'CIERRE'
if self.kind == 'open':
kind = 'APERTURA'
_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(),
'lines': _data,
}
self.parent.action_print_count_money(data)
class DialogExpenses(QuickDialog):
def __init__(self, parent):
self._parent = parent
width, height = get_screen()
grid = QGridLayout()
self.screen_size = parent.screen_size
self.button_add = CustomButton(
self,
id='button_add_expense',
size='small',
icon=get_icon('plus'),
title='AGREGAR',
method='action_add_expense',
name_style='mini_button',
)
grid.addWidget(self.button_add, 1, 0)
# self.button_test = CustomButton(
# self,
# id='button_add_expense',
# size='small',
# icon=get_icon('plus'),
# title='BORRAR',
# method='test_delete',
# name_style='mini_button',
# )
# grid.addWidget(self.button_test, 1, 1)
_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': 'float', 'change': 'set_total'},
)
self.model = TableEdit(self, [], fields)
self.table = TableView('model_expenses', self.model, _sizes, editable=True)
self.table.hideColumn(0)
grid.addWidget(self.table, 2, 0, 1, 2)
label_total = QLabel('TOTAL:')
label_total.setObjectName('label_total_expenses')
label_total.setAlignment(alignCenter)
grid.addWidget(label_total, 3, 0)
self.field_total = FieldMoney(self, 'field_total_expenses')
self.field_total.setObjectName('field_total_expenses')
self.field_total.setAlignment(alignLeft)
grid.addWidget(self.field_total, 3, 1)
grid.setSpacing(10)
super(DialogExpenses, self).__init__(parent, 'action', widgets=[grid])
self.setGeometry(0, 0, int(width * 0.5), int(height * 0.7))
self.setWindowTitle('GASTOS')
self.id_count = -1
self.load()
def exec(self):
self.clear()
self.load()
super(DialogExpenses, self).exec()
def load(self):
if not self.parent.data_expenses:
return
model_add = self.model.add_record
for rec in self.parent.data_expenses:
data = [
rec['id'],
rec['invoice_number'],
rec['description'],
rec['reference'],
rec['amount']
]
model_add(data)
self.field_total.setText(str(self.model.get_sum(4)))
def set_total(self, args=None):
self.field_total.setText(str(self.model.get_sum(4)))
def save(self):
for d in self.model._data:
args = {
'statement': self.parent.statement_cash['id'],
'invoice_number': d[1],
'description': d[2],
'reference': d[3],
'amount': d[4].replace(',', '') if isinstance(d[4], str) else d[4],
}
obj_id = d[0]
if d[0] > 0:
self.parent.Expenses.write([obj_id], args)
else:
args['id'] = obj_id
rec = self.parent.Expenses.create(args)
for d in self.model._data:
if obj_id == d[0]:
d[0] = rec[0]
def action_add_expense(self):
record = [self.id_count, '', '', '', 0]
self.id_count += -1
self.model.add_record(record)
self.set_total()
def dialog_accepted(self):
self.save()
super(DialogExpenses, self).dialog_accepted()
def clear(self):
self.model.clearData()
self.set_total()
class DialogTaxes(QuickDialog):
def __init__(self, parent):
if parent.shop_taxes:
taxes = ((str(e['id']), e['name']) for e in parent.shop_taxes)
else:
taxes = []
data = {
'name': 'tax',
'values': taxes,
'heads': ['ID', 'VALOR'],
}
string = 'ESCOJA EL IMPUESTO'
super(DialogTaxes, self).__init__(parent, 'selection', string, data)
class DialogSource(QuickDialog):
def __init__(self, parent):
vbox_ = create_vbox(parent, parent.sources, parent.on_selected_source)
super(DialogSource, self).__init__(parent, 'action', widgets=[vbox_],
buttons=False)
self.setWindowTitle('SELECCIONE EL CANAL')
width, height = get_screen()
self.setFixedSize(int(width * 0.6), int(height * 0.7))
class DialogPaymentTerm(QuickDialog):
def __init__(self, parent):
vbox_ = create_vbox(parent, parent._payment_terms,
parent.on_selected_payment_term)
super(DialogPaymentTerm, self).__init__(parent, 'action', widgets=[vbox_])
self.setWindowTitle('PLAZO DE PAGO')
class DialogPayment(QuickDialog):
def __init__(self, parent):
vbox_ = create_vbox(parent, parent._journals, parent.on_selected_payment)
width, height = get_screen()
super(DialogPayment, self).__init__(parent, 'action', widgets=[vbox_])
self.setWindowTitle('EL MEDIO DE PAGO:')
self.setFixedSize(int(width * 0.8), int(height * 0.7))
class Position(QuickDialog):
def __init__(self, parent):
field = 'position_ask'
data = (field, {'name': 'POSICION'})
super(Position, self).__init__(parent, 'action', data=[data])
class Comment(QuickDialog):
def __init__(self, parent):
field = 'comment'
data = (field, {'name': 'COMENTARIO', 'type': 'text'})
super(Comment, self).__init__(parent, 'action', data=[data])
class TipAmount(QuickDialog):
def __init__(self, parent):
vbox_ = QVBoxLayout()
grid = QGridLayout()
label_tip_amount_ask = QLabel('VALOR PROPINA:')
label_tip_amount_ask.setAlignment(alignCenter)
label_tip_amount_ask.setObjectName('label_tip_amount_ask')
grid.addWidget(label_tip_amount_ask, 1, 1)
parent.field_tip_amount_ask = QLineEdit()
parent.field_tip_amount_ask.setObjectName('field_tip_amount_ask')
grid.addWidget(parent.field_tip_amount_ask, 1, 2)
vbox_.addLayout(grid)
parent.field_tip_amount_invoice = QCheckBox()
parent.field_tip_amount_invoice.setText('INCLUIR EN FACTURA')
vbox_.addWidget(parent.field_tip_amount_invoice)
super(TipAmount, self).__init__(parent, 'action', widgets=[vbox_])
class DeliveryAmount(QuickDialog):
def __init__(self, parent):
vbox_ = QVBoxLayout()
grid = QGridLayout()
label_delivery_amount_ask = QLabel('VALOR DEL DOMICILO:')
label_delivery_amount_ask.setAlignment(alignCenter)
label_delivery_amount_ask.setObjectName('label_delivery_amount_ask')
grid.addWidget(label_delivery_amount_ask, 1, 1)
parent.field_delivery_amount_ask = QLineEdit()
parent.field_delivery_amount_ask.setObjectName('field_delivery_amount_ask')
grid.addWidget(parent.field_delivery_amount_ask, 1, 2)
vbox_.addLayout(grid)
parent.field_delivery_amount_invoice = QCheckBox()
parent.field_delivery_amount_invoice.setText('INCLUIR EN FACTURA')
vbox_.addWidget(parent.field_delivery_amount_invoice)
super(DeliveryAmount, self).__init__(parent, 'action', widgets=[vbox_])
class DialogSalesmanCode(QuickDialog):
def __init__(self, parent):
field = 'salesman_code_ask'
data = (field, {'name': 'CODIGO VENDEDOR', 'password': True})
super(DialogSalesmanCode, self).__init__(parent, 'action', data=[data])
class ProductEdit(QuickDialog):
def __init__(self, parent):
self._parent = parent
self.store = {}
self.active_line = {}
vbox_product = QVBoxLayout()
grid = QGridLayout()
width, height = get_screen()
self.label_product = QLabel()
self.label_product.setAlignment(alignCenter)
self.label_product.setObjectName('label_product')
vbox_product.addWidget(self.label_product)
if parent._config.get('show_fractions'):
self.field_description = QLineEdit()
self.field_description.setObjectName('field_description')
self.field_description.textChanged.connect(
lambda: self.update_line('description')
)
grid.addWidget(self.field_description, 1, 1, 1, 2)
label_fraction = QLabel('FRACCION:')
label_fraction.setObjectName('label_fraction')
grid.addWidget(label_fraction, 2, 1)
self.field_combobox_fraction = ComboBox(
parent, 'fraction', {'values': FRACTIONS}
)
grid.addWidget(self.field_combobox_fraction, 2, 2)
self.field_combobox_fraction.currentIndexChanged.connect(
lambda: self.update_line('qty_fraction')
)
label_qty = QLabel('CANTIDAD:')
label_qty.setObjectName('label_qty')
grid.addWidget(label_qty, 3, 1)
self.field_qty = QDoubleSpinBox()
self.field_qty.setObjectName('field_qty')
self.field_qty.setMinimum(0)
self.field_qty.setMaximum(100000)
decimals = 2
if parent._config.get('decimals_digits_quantity'):
decimals = parent._config['decimals_digits_quantity']
self.field_qty.setDecimals(decimals)
self.field_qty.setAlignment(alignCenter)
grid.addWidget(self.field_qty, 3, 2)
self.field_qty.valueChanged.connect(
lambda: self.update_line('quantity')
)
label_price = QLabel('PRECIO:')
label_price.setObjectName('label_price')
grid.addWidget(label_price, 4, 1)
self.field_price = FieldMoney(self, 'field_price', {}, readonly=False)
self.field_price.setObjectName('field_price')
grid.addWidget(self.field_price, 4, 2)
self.field_price.textChanged.connect(
lambda: self.update_line('unit_price')
)
self.field_note = QTextEdit('')
self.field_note.setObjectName('row_field_note')
grid.addWidget(self.field_note, 5, 1, 5, 2)
self.field_note.textChanged.connect(lambda: self.update_line('note'))
button_delete = CustomButton(
parent,
id='button_delete',
size='small',
icon=get_icon('delete_line'),
title='ELIMINAR',
method='action_delete_line',
name_style='mini_button',
)
button_discounts = CustomButton(
parent,
id='button_discount',
size='small',
icon=get_icon('discount'),
title=('DESCUENTO/BONO'),
method='action_discount_line',
name_style='mini_button',
)
button_discounts_bono = CustomButton(
parent,
id='button_discount_bono',
size='small',
icon=get_icon('discount'),
title=('BONO/ABIERTO'),
method='action_discount_bono_line',
name_style='mini_button',
)
button_addition = CustomButton(
parent,
id='button_addition',
size='small',
icon=get_icon('combine_product'),
title=('COMBINAR'),
method='action_combine_line',
name_style='mini_button',
)
button_combo = CustomButton(
parent,
id='button_combo',
size='small',
icon=get_icon('combo'),
title=('ELECCION'),
method='action_combo',
name_style='mini_button',
)
hbox = QHBoxLayout()
vbox_product.addLayout(grid, 1)
vbox_product.addLayout(hbox, 0)
hbox.addWidget(button_delete, 0)
hbox.addWidget(button_discounts, 0)
hbox_checkbox_base = QHBoxLayout()
vbox_product.addLayout(hbox_checkbox_base, 0)
self.checkbox_base = QCheckBox()
self.checkbox_base.setText('PRECIO BASE')
self.checkbox_base.setMaximumSize(120, 0)
if parent.environment == 'restaurant':
hbox.addWidget(button_discounts_bono, 0)
hbox.addWidget(button_combo, 0)
hbox.addWidget(button_addition, 0)
else:
hbox.addWidget(self.checkbox_base, 0)
super(ProductEdit, self).__init__(parent, 'action', widgets=[vbox_product])
self.setFixedSize(int(width * 0.5), int(height * 0.7))
def get(self):
return self.active_line
def close(self):
super(ProductEdit, self).close()
self.clear()
def closeEvent(self, event):
super(QuickDialog, self).closeEvent(event)
self.clear()
def clear(self):
self.store = {}
self.active_line = {}
self.checkbox_base.setChecked(False)
def dialog_rejected(self):
super(ProductEdit, self).dialog_rejected()
self.clear()
def dialog_accepted(self):
super(ProductEdit, self).dialog_accepted()
self.parent.dialog_product_edit_accepted(self.store, self.active_line)
def set_line(self, record):
self.active_line = record
self.show()
# name = record.get('product.template.name', None)
# if not name:
name = record['product.']['name']
self.label_product.setText(name)
if hasattr(self, 'field_description'):
self.field_description.setText(record['description'])
self.field_qty.setValue(float(record['quantity']))
self.field_price.setText(str(record['unit_price_w_tax']))
self.field_note.setText(str(record['note']))
self.field_note.setFocus()
def update_line(self, field):
value = None
self.store['id'] = self.active_line['id']
if field == 'quantity':
value = Decimal(self.field_qty.value())
if field == 'unit_price':
value = self.field_price.text()
value = value.replace(',', '')
if field == 'qty_fraction':
qty = self.field_combobox_fraction.get_id()
self.field_qty.setValue(float(qty))
value = self.field_combobox_fraction.get_label()
self.store['quantity'] = qty
price_ = self.parent.get_product_fraction_prices(
self.active_line['product.']['id'],
self.active_line['sale'],
qty
)
if price_ and price_.get('unit_price_w_tax'):
price_list = str(price_['unit_price_w_tax'])
self.field_price.setText(price_list)
self.store['unit_price'] = price_list
if hasattr(self, 'field_description'):
if field == 'description':
value = self.field_description.text()
if field == 'note':
value = self.field_note.toPlainText()
if value:
self.store[field] = value
class CombineProduct(QuickDialog):
def __init__(self, parent):
self.box = QVBoxLayout()
width, height = get_screen()
self.method_action = getattr(parent, 'on_selected_item_mix')
self.parent = parent
self.box.setObjectName('grid_buttons')
self.filter_field = QLineEdit()
self.filter_field.setObjectName('field_filter_addition')
self.filter_field.setPlaceholderText('BUSCAR...')
self.filter_field.textChanged.connect(self.filter_products)
self.box.addWidget(self.filter_field)
super(CombineProduct, self).__init__(parent, 'action', widgets=[self.box])
self.setWindowTitle('SELECCIONE LA COMBINACION')
self.setFixedSize(int(width * 0.8), int(height * 0.9))
def set_buttons(self, values):
self.values = values
self.set_products(values)
def set_products(self, values):
grid_buttons = GridButtons(
self.parent,
values,
5,
action=self.method_action,
style='standard_button'
)
if hasattr(self, 'scroll_area'):
_ = self.box.removeWidget(self.scroll_area)
self.scroll_area = QScrollArea()
self.scroll_area.setWidgetResizable(True)
self.scroll_area.setWidget(grid_buttons)
self.box.addWidget(self.scroll_area)
def filter_products(self, text):
if len(text) == 0:
self.set_products(self.values)
return
if len(text) <= 2:
return
filtered = []
text_list = text.upper().split(' ')
for v in self.values:
for t in text_list:
if t in v['rec_name']:
filtered.append(v)
self.set_products(filtered)
class DialogComboProduct(QuickDialog):
def __init__(self, parent):
qwidget = QWidget()
self.hbox = QHBoxLayout(qwidget)
qwidget.setFixedHeight(50)
width, height = get_screen()
self.method_action = getattr(parent, 'on_selected_item_combo')
self.parent = parent
label = QLabel('SELECCIONE LOS PRODUCTOS')
label.setObjectName('label_combo_product')
self.hbox.addWidget(label)
self.label_qty_min = QLabel('CANT. MIN.')
self.label_qty_min.setObjectName('label_qty_min')
self.hbox.addWidget(self.label_qty_min)
self.label_qty_min_req = QLabel("")
self.label_qty_min_req.setObjectName('label_qty_min_req')
self.hbox.addWidget(self.label_qty_min_req)
self.label_qty = QLabel('CANT.')
self.label_qty.setObjectName('label_qty')
self.hbox.addWidget(self.label_qty)
self.label_qty_add = QLabel("")
self.label_qty_add.setObjectName('label_qty_add')
self.hbox.addWidget(self.label_qty_add)
self.vbox = QVBoxLayout()
self.vbox.setObjectName('grid_buttons')
self.vbox.addWidget(qwidget)
super(DialogComboProduct, self).__init__(
parent, 'action', widgets=[self.vbox]
)
self.setWindowTitle('PRODUCTO EN COMBO')
self.setFixedSize(int(width * 0.7), int(height * 0.6))
def set_buttons(self, values):
self.values = values
self.set_products(values)
def set_products(self, values):
grid_buttons = GridButtons(
self.parent,
values,
4,
action=self.method_action,
style='standard_button'
)
if hasattr(self, 'scroll_area'):
_ = self.vbox.removeWidget(self.scroll_area)
self.scroll_area = QScrollArea()
self.scroll_area.setWidgetResizable(True)
self.scroll_area.setWidget(grid_buttons)
self.vbox.addWidget(self.scroll_area)
def close(self):
if self.validate_close_dialog():
self.label_qty_add.setText("")
self.label_qty_min_req.setText("")
super(QuickDialog, self).close()
def closeEvent(self, event):
if self.validate_close_dialog():
super(QuickDialog, self).closeEvent(event)
def dialog_rejected(self):
if self.validate_close_dialog():
super().dialog_rejected()
def dialog_accepted(self):
if self.validate_close_dialog():
super().dialog_accepted()
def validate_close_dialog(self):
qty_add = self.label_qty_add.text()
qty_req = self.label_qty_min_req.text()
if qty_req:
if not qty_add or int(qty_req) - int(qty_add) > 0:
dialog = self.parent.dialog('qty_combo_min_req', extra_message=f"cantidad minima {qty_req} has agregado {qty_add}")
dialog.exec()
return False
return True
class DialogSplitSale(QuickDialog):
def __init__(self, parent):
self._parent = parent
box = QVBoxLayout()
box.setObjectName('box_sale_split')
width, height = get_screen()
self.parent = parent
self.label = QLabel()
self.label_number = QLabel()
box.addWidget(self.label)
box.addWidget(self.label_number)
self.label.setAlignment(alignCenter)
self.label_number.setAlignment(alignCenter)
self.label.setWordWrap(True)
self.label_number.setWordWrap(True)
super(DialogSplitSale, self).__init__(parent, 'action', widgets=[box])
self.setWindowTitle('DIVIDIR CUENTA')
self.setFixedSize(int(width * 0.4), int(height * 0.3))
self.label.setObjectName('label_h2')
self.label_number.setObjectName('label_h1')
def ask(self):
msg = 'DESEA CREAR UN PEDIDO CON LOS PRODUCTOS SELECCIONADOS?'
self.label.setText(msg)
self.label_number.setText('')
return self.exec()
def info(self, number):
self.label.setText('PEDIDO CREADO EXITOSAMENTE!')
self.label_number.setText(number)
self.exec()
class Help(HelpDialog):
def __init__(self, parent):
super(Help, self).__init__(parent)
shortcuts = (
('PANEL DE CONTROL', 'F1'),
('BUSCAR PRODUCTO', 'F2'),
('MEDIO DE PAGO', 'F3'),
('BUSCAR CLIENTE', 'F4'),
('DESCUENTO GLOBAL', 'F5'),
('ENVIAR ORDEN', 'F6'),
('IMPRIMIR ORDEN/FACTURA', 'F7'),
('PLAZO DE PAGO', 'F8'),
('BUSCAR ORDEN', 'F9'),
('CONSULTAR PRECIO', 'F10'),
('NUEVA VENTA', 'F11'),
('DOMICILIARIO', 'F12'),
('POSICION', 'Insert'),
('FACTURAR', 'End'),
('COMENTARIO', 'COMILLAS DOBLE (")'),
('AGENTE', 'PUNTO Y COMA (;)'),
)
self.set_shortcuts(shortcuts)
class DialogListProduct(QuickDialog):
def __init__(self, parent):
self._parent = parent
grid = QGridLayout()
label_code = QLabel('CODIGO:')
label_code.setObjectName('label_info_product_code')
grid.addWidget(label_code, 1, 1)
self.input_code = QLineEdit()
self.input_code.setObjectName('input_info_product_code')
self.input_code.returnPressed.connect(lambda: self.search())
grid.addWidget(self.input_code, 1, 2)
class DialogTestPrinter(QuickDialog):
def __init__(self, parent):
self._parent = parent
width, height = get_screen()
grid = QGridLayout()
if parent.environment == 'restaurant':
_sizes = (100, 210, 210, 100)
fields = (
{'name': 'id', 'label': 'ID', 'type': 'integer', 'invisible': True},
{'name': 'name', 'label': 'NOMBRE', 'type': 'char', 'readonly': True},
{'name': 'interface', 'label': 'INTERFACE', 'type': 'char', 'readonly': True},
{'name': 'server', 'label': 'SERVIDOR', 'type': 'char', 'readonly': True},
{'name': 'row_characters', 'label': 'CARACTERES POR FILA', 'type': 'integer', 'readonly': True},
)
self.model = TableEdit(self, [], fields)
self.table = TableView('model_printers', self.model, _sizes, self.fill_fields)
self.table.hideColumn(0)
grid.addWidget(self.table, 0, 0, 2, 7)
label_interface = QLabel('INTERFACE:')
label_interface.setObjectName('label_interface')
grid.addWidget(label_interface, 3, 1)
self.combo_interface = ComboBox(parent, 'type_printer', {'values': TYPE_PRINTER})
grid.addWidget(self.combo_interface, 3, 2)
label_server = QLabel('SERVIDOR:')
label_server.setObjectName('label_server')
grid.addWidget(label_server, 3, 3)
self.input_server = QLineEdit()
self.input_server.setObjectName('input_server')
grid.addWidget(self.input_server, 3, 4)
label_row_characters = QLabel('CARACTERES POR FILA:')
label_row_characters.setObjectName('label_row_characters')
grid.addWidget(label_row_characters, 3, 5)
self.combo_row_characters = ComboBox(
parent, 'row_characters', {'values': ROW_CHARACTERS}
)
grid.addWidget(self.combo_row_characters, 3, 6)
super(DialogTestPrinter, self).__init__(
parent, 'action', widgets=[grid]
)
self.setWindowTitle('TEST IMPRESORA')
self.setFixedSize(int(width * 0.4), int(height * 0.3))
def load(self):
printers_shop = self.parent.printers_shop
if getattr(self, 'table', None) and printers_shop:
model_add = self.model.add_record
for k, v in printers_shop.items():
data = [
k,
v.get('name', ''),
v['interface'],
v['host'],
v['row_characters'],
]
model_add(data)
def exec_(self):
self.clear()
self.load()
super(DialogTestPrinter, self).exec_()
def clear(self):
self.model.clearData()
self.input_server.setText("")
self.combo_interface.set_from_id("")
self.combo_row_characters.set_from_id("")
def test_printer(self):
print('configure test')
server = self.input_server.text()
interface = self.combo_interface.get_id()
row_characters = self.combo_row_characters.get_id()
printer_test = {
'interface': interface,
'device': str(server),
'profile': 'TM-P80',
'row_characters': row_characters,
}
ctx_printing = {}
ctx_printing['company'] = 'OSCORP INC'
ctx_printing['sale_device'] = 'CAJA-10'
ctx_printing['shop'] = 'Shop Wall Boulevard'
ctx_printing['street'] = 'Cll 21 # 172-81. Central Park'
ctx_printing['user'] = 'Charles Chapplin'
ctx_printing['city'] = 'Dallas'
ctx_printing['zip'] = '0876'
ctx_printing['phone'] = '591 5513 455'
ctx_printing['id_number'] = '123456789-0'
ctx_printing['tax_regime'] = 'none'
receipt = Receipt(ctx_printing)
receipt.config_printer(printer_test)
return receipt.test_printer()
def dialog_accepted(self):
result = self.test_printer()
if result:
msg = 'Impresion Exitosa ✔'
else:
msg = '''\n\n Test de impresión ha fallado,
es posible que haya un problema con la conexión de energía, USB o red.
Para solucionar el problema, asegúrese de que la impresora esté conectada
correctamente a la fuente de alimentación y que el cable USB o Ethernet
esté conectado correctamente a la impresora y
al dispositivo desde el que está intentando imprimir.'''
self._parent.dialog('test_printer', extra_message=msg)
if result:
super(DialogTestPrinter, self).dialog_accepted()
def fill_fields(self, data):
self.input_server.setText(data[3])
self.combo_interface.set_from_id(data[2])
self.combo_row_characters.set_from_id(str(data[4]))
class DialogTestPrinter(QuickDialog):
def __init__(self, parent):
self._parent = parent
width, height = get_screen()
grid = QGridLayout()
if parent.environment == 'restaurant':
_sizes = (100, 210, 210, 100)
fields = (
{'name': 'id', 'label': 'ID', 'type': 'integer', 'invisible': True},
{'name': 'name', 'label': 'NOMBRE', 'type': 'char', 'readonly': True},
{'name': 'interface', 'label': 'INTERFACE', 'type': 'char', 'readonly': True},
{'name': 'server', 'label': 'SERVIDOR', 'type': 'char', 'readonly': True},
{'name': 'row_characters', 'label': 'CARACTERES POR FILA', 'type': 'integer', 'readonly': True},
)
self.model = TableEdit(self, [], fields)
self.table = TableView('model_printers', self.model, _sizes, self.fill_fields)
self.table.hideColumn(0)
grid.addWidget(self.table, 0, 0, 2, 7)
label_interface = QLabel('INTERFACE:')
label_interface.setObjectName('label_interface')
grid.addWidget(label_interface, 3, 1)
self.combo_interface = ComboBox(parent, 'type_printer', {'values': TYPE_PRINTER})
grid.addWidget(self.combo_interface, 3, 2)
label_server = QLabel('SERVIDOR:')
label_server.setObjectName('label_server')
grid.addWidget(label_server, 3, 3)
self.input_server = QLineEdit()
self.input_server.setObjectName('input_server')
grid.addWidget(self.input_server, 3, 4)
label_row_characters = QLabel('CARACTERES POR FILA:')
label_row_characters.setObjectName('label_row_characters')
grid.addWidget(label_row_characters, 3, 5)
self.combo_row_characters = ComboBox(
parent, 'row_characters', {'values': ROW_CHARACTERS}
)
grid.addWidget(self.combo_row_characters, 3, 6)
super(DialogTestPrinter, self).__init__(
parent, 'action', widgets=[grid]
)
self.setWindowTitle('TEST IMPRESORA')
self.setFixedSize(int(width * 0.4), int(height * 0.3))
def load(self):
printers_shop = self.parent.printers_shop
if getattr(self, 'table', None) and printers_shop:
model_add = self.model.add_record
for k, v in printers_shop.items():
data = [
k,
v.get('name', ''),
v['interface'],
v['host'],
v['row_characters'],
]
model_add(data)
def exec(self):
self.clear()
self.load()
super(DialogTestPrinter, self).exec()
def clear(self):
self.model.clearData()
self.input_server.setText("")
self.combo_interface.set_from_id("")
self.combo_row_characters.set_from_id("")
def test_printer(self):
print('configure test')
server = self.input_server.text()
interface = self.combo_interface.get_id()
row_characters = self.combo_row_characters.get_id()
printer_test = {
'interface': interface,
'device': str(server),
'profile': 'TM-P80',
'row_characters': row_characters,
}
ctx_printing = {}
ctx_printing['company'] = 'OSCORP INC'
ctx_printing['sale_device'] = 'CAJA-10'
ctx_printing['shop'] = 'Shop Wall Boulevard'
ctx_printing['street'] = 'Cll 21 # 172-81. Central Park'
ctx_printing['user'] = 'Charles Chapplin'
ctx_printing['city'] = 'Dallas'
ctx_printing['zip'] = '0876'
ctx_printing['phone'] = '591 5513 455'
ctx_printing['id_number'] = '123456789-0'
ctx_printing['tax_regime'] = 'none'
receipt = Receipt(ctx_printing)
receipt.config_printer(printer_test)
return receipt.test_printer()
def dialog_accepted(self):
result = self.test_printer()
if result:
msg = 'Impresion Exitosa ✔'
else:
msg = '''\n\n Test de impresión ha fallado,
es posible que haya un problema con la conexión de energía, USB o red.
Para solucionar el problema, asegúrese de que la impresora esté conectada
correctamente a la fuente de alimentación y que el cable USB o Ethernet
esté conectado correctamente a la impresora y
al dispositivo desde el que está intentando imprimir.'''
self._parent.dialog('test_printer', extra_message=msg)
if result:
super(DialogTestPrinter, self).dialog_accepted()
def fill_fields(self, data):
self.input_server.setText(data[3])
self.combo_interface.set_from_id(data[2])
self.combo_row_characters.set_from_id(str(data[4]))
class DialogInfoProduct(QuickDialog):
def __init__(self, parent):
self._parent = parent
self.products = []
vbox = QVBoxLayout()
grid = QGridLayout()
label_filter = QLabel('FILTRO:')
label_filter.setObjectName('label_info_product_filter')
grid.addWidget(label_filter, 1, 1)
self.input_filter = QLineEdit()
self.input_filter.setObjectName('input_info_product_filter')
self.input_filter.returnPressed.connect(lambda: self.search())
grid.addWidget(self.input_filter, 1, 2)
label_code = QLabel('CODIGO:')
label_code.setObjectName('label_info_product_code')
grid.addWidget(label_code, 2, 1)
self.input_code = QLineEdit()
self.input_code.setReadOnly(True)
self.input_code.setObjectName('input_info_product_code')
grid.addWidget(self.input_code, 2, 2)
label_name = QLabel('NOMBRE:')
label_name.setObjectName('label_info_product_name')
grid.addWidget(label_name, 3, 1)
self.input_name = QLineEdit()
self.input_name.setReadOnly(True)
self.input_name.setObjectName('input_info_product_name')
grid.addWidget(self.input_name, 3, 2)
label_price = QLabel('PRECIO:')
label_price.setObjectName('label_info_product_price')
grid.addWidget(label_price, 4, 1)
self.input_price = QLineEdit()
self.input_price.setReadOnly(True)
self.input_price.setObjectName('input_info_product_price')
grid.addWidget(self.input_price, 4, 2)
label_quantity = QLabel('CANTIDAD:')
label_quantity.setObjectName('label_info_product_quantity')
grid.addWidget(label_quantity, 5, 1)
self.input_quantity = QLineEdit()
self.input_quantity.setReadOnly(True)
self.input_quantity.setObjectName('input_info_product_quantity')
grid.addWidget(self.input_quantity, 5, 2)
vbox.addLayout(grid)
super(DialogInfoProduct, self).__init__(parent, 'help', widgets=[vbox])
self.setWindowTitle('INFO. PRODUCT')
self.ok_button.setDefault(False)
width, height = get_screen()
self.setGeometry(0, 0, int(width * 0.4), int(height * 0.7))
self.input_filter.setFocus()
def fill(self, values):
self.input_code.setText(values['code'])
self.input_name.setText(values['name'])
extra_tax = values['extra_tax'] if values.get('extra_tax') else 0
sale_price_w_tax = values['template.']['sale_price_w_tax']
sale_price = "{:,}".format(round(sale_price_w_tax + extra_tax, 0))
self.input_price.setText(sale_price)
self.input_quantity.setText(str(values['quantity']))
def search(self, values=None):
self.ok_button.setDefault(False)
filter = self.input_filter.text()
if not filter:
return
domain = [
('template.salable', '=', True),
('template.account_category', '!=', None),
]
domain.append([
'OR',
('code', 'ilike', '%' + filter + '%'),
('name', 'ilike', '%' + filter + '%')
])
if self.parent._onebarcode_activated:
domain.append(('barcode', 'ilike', '%' + filter + '%'))
products = self._parent.Product.find(domain, ctx=self._parent.stock_context,
fields=['name', 'code', 'description',
'id', 'list_price',
'quantity', 'rec_name', 'template',
'extra_tax', 'template.sale_price_w_tax',
'write_date'])
if not products:
self._parent.message_bar.set('product_not_found')
return False
elif len(products) > 1:
self.products = products
self.create_dialog_select_item(products)
else:
product = products[0]
if product:
self.fill(product)
def on_selected_product(self, row=None):
code = row[0]
for product in self.products:
if product['code'] == code:
self.fill(product)
self.dialog_select_item.hide()
break
def create_dialog_select_item(self, products):
parent = self._parent
width, height = get_screen()
grid = QGridLayout()
_sizes = (160, 320)
fields = (
{'label': 'CODIGO', 'type': 'char', '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))
grid.addWidget(self.table, 1, 0, 1, 2)
self.dialog_select_item = QuickDialog(parent, 'action', widgets=[grid], readonly=True, buttons=True)
self.dialog_select_item.setWindowTitle('PRODUCTOS')
self.load(products)
self.dialog_select_item.show()
def load(self, products):
if not products:
return
for rec in products:
data = [
rec['code'],
rec['name'],
]
self.model.add_record(data)
def show(self):
super(DialogInfoProduct, self).show()
self.input_filter.setFocus()
def clear(self):
self.input_filter.setText('')
self.input_code.setText('')
self.input_name.setText('')
self.input_price.setText('')
self.input_quantity.setText('')
def dialog_accepted(self):
self.clear()
super(DialogInfoProduct, self).dialog_accepted()
class DialogCollection(QuickDialog):
def __init__(self, parent):
self._parent = parent
self.parties = []
self.party_id = None
self.statements = {}
vbox = QVBoxLayout()
grid = QGridLayout()
label_filter = QLabel('FILTRO:')
label_filter.setObjectName('label_collection_filter')
grid.addWidget(label_filter, 1, 1)
self.input_filter = QLineEdit()
self.input_filter.setObjectName('input_collection_filter')
self.input_filter.editingFinished.connect(lambda: self.search())
self.input_filter.returnPressed.connect(lambda: self.search())
grid.addWidget(self.input_filter, 1, 2)
label_id_number = QLabel('DOCUMENTO:')
label_id_number.setObjectName('label_party_id_number')
grid.addWidget(label_id_number, 2, 1)
self.input_id_number = QLineEdit()
self.input_id_number.setReadOnly(True)
self.input_id_number.setObjectName('input_party_id_number')
grid.addWidget(self.input_id_number, 2, 2)
label_name = QLabel('NOMBRE:')
label_name.setObjectName('label_party_name')
grid.addWidget(label_name, 3, 1)
self.input_name = QLineEdit()
self.input_name.setReadOnly(True)
self.input_name.setObjectName('input_party_name')
grid.addWidget(self.input_name, 3, 2)
label_amount = QLabel('VALOR:')
label_amount.setObjectName('label_collection_amount')
grid.addWidget(label_amount, 4, 1)
self.input_amount = QLineEdit()
self.input_amount.setObjectName('input_collection_amount')
grid.addWidget(self.input_amount, 4, 2)
label_payment_method = QLabel('MODO DE PAGO:')
label_payment_method.setObjectName('label_collection_payment_method')
grid.addWidget(label_payment_method, 5, 1)
self.combobox_payment_method = ComboBox(
parent, 'payment_method_collection', {'values': self.get_payment_methods()}
)
grid.addWidget(self.combobox_payment_method, 5, 2)
label_voucher_number = QLabel('NUMERO COMPROBANTE:')
label_voucher_number.setObjectName('label_collection_voucher_number')
grid.addWidget(label_voucher_number, 6, 1)
self.input_voucher_number = QLineEdit()
self.input_voucher_number.setObjectName('input_collection_voucher_number')
grid.addWidget(self.input_voucher_number, 6, 2)
vbox.addLayout(grid)
super(DialogCollection, self).__init__(parent, 'help', widgets=[vbox])
self.setWindowTitle('RECAUDO')
self.ok_button.setDefault(False)
width, height = get_screen()
self.setGeometry(0, 0, int(width * 0.4), int(height * 0.5))
self.input_filter.setFocus()
def fill(self, values):
self.input_id_number.setText(values['id_number'])
self.input_name.setText(values['name'])
self.party_id = values['id']
def get_payment_methods(self):
domain = [
["sale_device", "=", self._parent.device['id']],
["state", "=", "draft"]
]
statements = self._parent.Statement.find(domain,
fields=['rec_name', 'journal.require_voucher'])
records = [('', '')]
statements_ = {}
for st in statements:
statements_[st['id']] = st
records.append((st['id'], st['rec_name']))
self.statements = statements_
return records
def search(self, values=None):
self.ok_button.setDefault(False)
filter = self.input_filter.text()
if not filter:
return
domain = ['OR',
('id_number', 'ilike', '%' + filter + '%'),
('name', 'ilike', '%' + filter + '%'),
]
parties = self._parent.Party.find(domain,
fields=['name', 'id_number'])
if not parties:
self.create_dialog_message('TERCERO NO ENCONTRADO..!', 'error')
return False
elif len(parties) > 1:
self.parties = parties
self.create_dialog_select_item(parties)
else:
party = parties[0]
if party:
self.fill(party)
def on_selected_party(self, row=None):
id_number = row[0]
for party in self.parties:
if party['id_number'] == id_number:
self.fill(party)
self.dialog_select_item.hide()
break
def create_dialog_select_item(self, parties):
parent = self._parent
width, height = get_screen()
grid = QGridLayout()
_sizes = (160, 320)
fields = (
{'label': 'DOCUMENTO', 'type': 'char', 'readonly': False},
{'label': 'NOMBRE', 'type': 'char', 'readonly': False},
)
self.model = TableEdit(self, [], fields)
self.table = TableView('model_party', self.model, _sizes, editable=False, method_selected_row=self.on_selected_party)
self.table.setFixedSize(int(width * 0.35), int(height * 0.4))
grid.addWidget(self.table, 1, 0, 1, 2)
self.dialog_select_item = QuickDialog(parent, 'action', widgets=[grid], readonly=True, buttons=True)
self.dialog_select_item.setWindowTitle('TERCEROS')
self.load(parties)
self.dialog_select_item.show()
def load(self, parties):
if not parties:
return
for rec in parties:
data = [
rec['id_number'],
rec['name'],
]
self.model.add_record(data)
def show(self):
super(DialogCollection, self).show()
self.input_filter.setFocus()
def clear(self):
self.input_filter.setText('')
self.input_id_number.setText('')
self.input_name.setText('')
self.input_amount.setText('')
self.combobox_payment_method.set_none()
self.input_voucher_number.setText('')
self.party_id = None
def dialog_accepted(self):
args = {
'party': self.party_id,
'amount': self.input_amount.text(),
'statement': self.combobox_payment_method.get_id(),
'voucher_number': self.input_voucher_number.text()
}
require_voucher = self.statements[int(args['statement'])]['journal.']['require_voucher']
if not args.get('voucher_number') and require_voucher:
self.create_dialog_message('REQUIERE COMPROBANTE', 'info')
return False
rec = self._parent.Statement.apply_payment_collection(args)
if rec.get('status') and rec.get('status') == 'ok':
self.create_dialog_message(rec['message'], 'info')
else:
self.create_dialog_message(rec['message'], 'error')
self.clear()
super(DialogCollection, self).dialog_accepted()
def create_dialog_message(self, message, kind):
parent = self._parent
width, height = get_screen()
self.dialog_message = QuickDialog(parent, kind, string=message, readonly=True, buttons=True)