presik_pos/app/frontwindow.py

375 lines
15 KiB
Python

import os
import time
from datetime import date
import logging
from pathlib import Path
from PyQt5.QtWidgets import QMainWindow, QDesktopWidget, QLineEdit
from PyQt5.QtCore import QTimer, QThread, pyqtSignal
from .commons.dialogs import QuickDialog
from .commons.dblogin import safe_reconnect
from .proxy import FastModel
from .constants import SCREENS
from .dialogs import (
Help, ControlPanel, SearchSale, SearchParty, SearchProduct, Position,
Comment, DialogPayment, DialogVoucher, DialogPrintInvoice, ProductEdit,
DialogGlobalDiscount, DialogPaymentTerm, DialogStock, DialogOrder,
DialogForceAssign, DialogTaxes, DialogCancelInvoice, DialogAgent,
DialogConsumer, DialogManageTables, DialogMoneyCount, CombineProduct,
DialogAuthDiscounts, DeliveryPartySelected, DialogTableDeliveryParty,
DialogHistoricSales, DialogSaleForm, DialogSource, DialogReports,
DialogDeliveryParty, TipAmount, DeliveryAmount, DialogSalesmanCode,
DialogFixedDiscounts, DialogFixedDiscountsManual, DialogComboProduct, DialogSplitSale, DialogExpenses,
DialogInfoProduct
)
from .constants import DIALOG_REPLY_YES
from .version import __version__
__all__ = ['FrontWindow', 'ClearUi']
parent = Path(__file__).parent
file_base_css = os.path.join(str(parent), 'css', 'base.css')
_DEFAULT_TIMEOUT = 60000 # on ms (100 minutes)
class FrontWindow(QMainWindow):
def __init__(self, connection, params, title=None, show_mode=None):
super(FrontWindow, self).__init__()
if not title:
title = 'APLICACION'
self._state = None
self._keyStates = {}
self.window().setWindowTitle(title)
self.setObjectName('WinMain')
self.conn = connection
self.version = __version__
self._context = connection.context
self.set_params(params)
self.logger = logging.getLogger('app_logger')
"""
We need get the size of screen (display)
--------------- -------------------
name width (px)
--------------- -------------------
small screen =< 1024
medium screen > 1024 and =< 1366
large screen > 1366
"""
screen = QDesktopWidget().screenGeometry()
self.setGeometry(0, 0, screen.width(), screen.height())
self.screen_width = screen.width()
self.screen_height = screen.height()
self.screen_size = 'large'
if self.screen_width <= 1024:
self.screen_size = 'small'
elif self.screen_width <= 1366:
self.screen_size = 'medium'
print('self.screen_size > ', self.screen_size)
self.timeout = _DEFAULT_TIMEOUT
self.setFocus()
self.global_timer = 0
_theme = params['theme'] if params.get('theme') else None
self.profile_printer = params['profile_printer'] if params.get('profile_printer') else 'TM-P80'
self.set_style(SCREENS[self.screen_size], _theme)
self.label_color = 'gray'
self.label_color_2 = ''
if _theme == 'dark':
self.label_color = 'light'
self.label_color_2 = 'orange'
self.window().showMaximized()
def filter_cache(self, data, filter, target):
res = []
for d in data:
for t in target:
if t in d[filter]:
res.append(d)
return res
def get_geometry(self):
screen = QDesktopWidget().screenGeometry()
return screen.width(), screen.height()
def set_style(self, file_css, theme_css=None):
styles = []
if theme_css:
theme_css = os.path.join(str(parent), 'css', theme_css + '.css')
for style in [theme_css or file_base_css, file_css]:
with open(style, 'r') as infile:
styles.append(infile.read())
self.setStyleSheet(''.join(styles))
def set_timeout(self):
if self.active_timeout != 'True':
return
self.timeout = eval(self.timeout)
if not self.timeout:
self.timeout = _DEFAULT_TIMEOUT
timer = QTimer(self)
timer.timeout.connect(self.count_time)
timer.start(1000)
def count_time(self):
self.global_timer += 1
if self.global_timer > self.timeout:
self.global_timer = 0
safe_reconnect()
def close(self):
dialog = self.dialog('confirm_exit', response=True)
response = dialog.exec_()
if response == DIALOG_REPLY_YES:
self.check_empty_sale()
if self.active_weighing and self.reader_thread:
self.reader_thread.onClose()
super(FrontWindow, self).close()
def dialog(self, name, response=False, widgets=None, extra_message=None):
kind, msg = self.stack_msg[name]
if extra_message:
print(extra_message)
msg += '\n' + extra_message
# if args:
# msg = msg % args
return QuickDialog(parent=self, kind=kind, string=msg, widgets=widgets)
def set_params(self, values):
for k, v in values.items():
if v in ('False', 'True'):
v = eval(v)
setattr(self, k, v)
def action_block(self):
safe_reconnect(self)
def dialog_password_accept(self):
self.connection()
def dialog_password_rejected(self):
self.connection()
def keyReleaseEvent(self, event):
self._keyStates[event.key()] = False
def create_dialogs(self):
self.dialog_control_panel = ControlPanel(self)
self.dialog_money_count = DialogMoneyCount(self)
self.dialog_search_sales = SearchSale(self)
self.dialog_search_parties = SearchParty(self)
self.dialog_search_products = SearchProduct(self)
self.dialog_position = Position(self)
self.dialog_tip_amount = TipAmount(self)
self.dialog_delivery_amount = DeliveryAmount(self)
self.dialog_comment = Comment(self)
self.dialog_payment = DialogPayment(self)
self.dialog_voucher = DialogVoucher(self)
self.dialog_print_invoice = DialogPrintInvoice(self)
self.dialog_global_discount = DialogGlobalDiscount(self)
self.dialog_auth_discount = DialogAuthDiscounts(self)
self.dialog_fixed_discount = DialogFixedDiscounts(self)
self.dialog_fixed_discount_manual = DialogFixedDiscountsManual(self)
self.dialog_payment_term = DialogPaymentTerm(self)
self.dialog_search_sales.activate_counter()
self.dialog_product_stock = DialogStock(self.dialog_search_products)
self.dialog_order = DialogOrder(self)
self.dialog_force_assign = DialogForceAssign(self)
self.field_password_force_assign_ask.setEchoMode(QLineEdit.Password)
self.dialog_tax = DialogTaxes(self)
self.dialog_cancel_invoice = DialogCancelInvoice(self)
self.dialog_product_edit = ProductEdit(self)
self.dialog_table_delivery_party = DialogTableDeliveryParty(self)
self.dialog_delivery_party_selected = DeliveryPartySelected(self)
self.dialog_delivery_party = DialogDeliveryParty(self)
self.dialog_salesman_code = DialogSalesmanCode(self)
self.dialog_reports = DialogReports(self)
self.dialog_source = DialogSource(self)
self.dialog_split_sale = DialogSplitSale(self)
self.dialog_expenses = DialogExpenses(self)
self.dialog_info_product = DialogInfoProduct(self)
if self._commission_activated:
self.dialog_agent = DialogAgent(self)
if self.enviroment == 'restaurant' and self._sale_pos_restaurant:
self.dialog_combine_product = CombineProduct(self)
self.dialog_combo_product = DialogComboProduct(self)
self.dialog_historic_sales = DialogHistoricSales(self)
self.dialog_sale_form = DialogSaleForm(self)
self.dialog_consumer = DialogConsumer(self)
self.dialog_manage_tables = DialogManageTables(self)
def action_help(self):
Help(self).show()
def resize_window_tablet_dev(self):
self.resize(690, self.get_geometry()[1])
def load_modules(self):
self._sale_pos_restaurant = None
self.Module = FastModel('ir.module', self.ctx)
self.Config = FastModel('sale.configuration', self.ctx)
self._config, = self.Config.find([('id', '=', 1)])
self.discount_method = self._config.get('discount_pos_method')
self.allow_discount_handle = self._config.get('allow_discount_handle', None)
self.sale_automatic = False
if self.enviroment == 'retail' and self._config.get('new_sale_automatic'):
self.sale_automatic = True
self._commission_activated = self.Module.find([
('name', '=', 'commission'),
('state', '=', 'activated'),
])
# self._source = self.Module.find([
# ('name', '=', 'sale_source'),
# ('state', '=', 'activated'),
# ])
self._credit_limit_activated = self.Module.find([
('name', '=', 'account_credit_limit'),
('state', '=', 'activated'),
])
_product = {
'name': 'product.product',
'fields': [
'template.name', 'code', 'barcode', 'write_date',
'description', 'template.sale_price_w_tax',
'template.account_category'
]
}
self.cache_local = self._config.get('cache_products_local')
if self._config['show_location_pos']:
_product['fields'].append('location_')
if self._config['show_stock_pos'] in ('value', 'icon'):
if self._config['show_stock_pos'] == 'value':
_product['fields'].append('quantity')
if self._config['show_brand']:
_product['fields'].append('brand.name')
if self._config['encoded_sale_price']:
_product['fields'].extend(['image', 'image_icon', 'encoded_sale_price'])
if self.enviroment == 'restaurant':
self._sale_pos_restaurant = self.Module.find([
('name', '=', 'sale_pos_frontend_rest'),
('state', '=', 'activated'),
])
if self._sale_pos_restaurant:
self.PartyConsumer = FastModel('party.consumer', self.ctx)
if self._config['delivery_product']:
self._delivery_product = 0
self.User = FastModel('res.user', self.ctx)
self._user, = self.User.find([('login', '=', self.user)])
self.Company = FastModel('company.company', self.ctx)
self._company, = self.Company.find([('id', '=', 1)])
self.logo = self._company['logo']
if not self._user['sale_device']:
return 'user_not_permissions_device'
self.ctx['user'] = self._user['id']
self.Sale = FastModel('sale.sale', self.ctx)
self.SaleLine = FastModel('sale.line', self.ctx)
self.Product = FastModel('product.product', self.ctx)
self.Journal = FastModel('account.statement.journal', self.ctx)
self.Statement = FastModel('account.statement', self.ctx)
self.Expenses = FastModel('sale_pos.expenses_daily', self.ctx)
self.Employee = FastModel('company.employee', self.ctx)
self.Shop = FastModel('sale.delivery_party', self.ctx)
self.SaleDiscont = FastModel('sale.discount', self.ctx)
self.Device = FastModel('sale.device', self.ctx)
self.Category = FastModel('product.category', self.ctx)
self.PaymentTerm = FastModel('account.invoice.payment_term', self.ctx)
self.Party = FastModel('party.party', self.ctx)
self.DeliveryParty = FastModel('sale.delivery_party', self.ctx)
self.Taxes = FastModel('account.tax', self.ctx)
self.Discount = FastModel('sale.discount', self.ctx, fields=[
'name', 'active', 'discount', 'type_discount'
])
self.ActionReport = FastModel('ir.action.report', self.ctx)
if self._commission_activated:
self.Agent = FastModel('commission.agent', self.ctx)
self.Comission = FastModel('commission', self.ctx)
if self._sale_pos_restaurant:
self.RestTables = FastModel('sale.shop.table', self.ctx)
self.Consumer = FastModel('party.consumer', self.ctx)
self.device, = self.Device.find([
('id', '=', self._user['sale_device']['id']),
])
self.shop = self.device['shop']
self.shop_taxes = self.shop['taxes']
self.company = self.shop['company']
self._journals = self.device['journals']
self.salesman_ids = [s['id'] for s in self.shop.get('salesmans', [])]
dom_salesman = [
('company', '=', self.company['id']),
]
if self.salesman_ids:
dom_salesman.append(('id', 'in', self.salesman_ids))
self.discounts = self.Discount.find([
('type_discount', '=', 'percentage')
])
self.discounts_fixed = self.Discount.find([])
self.delivery_man_table = self.shop.get('delivery_man', [])
if self.delivery_man_table:
self.delivery_man = [d for d in self.delivery_man_table if d['active']]
self._payment_terms = self.PaymentTerm.find([
('active', '=', True)
], order=[('name', 'ASC')])
self.type_pos_user = self._context.get('type_pos_user')
if not self.type_pos_user:
return 'user_without_permission'
self.user_can_delete = self.type_pos_user in ('frontend_admin', 'cashier')
self.product_categories = self.device['shop']['product_categories']
self.salesman_required = self.device['shop']['salesman_pos_required']
self.default_party = self.shop['party']
if not self.default_party:
return 'missing_party_configuration'
self.default_journal = self.device['journal']
if not self.default_journal:
return 'missing_journal_device'
self.default_payment_term = self.shop['payment_term']
self._password_admin = self._config.get('password_admin_pos')
self._password_force_assign = self._config.get('password_force_assign')
self._action_report, = self.ActionReport.find([
('report_name', '=', 'account.invoice'),
])
if self._config['show_stock_pos'] in ('value', 'icon'):
self.stock_context = {
'stock_date_end': date.today(),
'locations': [self.shop['warehouse']['id']],
}
# if self._source:
self.Source = FastModel('sale.source', self.ctx)
self.Pricelist = FastModel('product.price_list', self.ctx)
return True
class ClearUi(QThread):
sigActionClear = pyqtSignal()
state = None
def __init__(self, wait_time):
QThread.__init__(self)
self.wait_time = wait_time
def run(self):
time.sleep(self.wait_time)
self.sigActionClear.emit()