371 lines
16 KiB
Python
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
|