presik_pos/app/frontwindow.py

371 lines
16 KiB
Python

import logging
import os
from datetime import date
from pathlib import Path
from PySide6.QtGui import QGuiApplication
from PySide6.QtWidgets import QLineEdit, QMainWindow
from .commons.dialogs import QuickDialog
from .constants import DIALOG_REPLY_YES, 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, DialogTestPrinter,
DialogSaleToTransfer, DialogSearchFolioTransfer,
DialogSearchSaleTransfer
)
from .proxy import Model, logout
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)
self.dialog_test_printer = DialogTestPrinter(self)
if self._commission_activated:
self.dialog_agent = DialogAgent(self)
if self._hotel_activated:
self.dialog_search_folio_transfer = DialogSearchFolioTransfer(self)
self.dialog_search_sale_transfer = DialogSearchSaleTransfer(self)
self.dialog_sale_to_transfer = DialogSaleToTransfer(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
self.Module = Model('ir.module', self.ctx, main_window=self)
module_names = [
'sale_pos_frontend_rest', 'sale_pos',
'sale_pos_frontend', 'account_credit_limit',
'product_onebarcode', 'hotel']
modules = self.Module.find([
('name', 'in', module_names),
('state', '=', 'activated'),
])
self.modules = {m['name']: m for m in modules}
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
self._onebarcode_activated = 'product_onebarcode' in self.modules
self._hotel_activated = 'hotel' in self.modules
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.Device = Model('sale.device', 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 and not self.sale_device_code:
return 'user_not_permissions_device'
if self.sale_device_code:
dom_device = ('code', '=', self.sale_device_code)
else:
dom_device = ('id', '=', sale_device)
devices = self.Device.find([dom_device])
if not devices:
return 'user_not_permissions_device'
self.device = devices[0]
shop_id = self.device['shop.']['id']
if shop_id not in self._user['shops']:
return 'user_not_permissions_device'
self.sale_device = self.device['id']
self.ctx['user'] = self._user['id']
self.ctx['sale_device'] = self.device['id']
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.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.shop = self.device['shop.']
self.shop_taxes = self.shop['taxes.']
self.company = self.shop['company']
self._journals = self.device['journals.']
self.sellers = {s['code']: s 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
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(
args=[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']],
}
if self._hotel_activated:
self.Folio = Model('hotel.folio', self.ctx, main_window=self)
self.Source = Model('sale.source', self.ctx, main_window=self)
self.Pricelist = Model('product.price_list', self.ctx, main_window=self)
return True