presik_pos/app/mainwindow.py

2752 lines
98 KiB
Python

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import sys
import os
import logging
import base64
from decimal import Decimal
from datetime import datetime, timedelta, date
from collections import OrderedDict
from PyQt5.QtCore import Qt, QDate
from .tools import get_icon, to_float, to_numeric
from PyQt5.QtWidgets import (
QLabel, QHBoxLayout, QVBoxLayout, QWidget, QLineEdit, QGridLayout,
QSizePolicy, QFrame
)
from .frontwindow import FrontWindow
from app.commons.action import Action
from app.commons.forms import GridForm, ComboBox, FieldNumeric
from app.commons.messages import MessageBar
from app.commons.table import TableView
from app.commons.model import TableModel, TableModelEdit
from app.commons.menu_buttons import MenuDash
from .localdb import LocalDB
from .reporting import Receipt
from .buttonpad import ButtonsStacked, ButtonsFunction, StartButtons
from .states import STATES, RE_SIGN
from .commons.custom_button import CustomButton
from .threads import DoInvoice
from .store import StoreView
from .constants import (
PATH_PRINTERS, DELTA_LOCALE, STRETCH, alignRight, alignLeft, alignCenter,
alignHCenter, DIALOG_REPLY_NO, ZERO, RATE_CREDIT_LIMIT,
CONVERSION_DIGITS, MONEY, MINIMUM_DATE,
)
from .dialogs import DialogDeliveryParty
invoice_type = [('P', ('POS'))]
class MainWindow(FrontWindow):
def __init__(self, connection, params):
title = "PRESIK | SMART POS"
global CONNECTION
CONNECTION = connection
super(MainWindow, self).__init__(connection, params, title)
self.payment_ctx = {}
self.set_keys()
self.stock_context = None
self._sale = {}
self.ctx = self._context
self.ctx['params'] = params
response = self.load_modules()
if response is not True:
d = self.dialog(response)
d.exec_()
super(MainWindow, self).close()
return
self.setup_sale_line()
self.setup_delivery_party()
self.setup_sale_consumer()
self.setup_payment()
self.set_domains()
self.setup_money_count()
self.create_gui()
self.message_bar.load_stack(self.stack_msg)
self.journal = {}
if not hasattr(self, 'auto_print_commission'):
self.auto_print_commission = False
self.active_usb_printers = []
if os.name == 'posix' and os.path.exists(PATH_PRINTERS):
self.set_printers_usb(PATH_PRINTERS)
self.set_printing_context()
self.create_statusbar()
self.reader_thread = None
self._current_line_id = None
self._amount_text = ''
self._sign = None
self.create_dialogs()
if self.sale_automatic:
self.create_new_sale()
if not hasattr(self, 'active_weighing'):
self.active_weighing = False
elif self.active_weighing is True:
from .electronic_scale import ScaleReader
self.reader_thread = ScaleReader()
self.reader_thread.sigSetWeight.connect(self.set_weight_readed)
self.do_invoice = DoInvoice(self, self._context)
self.do_invoice.sigDoInvoice.connect(self.__do_invoice_thread)
self.set_state('disabled')
sale_fields = [
'number', 'party', 'sale_date', 'comment', 'position',
'description', 'invoice_number', 'tip_amount', 'delivery_amount',
'salesman', 'state', 'kind', 'channel', 'reference',
'invoice_type', 'consumer', 'delivery_party', 'table_assigned'
]
self.store = StoreView(self, sale_fields)
if self.cache_local:
self.set_cache_company()
self.set_cache_products()
for j in self._journals:
if j['id'] == self.default_journal['id']:
self.default_journal = j
def set_domains(self):
self.domain_search_product = [
('code', '!=', None),
('active', '=', True),
('template.salable', '=', True),
('template.account_category', '!=', None),
]
if self.shop['product_categories']:
self.domain_search_product.append(
('account_category', 'in', self.shop['product_categories'])
)
def set_cache_company(self):
self.local_db = LocalDB()
self.local_db.create_table_config()
self._local_config = self.local_db.get_config()
if not self._local_config:
company_id = self.device['shop']['company']['id']
self._local_config = self.local_db.set_config([company_id])
def set_cache_products(self):
self.local_db.create_table_product()
local_products = self.local_db.get_local_products()
config = self.local_db.get_config()
_sync_date = config[1]
products = self.Product.sync_get_products({
'write_date': _sync_date,
'shop_id': self.ctx['shop']
})
self.local_db.update_products(products, local_products)
now = datetime.now()
self.local_db.set_config_sync(str(now))
def set_printers_usb(self, PATH_PRINTERS):
for usb_dev in os.listdir(PATH_PRINTERS):
if 'lp' not in usb_dev:
continue
path_device = os.path.join(PATH_PRINTERS, usb_dev)
self.active_usb_printers.append(['usb', path_device])
def get_current_sale(self):
if hasattr(self, '_sale') and self._sale['id']:
sales = self.Sale.find([
('id', '=', self._sale['id'])
])
if not sales:
return
return sales[0]
def check_empty_sale(self):
sale = self.get_current_sale()
if sale and self.model_sale_lines.rowCount() == 0 \
and sale['state'] == 'draft' and not sale['number']:
self.delete_current_sale()
def delete_current_sale(self):
if self._sale['id']:
args = {'id': self._sale['id']}
self.Sale.cancel_sale(args)
def set_printing_context(self):
# Printing invoice context
if self.printer_sale_name:
if ">" in self.printer_sale_name:
self.printer_sale_name = str(str("\\") + self.printer_sale_name.replace('>', str('\\')))
ctx_printing = self.Sale.get_printing_context({
'device_id': self.device['id'],
'user': self.user,
})
ctx_printing['row_characters'] = self.row_characters
ctx_printing['delta_locale'] = DELTA_LOCALE
locale_logo = ''
if self.logo:
locale_logo = os.path.join(os.path.abspath(
os.path.dirname(__file__)), 'logo.png')
f = open(locale_logo, "wb")
f.write(base64.decodestring(self.logo.encode()))
f.close()
self.receipt_sale = Receipt(ctx_printing, logo=locale_logo)
# Printing order context
if self.print_order:
self.receipt_order = Receipt(ctx_printing)
self.set_default_printer()
def set_default_printer(self, printer=None):
if self.active_usb_printers:
self.printer_sale_name = self.active_usb_printers[0]
if not printer and self.printer_sale_name:
printer = {
'interface': self.printer_sale_name[0],
'device': self.printer_sale_name[1],
'profile': self.profile_printer,
}
if printer:
self.receipt_sale.set_printer(printer)
def button_new_sale_pressed(self):
self.create_new_sale()
def button_send_to_pay_pressed(self):
# Return sale to draft state
if not self._check_quantity():
return
args = {'sale_id': self._sale['id']}
self.Sale.to_quote(args)
if self.model_sale_lines.rowCount() > 0:
if self.check_salesman():
# self.state_disabled()
pass
try:
self.Sale.generate_shipment({
'sale_id': self._sale['id'],
})
self.dialog('order_dispatched')
except:
self.dialog('error_order_dispatched')
def button_to_draft_pressed(self):
# Return sale to draft state
if hasattr(self, '_sale'):
self.Sale.to_draft(self._sale['id'])
# self.state_disabled()
def create_gui(self):
panels = QHBoxLayout()
panels.setSpacing(0)
panels.setContentsMargins(0, 0, 0, 0)
panel_left = QWidget()
panel_left.setObjectName('panel_left')
vbox_left = QVBoxLayout()
vbox_left.setSpacing(0)
vbox_left.setContentsMargins(0, 0, 0, 0)
if self.screen_size == 'small':
max_size = 620
else:
max_size = 1300
panel_left.setMaximumWidth(max_size)
panel_left.setLayout(vbox_left)
panel_left.setContentsMargins(0, 0, 0, 0)
self.panel_right = QVBoxLayout()
self.panel_right.setSpacing(4)
self.panel_right.setObjectName('panel_right')
self.panel_right.setContentsMargins(3, 3, 3, 3)
left_head = QHBoxLayout()
left_head.setSpacing(4)
left_invoice = QHBoxLayout()
left_invoice.setSpacing(4)
board = QVBoxLayout()
board.setSpacing(0)
# CREATE START FRONT
self.start_front = QWidget()
self.start_front.setObjectName('start_front')
start_front = StartButtons(self)
self.start_front.setLayout(start_front)
# CREATE ORDER FRONT
self.order_front = QWidget()
self.order_front.setObjectName('order_front')
vbox_order_front = QVBoxLayout()
vbox_order_front.setSpacing(4)
vbox_order_front.addLayout(left_head)
vbox_order_front.addLayout(left_invoice)
self.order_front.setLayout(vbox_order_front)
# CONFIGURE BOARD
board.addWidget(self.start_front, 0)
board.addWidget(self.order_front, 0)
# LEFT HEAD COMPONENTS
start_front = CustomButton(
self,
id='button_start',
size=self.screen_size,
icon=get_icon('start_front'),
title=self.tr('START'),
method='see_start_front',
name_style='mini_button',
)
self.message_bar = MessageBar()
self.field_amount = FieldNumeric(self, 'amount', {})
self.field_amount.setObjectName('field_amount')
self.field_sign = QLabel(' ')
self.field_sign.setObjectName('field_sign')
left_head.addWidget(start_front, 0)
left_head.addLayout(self.message_bar, 1)
left_head.addWidget(self.field_sign, 0)
left_head.addWidget(self.field_amount, 1)
# LEFT INVOICE COMPONENTS
self.label_input = QLabel()
# self.label_input.setFocus()
self.label_input.setObjectName('label_input')
size_input = 100
if self.screen_size == 'large':
size_input = 300
self.label_input.setMaximumWidth(size_input)
if self.shop.get('manual_authorization'):
invoice_type.append(('M', 'MANUAL'))
if self.shop.get('electronic_authorization'):
invoice_type.append(('1', ('VENTA ELECTRONICA')))
self.field_invoice_type = ComboBox(self, 'invoice_type', {
'values': invoice_type,
'on_change': 'action_invoice_type_selection_changed'
})
left_invoice.addWidget(self.label_input, 1)
left_invoice.addWidget(self.field_invoice_type, 0)
self.field_invoice = QLineEdit('')
self.field_invoice.setReadOnly(True)
self.field_invoice.setObjectName('field_invoice')
self.field_invoice.setPlaceholderText(self.tr('No Invoice'))
left_invoice.addWidget(self.field_invoice, 1)
self.field_state = QLineEdit('STATE')
self.field_state.setReadOnly(True)
self.field_state.setObjectName('field_state')
left_invoice.addWidget(self.field_state)
# LEFT TABLE COMPONENTS
values = self.get_menu_control_panel()
self.menu_control_panel = ButtonsFunction(self, values=values)
button_functions = ButtonsFunction(self)
info_fields = [
('party', {
'name': self.tr('CUSTOMER'),
'readonly': True,
'placeholder': False,
'size': self.screen_size,
'color': self.label_color
}),
('sale_date', {
'name': self.tr('DATE'),
'readonly': True,
'placeholder': False,
'size': self.screen_size,
'color': self.label_color
}),
('salesman', {
'name': self.tr('SALESMAN'),
'readonly': True,
'placeholder': False,
'size': self.screen_size,
'color': self.label_color
}),
('number', {
'name': self.tr('No ORDER'),
'placeholder': False,
'readonly': True,
'size': self.screen_size,
'color': self.label_color
}),
('payment_term', {
'name': self.tr('PAYMENT TERM'),
'readonly': True,
'invisible': False,
'placeholder': False,
'size': self.screen_size,
'color': self.label_color
}),
('delivery_party', {
'name': self.tr('DELIVERY MEN'),
'placeholder': False,
'size': self.screen_size,
'color': self.label_color
})
]
if self._web_channel:
self.channels = self.Channel.find([])
info_fields.append(
('channel', {
'name': self.tr('CHANNEL'),
'readonly': True,
'placeholder': False,
'size': self.screen_size,
'color': self.label_color
}))
if self._config['show_position_pos']:
info_fields.append(('position', {
'name': self.tr('POSITION'),
'readonly': True,
'placeholder': False,
'size': self.screen_size,
'color': self.label_color
}))
if self._commission_activated and self._config['show_agent_pos']:
info_fields.append(('agent', {
'name': self.tr('AGENT'),
'placeholder': False,
'readonly': True,
'size': self.screen_size,
'color': self.label_color
}))
_cols = 2
self.field_delivery_charge = None
if self._config['show_delivery_charge']:
info_fields.append(
('delivery_charge', {
'name': self.tr('DELIVERY CHARGE'),
'placeholder': False,
'type': 'selection',
'on_change': 'action_delivery_charge_selection_changed',
'values': [
('', ''),
('customer', self.tr('CUSTOMER')),
('company', self.tr('COMPANY')),
],
'size': self.screen_size,
'color': self.label_color
}))
self.field_table_assigned = None
if self._sale_pos_restaurant:
info_fields.append(
('consumer', {
'name': self.tr('CONSUMER'),
'placeholder': False,
'size': self.screen_size,
'color': self.label_color
}))
KIND = [
('', ''),
('take_away', self.tr('TAKE AWAY')),
('delivery', self.tr('DELIVERY')),
('to_table', self.tr('TO TABLE'))
]
info_fields.append(
('kind', {
'name': self.tr('KIND'),
'placeholder': False,
'type': 'selection',
'on_change': 'action_kind_selection_changed',
'values': KIND,
'size': self.screen_size,
'color': self.label_color
}))
PAYMENT_METHODS = [
('', ''),
('cash', self.tr('CASH')),
('terminal', self.tr('TERMINAL')),
]
info_fields.append(
('payment_method', {
'name': self.tr('PAYMENT METHOD'),
'placeholder': False,
'type': 'selection',
'on_change': 'action_payment_method_selection_changed',
'values': PAYMENT_METHODS,
'size': self.screen_size,
'color': self.label_color
}))
info_fields.append(
('table_assigned', {
'name': self.tr('ASSIGNED TABLE'),
'placeholder': False,
'size': self.screen_size,
'color': self.label_color
}))
col_sizes_tlines = [field['width'] for field in self.fields_sale_line]
self.table_sale_lines = TableView('model_sale_lines',
self.model_sale_lines, col_sizes_tlines,
method_selected_row=self.sale_line_selected
)
for i, f in enumerate(self.model_sale_lines._fields, 0):
if f.get('invisible'):
self.table_sale_lines.hideColumn(i)
invisible = False
if self.enviroment == 'restaurant':
invisible = True
_fields_amounts = [
('untaxed_amount', {
'name': self.tr('SUBTOTAL'),
'readonly': True,
'type': 'money',
'size': self.screen_size,
'color': self.label_color,
'invisible': invisible,
}),
('taxes_amount', {
'name': self.tr('TAXES'),
'readonly': True,
'type': 'money',
'size': self.screen_size,
'color': self.label_color,
'invisible': invisible,
}),
('discount', {
'name': self.tr('DISCOUNT'),
'readonly': True,
'type': 'money',
'size': self.screen_size,
'color': self.label_color,
'invisible': invisible,
}),
('tip_amount', {
'name': self.tr('VR. PROPINA'),
'type': 'money',
'size': self.screen_size,
'color': self.label_color,
}),
('delivery_amount', {
'name': self.tr('VR. DOMIC'),
'type': 'money',
'size': self.screen_size,
'color': self.label_color,
}),
('total_amount', {
'name': self.tr('TOTAL'),
'readonly': True,
'type': 'money',
'size': self.screen_size,
'color': 'black',
'font_size': 'big',
}),
('net_amount', {
'name': self.tr('NETO TOTAL'),
'readonly': True,
'type': 'money',
'size': self.screen_size,
'color': 'black',
'font_size': 'big',
}),
('paid_amount', {
'name': self.tr('PAID'),
'readonly': True,
'type': 'money',
'size': self.screen_size,
'color': self.label_color,
}),
('residual_amount', {
'name': self.tr('PENDING'),
'readonly': True,
'type': 'money',
'size': self.screen_size,
'color': self.label_color_2 or 'blue'
}),
('change', {
'name': self.tr('CHANGE'),
'readonly': True,
'type': 'money',
'size': self.screen_size,
'color': self.label_color_2 or 'orange'
})
]
fields_amounts = OrderedDict(_fields_amounts)
self.grid_amounts = GridForm(self, fields_amounts, col=1)
self.buttons_stacked = ButtonsStacked(self)
self.table_payment = TableView('table_payment',
self.table_payment_lines, [250, STRETCH])
self.grid_info = GridForm(self, OrderedDict(info_fields), col=_cols)
vbox_order_front.addWidget(self.table_sale_lines, 1)
vbox_left.addLayout(board, 0)
if self.enviroment == 'restaurant':
self.panel_right_box = QWidget()
values = self.get_product_by_categories()
self.menu_dash = MenuDash(self, values, 'on_selected_item')
self.order_front.hide()
vbox_order_front.addLayout(button_functions, 0)
vbox_order_front.addLayout(self.grid_info, 0)
self.panel_right.addWidget(self.menu_dash, 1)
_panel_right_box = QVBoxLayout()
_panel_right_box.addLayout(self.grid_amounts, 0)
_panel_right_box.addLayout(self.buttons_stacked, 0)
self.panel_right_box.setLayout(_panel_right_box)
self.panel_right.addWidget(self.panel_right_box)
else:
vbox_left.addLayout(self.grid_info, 1)
self.panel_right.addLayout(self.grid_amounts, 1)
self.panel_right.addLayout(button_functions, 1)
self.panel_right.addLayout(self.buttons_stacked, 0)
self.panel_right.addWidget(self.table_payment)
panels.addWidget(panel_left, 1)
panels.addLayout(self.panel_right, 0)
widget = QWidget()
widget.setLayout(panels)
self.setCentralWidget(widget)
def show_right_panel(self, bool):
if bool:
self.panel_right_box.show()
else:
self.panel_right_box.hide()
def button_plus_pressed(self):
error = False
if self._input_text == '' and self._amount_text == '0':
return
if self._state in ('paid', 'disabled'):
return
if self._sign in ('*', '-', '/'):
if hasattr(self, '_sale_line') and self._sale_line \
and self._sale_line.get('type') and self._state == 'add' \
and self.model_sale_lines.rowCount() > 0:
if self._sign == '*':
self._process_quantity(self._amount_text)
else:
error = not(self._process_price(self._amount_text))
elif self._state in ['add', 'cancel', 'accept']:
self.clear_right_panel()
self.add_product(code=self._input_text)
elif self._state == 'payment':
is_paid = self._process_pay(self.field_amount.text())
if not is_paid:
self.set_state('payment')
self.clear_input_text()
self.clear_amount_text()
return
self.set_state('finished')
else:
logging.warning('Unknown command/text')
self._clear_context(error)
def see_start_front(self):
self.change_view_to('start_front')
def change_view_to(self, to_view):
if to_view == 'start_front':
self.order_front.hide()
self.start_front.show()
else:
self.start_front.hide()
self.order_front.show()
def action_read_weight(self):
self.reader_thread.start()
def set_weight_readed(self):
if not self.reader_thread or not self.reader_thread.best_weight:
return
if self.reader_thread.best_weight:
self.amount_text_changed(self.reader_thread.best_weight)
self._process_quantity(self._amount_text)
self._clear_context(False)
self.reader_thread.fZERO()
def _clear_context(self, error=False):
self.clear_input_text()
self.clear_amount_text()
self.clear_sign()
if self.state == 'disabled':
self.message_bar.set('not_sale')
elif self._state not in ('warning', 'cash', 'payment') and not error:
self.message_bar.set('system_ready')
else:
self.set_state('add')
def _process_quantity(self, text):
eval_value = text.replace(',', '.')
rec = {}
try:
quantity = Decimal(eval_value)
product_id = self.product_id
if product_id and self.stock_context:
_product, = self.Product.find([
('id', '=', product_id)],
ctx=self.stock_context
)
if _product and 'quantity' in _product:
if not self._check_stock_quantity(_product, quantity):
return False
if self._current_line_id:
self._sale_line['quantity'] = float(quantity)
args = {
'id': self._sale_line['id'],
'quantity': quantity,
}
rec = self.SaleLine.faster_set_quantity(args)
except:
return self.message_bar.set('quantity_not_valid')
self.message_bar.set('system_ready')
self.model_sale_lines.update_record(rec)
self.set_amounts()
def _process_price(self, text):
discount_valid = True
eval_value = text.replace(',', '')
value = float(eval_value)
if self._sign == '-':
if self.discount_method == 'percentage' and value > 90:
discount_valid = False
else:
discount_valid = self.set_discount(eval_value)
elif self._sign == '/':
if value <= 0:
return
sale_line, = self.SaleLine.find([
('id', '=', self._current_line_id)
])
price_w_tax = sale_line['product']['sale_price_w_tax']
if price_w_tax <= Decimal(value):
# Change unit price
discount_valid = self.set_unit_price(value)
self.set_discount(0)
else:
eval_value = (1 - (value / price_w_tax)) * 100
if self.discount_method == 'fixed':
eval_value = price_w_tax - value
discount_valid = self.set_discount(eval_value)
if not discount_valid:
self.message_bar.set('discount_not_valid')
return False
self.message_bar.set('system_ready')
self.set_amounts()
return True
def _process_pay(self, text):
if not self.validate_done_sale():
return
val = Decimal(text.replace(',', ''))
# FIXME
# if self._commission_activated:
# if self._journals[self.field_journal_id]['kind'] == 'payment':
# agent_id = None
# if self.field_agent_id:
# agent_id = self.field_agent_id
# else:
# agent_id = self.field_agent_ask.get_id()
#
# if not agent_id:
# self.message_bar.set('missing_agent')
# return False
cash_received = Decimal(val)
self.set_amounts()
# residual_amount = self._sale['residual_amount']
residual_amount = self.store.get('residual_amount')
if residual_amount <= 0:
# The sale is paid
self._done_sale()
return True
change = float(cash_received) - residual_amount
if residual_amount >= cash_received:
amount_to_add = cash_received
else:
amount_to_add = residual_amount
all_money = float(cash_received) + self.store.get('paid_amount')
res = self.add_payment(amount_to_add, all_money, change)
if res.get('msg') == 'statement_closed':
self.dialog('statement_closed')
return False
if change < ZERO:
residual_amount = abs(change)
else:
residual_amount = ZERO
self.store.set({'residual_amount': residual_amount})
self.set_amount_received(all_money)
if residual_amount <= 0:
self._done_sale()
return True
for j in self._journals:
if j['id'] == self.default_journal['id']:
self.journal = j
if res['msg'] == 'missing_money':
self.message_bar.set('enter_payment', self.default_journal['name'])
return False
if change < ZERO:
self.message_bar.set('enter_payment', self.default_journal['name'])
residual_amount = res['residual_amount']
self.store.set({
'residual_amount': residual_amount,
'change': change,
})
if residual_amount <= 0:
self._done_sale()
return True
def validate_done_sale(self):
if self.model_sale_lines.rowCount() == 0:
self.dialog('sale_without_products')
self.set_state('add')
self.message_bar.set('system_ready')
return
return True
def _get_total_amount(self):
return self.model_sale_lines.get_sum('amount_w_tax')
def set_discount_amount(self):
res = 0
if self.store.sale_id:
res = self.Sale.get_discount_total({
'sale_id': self.store.sale_id
})
self.store.set({'discount': res})
def amount_text_changed(self, text=None):
if text:
self._amount_text += text
self.field_amount.setText(self._amount_text)
def input_text_changed(self, text=None):
if text:
self._input_text += text
elif text == '':
self._input_text = ''
self.label_input.setText(self._input_text)
def __do_invoice_thread(self):
try:
res = self.Sale.faster_post_invoice({
'sale_id': self.sale_to_post_id
})
except:
self.dialog('invoice_done_failed')
return
if not res['result']:
self.dialog('send_electronic_failed')
return
if self.store.get('is_credit'):
return
self.Sale.reconcile_invoice({'sale_id': self.sale_to_post_id})
def _done_sale(self, is_credit=False):
self.store.set({'is_credit': is_credit})
# We need create this temp variable called sale_to_post_id for this
# thread, because self.store.sale_id is deleted inmediately,
# so post invoice and reconcile it will fail if reference to sale_id
# is missing or None
self.sale_to_post_id = self.store.sale_id
table_assigned = self.store.get('table_assigned')
if table_assigned:
self.RestTables.write(
[table_assigned['id']], {
'state': 'available',
'sale': None,
}
)
self.do_invoice.start()
try:
if self.print_receipt == 'automatic':
_copies = self.device['shop']['invoice_copies']
if not is_credit:
self.print_invoice(copies=_copies, open_box=True)
if self.print_order and self.print_auto_order:
self.action_print_order()
except:
logging.error(sys.exc_info()[0])
# if not is_credit and self._commission_activated:
# agent_id = self.field_agent_ask.get_id()
# if self.auto_print_commission and agent_id:
# self.print_equivalent_invoice(self._sale['id'])
self.change_view_to('start_front')
if self.sale_automatic and self.type_pos_user not in ('cashier', 'order'):
self.create_new_sale()
# self.state_disabled()
self.message_bar.set('system_ready')
return True
def print_invoice(self, sale_id=None, type_doc='invoice', open_box=False, copies=1):
if not sale_id:
sale_id = self.store.sale_id
args = {
'sale_id': sale_id,
'type_doc': type_doc,
}
data = self.Sale.get_data(args)
for i in range(copies):
self.receipt_sale.print_sale(data, type_doc, open_box)
def button_duplicate_sale(self):
if self.sale_customer_selected:
res = self.Sale.duplicate_sale({
'sale_id': self.sale_customer_selected,
})
self.load_sale(res['sale_id'])
self.dialog_search_consumer.close()
self.dialog_table_sale_consumer.close()
self.dialog_sale_consumer_selected.close()
def button_create_delivery_party(self):
self.clear_delivery_party()
self.dialog_delivery_party_selected.show()
def button_sale_consumer_history(self):
if self._consumer:
delta = str(datetime.now() - timedelta(180))
dom = [
('create_date', '>=', delta),
('state', 'in', ['processing', 'done']),
('consumer', '=', self._consumer['id']),
]
self.model_sale_consumer.reset()
sales = self.Sale.find(dom, limit=10)
for record in sales:
self.model_sale_consumer.add_record(record)
self.dialog_table_sale_consumer.exec_()
def button_accept_pressed(self):
if not self._check_quantity() or not self._sale.get('id'):
return
if not self._sale['id'] or not self.model_sale_lines.rowCount() > 0:
return
self.set_state('accept')
def button_cash_pressed(self):
if not self.check_salesman():
return
if not self.validate_payment_term():
return
sale_id = self._sale['id']
res, msg = self.Sale.faster_process({'sale_id': sale_id})
if msg:
self.message_bar.set(msg)
return
self.set_amounts(res)
self._sale['number'] = res['number']
self.field_number.setText(self._sale['number'])
self.field_invoice.setText(res['invoice_number'])
self.field_amount.setText('')
if self.type_pos_user == 'salesman':
self.print_invoice(sale_id)
res = self._print_order(sale_id, 'delivery')
if self.sale_automatic:
self.create_new_sale()
return
if self.type_pos_user != 'cashier':
self.field_invoice_type.set_enabled(False)
self.message_bar.set('enter_payment', self.default_journal['name'])
self.set_state('payment')
self.label_input.setFocus()
self.table_sale_lines.setDisabled(True)
if self.enviroment == 'restaurant':
self.menu_dash.setDisabled(True)
def action_reservations(self):
logging.info('Buscando reservas.....')
def action_tables(self):
self.manage_tables.open_tables()
self.dialog_manage_tables.exec_()
def action_tip(self):
if self._state in ['finished']:
return
value = self.field_tip_amount_ask.text()
if not value and self._config['tip_rate']:
total_amount = int(self._get_total_amount())
value = int((self._config['tip_rate'] / 100) * total_amount)
self.field_tip_amount_ask.setText(str(value))
else:
self.dialog_tip_amount.exec_()
value = self.field_tip_amount_ask.text()
value = int(value)
res = self.store.update({'tip_amount': value})
self.set_amounts(res)
def action_delivery(self):
if self._state in ['finished']:
return
self.dialog_delivery_amount.exec_()
value = self.field_delivery_amount_ask.text()
value = int(value)
res = self.store.update({'delivery_amount': value})
self.set_amounts(res)
def action_salesman(self):
if self._state in ['cash']:
return
self.dialog_salesman.exec_()
def action_delivery_party(self):
self.dialog_delivery_party.exec_()
def action_delivery_party_panel(self):
self.dialog_control_panel.close()
self.dialog_table_delivery_party.exec_()
def action_control_panel(self):
self.dialog_control_panel.exec_()
def clear_money_count_table(self):
new_data = [[d[0], 0, 0] for d in self.model_money_count._data]
self.model_money_count._data = new_data
def dialog_money_count_accepted(self):
return True
def action_open_statement(self):
if not self.dialog_money_count.exec_():
return
res = self.Sale.faster_open_statement({
'device': self.device['id'],
'total_money': Decimal(
self.row_field_total_money.text().replace(',', '')
),
})
if res['result']:
self.dialog('statement_created')
self.row_field_total_money.setText('0')
self.clear_money_count_table()
def action_closed_statement(self):
if not self.dialog_money_count.exec_():
return
res = self.Sale.faster_close_statement({
'device': self.device['id'],
'data': self.model_money_count._data,
})
if res['result']:
self.dialog('statement_finish')
self.row_field_total_money.setText('0')
self.clear_money_count_table()
def action_table_discount(self):
self.dialog_global_discount_table.exec_()
def action_tax(self):
self.dialog_tax.exec_()
def button_payment_pressed(self):
if self._state not in ('cash', 'payment'):
self.dialog('add_payment_sale_draft')
return
self.dialog_payment.exec_()
def _check_credit_capacity(self, party):
if party['credit_limit_amount']:
if (party['credit_limit_amount'] * Decimal(RATE_CREDIT_LIMIT)) < (
party['credit_amount'] + self._get_total_amount()):
self.dialog('credit_limit_capacity')
return True
def validate_payment_term(self):
payment_term = self.store.get('payment_term')
is_credit = payment_term.get('is_credit', None)
if not is_credit:
return True
party, = self.Party.find([('id', '=', self.party_id)])
if self._credit_limit_activated:
if self.party_id == self.default_party['id']:
self.dialog('customer_not_credit')
return False
elif not party['credit_limit_amount']:
self.dialog('customer_not_credit')
return False
self._credit_amount = self.Sale.get_credit_amount_party({'party_id': self.party_id})
self._credit_limit_amount = party['credit_limit_amount']
if is_credit and self._credit_limit_amount and \
self._credit_limit_amount < (self._credit_amount + self._get_total_amount()):
self.dialog('credit_limit_exceed')
return False
return True
def action_payment_term_selection_changed(self):
is_credit = self._payment_terms[str(self.field_payment_term_id)]['is_credit']
self.Sale.write([self._sale['id']], {'payment_term': self.field_payment_term_id})
self.field_payment_term.setText(self._payment_terms[str(self.field_payment_term_id)]['name'])
if is_credit and self.type_pos_user != 'salesman':
if self.validate_credit_limit():
self._done_sale(is_credit=True)
def validate_credit_limit(self):
if self._credit_limit_amount and self._credit_limit_amount < (self._credit_amount + self._get_total_amount()):
self.dialog('credit_limit_exceed')
return False
else:
return True
def action_delivery_charge_selection_changed(self, index):
val = self.field_delivery_charge.get_id()
if val:
self.Sale.write([self._sale['id']], {'delivery_charge': val})
def action_kind_selection_changed(self, index):
val = self.field_kind.get_id()
self.store.update({'kind': val})
def action_payment_method_selection_changed(self, index):
val = self.field_payment_method.get_id()
self.store.update({'payment_method': val})
def action_invoice_type_selection_changed(self, index):
val = self.field_invoice_type.get_id()
if val and self._sale and self._sale.get('id'):
self.Sale.write([self._sale['id']], {'invoice_type': val})
def action_tax_selection_changed(self):
res = self.Sale.add_tax(self._sale['id'], self.field_tax_id,
self._context)
self.set_amounts(res)
def action_consumer(self):
if not self._consumer.get('id'):
self.clear_dialog_consumer()
else:
self.set_consumer()
self.dialog_search_consumer.show()
self.row_field_phone.setFocus()
def action_print_sale(self):
number = self.field_invoice.text()
if not number:
number = self.field_number.text()
if number:
self.field_invoice_number_ask.setText(number)
res = self.dialog_print_invoice.exec_()
if res == DIALOG_REPLY_NO:
return
number = self.field_invoice_number_ask.text()
printer_id = self.field_printer_ask.get_id()
type_doc = self.field_type_ask.get_id()
sale_id = None
if number:
if type_doc in ['order', 'delivery']:
if number == self._sale.get('number'):
sale_id = self._sale['id']
else:
sales = self.Sale.find([('number', '=', number)])
if sales:
sale_id = sales[0]['id']
else:
args = {'number': number}
sale = self.Sale.get_sale_from_invoice(args)
if sale:
sale_id = sale['id']
else:
sale_id = self._sale['id']
if not sale_id:
return self.message_bar.set('sale_number_not_found')
if printer_id == '1':
self.print_invoice(sale_id, type_doc=type_doc)
else:
self.print_odt_invoice(sale)
def print_odt_invoice(self, sale):
if not sale.get('invoices'):
return
invoice_id = sale['invoices'][0]
model = u'account.invoice'
data = {
'model': model,
'action_id': self._action_report['id'],
'id': invoice_id,
'ids': [invoice_id],
}
ctx = {'date_format': u'%d/%m/%Y'}
ctx.update(self._context)
Action.exec_report(self.conn, u'account.invoice', data, direct_print=True, context=ctx)
def action_comment(self):
self.dialog_comment.exec_()
comment = self.field_comment.toPlainText()
if comment:
self.Sale.write([self._sale['id']], {'comment': comment})
def action_position(self):
self.dialog_position.exec_()
position = self.field_position.text()
self.store.update({'position': position})
def action_agent(self):
self.dialog_agent.exec_()
res = self.field_commission_ask.text()
if not res:
return
commission = float(res)
sale, = self.Sale.find([
('id', '=', self._sale['id']),
])
self.field_agent_id = self.field_agent_ask.get_id()
if self.field_agent_id and commission:
agent, = self.Agent.find([
('id', '=', self.field_agent_id),
])
if commission <= agent['plan']['percentage']:
self.Sale.write([self._sale['id']], {
'agent': self.field_agent_id,
'commission': int(commission),
})
else:
self.message_bar.set('invalid_commission')
return
self.message_bar.set('system_ready')
comm_string = str('[' + str(commission) + ']' + ' ') + (str(self.field_agent_ask.text()))
self.field_agent.setText(comm_string)
self._set_commission_amount(sale['untaxed_amount'], commission)
def _set_commission_amount(self, untaxed_amount, commission):
untaxed_amount = int(untaxed_amount)
commission = int(commission)
total = ((untaxed_amount * commission) / 100)
self.field_commission_amount.setText(str(total))
def action_party(self):
if self._state in ['cash']:
return
self.dialog_search_parties.clear_rows()
self.dialog_search_parties.execute()
def action_global_discount(self, sale_id=None):
if self._state in ['accept', 'cash']:
return
self.dialog_global_discount.exec_()
discount = self.field_global_discount_ask.text()
if discount and discount.isdigit():
self.validate_discount(discount)
def validate_discount(self, record):
if self.model_sale_lines.rowCount() > 0:
lines = [line['id'] for line in self.model_sale_lines._data]
res = self.set_discount(int(record['discount']), lines)
if not res:
self.message_bar.set('discount_not_valid')
return False
def _print_order(self, sale_id, kind, reversion=False):
result = False
try:
args = {
'sale_id': sale_id,
'reversion': reversion,
'repeat': False,
}
orders, sale_number = self.Sale.get_order2print(args)
self._sale['number'] = sale_number
self.field_number.setText(self._sale['number'])
result = self.receipt_order.print_orders(orders, reversion, kind)
except:
logging.error('Printing order fail!')
return result
def action_print_order(self, sale_id=None, reversion=False):
res = self.dialog_order.exec_()
if res == DIALOG_REPLY_NO:
return
kind = 'dispatch'
if self.enviroment == 'restaurant':
kind = 'command'
if not self.print_order:
return
if not sale_id and self._sale['id']:
sale_id = self._sale['id']
result = self._print_order(sale_id, kind)
if result:
# Show dialog if send sale order was successful
self.dialog('order_successfully')
else:
self.dialog('order_failed')
if self.enviroment == 'restaurant':
self.change_view_to('start_front')
def action_channel(self):
if self._state != 'cash':
self.dialog_channel.exec_()
def action_payment_term(self):
if self._state == 'cash' or self.type_pos_user == 'salesman':
self.dialog_payment_term.exec_()
def action_new_sale(self):
if self._state in ['cash']:
return
if not self._sale['id']:
return
if self._ask_new_sale():
self.create_new_sale()
def numpad_price_clicked(self):
code = self.label_input.text()
product = self._search_product(code)
if not product:
return
def _ask_new_sale(self):
dialog = self.dialog('new_sale', response=True)
res = dialog.exec_()
if res == DIALOG_REPLY_NO:
return False
return True
def action_cancel(self):
if self._state == 'disabled':
return
if self.type_pos_user == 'cashier':
self.dialog_cancel_invoice.exec_()
password = self.field_password_for_cancel_ask.text()
if password != self._password_admin:
return self.dialog('not_permission_for_cancel')
if not self._sale['id']:
return
if self._state in ('cash', 'payment') and not self.user_can_delete:
return self.dialog('not_permission_delete_sale')
if self.type_pos_user in ('order', 'salesman') and \
self._sale.get('invoice_number'):
return self.dialog('not_permission_delete_sale')
dialog = self.dialog('cancel_sale', response=True)
response = dialog.exec_()
if response == DIALOG_REPLY_NO:
return
self.Sale.cancel_sale(self._sale['id'])
self.field_password_for_cancel_ask.setText('')
self.set_state('cancel')
self.clear_right_panel()
if self.sale_automatic:
self.create_new_sale()
def action_search_product(self):
if self._state == 'cash':
return
self.dialog_search_products.show()
def action_start_delivery(self):
# self.store.clear()
self.create_new_sale(kind='delivery')
def action_start_table(self):
# self.store.clear()
self.create_new_sale(kind='to_table')
def action_start_take_away(self):
# self.store.clear()
self.create_new_sale(kind='take_away')
def action_search_sale(self):
delta = str(datetime.now() - timedelta(2))
if self.type_pos_user == 'cashier':
dom = ['OR', [
('create_date', '>=', delta),
('state', 'in', ['quotation', 'confirmed']),
], [
('state', '=', 'processing'),
('invoice.state', '=', 'draft'),
('invoice.type', '=', 'out'),
]]
elif self.type_pos_user in ('order', 'salesman'):
dom = [
('state', '=', 'draft'),
('create_date', '>=', delta),
]
else:
dom = [
('state', 'in', ['draft', 'quotation', 'confirmed']),
('create_date', '>=', delta),
]
fields = self.dialog_search_sales.fields_names
sales = self.Sale.find(dom, fields=fields, order=[('id', 'DESC')])
self.dialog_search_sales.set_from_values(sales)
if self.enviroment == 'retail':
dom_draft = [
('create_date', '>=', delta),
('state', '=', 'draft'),
('invoice_number', '!=', None),
]
sales_draft = self.Sale.find(dom_draft)
self.dialog_search_sales.set_counter_control(sales_draft)
response = self.dialog_search_sales.execute()
self.field_invoice_type.set_enabled(True)
if response == DIALOG_REPLY_NO:
return
def on_selected_sale(self):
sale_id = self.dialog_search_sales.get_id()
if not sale_id:
return
self.load_sale(sale_id)
self.setFocus()
self.label_input.setFocus()
self.change_view_to('order_front')
def on_selected_party(self, party_id=None):
if not party_id:
party_id = self.dialog_search_parties.get_id()
if not party_id:
return
party, = self.Party.find([('id', '=', party_id)])
address_id = ''
if party['addresses']:
address_id = party['addresses'][0]['id']
values = {
'party': {'id': party_id, 'name': party['name']},
'invoice_address': address_id,
'shipment_address': address_id,
}
payment_term = party.get('customer_payment_term')
if payment_term:
values['payment_term'] = payment_term
if party.get('salesman'):
values.update({'salesman': party.get('salesman')})
self.store.update(values)
self.party_id = party_id
# if self._credit_limit_activated:
# self._check_credit_capacity(party)
self.message_bar.set('system_ready')
self.setFocus()
self.label_input.setFocus()
def load_sale(self, sale_id):
# loads only draft sales
self.clear_data()
self.clear_left_panel()
self.clear_right_panel()
self.store.clear()
sale, = self.Sale.find([('id', '=', sale_id)])
self.store.set_sale(sale['id'])
self.store.set(sale)
self._sale.update(sale)
self.table_payment_lines.reset()
self._set_sale_date()
self.journal = {}
if self.field_delivery_charge:
self.field_delivery_charge.set_enabled(True)
if sale.get('delivery_charge'):
self.field_delivery_charge.set_from_id(sale['delivery_charge'])
if sale.get('table_assigned'):
self.field_table_assigned.setText(sale['table_assigned']['name'] or '')
consumer = sale.get('consumer', None)
if consumer:
self.field_consumer.setText(consumer['name'] or '')
self._consumer, = self.Consumer.find([
('id', '=', consumer['id']),
])
self.field_change.zero()
if self._commission_activated:
if hasattr(self, 'field_agent') and sale.get('agent') \
and sale.get('commission'):
commission = sale.get('commission')
self.field_agent.setText('[' + str(int(commission)) + ']' + ' ' + sale['agent']['name'])
self.field_agent_id = sale['agent']['id']
self.field_agent_ask.setText(sale['agent']['name'])
self.field_commission_ask.setText(str(commission))
self._set_commission_amount(sale['untaxed_amount'], commission)
self.line_ids = [l['id'] for l in sale.get('lines')]
if sale.get('lines'):
lines = self.SaleLine.find([
('id', 'in', self.line_ids),
])
sale['lines'] = lines
for line in lines:
self.add_sale_line(line)
if sale.get('payments'):
for payment in sale['payments']:
self.table_payment_lines.record_add(payment)
self.set_state('add')
self.party_id = sale['party']['id']
self.set_amounts(sale)
self.set_amount_received()
self.field_amount.setText('')
self.message_bar.set('system_ready')
if self.type_pos_user in ('cashier', 'order', 'salesman'):
self.table_sale_lines.setEnabled(True)
if self.enviroment == 'restaurant':
self.table_sale_lines.setEnabled(True)
self.menu_dash.setDisabled(False)
def set_change_amount(self):
amount_paid = self.table_payment_lines.get_sum('amount')
res = amount_paid - self._get_total_amount()
self.field_change.setText(res)
def set_amount_received(self, cash_received=ZERO):
pass
def set_amounts(self, res=None):
if not res:
res = self.Sale.get_amounts({'sale_id': self._sale['id']})
self.store.set(res)
# self.set_discount_amount()
def _get_products_by_category(self, cat_id):
records = self.Product.find([
('code', '!=', None),
('template.salable', '=', True),
('template.categories', '=', cat_id),
])
return records
def get_product_by_categories(self):
self.allow_categories = [
pc for pc in self.product_categories if not pc['parent'] and not pc['accounting']
]
for cat in self.allow_categories:
cat['icon'] = get_icon(cat['name_icon'])
if cat.get('childs'):
for child in cat.get('childs'):
child['items'] = self._get_products_by_category(child['id'])
else:
cat['items'] = self._get_products_by_category(cat['id'])
return self.allow_categories
def get_menu_control_panel(self):
menu_dash = [
['button_open', self.tr('OPEN STATEMENTS'), 'action_open_statement'],
['button_closed', self.tr('CLOSED STATEMENTS'), 'action_closed_statement'],
# ['button_money', self.tr('COUNT MONEY'), 'action_count_money'],
['button_discount', self.tr('GLOBAL DISCOUNT'), 'action_table_discount'],
['button_delivery_party', self.tr('DELIVERY MEN'), 'action_delivery_party_panel'],
['button_help', self.tr('HELP'), 'action_help'],
]
return menu_dash
def _get_childs(self, parent_cat):
res = {}
for cat_id in parent_cat['childs']:
sub_categories = self.Category.find([
('parent', '=', parent_cat['id'])
])
for sub_cat in sub_categories:
res.update(self._get_childs(sub_cat))
res = {
'id': parent_cat['id'],
'name': parent_cat['name'],
'childs': parent_cat['childs'],
'records': [],
'obj': parent_cat,
}
return res
def get_category_items(self, records):
records_by_category = {}
def _get_tree_categories(cat):
sub_categories = {}
if not cat['childs']:
sub_categories[cat['name']] = records_by_category.get(cat['id']) or []
else:
for child in cat['childs']:
sub_categories.update(_get_tree_categories(
self.target_categories[child]['obj']))
return sub_categories
for record in records:
cat_id = record.get('template.account_category')
if cat_id not in records_by_category.keys():
records_by_category[cat_id] = []
records_by_category[cat_id].append(record)
res = {}
for ac in self.allow_categories:
res[ac['name']] = _get_tree_categories(ac)
return res
def on_selected_product(self):
if self.dialog_search_products.current_row:
self._current_line_id = None
self.clear_right_panel()
self.add_product(record=self.dialog_search_products.current_row)
def on_selected_icon_product(self):
if self.dialog_search_products.current_row:
code = self.dialog_search_products.current_row['code']
products = self.Product.find([
('code', '=', code)
])
if not products:
return
product = products[0]
# image = Image(name='product_icon')
# if not product['image']:
# return
#
# b64image = product['image'].encode()
# image.set_image(b64image, kind='bytes')
# image.activate()
def on_selected_stock_product(self):
if self.dialog_search_products.current_row:
code = self.dialog_search_products.current_row['code']
res = self.Product.get_stock_by_locations({'code': code})
self.dialog_product_stock.update_values(res)
self.dialog_product_stock.show()
def on_selected_item_mix(self, record):
list_price = self._current_line['product'].get('list_price')
if list_price < record['list_price']:
# Update price in selected_line
self.set_unit_price(record['template']['sale_price_w_tax'])
list_price = None
self.on_selected_item(record, list_price)
def on_selected_item(self, record, list_price=None):
if record:
self.clear_right_panel()
self.add_product(record=record, list_price=list_price)
def on_selected_salesman(self, salesman):
if salesman:
salesman_data = {
'id': salesman['id'],
'name': salesman['rec_name'],
}
self.store.update({'salesman': salesman_data})
self.dialog_salesman.close()
def on_selected_discount(self, discount):
if discount:
self.validate_discount(discount)
self.dialog_global_discount_table.close()
self.dialog_control_panel.close()
def on_selected_delivery_party(self, delivery_party_id):
if delivery_party_id:
self.store.update({'delivery_party': delivery_party_id})
self.dialog_delivery_party.close()
def on_selected_payment_term(self, payterm_id):
if payterm_id:
self.field_payment_term_id = payterm_id
self.action_payment_term_selection_changed()
self.dialog_payment_term.close()
def on_selected_channel(self, channel):
self.store.update({'channel': channel})
self.dialog_channel.close()
def on_selected_payment(self, journal):
self.journal = journal
if journal.get('id'):
self.field_journal_id = journal['id']
self.dialog_payment.close()
self.message_bar.set('enter_payment', journal['rec_name'])
def on_search_product(self):
target = self.dialog_search_products.filter_field.text()
if not target:
return
target_words = target.split(' ')
domain = [
('template.active', '=', True),
('active', '=', True),
('template.salable', '=', True),
]
for tw in target_words:
if len(tw) <= 1:
continue
clause = [
'OR',
('template.name', 'ilike', '%{:}%'.format(tw)),
('description', 'ilike', '%{:}%'.format(tw)),
('code', 'ilike', '%{:}%'.format(tw))
]
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']]
domain.append(('template.categories', 'in', categories_id))
if not domain:
return
if self.cache_local:
domain = [clause]
products = self.local_db.find_product_elastic(domain, limit=100)
else:
fields = self.dialog_search_products.fields_names
products = self.Product.find(domain, fields=fields,
limit=100, ctx=self.stock_context)
self.dialog_search_products.set_from_values(products)
def on_search_party(self):
target = self.dialog_search_parties.filter_field.text()
if not target:
return
target_words = target.split(' ')
domain = [('id_number', '!=', None)]
for tw in target_words:
if len(tw) <= 2:
continue
or_clause = [
'OR',
('name', 'ilike', '%' + tw + '%'),
('contact_mechanisms.value', 'like', tw + '%'),
('id_number', 'like', tw + '%')
]
domain.append(or_clause)
fields_names = self.dialog_search_parties.fields_names
parties = self.Party.find(domain, fields=fields_names)
self.dialog_search_parties.set_from_values(parties)
def clear_data(self):
self._sale = {'total_amount': 0, 'tip_amount': 0, 'delivery_amount': 0}
self.party_name = None
self._sale_line = {'id': None}
self._total_amount = {}
self._sale_lines_taxes = {}
self.field_journal_id = self.default_journal['id']
self.field_voucher_ask.setText('')
def clear_left_panel(self):
self.field_party.setText('')
self.field_salesman.setText('')
self.field_salesman_id = None
self.field_invoice_type.set_from_id('P')
self.field_party_id = None
self.field_agent_id = None
self.field_payment_term_id = self.default_payment_term['id']
self.field_payment_term.setText(self.default_payment_term['name'])
self.field_sale_date.setText('')
self.field_global_discount_ask.setText('')
self.field_amount.setText('')
self.field_number.setText('')
self.field_state.setText('')
self.current_comment = ''
if hasattr(self, 'field_consumer'):
self.field_consumer.setText('')
if self.field_delivery_charge:
self.field_delivery_charge.set_from_id('')
if self.field_table_assigned:
self.field_table_assigned.setText('')
if hasattr(self, 'field_comment'):
self.field_comment.document().clear()
if self._commission_activated and hasattr(self, 'field_agent'):
self.field_agent.setText('')
self.field_agent_ask.setText('')
self.field_commission_ask.setText('')
self.field_commission_amount.setText('')
self.model_sale_lines.reset()
self.clear_input_text()
self.clear_amount_text()
def clear_right_panel(self):
self.field_invoice.setText('')
self.field_tip_amount.setText('')
self.field_delivery_amount.setText('')
self.field_untaxed_amount.zero()
self.field_net_amount.zero()
self.field_taxes_amount.zero()
self.field_total_amount.zero()
self.field_change.zero()
self.field_paid_amount.zero()
self.field_discount.zero()
self.field_residual_amount.zero()
self.table_payment_lines.reset()
def state_enabled(self):
pass
def state_disabled(self):
self.payment_ctx = {}
self.clear_left_panel()
self.table_sale_lines.setDisabled(True)
self.set_state('disabled')
if self.field_delivery_charge:
self.field_delivery_charge.set_enabled(False)
def create_new_sale(self, kind=None):
if self.enviroment == 'restaurant' and self._sale_pos_restaurant:
self.clear_dialog_consumer()
# self.check_empty_sale()
if self.type_pos_user == 'cashier':
self.message_bar.set('not_sale')
# self.state_disabled()
return
self.store.clear()
self.journal = {}
self.set_state('add')
self.input_text_changed('')
self.amount_text_changed('0')
self.clear_sign()
self.show_right_panel(True)
self.consumer_id = None
self.payment_ctx = {}
self.table_sale_lines.setEnabled(True)
self.field_invoice_type.set_enabled(True)
self.clear_data()
self.clear_right_panel()
self.clear_left_panel()
self.message_bar.set('system_ready')
to_create = {
'shop': self.shop['id'],
'invoice_type': 'P',
'company': self.company['id'],
'party': self.default_party['id'],
'sale_device': self.device['id'],
'payment_term': self.default_payment_term['id'],
}
if kind:
kind_dict = {'kind': kind}
to_create.update(kind_dict)
self._sale = self.Sale.new_sale(to_create)
self.store.set(self._sale)
if kind:
self.store.set(kind_dict)
# FIXME ADD MORE
self._sale.update({
'total_amount': 0
})
self.party_id = self.default_party['id']
if self._sale.get('id') and self.field_delivery_charge:
if self.field_delivery_charge:
self.field_delivery_charge.set_enabled(True)
self.change_view_to('order_front')
if self.enviroment == 'restaurant':
self.menu_dash.setDisabled(False)
def _set_sale_date(self):
if self._sale.get('sale_date'):
local_date = self._sale['sale_date']
if isinstance(local_date, date):
local_date = local_date.isoformat()
self.field_sale_date.setText(local_date)
def _search_product(self, code):
domain = [
('template.salable', '=', True),
('template.account_category', '!=', None),
]
domain.append(['OR',
('barcode', '=', code),
('code', '=', code)])
if self.cache_local:
clause = ['OR',
('barcode', '=', '%{:}%'.format(code)),
('code', '=', '%{:}%'.format(code))]
domain = [clause]
products = self.local_db.find_product_elastic(domain, limit=100)
else:
products = self.Product.find(domain, ctx=self.stock_context)
if not products or len(products) > 1:
self.message_bar.set('product_not_found')
return False
else:
product = products[0]
return product
def _check_quantity(self):
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 product_id:
product, = self.Product.find([('id', '=', product_id)], ctx=self.stock_context)
if 'quantity' in product and not self._check_stock_quantity(product):
return False
return True
def check_salesman(self):
salesman = self.store.get('salesman')
if self.salesman_required and not salesman:
dialog = self.dialog('missing_salesman')
dialog.exec_()
return False
return True
def add_product(self, record=None, code=None, list_price=None):
if self._state == 'disabled':
self.message_bar.set('must_load_or_create_sale')
return
product_id = None
if record:
product_id = record['id']
elif code:
# REMOVE ME
product = self._search_product(code)
if product:
product_id = product['id']
elif product:
product_id = product['id']
if not product_id:
self._state = 'warning'
return
data = {
'sale_id': self._sale['id'],
'product_id': product_id,
'qty': 1,
}
if list_price:
data['list_price'] = list_price
res = self.Sale.faster_add_product(data)
self._sale_line = res
self._current_line_id = res['id']
self.add_sale_line(res)
self._sale_line['product'] = record
self.product_id = product_id
self.set_amounts()
self.set_state('add')
def _check_stock_quantity(self, product, request_qty=None):
if not isinstance(product['quantity'], (str, int, float, Decimal)):
return True
qty_ = Decimal(product['quantity'])
if self._password_force_assign:
if (request_qty and qty_ < request_qty) or (qty_ <= 0):
self.message_bar.set('without_stock_quantity', product['name'])
self.dialog_force_assign.exec_()
password = self.field_password_force_assign_ask.text()
self.field_password_force_assign_ask.setText('')
if password != self._password_force_assign:
self.message_bar.set('not_can_force_assign')
return False
else:
self.message_bar.set('system_ready')
return True
def add_sale_line(self, record):
if not record.get('unit.symbol'):
record['unit.symbol'] = record['unit']['symbol']
if isinstance(record['product'], dict):
if not record.get('product.template.name'):
record['product.template.name'] = record['product']['template']['name']
if not record.get('product.code'):
record['product.code'] = record['product']['code']
if record.get('order_sended'):
record['order_sended'] = ''
rec = self.model_sale_lines.add_record(record)
self.field_amount.setText(rec['amount_w_tax'])
def sale_line_selected(self, line):
if self._state in ('cash', 'payment'):
return
self._current_line = line
self._current_line_id = line['id']
product_id = None
if isinstance(line['product'], int):
product_id = line['product']
elif isinstance(line['product'], dict):
product_id = line['product']['id']
self.product_id = product_id
self.label_product.setText(line['product.template.name'])
self.row_field_description.setText(line['description'])
self.row_field_qty.setValue(float(line['quantity']))
self.row_field_price.setText(str(line['unit_price_w_tax']))
self.row_field_note.setText(str(line['note']))
self.dialog_product_edit.show()
self.row_field_note.setFocus()
def sale_consumer_selected(self, data):
self.sale_customer_selected = data['id']
self.row_sale_party.setText(data['party']['name'])
self.row_sale_number.setText(data['number'])
self.row_sale_date.setText(data['sale_date'])
self.row_sale_tax_amount.setText(str(data['tax_amount']))
self.row_sale_untaxed.setText(str(data['untaxed_amount']))
self.row_sale_total.setText(str(data['total_amount_cache']))
self.model_sale_customer_lines.reset()
for line in data['lines']:
self.model_sale_customer_lines.add_record(line)
self.dialog_sale_consumer_selected.exec_()
def clear_delivery_party(self):
self._delivery_party_selected = None
self.row_delivery_party.setText('')
self.row_id_number.setText('')
self.row_phone.setText('')
self.row_number_plate.setText('')
self.row_type_vehicle.set_from_id('')
self.row_delivery_party_active.setChecked(True)
def delivery_party_selected(self, data):
self._delivery_party_selected = data['id']
self.row_delivery_party.setText(data['rec_name'])
self.row_id_number.setText(data['party']['id_number'])
self.row_number_plate.setText(data['number_plate'])
if data.get('type_vehicle'):
self.row_type_vehicle.set_from_id(data['type_vehicle'])
self.row_delivery_party_active.setChecked(data['active'])
self.dialog_delivery_party_selected.show()
self.row_delivery_party_active.setFocus()
def setup_money_count(self):
self.model_money_count = TableModelEdit(self, MONEY)
def setup_sale_line(self):
product_code = {
'name': 'product.code',
'align': alignRight,
'description': self.tr('COD'),
'width': 80
}
product = {
'name': 'product.template.name',
'align': alignLeft,
'description': self.tr('NAME'),
'width': STRETCH
}
description = {
'name': 'description',
'align': alignLeft,
'description': self.tr('DESCRIPTION'),
'width': 180
}
uom = {
'name': 'unit.symbol',
'align': alignHCenter,
'description': self.tr('UNIT'),
'width': 50
}
qty = {
'name': 'quantity',
'format': '{:3,.%sf}',
'align': alignRight,
'description': self.tr('QTY'),
'digits': ('unit.symbol', CONVERSION_DIGITS),
'width': 80
}
discount = {
'name': 'discount',
'format': '{0:.0%}',
'align': alignRight,
'description': self.tr('DISC'),
'width': 50
}
amount = {
'name': 'amount_w_tax',
'format': '{:,d}',
'align': alignRight,
'description': self.tr('SUBTOTAL'),
'width': 100
}
note = {
'name': 'note',
'align': alignLeft,
'description': self.tr('NOTE'),
'invisible': True,
'width': 100
}
unit_price = {
'name': 'unit_price_w_tax',
'format': '{:5,.1f}',
'align': alignLeft,
'description': self.tr('UNIT PRICE W TAX'),
'invisible': True,
'width': 100
}
qty_fraction = {
'name': 'qty_fraction',
'align': alignHCenter,
'description': self.tr('FRAC'),
'width': 50
}
commanded = {
'name': 'order_sended',
'align': alignHCenter,
'description': self.tr('COMMANDED'),
'width': 60
}
self.fields_sale_line = [product, uom, qty, discount,
amount, note, unit_price]
if self.enviroment == 'retail':
self.fields_sale_line.insert(0, product_code)
if self.enviroment == 'restaurant':
self.fields_sale_line.insert(1, commanded)
if self._config.get('show_description_pos'):
self.fields_sale_line.insert(2, description)
if self._config.get('show_fractions'):
self.fields_sale_line.insert(4, qty_fraction)
self.model_sale_lines = TableModel('sale.line', self.fields_sale_line)
self.model_sale_customer_lines = TableModel('sale.line', self.fields_sale_line)
def setup_sale_consumer(self):
number = {
'name': 'number',
'align': alignCenter,
'description': self.tr('NUMBER'),
'width': 200
}
invoice_number = {
'name': 'invoice_number',
'align': alignCenter,
'description': self.tr('INVOICE NUMBER'),
'width': 200
}
consumer = {
'name': 'consumer.name',
'align': alignCenter,
'description': self.tr('CONSUMER'),
'width': 300
}
sale_date = {
'name': 'sale_date',
'align': alignCenter,
'description': self.tr('DATE'),
'width': 300
}
total_amount_cache = {
'name': 'total_amount_cache',
'align': alignCenter,
'description': self.tr('TOTAL AMOUNT'),
'width': 300
}
self.fields_sale_consumer = [number, invoice_number, consumer, sale_date,
total_amount_cache]
self.model_sale_consumer = TableModel('sale.sale', self.fields_sale_consumer)
def setup_delivery_party(self):
party = {
'name': 'rec_name',
'align': alignLeft,
'description': self.tr('PARTY'),
'width': 380
}
id_number = {
'name': 'party.id_number',
'align': alignLeft,
'description': self.tr('ID NUMBER'),
'width': 200
}
phone = {
'name': 'party.phone',
'align': alignLeft,
'description': self.tr('PHONE'),
'width': 200
}
number_plate = {
'name': 'number_plate',
'align': alignCenter,
'description': self.tr('NUMBER PLATE'),
'width': 200
}
type_vehicle = {
'name': 'type_vehicle',
'align': alignCenter,
'description': self.tr('TYPE VEHICLE'),
'width': 300
}
self.fields_delivery_party = [party, id_number, phone, number_plate, type_vehicle]
self.model_delivery_party = TableModel('sale.delivery_party', self.fields_delivery_party)
for record in self.delivery_man_table:
self.model_delivery_party.add_record(record)
self.delivery_parties = [d for d in self.model_delivery_party._data if d['active']]
def setup_payment(self):
pay_fields = [{
'name': 'statement',
'align': alignLeft,
'description': self.tr('STATEMENT JOURNAL'),
}, {
'name': 'amount',
'align': alignRight,
'format': '{:5,.1f}',
'description': self.tr('AMOUNT'),
}, {
'name': 'voucher',
'align': alignCenter,
'description': self.tr('VOUCHER'),
}]
self.table_payment_lines = TableModel('account.statement.line', pay_fields)
def action_table(self):
self.table_sale_lines.setFocus()
def on_change_line_selected(self, key):
self.table_sale_lines.moved_selection(key)
def action_addition_line(self):
if not self._current_line:
return
categories = self._current_line['product'].get('categories')
if not categories:
return
categories_ids = [cat['id'] for cat in categories]
mixables = self.Product.find([
('categories', 'in', categories_ids),
])
self.dialog_addition_product.set_products(mixables)
self.dialog_addition_product.exec_()
self.dialog_addition_product.close()
def action_delete_line(self):
"""Delete Product """
if self.model_sale_lines.rowCount() <= 0 or self._state == 'cash':
return
self.table_sale_lines.setFocus()
# if not removed_item:
removed_item = self.table_sale_lines.delete_item(ignore_focus=True)
self.SaleLine.delete([removed_item['id']])
self.set_amounts()
self._current_line_id = None
self.setFocus()
self.label_input.setFocus()
self.dialog_product_edit.hide()
sale_number = self.store.get('number')
if self.enviroment == 'restaurant':
if removed_item and self.print_order and sale_number:
self.action_print_order(self._sale['id'], removed_item)
if self._config['tip_product']['code'] == removed_item['product.code']:
self.Sale.write([self._sale['id']], {'tip': None})
def set_discount(self, eval_value, lines_ids=[]):
res = False
try:
value = round(float(str(eval_value)), 6)
except ValueError:
logging.warning('ValueError > ', ValueError)
return
if float(value) < 0:
return False
if not lines_ids:
target_lines = [self._current_line_id]
else:
target_lines = lines_ids
records = self.SaleLine.faster_set_discount({
'line_ids': target_lines,
'value': value
})
for rec in records:
self.model_sale_lines.update_record(rec)
if records:
res = True
self.set_amounts()
return res
def set_unit_price(self, value):
rec = self.SaleLine.set_faster_unit_price({
'id': self._current_line_id,
'value': value,
})
if rec:
self.model_sale_lines.update_record(rec)
self.set_amounts()
return True
return False
def add_payment(self, amount, cash_received=0, change=0):
voucher_number = None
if not self.journal:
journal = self.default_journal
else:
journal = self.journal
if journal.get('require_voucher'):
self.dialog_voucher.exec_()
voucher_number = self.field_voucher_ask.text()
if voucher_number is None or voucher_number == '':
return self.add_payment(amount)
res = self.Sale.faster_add_payment({
'sale_id': self._sale['id'],
'journal_id': journal['id'],
'amount': to_numeric(amount),
'voucher_number': voucher_number,
'cash_received': to_numeric(cash_received),
'change': to_numeric(change)
})
if res.get('msg') not in ('missing_money', 'ok'):
self.dialog(res['msg'])
return res
residual_amount = res.pop('residual_amount')
change = res.pop('change')
paid_amount = res.pop('paid_amount')
self.store.set({
'residual_amount': residual_amount,
'change': change,
'paid_amount': paid_amount,
})
self.table_payment_lines.add_record(res)
return res
def set_keys(self):
self.keys_numbers = list(range(Qt.Key_0, Qt.Key_9 + 1))
self.keys_alpha = list(range(Qt.Key_A, Qt.Key_Z + 1))
self.keys_period = [Qt.Key_Period]
self.show_keys = self.keys_numbers + self.keys_alpha + self.keys_period
self.keys_special = [Qt.Key_Asterisk, Qt.Key_Comma, Qt.Key_Minus, Qt.Key_Slash]
self.keys_input = [Qt.Key_Backspace]
self.keys_input.extend(self.keys_special)
self.keys_input.extend(self.show_keys)
self.keys_input.extend(self.keys_numbers)
self.keys_input.extend([Qt.Key_Return, Qt.Key_Plus])
def set_state(self, state='add'):
self._state = state
state = STATES[state]
self._re = state['re']
if not self.type_pos_user == 'order':
if not self.buttons_stacked.stacked.currentWidget():
return
if state['button']:
self.buttons_stacked.stacked.setCurrentWidget(
getattr(self.buttons_stacked, state['button'])
)
self.buttons_stacked.stacked.currentWidget().setVisible(True)
else:
self.buttons_stacked.stacked.currentWidget().setVisible(False)
def key_pressed(self, text):
if not self._sign and self._state not in ('cash', 'payment'):
# FIXME
# if self._re.match(self._input_text + text):
# self.input_text_changed(text)
pass
else:
if RE_SIGN['quantity'].match(self._amount_text + text):
self.amount_text_changed(text)
def clear_sign(self):
self._sign = None
self.field_sign.setText(' {0} '.format(' '))
def sign_text_changed(self, sign):
self._sign = sign
self.field_sign.setText(' {0} '.format(sign))
if hasattr(self, '_sale_line') and self._sale_line:
if sign == '-':
self.message_bar.set('enter_discount')
elif sign == '/':
self.message_bar.set('enter_new_price')
elif sign == '*':
self.message_bar.set('enter_quantity')
if self.active_weighing and self._sale_line['unit_symbol'] != 'u':
self.action_read_weight()
def key_special_pressed(self, value):
self.clear_amount_text()
self.clear_input_text()
if value not in ['-', '/', '*']:
return
self.sign_text_changed(value)
def key_backspace_pressed(self):
if self._sign or self._state in ('cash', 'payment'):
self._amount_text = self._amount_text[:-1]
self.amount_text_changed()
self.label_input.setFocus()
else:
self._input_text = self._input_text[:-1]
self.input_text_changed()
def set_text(self, text):
if not self._state == 'cash':
self.input_text_changed(text)
else:
self.amount_text_changed(text)
def clear_input_text(self):
self.input_text_changed('')
def clear_amount_text(self):
self._amount_text = '0'
self.amount_text_changed()
def keyPressEvent(self, event):
self._keyStates[event.key()] = True
key = event.key()
if self._state == 'add' and key not in self.keys_input and \
key not in (Qt.Key_Enter, Qt.Key_End):
# Clear ui context when keys function are pressed
self._clear_context()
if key in (Qt.Key_Return, Qt.Key_Plus):
self.button_plus_pressed()
elif key in self.show_keys:
# No allow change quantity o discount in state == cash
if self._state in ('cash', 'payment') and key not in self.keys_numbers:
return
self.key_pressed(event.text())
elif key in self.keys_special:
if self._state == 'cash' or not self._current_line_id:
return
self.key_special_pressed(event.text())
elif key == Qt.Key_Backspace:
self.key_backspace_pressed()
elif key == Qt.Key_Escape:
if self._state not in ('cash', 'payment'):
self._clear_context()
# self.close()
elif key == Qt.Key_F1:
# help = Help(self).show()
self.action_control_panel()
elif key == Qt.Key_F9:
self.action_search_sale()
elif key == Qt.Key_F11:
self.action_new_sale()
elif key == Qt.Key_F7:
self.action_print_sale()
elif self._state == 'disabled':
self.message_bar.set('must_load_or_create_sale')
return
elif key in (Qt.Key_Enter, Qt.Key_End):
if self.type_pos_user in ['order', 'salesman']:
return
if self._state == 'add':
self.button_accept_pressed()
elif self._state in ['cash', 'accept']:
self.button_cash_pressed()
elif key == Qt.Key_F2:
self.action_search_product()
elif key == Qt.Key_F3:
self.action_payment()
elif key == Qt.Key_F4:
self.action_party()
elif key == Qt.Key_F5:
self.action_global_discount()
elif key == Qt.Key_F6:
self.action_print_order()
elif key == Qt.Key_F8:
self.action_payment_term()
elif key == Qt.Key_F10:
self.action_table()
elif key == Qt.Key_F12:
self.action_cancel()
elif key == Qt.Key_Home:
self.action_salesman()
elif key == Qt.Key_Down or key == Qt.Key_Up:
self.on_change_line_selected(key)
elif key == Qt.Key_Insert:
self.action_position()
elif key == Qt.Key_Semicolon and self._commission_activated:
sale = self.get_current_sale()
if sale['state'] == 'draft' and self._state not in ['cash', 'payment']:
self.action_agent()
elif key == Qt.Key_QuoteDbl:
self.action_comment()
elif key == Qt.Key_Question:
self.action_tax()
@property
def state(self):
return self._state
def update_sale_line(self, field):
value = None
self.state_line['id'] = self._current_line_id
if field == 'quantity':
value = Decimal(self.row_field_qty.value())
if field == 'unit_price':
value = self.row_field_price.text()
if field == 'qty_fraction':
qty = self.field_combobox_fraction.get_id()
self.row_field_qty.setValue(float(qty))
value = self.field_combobox_fraction.get_label()
self.state_line['quantity'] = qty
price_ = self.Sale.get_product_prices({
'ids': [self._sale_line['product']['id']],
'quantity': float(qty),
'sale_id': self._sale['id'],
})
if price_ and price_.get('unit_price_w_tax'):
price_list = str(price_['unit_price_w_tax'])
self.row_field_price.setText(price_list)
self.state_line['unit_price'] = price_list
if field == 'description':
value = self.row_field_description.text()
if field == 'note':
value = self.row_field_note.toPlainText()
if value:
self.state_line[field] = value
def dialog_product_edit_accepted(self):
if not self.state_line:
return
_record = None
if self.state_line.get('unit_price'):
unit_price = self.state_line.pop('unit_price')
self._sign = '/'
self._process_price(unit_price)
self._sign = None
_record = self.SaleLine.write([self._current_line_id], {})
if self.state_line.get('quantity'):
quantity = self.state_line.pop('quantity')
_record = self.SaleLine.faster_set_quantity({
'id': self._current_line_id,
'quantity': to_float(quantity, 2)
})
if self.state_line.get('description'):
_record = self.SaleLine.write([self._current_line_id], {
'description': self.state_line['description']
})
if self.state_line.get('note'):
_record = self.SaleLine.write([self._current_line_id], {
'note': self.state_line['note']
})
if _record:
if not _record.get('unit.symbol'):
_record['unit.symbol'] = _record['unit']['symbol']
if not _record.get('product.template.name'):
_record['product.template.name'] = _record['product']['template']['name']
if not _record.get('product.code'):
_record['product.code'] = _record['product']['code']
self.model_sale_lines.update_record(_record)
self.set_amounts()
self.state_line = {}
def dialog_search_consumer_accepted(self):
if not self.state_consumer:
return
if self._consumer:
res = self.Sale.update_consumer({
'id': self._consumer['id'],
'fields': self.state_consumer,
})
else:
res = self.Sale.create_consumer({
'fields': self.state_consumer,
})
if res.get('msg') == 'ok':
self._consumer = res['consumer']
self.consumer_id = self._consumer['id']
self._sale['consumer'] = self.consumer_id
self.set_consumer()
self.field_consumer.setText(self._consumer['name'])
self.Sale.write([self._sale['id']], {'consumer': self.consumer_id})
if res.get('party'):
self.on_selected_party(res['party'])
def dialog_delivery_party_accepted(self):
if not self.state_delivery_party:
return
if hasattr(self, '_delivery_party_selected') and self._delivery_party_selected:
res = self.Sale.update_delivery_party({
'id': self._delivery_party_selected,
'data': self.state_delivery_party
})
self._delivery_party_selected = None
self.model_delivery_party.update_record(res)
else:
res = self.Sale.create_delivery_party({
'data': self.state_delivery_party,
'shop_id': self.ctx['shop']
})
self.model_delivery_party.add_record(res)
self.delivery_parties = [d for d in self.model_delivery_party._data if d['active']]
self.dialog_delivery_party = DialogDeliveryParty(self).get()
def update_delivery_party(self, field=''):
if field == 'delivery_party':
self.state_delivery_party['party'] = self.row_delivery_party.text()
if field == 'row_phone':
self.state_delivery_party['phone'] = self.row_phone.text()
if field == 'id_number':
self.state_delivery_party['id_number'] = self.row_id_number.text()
if field == 'number_plate':
self.state_delivery_party['number_plate'] = self.row_number_plate.text()
if field == 'type_vehicle':
self.state_delivery_party['type_vehicle'] = self.row_type_vehicle.get_id()
if field == 'delivery_party_active':
self.state_delivery_party['active'] = self.row_delivery_party_active.isChecked()
def update_consumer_data(self, field=''):
if field == 'notes':
self.state_consumer['notes'] = self.row_field_consumer_notes.toPlainText()
if field == 'address':
self.state_consumer['address'] = self.row_field_address.text()
elif field == 'id_number':
self.state_consumer['id_number'] = self.row_field_id_number.text()
elif field == 'name':
self.state_consumer['name'] = self.row_field_consumer.text()
elif field == 'birthday':
self.state_consumer['birthday'] = self.row_field_birthday.date().toPyDate()
elif field == 'phone':
self._text_field_phone = self.row_field_phone.text()
if self._text_field_phone:
self.state_consumer['phone'] = self._text_field_phone
consumers = self.PartyConsumer.find([
('phone', '=', self._text_field_phone),
])
if not consumers:
self._consumer = {}
self.row_field_address.setText('')
self.row_field_consumer.setText('')
self.row_field_id_number.setText('')
self.row_field_birthday.setDate(MINIMUM_DATE)
self.row_field_consumer_notes.clear()
else:
self.button_history_customer.setVisible(True)
self._consumer = consumers[0]
self.set_consumer()
# self.row_field_address.setText(self._consumer['address'])
# self.row_field_consumer.setText(self._consumer['name'])
# self.row_field_id_number.setText(self._consumer['id_number'])
# self.row_field_consumer_notes.insertPlainText(
# self._consumer['notes'])
# if self._consumer.get('birthday'):
# y, m, d = self._consumer['birthday'].split('-')
# self.row_field_birthday.setDate(QDate(int(y), int(m), int(d)))
def action_table_assigned(self, table, name, trasition_state):
current_table = self._sale.get('table_assigned')
current_sale_id = self._sale['id']
table_id = table['id']
table_sale_id = table['sale_id']
new_table_id = table_id
table_state = table['state']
sale_id = current_sale_id
if table_state == 'occupied':
if current_sale_id != table_sale_id and trasition_state == 'occupied':
return False
elif current_table and current_table['id'] == table_id and trasition_state == 'available':
name = ''
new_table_id = None
current_sale_id = None
vals = {'table_assigned': {
'id': table_id,
'name': name,
}}
self.store.set(vals)
# self._sale['table_assigned.state'] = trasition_state
self.RestTables.write([table_id], {
'state': trasition_state,
'sale': current_sale_id,
})
self.Sale.write([self.store.sale_id], {'table_assigned': new_table_id})
return {
'state': trasition_state,
'sale': sale_id,
}
def action_see_table_sale(self, table_id):
table_, = self.RestTables.find([
('id', '=', table_id),
], limit=1)
sale = table_['sale']
if sale:
self.load_sale(sale['id'])
self.dialog_manage_tables.hide()
def clear_dialog_consumer(self):
self._consumer = {}
self.row_field_phone.setText('')
self.row_field_address.setText('')
self.row_field_consumer.setText('')
self.row_field_id_number.setText('')
self.row_field_birthday.setDate(QDate(2000, 1, 1))
self.row_field_consumer_notes.clear()
self.button_history_customer.setVisible(False)
def set_consumer(self):
self.row_field_consumer_notes.clear()
self.row_field_phone.setText(self._consumer['phone'])
self.row_field_consumer.setText(self._consumer['name'])
self.row_field_address.setText(self._consumer['address'])
id_number = self._consumer.get('id_number')
if id_number:
self.row_field_id_number.setText(id_number)
self.row_field_consumer_notes.insertPlainText(
self._consumer['notes']
)
if self._consumer.get('birthday'):
y, m, d = self._consumer['birthday'].split('-')
self.row_field_birthday.setDate(QDate(int(y), int(m), int(d)))
# 2798