presik_pos/app/mainwindow.py

2484 lines
93 KiB
Python

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import sys
import os
import logging
from decimal import Decimal
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QDate
from .tools import get_icon, to_float, to_numeric
from .dialogs import (Help, SearchSale, SearchParty, SearchProduct, Position,
Comment, DialogPayment, DialogSalesman, DialogVoucher, DialogPrintInvoice,
DialogGlobalDiscount, DialogPaymentTerm, DialogStock, DialogOrder,
DialogForceAssign, DialogTaxes, DialogCancelInvoice, SaleLine, DialogAgent,
DialogConsumer, DialogManageTables)
from datetime import datetime, timedelta, date
from collections import OrderedDict
# from PyQt5.QtGui import QTouchEvent
from PyQt5.QtWidgets import (QLabel, QHBoxLayout, QVBoxLayout,
QWidget, QGridLayout, QLineEdit)
from app.commons.action import Action
from app.commons.forms import GridForm, ComboBox, FieldNumeric
from app.commons.messages import MessageBar
from app.commons.image import Image
from app.commons.table import TableView
from app.commons.model import TableModel, Modules
from app.commons.frontwindow import FrontWindow
from app.commons.menu_buttons import MenuDash
from .proxy import FastModel
from .localdb import LocalStore
from .reporting import Receipt
from .buttonpad import Buttonpad
from .states import STATES, RE_SIGN
from .constants import (PATH_PRINTERS, DELTA_LOCALE, STRETCH, alignRight,
alignLeft, alignCenter, alignHCenter, alignVCenter,
DIALOG_REPLY_NO, DIALOG_REPLY_YES, ZERO,
RATE_CREDIT_LIMIT, SCREENS, FILE_BANNER,
CONVERSION_DIGITS)
INVOICE_TYPE = [('', '')]
class MainWindow(FrontWindow):
def __init__(self, connection, params):
title = "PRESIK | SMART POS"
global CONNECTION
self.conn = connection
CONNECTION = connection
super(MainWindow, self).__init__(connection, params, title)
print('Screen Size: > ', self.screen_size)
_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.is_clear_right_panel = True
self.payment_ctx = {}
self.set_keys()
self.stock_context = None
self.ctx = self._context
self.ctx['params'] = params
self.label_color = 'gray'
self.label_color_2 = ''
if _theme == 'dark':
self.label_color = 'light'
self.label_color_2 = 'orange'
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_payment()
self.set_domains()
self.create_gui()
self.message_bar.load_stack(self.stack_msg)
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()
if not self.tablet_mode:
self.create_statusbar()
self.window().showMaximized()
if not self.tablet_mode:
self.grabKeyboard()
self.reader_thread = None
self._current_line_id = None
self._amount_text = ''
self._sign = None
self.create_dialogs()
self.createNewSale()
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_cache_company()
self.set_cache_products()
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 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 set_cache_company(self):
self.store = LocalStore()
self.store.create_table_config()
self._local_config = self.store.get_config()
if not self._local_config:
company_id = self.device['shop']['company']['id']
self._local_config = self.store.set_config([company_id])
def set_cache_products(self):
self.store.create_table_product()
local_products = self.store.get_local_products()
config = self.store.get_config()
_sync_date = config[1]
products = self.Product.sync_get_products(
{'write_date': _sync_date,
'shop_id': self.ctx['shop']
})
self.store.update_products(products, local_products)
now = datetime.now()
self.store.set_config_sync(str(now))
def event(self, evento):
event_type = super(MainWindow, self).event(evento)
# touch = QTouchEvent(event_type)
return event_type
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.ModSale.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 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(MainWindow, self).close()
def delete_current_sale(self):
if self._sale['id']:
self._PosSale.cancel_sale(self._sale['id'], self._context)
def resize_window_tablet_dev(self):
self.resize(690, self.get_geometry()[1])
def set_stack_messages(self):
super(MainWindow, self).set_stack_messages()
self.stack_msg.update({
'system_ready': ('info', self.tr('SYSTEM READY...')),
'confirm_exit': ('warning', self.tr('DO YOU WANT TO EXIT?')),
'confirm_credit': ('question', self.tr('PLEASE CONFIRM YOUR PAYMENT TERM AS CREDIT?')),
'sale_number_not_found': ('warning', self.tr('SALE ORDER / INVOICE NUMBER NOT FOUND!')),
'sale_closed': ('error', self.tr('THIS SALE IS CLOSED, YOU CAN NOT TO MODIFY!')),
'discount_not_valid': ('warning', self.tr('DISCOUNT VALUE IS NOT VALID!')),
'add_payment_sale_draft': ('info', self.tr('YOU CAN NOT ADD PAYMENTS TO SALE ON DRAFT STATE!')),
'enter_quantity': ('question', self.tr('ENTER QUANTITY...')),
'enter_discount': ('question', self.tr('ENTER DISCOUNT...')),
'enter_payment': ('question', self.tr('ENTER PAYMENT AMOUNT BY: %s')),
'enter_new_price': ('question', self.tr('ENTER NEW PRICE...')),
'order_successfully': ('info', self.tr('ORDER SUCCESUFULLY SENT.')),
'order_failed': ('warning', self.tr('FAILED SEND ORDER!')),
'missing_agent': ('warning', self.tr('MISSING AGENT!')),
'missing_salesman': ('warning', self.tr('THERE IS NOT SALESMAN FOR THE SALE!')),
'sale_without_products': ('warning', self.tr('YOU CAN NOT CONFIRM A SALE WITHOUT PRODUCTS!')),
'user_without_permission': ('error', self.tr('USER WITHOUT PERMISSION FOR SALE POS!')),
'quantity_not_valid': ('error', self.tr('THE QUANTITY IS NOT VALID...!')),
'user_not_permissions_device': ('error', self.tr('THE USER HAVE NOT PERMISSIONS FOR ACCESS TO DEVICE!')),
'missing_party_configuration': ('warning', self.tr('MISSING THE DEFAULT PARTY ON SHOP CONFIGURATION!')),
'missing_journal_device': ('error', self.tr('MISSING SET THE JOURNAL ON DEVICE!')),
'statement_closed': ('error', self.tr('THERE IS NOT A STATEMENT OPEN FOR THIS DEVICE!')),
'product_not_found': ('warning', self.tr('PRODUCT NOT FOUND!')),
'must_load_or_create_sale': ('warning', self.tr('FIRST YOU MUST CREATE/LOAD A SALE!')),
'new_sale': ('warning', self.tr('DO YOU WANT CREATE NEW SALE?')),
'cancel_sale': ('question', self.tr('ARE YOU WANT TO CANCEL SALE?')),
'not_permission_delete_sale': ('info', self.tr('YOU HAVE NOT PERMISSIONS FOR DELETE THIS SALE!')),
'not_permission_for_cancel': ('info', self.tr('YOU HAVE NOT PERMISSIONS FOR CANCEL THIS SALE!')),
'customer_not_credit': ('info', self.tr('THE CUSTOMER HAS NOT CREDIT!')),
'agent_not_found': ('warning', self.tr('AGENT NOT FOUND!')),
'invalid_commission': ('warning', self.tr('COMMISSION NOT VALID!')),
'credit_limit_exceed': ('info', self.tr('CREDIT LIMIT FOR CUSTOMER EXCEED!')),
'credit_limit_capacity': ('info', self.tr('THE CUSTOMER CREDIT CAPACITY IS ABOVE 80%')),
'not_can_force_assign': ('warning', self.tr('YOU CAN NOT FORCE ASSIGN!')),
'send_electronic_failed': ('info', self.tr('FALLO EL ENVIO DE FACTURA!')),
'invoice_done_failed': ('info', self.tr('FALLO FINALIZACIÓN DE FACTURA!')),
'without_stock_quantity': ('info', self.tr('PRODUCT WITHOUT STOCK: %s')),
'not_sale': ('info', self.tr('NOT SALE!...'))
})
def load_modules(self):
modules = Modules(self, self.conn)
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._commission_activated = self.Module.find([
('name', '=', 'commission'),
('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')
self._products = {}
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'])
_PosSale = {
'name': '_PosSale',
'model': 'sale.sale',
'fields': ['number', 'party', 'party.name', 'salesman', 'lines',
'position', 'total_amount_cache', 'salesman.party.name',
'payment_term', 'payment_term.name', 'invoices',
'payments', 'untaxed_amount', 'state', 'tax_amount',
'total_amount', 'residual_amount', 'paid_amount', 'invoice',
'invoice.state', 'invoice_number', 'invoice.number', 'invoices',
'delivery_charge', 'sale_date', 'invoice_type'],
'methods': (
'get_printing_context', 'cancel_sale', 'get_amounts',
'get_discount_total', 'process_sale', 'reconcile_invoice',
'post_invoice', 'get_data', 'add_value', 'faster_add_product',
'get_product_prices', 'add_payment', 'get_order2print',
'get_sale_from_invoice', 'add_tax', 'check_state', 'to_quote',
'to_draft', 'new_sale', 'on_change', 'get_salesman_in_party',
)
}
_Tables = self._Tables = None
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)
_Tables = {
'name': '_Tables',
'model': 'sale.shop.table',
'fields': ('name', 'shop', 'capacity', 'state')
}
_PosSale['fields'].extend(['table_assigned', 'table_assigned.name', 'table_assigned.state'])
if self._commission_activated:
_PosSale['fields'].extend(['agent', 'agent.party.name', 'commission'])
self.User = FastModel('res.user', self.ctx)
self._user, = self.User.find([('login', '=', self.user)])
if not self._user['sale_device']:
return 'user_not_permissions_device'
self.ctx['user'] = self._user['id']
self.ModSale = FastModel('sale.sale', self.ctx)
self.ModSaleLine = FastModel('sale.line', self.ctx)
self.Product = FastModel('product.product', self.ctx)
self.Journal = FastModel('account.statement.journal', self.ctx)
self.Employee = FastModel('company.employee', 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.Taxes = FastModel('account.tax', self.ctx)
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)
models_to_work = [_PosSale]
if _Tables:
models_to_work.append(_Tables)
modules.set_models(models_to_work)
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 = dict([(j['id'], j) for j in self.device['journals']])
self.salesman_ids = [s['id'] for s in self.shop['salesmans']] \
if self.shop.get('salesmans') else []
dom_salesman = [
('company', '=', self.company['id']),
]
if self.salesman_ids:
dom_salesman.append(('id', 'in', self.salesman_ids))
self.employees = self.Employee.find(dom_salesman)
self._payment_terms = self.PaymentTerm.get_payment_term_pos()
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._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']],
}
return True
def create_dialogs(self):
# self.create_wizard_new_sale()
self.dialog_search_sales = SearchSale(self).get()
self.dialog_search_parties = SearchParty(self).get()
self.dialog_search_products = SearchProduct(self).get()
self.dialog_position = Position(self).get('action')
self.dialog_comment = Comment(self).get('action')
self.dialog_payment = DialogPayment(self).get('selection')
self.dialog_salesman = DialogSalesman(self).get('selection')
self.dialog_voucher = DialogVoucher(self).get('action')
self.dialog_print_invoice = DialogPrintInvoice(self).get('action')
self.dialog_global_discount = DialogGlobalDiscount(self).get('action')
self.dialog_payment_term = DialogPaymentTerm(self).get('selection')
self.dialog_search_sales.activate_counter()
self.dialog_product_stock = DialogStock(self.dialog_search_products).get('selection')
self.dialog_order = DialogOrder(self).get('action')
self.dialog_force_assign = DialogForceAssign(self).get('action')
self.field_password_force_assign_ask.setEchoMode(QLineEdit.Password)
self.dialog_tax = DialogTaxes(self).get('selection')
self.dialog_cancel_invoice = DialogCancelInvoice(self).get('action')
self.dialog_product_edit = SaleLine(self).get('action')
if self._commission_activated:
self.dialog_agent = DialogAgent(self).get('action')
if self.enviroment == 'restaurant' and self._sale_pos_restaurant:
self.dialog_search_consumer = DialogConsumer(self).get('action')
self.dialog_manage_tables = DialogManageTables(self).get('action')
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._PosSale.get_printing_context(
[self.device['id']], self.user, self._context)
ctx_printing['row_characters'] = self.row_characters
ctx_printing['delta_locale'] = DELTA_LOCALE
self.receipt_sale = Receipt(ctx_printing)
# 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.createNewSale()
def button_send_to_pay_pressed(self):
# Return sale to draft state
if not self._check_quantity():
return
self._PosSale.to_quote(self._sale['id'], self._context)
if self.model_sale_lines.rowCount() > 0:
if self.check_salesman():
self.state_disabled()
def button_to_draft_pressed(self):
# Return sale to draft state
if hasattr(self, '_sale'):
self._PosSale.to_draft(self._sale['id'], self._context)
self.state_disabled()
def create_gui(self):
panels = QHBoxLayout()
panel_left = QVBoxLayout()
panel_right = QVBoxLayout()
left_head = QHBoxLayout()
left_table = None
left_bottom = QHBoxLayout()
self.message_bar = MessageBar()
self.label_input = QLabel()
self.label_input.setFocus()
self.label_input.setObjectName('label_input')
if self.enviroment == 'restaurant':
values = self.get_product_by_categories()
menu_dash = MenuDash(self, values, 'on_selected_item')
if not self.tablet_mode:
_label_type_invoice = QLabel(self.tr(' TYPE INVOICE:'))
_label_type_invoice.setObjectName('label_invoice')
_label_type_invoice.setAlignment(alignRight | alignVCenter)
self.field_amount = FieldNumeric(self, 'amount', {})
self.field_amount.setObjectName('field_amount')
self.field_sign = QLabel(' ')
self.field_sign.setObjectName('field_sign')
layout_message = QGridLayout()
layout_message.setColumnStretch(0, 1)
layout_message.addLayout(self.message_bar, 0, 0, 2, 0)
INVOICE_TYPE.append(('P', ('POS')))
if self.shop.get('credit_note_electronic_authorization'):
INVOICE_TYPE.append(('91', ('NOTA CREDITO ELECTRONICA')))
if self.shop.get('debit_note_electronic_authorization'):
INVOICE_TYPE.append(('92', ('NOTA DEBITO ELECTRONICA')))
if self.shop.get('manual_authorization'):
INVOICE_TYPE.append(('M', 'MANUAL'))
if self.shop.get('computer_authorization'):
INVOICE_TYPE.append(('C', ('COMPUTADOR')))
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'
})
if not self.tablet_mode:
layout_message.addWidget(self.label_input, 2, 0)
layout_message.addWidget(_label_type_invoice, 2, 1)
layout_message.addWidget(self.field_invoice_type, 2, 2)
else:
layout_message.addWidget(self.label_input, 2, 0, 1, 2)
layout_message.addWidget(self.field_invoice_type, 2, 3)
left_head.addLayout(layout_message, 0)
left_head.addWidget(self.field_sign, 0)
left_head.addWidget(self.field_amount, 0)
info_fields = [
('party', {
'name': self.tr('CUSTOMER'),
'readonly': True,
'placeholder': False,
'size': self.screen_size,
'color': self.label_color
}),
('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
}),
('order_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': self.tablet_mode,
'placeholder': False,
'size': self.screen_size,
'color': self.label_color
}),
]
self.field_state = QLineEdit('STATE')
self.field_state.setReadOnly(True)
self.field_state.setObjectName('field_state')
if self.tablet_mode or 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 not self.tablet_mode \
and self._config['show_agent_pos']:
info_fields.append(('agent', {
'name': self.tr('AGENT'),
'placeholder': self.tablet_mode,
'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.enviroment == 'restaurant' and self._sale_pos_restaurant:
info_fields.append(
('delivery_men', {
'name': self.tr('DELIVERY MEN'),
'placeholder': False,
'size': self.screen_size,
'color': self.label_color
}))
info_fields.append(
('delivery_time', {
'name': self.tr('DELIVERY TIME'),
'placeholder': False,
'size': self.screen_size,
'color': self.label_color
}))
info_fields.append(
('delivery_way', {
'name': self.tr('DELIVERY WAY'),
'placeholder': False,
'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
}))
self.grid_info = GridForm(self, OrderedDict(info_fields), col=_cols)
col_sizes_tlines = [field['width'] for field in self.fields_sale_line]
left_table = TableView('model_sale_lines', self.model_sale_lines,
col_sizes_tlines, method_selected_row=self.sale_line_selected)
self.table_sale_lines = left_table
for i, f in enumerate(self.model_sale_lines._fields, 0):
if f.get('invisible'):
self.table_sale_lines.hideColumn(i)
_fields_amounts = [
('untaxed_amount', {
'name': self.tr('SUBTOTAL'),
'readonly': True,
'type': 'money',
'size': self.screen_size,
'color': self.label_color
}),
('taxes_amount', {
'name': self.tr('TAXES'),
'readonly': True,
'type': 'money',
'size': self.screen_size,
'color': self.label_color
}),
('discount', {
'name': self.tr('DISCOUNT'),
'readonly': True,
'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': self.label_color
}),
('paid', {
'name': self.tr('PAID'),
'readonly': True,
'type': 'money',
'size': self.screen_size,
'color': self.label_color
}),
('pending', {
'name': self.tr('PENDIENTE'),
'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)
_other_fields = [
('invoice', {
'name': self.tr('INVOICE'),
'placeholder': False,
'size': self.screen_size,
'color': self.label_color
}),
('state', {
'name': self.tr('STATE'),
'readonly': True,
'placeholder': False,
'size': self.screen_size,
'color': self.label_color
}),
]
other_fields = OrderedDict(_other_fields)
self.grid_other_fields = GridForm(self, other_fields, col=2)
self.buttonpad = Buttonpad(self)
self.pixmap_pos = Image(self, 'pixmap_pos', FILE_BANNER)
self.table_payment = TableView('table_payment', self.table_payment_lines,
[250, STRETCH])
panel_left.addLayout(left_head, 0)
panel_left.addWidget(left_table, 1)
panel_right.addWidget(self.pixmap_pos, 0)
left_bottom.addLayout(self.grid_info, 1)
if self.enviroment == 'restaurant':
panel_left.addLayout(self.buttonpad.functions, 1)
panel_right.addLayout(menu_dash, 1)
panel_right.addLayout(self.grid_amounts, 0)
panel_right.addLayout(self.buttonpad.stacked, 0)
else:
panel_right.addLayout(self.grid_amounts, 1)
panel_right.addLayout(self.buttonpad.functions, 1)
panel_right.addLayout(self.buttonpad.stacked, 0)
panel_right.addLayout(self.grid_other_fields, 1)
panel_right.addWidget(self.table_payment)
panel_left.addLayout(left_bottom, 0)
panels.addLayout(panel_left, 1)
panels.addLayout(panel_right, 0)
widget = QWidget()
widget.setLayout(panels)
self.setCentralWidget(widget)
def create_statusbar(self):
values = OrderedDict([
('stb_shop', {'name': self.tr('SHOP'), 'value': self.shop['name']}),
('stb_device', {'name': self.tr('DEVICE'), 'value': self.device['name']}),
('stb_database', {'name': self.tr('DATABASE'), 'value': self.database}),
('stb_user', {'name': self.tr('USER'), 'value': self.user}),
('stb_printer', {'name': self.tr('PRINTER'), 'value': self.printer_sale_name})
])
self.set_statusbar(values)
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 == 'cash':
is_paid = self._process_pay(self.field_amount.text())
if not is_paid:
self.clear_input_text()
self.clear_amount_text()
return
else:
logging.warning('Unknown command/text')
self._clear_context(error)
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') 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 = self._sale_line['product']
if _product and _product.get('quantity'):
if not self._check_stock_quantity(_product, quantity):
return
if self._current_line_id:
rec = self.ModSaleLine.faster_set_quantity({
'id': self._current_line_id,
'quantity': float(quantity)
})
except:
return self.message_bar.set('quantity_not_valid')
self.message_bar.set('system_ready')
self.model_sale_lines.update_record(rec)
self.update_total_amount()
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.ModSaleLine.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.update_total_amount()
return True
def _process_pay(self, text):
if not self.validate_done_sale():
return
val = Decimal(text.replace(',', ''))
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']
if residual_amount < 0:
# The sale is paid
self._done_sale()
return True
change = cash_received - residual_amount
if residual_amount >= cash_received:
amount_to_add = cash_received
else:
amount_to_add = residual_amount
all_money = cash_received + self._sale['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:
self.field_pending.setText(abs(change))
else:
self.field_pending.setText(str(ZERO))
self.set_amount_received(all_money)
if res['residual_amount'] < 0:
self._done_sale()
return True
self.field_journal_id = self.default_journal['id']
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'])
self.field_change.setText(change)
self._sale.update({
'residual_amount': res['residual_amount']
})
residual_amount = self._sale['residual_amount']
if self._sale['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._sale['id']:
res = self.ModSale.get_discount_total({
'sale_id': self._sale['id']
})
self.field_discount.setText(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.ModSale.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.sale_to_post['is_credit']:
return
self.ModSale.reconcile_invoice({
'sale_id': self.sale_to_post['id']
})
self.set_state('finished')
def _done_sale(self, is_credit=False):
self._sale['is_credit'] = is_credit
self.sale_to_post = self._sale
self.do_invoice.start()
if self._Tables and self._sale.get('table_assigned'):
self._Tables.write([self._sale['table_assigned']],
{'state': 'available'})
try:
if self.print_receipt == 'automatic':
_copies = self.device['shop']['invoice_copies']
if not is_credit:
self.print_invoice(copies=_copies)
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'])
if self.type_pos_user not in ('cashier', 'order') and self._config.get('new_sale_automatic'):
self.createNewSale()
else:
self.state_disabled()
return True
def print_invoice(self, sale_id=None, copies=1):
if not sale_id:
sale_id = self._sale['id']
data = self._PosSale.get_data(sale_id, self._context)
for i in range(copies):
self.receipt_sale.print_sale(data)
def button_accept_pressed(self):
if not self._check_quantity():
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.ModSale.faster_process({'sale_id': sale_id})
if msg:
self.message_bar.set(msg)
return
self.set_amounts(res)
self.field_invoice.setText(res['invoice_number'])
self.field_amount.zero()
if self.type_pos_user == 'salesman':
self.print_invoice(sale_id)
res = self._print_order(sale_id, 'delivery')
self.createNewSale()
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('cash')
self.buttonpad.setFocus()
self.label_input.setFocus()
def action_reservations(self):
logging.info('Buscando reservas.....')
def action_tables(self):
self.dialog_manage_tables.exec_()
def action_tip(self):
if self._config['tip_product'] and self._config['tip_rate']:
total_amount = int(self._get_total_amount())
self.add_product(code=self._config['tip_product']['code'])
self.button_plus_pressed()
eval_value = int((self._config['tip_rate'] / 100) * total_amount)
self.ModSaleLine.write(
[self._current_line_id], {'unit_price': Decimal(eval_value)}
)
self._PosSale.write([self._sale['id']], {'tip': Decimal(eval_value)})
self.update_total_amount()
def action_salesman(self):
if self._state in ['cash']:
return
self.dialog_salesman.exec_()
def action_tax(self):
self.dialog_tax.exec_()
def action_payment(self):
if self._state != 'cash':
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):
is_credit = self._payment_terms[str(self.field_payment_term_id)]['is_credit']
party, = self.Party.find([('id', '=', self.party_id)])
if is_credit:
if self.party_id == self.default_party['id']:
self.dialog('customer_not_credit')
return False
if self._credit_limit_activated:
if is_credit and not party['credit_limit_amount']:
self.dialog('customer_not_credit')
return False
self._credit_amount = self.ModSale.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._PosSale.write([self._sale['id']], {'payment_term': self.field_payment_term_id})
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_journal_selection_changed(self):
self.message_bar.set('enter_payment', self.field_journal_name)
def action_salesman_selection_changed(self):
self._PosSale.write([self._sale['id']], {'salesman': self.field_salesman_id})
def action_delivery_charge_selection_changed(self, index):
val = self.field_delivery_charge.get_id()
if val:
self._PosSale.write([self._sale['id']], {'delivery_charge': val})
def action_invoice_type_selection_changed(self, index):
val = self.field_invoice_type.get_id()
if val:
self._PosSale.write([self._sale['id']], {'invoice_type': val})
def action_tax_selection_changed(self):
res = self._PosSale.add_tax(self._sale['id'], self.field_tax_id,
self._context)
self._sale.update(res)
self.set_amounts()
def action_consumer(self):
self.dialog_search_consumer.clear_dialog()
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_order_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 = {}
if number:
if type_doc == 'order':
sales = self.ModSale.find([('number', '=', number)])
if sales:
sale = sales[0]
else:
sale = self._PosSale.get_sale_from_invoice([1], number,
self._context)
if not sale:
return self.message_bar.set('sale_number_not_found')
sale_id = sale['id']
else:
sale_id = self._sale['id']
if printer_id == '1':
self.print_invoice(sale_id)
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_ask.text()
if comment:
self._PosSale.write([self._sale['id']], {'comment': comment})
def action_position(self):
self.dialog_position.exec_()
position = self.field_position_ask.text()
if hasattr(self, 'field_position') and position:
self.field_position.setText(position)
self._PosSale.write([self._sale['id']], {'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.ModSale.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._PosSale.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():
if self.model_sale_lines.rowCount() > 0:
lines = [line['id'] for line in self.model_sale_lines._data]
res = self.set_discount(int(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:
orders = self._PosSale.get_order2print(sale_id, reversion, False, self._context)
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 = 'delivery'
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)
# try:
# orders = self._PosSale.get_order2print(sale_id, reversion,
# False, self._context)
# result = self.receipt_order.print_orders(orders, reversion, kind)
# print(result, orders)
# except:
# print('Error: printing order fail!')
if result:
# Show dialog if send sale order was successful
self.dialog('order_successfully')
else:
self.dialog('order_failed')
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.createNewSale()
if self.enviroment == 'restaurant':
self.wizard_new_sale()
def wizard_new_sale(self):
# self.action_position()
# self.action_salesman()
pass
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 == 'finished':
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 == 'cash' 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._PosSale.cancel_sale(self._sale['id'], self._context)
self.field_password_for_cancel_ask.setText('')
self.set_state('cancel')
self.clear_right_panel()
self.createNewSale()
def action_search_product(self):
if self._state == 'cash':
return
self.dialog_search_products.show()
def action_search_sale(self):
if self._state in ['cash']:
return
delta = str(datetime.now() - timedelta(4))
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),
]
sales = self.ModSale.find(dom, 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.ModSale.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.grabKeyboard()
def on_selected_party(self):
party_id = self.dialog_search_parties.get_id()
if not party_id:
return
party, = self.Party.find([('id', '=', party_id)])
values = {
'party': party_id,
'invoice_address': party['addresses'][0]['id'],
'shipment_address': party['addresses'][0]['id'],
}
payment_term = party.get('customer_payment_term')
if payment_term:
values['payment_term'] = payment_term['id']
self.field_payment_term.setText(str(payment_term['name']))
self.field_payment_term_id = payment_term['id']
else:
values['payment_term'] = self.default_payment_term['id']
self.field_payment_term_id = self.default_payment_term['id']
self.field_payment_term.setText(self.default_payment_term['name'])
self._PosSale.write([self._sale['id']], values)
self.party_id = party_id
self.field_party.setText(party['name'])
if party.get('salesman'):
self.field_salesman_id = party['salesman']['id']
self._PosSale.write([self._sale['id']], {'salesman': self.field_salesman_id})
self.field_salesman.setText(party['salesman']['name'])
# if self._credit_limit_activated:
# self._check_credit_capacity(party)
self.message_bar.set('system_ready')
self.setFocus()
self.label_input.setFocus()
self.grabKeyboard()
def load_sale(self, sale_id):
# loads only draft sales
self._products = {}
self.is_clear_right_panel = True
self.clear_data()
self.clear_left_panel()
self.clear_right_panel()
sale, = self.ModSale.find([('id', '=', sale_id)])
self._sale.update(sale)
self.table_payment_lines.reset()
self.field_order_number.setText(sale['number'] or '')
self.field_state.setText(sale['state'] or '')
self._set_sale_date()
if hasattr(self, 'field_position'):
self.field_position.setText(sale['position'] or '')
if sale.get('payment_term'):
self.field_payment_term_id = sale['payment_term']['id']
self.field_payment_term.setText(sale['payment_term']['name'] or '')
if sale.get('salesman'):
self.field_salesman.setText(sale['salesman']['name'] or '')
self.field_salesman_id = sale['salesman']['id']
res = self.ModSale.get_invoice_type({'sale_id': sale_id})
if res:
self.field_invoice_type.set_from_id(res['invoice_type'])
if sale.get('invoice_number'):
self.field_invoice.setText(sale['invoice_number'] or '')
else:
self.field_invoice.setText('')
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 '')
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.ModSaleLine.find([
('id', 'in', self.line_ids),
])
sale['lines'] = lines
for line in lines:
self.add_sale_line(line)
# if line.get('product'):
# self._products[line['product']['id']] = line['product']
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.field_party.setText(sale['party']['name'])
self.set_amounts(sale)
self.set_amount_received()
self.field_amount.zero()
if self.type_pos_user in ('cashier', 'order', 'salesman'):
self.table_sale_lines.setEnabled(True)
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):
residual_amount = self._sale['residual_amount']
if cash_received:
amount = cash_received
else:
amount = self._sale['paid_amount']
self.field_pending.setText(residual_amount)
self.field_paid.setText(amount)
def update_total_amount(self):
self.set_amounts()
def set_amounts(self, res=None):
if not res:
res = self._PosSale.get_amounts([self._sale['id']], self._context)
self._sale.update(res)
residual_amount = 0
if res.get('residual_amount'):
residual_amount = res['residual_amount']
self.field_pending.setText(residual_amount)
self.field_untaxed_amount.setText(res['untaxed_amount'])
self.field_taxes_amount.setText(res['tax_amount'])
self.field_total_amount.setText(res['total_amount'])
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 [
[r['id'], r['code'], r['name'], r['template']['sale_price_w_tax']] for r in 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'])
cat['items'] = self._get_products_by_category(cat['id'])
return self.allow_categories
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(product=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(self, product_id):
if product_id:
self.clear_right_panel()
self.add_product(id=product_id)
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),
]
for tw in target_words:
if len(tw) <= 1:
continue
clause = ['OR',
('template.name', 'ilike', '%{:}%'.format(tw)),
('description', 'ilike', '%{:}%'.format(tw))]
domain.append(clause)
if self.shop.get('product_categories'):
categories_id = [ct['id'] for ct in self.shop['product_categories']]
domain.append(('template.account_category', 'in', categories_id))
if not domain:
return
if self.cache_local:
products = self.store.find_product_elastic(domain, limit=100)
else:
products = self.Product.find(domain, 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)
parties = self.Party.find(domain)
self.dialog_search_parties.set_from_values(parties)
def clear_data(self):
self._sale = {'total_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']
def clear_left_panel(self):
# self.message_bar.set('system_ready')
self.field_party.setText('')
self.field_salesman.setText('')
self.field_salesman_id = None
self.field_invoice_type.set_from_id('')
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_date.setText('')
self.field_global_discount_ask.setText('')
self.field_amount.zero()
self.field_order_number.setText('')
self.field_state.setText('')
self.current_comment = ''
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_ask'):
# self.field_comment_ask.document().clear()
pass
if hasattr(self, 'field_points'):
self.field_points.setText('')
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('')
if hasattr(self, 'field_position'):
self.field_position.setText('')
self.field_position_ask.setText('')
self.model_sale_lines.reset()
self.clear_input_text()
self.clear_amount_text()
def clear_right_panel(self):
if self.is_clear_right_panel:
return
self.field_invoice.setText('')
self.field_untaxed_amount.zero()
self.field_taxes_amount.zero()
self.field_total_amount.zero()
self.field_change.zero()
self.field_paid.zero()
self.field_discount.zero()
self.field_pending.zero()
self.table_payment_lines.reset()
self.is_clear_right_panel = True
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 createNewSale(self):
self._products = {}
if self.enviroment == 'restaurant' and self._sale_pos_restaurant:
self.dialog_search_consumer.clear_dialog()
self.check_empty_sale()
if self.type_pos_user == 'cashier':
self.message_bar.set('not_sale')
self.state_disabled()
return
self.set_state('add')
self.input_text_changed('')
self.amount_text_changed('0')
self.clear_sign()
self.global_timer = 0
self.payment_ctx = {}
self.is_clear_right_panel = False
self.table_sale_lines.setEnabled(True)
self.field_invoice_type.set_enabled(True)
self.clear_data()
self.clear_left_panel()
self.message_bar.set('system_ready')
self._sale = self._PosSale.new_sale([], {
'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']
}, self._context)
self.field_party.setText(self._sale['party_name'])
self.field_invoice_type.set_from_id(self._sale['invoice_type'])
self.field_state.setText(self._sale['state'])
# FIXME ADD MORE
self._sale.update({
'total_amount': 0
})
self.party_id = self.default_party['id']
if self._sale.get('id'):
self._set_sale_date()
self.field_order_number.setText(self._sale['number'])
if self.field_delivery_charge:
self.field_delivery_charge.set_enabled(True)
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_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:
products = self.store.find_product_elastic(domain, limit=100)
else:
products = self.Product.find(domain, ctx=self.stock_context)
# products = self.Product.find(domain)
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_prod in self._products.values():
if not self._check_stock_quantity(line_prod):
return False
return True
def check_salesman(self):
if self.salesman_required and not self.field_salesman_id:
dialog = self.dialog('missing_salesman')
dialog.exec_()
return False
return True
def add_product(self, id=None, code=None, product=None):
if self._state == 'disabled':
self.message_bar.set('must_load_or_create_sale')
return
product_id = None
if id:
product_id = 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
}
res = self.ModSale.faster_add_product(data)
self._sale_line = res
self._current_line_id = res['id']
self.add_sale_line(res)
self._sale_line['product'] = product
self._products[product['id']] = product
self.update_total_amount()
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_admin:
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_admin:
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']
rec = self.model_sale_lines.add_record(record)
self.field_amount.setText(rec['amount_w_tax'])
def sale_line_selected(self, product):
if self._state == 'cash':
return
self._current_line_id = product['id']
self.label_product.setText(product['product.template.name'])
self.row_field_description.setText(product['description'])
self.row_field_qty.setValue(float(product['quantity']))
self.row_field_price.setText(str(product['unit_price_w_tax']))
# self.row_field_note.setText(str(product['note']))
self.dialog_product_edit.show()
self.row_field_note.setFocus()
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': '{:5,.1f}',
'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
}
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._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)
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_delete_line(self):
if self.model_sale_lines.rowCount() <= 0 or self._state == 'cash':
return
self.table_sale_lines.setFocus()
removed_item = self.table_sale_lines.delete_item()
"""Delete product """
product = removed_item['product']
try:
if isinstance(product, dict):
del self._products[product['id']]
if isinstance(product, int):
del self._products[product]
except:
print('error')
self.ModSaleLine.delete([removed_item['id']])
self.set_amounts()
self.update_total_amount()
# self.clear_right_panel()
self._current_line_id = None
self.setFocus()
self.label_input.setFocus()
if self.enviroment == 'restaurant':
if removed_item and self.print_order:
self.action_print_order(self._sale['id'], removed_item)
if self._config['tip_product']['code'] == removed_item['product.code']:
self._PosSale.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.ModSaleLine.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.ModSaleLine.set_faster_unit_price({
'id': self._current_line_id,
'value': value,
})
if rec:
self.model_sale_lines.update_record(rec)
self.update_total_amount()
return True
return False
def add_payment(self, amount, cash_received=0, change=0):
voucher_number = None
if self._journals[self.field_journal_id]['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.ModSale.faster_add_payment({
'sale_id': self._sale['id'],
'journal_id': self.field_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
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.buttonpad.stacked.stacked.currentWidget():
return
if state['button']:
self.buttonpad.stacked.stacked.setCurrentWidget(
getattr(self.buttonpad.stacked, state['button'])
)
if not self.tablet_mode:
self.buttonpad.stacked.stacked.currentWidget().setVisible(True)
else:
self.buttonpad.stacked.stacked.currentWidget().setVisible(False)
def key_pressed(self, text):
if not self._sign and self._state != 'cash':
if self._re.match(self._input_text + text):
self.input_text_changed(text)
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 == 'cash':
self._amount_text = self._amount_text[:-1]
self.amount_text_changed()
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 == 'cash' 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']:
self._clear_context()
# self.close()
elif key == Qt.Key_F1:
help = Help(self).show()
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']:
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_Delete:
self.action_delete_line()
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']:
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.ModSale.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('quantity'):
quantity = self.state_line.pop('quantity')
self._process_quantity(str(quantity))
_record = self.ModSaleLine.faster_set_quantity({
'id': self._current_line_id,
'quantity': to_float(quantity, 2)
})
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.ModSaleLine.write([self._current_line_id], {})
if self.state_line.get('description'):
_record = self.ModSaleLine.write([self._current_line_id], {
'description': self.state_line['description']
})
if self.state_line.get('note'):
_record = self.ModSaleLine.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.update_total_amount()
self.state_line = {}
def dialog_search_consumer_accepted(self):
if not self.state_consumer:
return
if self._consumer:
res = self.ModSale.update_consumer({
'id': self._consumer['id'],
'fields': self.state_consumer,
})
if res['msg'] != 'ok':
print('error')
else:
res = self.ModSale.create_consumer({
'fields': self.state_consumer,
})
if res['msg'] != 'ok':
print('error')
def update_consumer_data(self, field=''):
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()
else:
self._consumer = consumers[0]
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'])
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, id, name, prev_state, new_state):
table_assigned = id
if self._sale.get('table_assigned') != id and prev_state == 'occupied':
return False
if self._sale.get('table_assigned') == id and new_state == 'available':
name = ''
table_assigned = None
self._sale['table_assigned'] = table_assigned
self._sale['table_assigned.state'] = new_state
self._Tables.write([id], {'state': new_state})
self._PosSale.write([self._sale['id']], {'table_assigned': table_assigned})
self.field_table_assigned.setText(name)
return True
def clear_dialog(self):
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.currentDate())
# def print_equivalent_invoice(self, sale_id):
# sale, = self.ModSale.find([('id', '=', sale_id)])
# if not sale['invoices']:
# return
#
# invoice_id = sale['invoices'][0]
# commissions = self._Commission.find([
# ('origin', '=', 'account.invoice,' + str(invoice_id))
# ])
#
# # if not commissions:
# # return
# # commission = commissions[0]
# # if not commission['invoice_line.invoice']:
# # return
# #
# # model = u'account.invoice'
# # data = {
# # 'model': model,
# # 'action_id': self._action_report_equivalent['id'],
# # 'id': commission['invoice_line.invoice'],
# # 'ids': [commission['invoice_line.invoice']],
# # }
# # 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)
class DoInvoice(QThread):
"""
Process invoices using a thread
"""
sigDoInvoice = pyqtSignal()
def __init__(self, main, context):
QThread.__init__(self)
def run(self):
self.sigDoInvoice.emit()