presik_pos/app/frontwindow.py

372 lines
16 KiB
Python

import os
import time
from datetime import date
import logging
from pathlib import Path
from PySide6.QtWidgets import QMainWindow, QLineEdit
from PySide6.QtGui import QGuiApplication
from .commons.dialogs import QuickDialog
# from .commons.dblogin import safe_reconnect
from .proxy import Model, logout
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, DialogAdvance,
DialogDeleteProduct, DialogCollection
)
from .constants import DIALOG_REPLY_YES
from .version import __version__
__all__ = ['FrontWindow']
parent = Path(__file__).parent
file_base_css = os.path.join(str(parent), 'css', 'base.css')
_DEFAULT_TIMEOUT = 60000 # on ms (100 minutes)
logger = logging.getLogger(__name__)
class FrontWindow(QMainWindow):
def __init__(self, context, 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.set_params(params)
"""
We need get the size of screen (display)
--------------- -------------------
name width (px)
--------------- -------------------
small screen =< 1024
medium screen > 1024 and =< 1366
large screen > 1366
"""
screen = QGuiApplication.primaryScreen().size()
# 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'
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 = QGuiApplication.primaryScreen().size()
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 closeEvent(self, event):
dialog = self.dialog('confirm_exit', response=True)
response = dialog.exec_()
if response == DIALOG_REPLY_YES:
# self.check_empty_sale() This function cancels sale if it has not number
logout(self.ctx)
if self.active_weighing and self.reader_thread:
self.reader_thread.onClose()
super(FrontWindow, self).close()
else:
event.ignore()
def dialog(self, name, response=False, widgets=None, extra_message=None):
kind, msg = self.stack_msg[name]
if extra_message:
msg += '\n' + extra_message
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 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_delete_product = DialogDeleteProduct(self)
self.dialog_advance = DialogAdvance(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.environment == '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)
else:
self.dialog_collection = DialogCollection(self)
def action_help(self):
Help(self).show()
def resize_window_tablet_dev(self):
self.resize(690, self.get_geometry()[1])
def get_allow_categories_ids(self):
allow_cat = []
allow_cat_append = allow_cat.append
allow_cat_extend = allow_cat.extend
for pc in self.product_categories:
allow_cat_append(pc['id'])
allow_cat_extend(pc['childs'])
return allow_cat
def load_modules(self):
self._sale_pos_restaurant = None
time1 = time.time()
self.Module = Model('ir.module', self.ctx, main_window=self)
module_names = [
'sale_pos_frontend_rest', 'sale_pos',
'sale_pos_frontend', 'account_credit_limit']
modules = self.Module.find([
('name', 'in', module_names),
('state', '=', 'activated'),
])
self.modules = {m['name']: m for m in modules}
print(time.time() - time1, 'final')
self.Config = Model('sale.configuration', self.ctx, main_window=self)
self.Sale = Model('sale.sale', self.ctx, main_window=self)
self._config, = self.Config.find([('id', '=', 1)])
if not isinstance(self._config, dict):
fields = [
'tip_product.code', 'show_description_pos',
'show_position_pos', 'show_stock_pos', 'password_force_assign',
'tip_rate', 'show_agent_pos', 'discount_pos_method', 'show_brand',
'show_location_pos', 'show_delivery_charge', 'use_price_list',
'decimals_digits_quantity', 'password_admin_pos', 'show_fractions',
'new_sale_automatic', 'show_product_image',
'encoded_sale_price',
'delivery_product.list_price', 'delivery_product.code',
'delivery_product.name', 'allow_discount_handle',
'cache_products_local', 'show_party_categories',
'print_lines_product', 'uvt_pos'
]
self._config, = self.Config.find([('id', '=', 1)], fields=fields)
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.environment == 'retail' and self._config.get('new_sale_automatic'):
self.sale_automatic = True
res = self.Sale.fields_get(['commission'])
self._commission_activated = True if res.get('commission') else False
self._credit_limit_activated = 'account_credit_limit' in self.modules
# _product = {
# 'name': 'product.product',
# 'fields': [
# 'template.name', 'code', '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('template.brand.name')
# if self._config['encoded_sale_price']:
# _product['fields'].extend(
# ['image', 'image_icon', 'encoded_sale_price'])
self.User = Model('res.user', self.ctx, main_window=self)
self._user, = self.User.find([('login', '=', self.user)])
self.Company = Model('company.company', self.ctx, main_window=self)
self._company, = self.Company.find([('id', '=', 1)])
self.logo = self._company['logo']
sale_device = self._user['sale_device']
if not sale_device:
return 'user_not_permissions_device'
self.ctx['user'] = self._user['id']
self.ctx['sale_device'] = sale_device
self.ctx['shop'] = self._user['shop']
self.SaleLine = Model('sale.line', self.ctx, main_window=self)
self.Product = Model('product.product', self.ctx, main_window=self)
self.Journal = Model('account.statement.journal', self.ctx, main_window=self)
self.Statement = Model('account.statement', self.ctx, main_window=self)
self.Expenses = Model('sale_pos.expenses_daily', self.ctx, main_window=self)
self.Employee = Model('company.employee', self.ctx, main_window=self)
self.Shop = Model('sale.delivery_party', self.ctx, main_window=self)
self.SaleDiscont = Model('sale.discount', self.ctx, main_window=self)
self.Device = Model('sale.device', self.ctx, main_window=self)
self.Category = Model('product.category', self.ctx, main_window=self)
self.PaymentTerm = Model('account.invoice.payment_term', self.ctx, main_window=self)
self.Party = Model('party.party', self.ctx, main_window=self)
self.DeliveryParty = Model('sale.delivery_party', self.ctx, main_window=self)
self.Taxes = Model('account.tax', self.ctx, main_window=self)
self.Discount = Model('sale.discount', self.ctx, fields=[
'name', 'active', 'discount', 'type_discount'
], main_window=self)
self.ActionReport = Model('ir.action.report', self.ctx, main_window=self)
if self._commission_activated:
self.Agent = Model('commission.agent', self.ctx, main_window=self)
self.Comission = Model('commission', self.ctx, main_window=self)
self.device, = self.Device.find([
('id', '=', self._user['sale_device']),
])
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),
# ]
# 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.discounts = [dsc for dsc in self.discounts_fixed if dsc['type_discount'] == 'percentage']
self.delivery_man_table = self.shop.get('delivery_man.', [])
if self.delivery_man_table:
self.delivery_man_table = [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._user.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.shop['product_categories.']
self.allow_categories_ids = self.get_allow_categories_ids()
self.salesman_required = self.shop['salesman_pos_required']
self.default_party = self.shop['party.']
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')
if self.environment == 'restaurant':
self._sale_pos_restaurant = 'sale_pos_frontend_rest' in self.modules
print(self._sale_pos_restaurant, 'validate rest')
if self._sale_pos_restaurant:
self.RestTables = Model('sale.shop.table', self.ctx, main_window=self)
self.Consumer = Model('party.consumer', self.ctx, main_window=self)
self.printers_shop, self.products_printers = self.Sale.get_product_printers(
self.shop['id'])
self._action_report_invoice, = self.ActionReport.find([
('report_name', '=', 'account.invoice'),
])
self._action_report_invoice_e, = self.ActionReport.find([
('report_name', '=', 'electronic_invoice_co.invoice_face'),
])
self._action_report_sale = self.ActionReport.find([
('report_name', '=', 'sale.sale'),
])
if self._config['show_stock_pos'] in ('value', 'icon'):
self.stock_context = {
'stock_date_end': date.today().strftime("%Y-%m-%d"),
'locations': [self.shop['warehouse']],
}
self.Source = Model('sale.source', self.ctx, main_window=self)
self.Pricelist = Model('product.price_list', self.ctx, main_window=self)
return True