# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from __future__ import unicode_literals from datetime import date, datetime, timedelta from sql import Table from trytond.pool import PoolMeta, Pool from trytond.model import fields, ModelSQL, ModelView from trytond.modules.product import price_digits from trytond.pyson import Eval from trytond.transaction import Transaction from trytond.wizard import ( Wizard, StateView, Button, StateReport ) from operator import attrgetter from decimal import Decimal from trytond.report import Report from trytond.i18n import gettext from .exceptions import (PayValidationError, ProductionValidationWarning, DeleteSaleError) from trytond.modules.sale_pos_frontend.sale import SaleSquareBox KIND = [ ('', ''), ('take_away', 'Take Away'), ('delivery', 'Delivery'), ('to_table', 'To Table') ] OPTIONS_STATUS = [ ('', ''), ('draft', 'Draft'), ('requested', 'Requested'), ('commanded', 'Commanded'), ('in_preparation', 'In Preparation'), ('dispatched', 'Dispatched'), ('delivered', 'Delivered'), ('rejected', 'Rejected'), ('cancelled', 'Cancelled'), ] class SaleMove(ModelSQL): "Sale - Stock Move" __name__ = "sale.sale-stock.move" _table = 'sale_sale-stock_move_rel' sale = fields.Many2One('sale.sale', 'Sale', ondelete='CASCADE', select=True, required=True) move = fields.Many2One('stock.move', 'Stock Move', ondelete='CASCADE', select=True, required=True) class Sale(metaclass=PoolMeta): __name__ = 'sale.sale' consumer = fields.Many2One('party.consumer', 'Consumer') table_assigned = fields.Many2One('sale.shop.table', 'Table Assigned', domain=[ ('shop', '=', Eval('shop')), ]) productions = fields.Function(fields.One2Many('production', None, 'Productions'), 'get_productions') production_moves = fields.Many2Many('sale.sale-stock.move', 'sale', 'move', 'Production Moves') order_status = fields.Selection(OPTIONS_STATUS, 'Order Status') order_status_string = order_status.translated('order_status') # delivery_time = fields.Numeric('Delivery Time (Min)', help="In Minutes") # shipping_time = fields.DateTime('Shipping Time') waiting_time = fields.Function(fields.Integer('Shipping Time', help="In Minutes"), 'get_waiting_time') order_status_time = fields.Many2One('sale.order_status.time', string='Times Order Status') @classmethod def __setup__(cls): super(Sale, cls).__setup__() @staticmethod def default_order_status(): return 'draft' def get_waiting_time(self, name=None): now = datetime.now() if self.state in ('draft', 'quotation', 'confirmed', 'processing'): delta = int((now - self.create_date).seconds / 60) return delta @classmethod def mark_commanded(cls, args): """ This method mark as commanded all products in sale, previous positive response of local printer """ Status = Pool().get('sale.order_status.time') Line = Pool().get('sale.line') lines_ = args.get('lines_ids', []) if args.get('sale_id'): sale = cls(args['sale_id']) sales = [sale] else: lines = Line.browse(lines_) sales = set(ln.sale for ln in lines) for sale in sales: to_write = {'order_status': 'commanded'} now = datetime.now() order_time = sale.order_status_time if order_time: Status.write([order_time], {'commanded': now}) else: status, = Status.create([{'commanded': now, 'requested': now, 'sale': sale.id}]) to_write['order_status_time'] = status cls.write([sale], to_write) if args.get('lines_ids'): lines_ids = args['lines_ids'] lines = Line.browse(lines_ids) Line.write(list(lines), {'order_sended': True, 'status_order': 'commanded'}) @classmethod def do(cls, sales): if sales: ShopTable = Pool().get('sale.shop.table') tables = ShopTable.search([('sale', 'in', [s.id for s in sales])]) if tables: ShopTable.write(tables, {'sale': None, 'state': 'available'}) @classmethod def get_orders_to_command(cls, args): # function deprecated for remove pool = Pool() Line = pool.get('sale.line') shop = args['shop'] _date = str(datetime.now() - timedelta(hours=1)) fields = [ 'sale.number', 'quantity', 'note', 'product.tasks.printers.shop', 'product.tasks.printers.name', 'product.tasks.printers.host', 'product.tasks.printers.interface', 'product.tasks.printers.port', 'product.tasks.printers.row_characters', 'product.tasks.name'] dom = [ ("sale.shop", "=", shop), ("sale.state", "in", ("draft", "quotation")), ("status_order", "=", 'requested'), ("create_date", ">=", _date), ] if args.get('sale_id'): dom.append(('sale', '=', args['sale'])) lines = Line.search_read( dom, fields_names=fields, order=[('sale', 'ASC')]) data = {} for line in lines: sale_id = line['sale.']['id'] sale_number = line['sale.']['number'] qty = line['quantity'] note = line['note'] id_ = str(line['id']) try: data[sale_id] except Exception: data[sale_id] = { 'id': sale_id, 'tasks': {}, 'orders': [] } for t in line['product.']['tasks.']: line_ = { 'quantity': qty, 'note': note, 'name': t['name'], 'line': id_, 'task': str(t['id'])} for p in t['printers.']: key = str(p['id']) if p['shop'] == shop: value = { **line_, 'printer': p['id'] } try: data[sale_id]['tasks'][key]['lines'].append(line_) except Exception: p['device'] = p['host'] p['profile'] = '' data[sale_id]['tasks'][key] = { 'printer': p, 'sale': sale_number, 'work_station': p['name'], 'lines': [line_] } for sale_id, value in data.items(): args = { 'sale_id': sale_id, 'repeat': False, } orders, _ = cls.get_order2print(args) value['orders'] = orders return list(data.values()) def get_data_for_stations(self): # function deprecated data_grouped_printer = {} if not self.number: self.set_number([self]) data_sale = self.number shop = self.shop line_commanded = [] for line in self.lines: line_commanded.append(line) qty = line.quantity note = line.note line_id = line.id tasks = line.product.tasks att_getter = attrgetter("name") att_getter_p = attrgetter("host", "interface", "port", "row_characters") for t in tasks: station = t.work_station station_id = station.id name = att_getter(t) value = { 'name': name, 'qty': qty, 'note': note, 'id': line_id, 'task_id': t.id} for p in t.work_station.printers: key = str(p.id) + '_' + str(station_id) if p.shop == shop: try: data_grouped_printer[key]['lines'].append(value) except Exception: host, interface, port, row_characters = att_getter_p(p) value_printer = { 'device': host, 'interface': interface, 'profile': '', 'row_characters': row_characters } data_grouped_printer[key] = {} data_grouped_printer[key]['printer'] = value_printer data_grouped_printer[key]['sale'] = data_sale data_grouped_printer[key]['work_station'] = station.name data_grouped_printer[key]['lines'] = [value] # Line.write(line_commanded, {'status_order': 'commanded'}) return data_grouped_printer @classmethod def delete(cls, sales): has_order_sended = any(line.order_sended for sale in sales for line in sale.lines) if has_order_sended: raise DeleteSaleError( gettext('sale_pos_frontend_rest.msg_sale_delete_error')) super(Sale, cls).delete(sales) @classmethod def transition_pay_(cls, sales_to_pay): pool = Pool() Statement = pool.get('account.statement') StatementLine = pool.get('account.statement.line') for sale_pay in sales_to_pay: sale = sale_pay['sale'] journal_id = sale_pay['journal_id'] statements = Statement.search([ ('journal', '=', journal_id), ('state', '=', 'draft'), ('sale_device', '=', sale.sale_device), ], order=[('date', 'DESC')]) if not statements: raise PayValidationError( gettext('sale_pos_frontend_rest.msg_message_error', s='A draft statement payments has not been created.')) if not sale.number: cls.set_number([sale]) if not sale.party.account_receivable: raise PayValidationError( gettext('sale_pos_frontend_rest.msg_party_not_account_receivable', s=sale.party.name)) account = sale.party.account_receivable.id payment = StatementLine( statement=statements[0].id, date=date.today(), amount=sale.total_amount, party=sale.party.id, account=account, description=sale.number, sale=sale.id, ) payment.save() sale.save() cls.workflow_to_end([sale]) @classmethod def update_consumer(cls, args, context={}): Consumer = Pool().get('party.consumer') fields = args['fields'] consumer = Consumer(args['id']) for key, value in fields.items(): if hasattr(consumer, key): Consumer.write([consumer], {key: value}) return cls._get_object(consumer) @classmethod def create_consumer(cls, args, context={}): Consumer = Pool().get('party.consumer') consumer = None notes = '' if args: # fields = args['fields'] print('args....', args) consumer, = Consumer.create([args]) # if consumer and consumer.party: # party = consumer.party # party.write([party], {'notes': notes}) # return cls._get_object(consumer) return { 'id': consumer.id, 'name': consumer.name, 'phone': consumer.phone, 'address': consumer.address or '', 'notes': consumer.notes, 'delivery': consumer.delivery } @classmethod def _get_object(cls, consumer): obj_ = { 'msg': 'ok', # 'party': None, 'consumer': { 'id': consumer.id, 'name': consumer.name, 'phone': consumer.phone, 'address': consumer.address or '', 'notes': consumer.notes or '', }, } if consumer.party: obj_['party'] = consumer.party.id return obj_ @classmethod def _move(cls, from_location, to_location, company, product, uom, quantity): Move = Pool().get('stock.move') move = Move( product=product, uom=uom, quantity=quantity, from_location=from_location, to_location=to_location, company=company, currency=company.currency if company else None, state='draft', ) return move @classmethod def _explode_move_values(cls, from_location, to_location, company, bom_io, quantity): move = cls._move(from_location, to_location, company, bom_io.product, bom_io.uom, quantity) move.from_location = from_location.id if from_location else None move.to_location = to_location.id if to_location else None move.unit_price_required = move.on_change_with_unit_price_required() return move @classmethod def _create_productions(cls, lines): pool = Pool() Move = Pool().get('stock.move') Location = pool.get('stock.location') Bom = pool.get('production.bom') Uom = pool.get('product.uom') for line in lines: if hasattr(line, 'production') and line.production: return if line.product.producible: boms = Bom.search([ ('output_products', '=', line.product.id) ]) if not boms: continue raise ProductionValidationWarning( gettext('sale_pos_frontend_rest.msg_msg_product_without_bom', product=line.product.rec_name)) else: bom_ = boms[0] locations = Location.search([ ('type', '=', 'production'), ]) location_ = locations[0] if locations else None if not hasattr(line, 'sale'): return sale = line.sale date_ = sale.sale_date product_ = line.product if not (bom_ and product_ and product_.default_uom): return if sale.warehouse: storage_location = sale.warehouse.storage_location else: storage_location = None factor = bom_.compute_factor(product_, line.quantity or 0, product_.default_uom) inputs = [] for input_ in bom_.inputs: quantity = input_.compute_quantity(factor) move = cls._explode_move_values(storage_location, location_, sale.company, input_, quantity) if move: move.planned_date = date_ move.effective_date = date_ move.save() inputs.append(move) quantity = Uom.compute_qty(input_.uom, line.quantity, input_.product.default_uom, round=False) outputs = [] for output in bom_.outputs: quantity = output.compute_quantity(factor) move = cls._explode_move_values(location_, storage_location, sale.company, output, quantity) if move: move.planned_date = date_ move.effective_date = date_ move.unit_price = Decimal(0) move.save() outputs.append(move) moves = inputs + outputs Move.do(inputs + outputs) sale.production_moves = moves sale.save() def get_productions(self, name): productions = [] for line in self.lines: if hasattr(line, 'production') and line.production: productions.append(line.production) return productions class SaleForceDraft(Wizard): __name__ = 'sale_pos.force_draft' def transition_force_draft(self): pool = Pool() Sale = pool.get('sale.sale') Production = pool.get('production') ids = Transaction().context['active_ids'] stock_move_table = Table('stock_move') cursor = Transaction().connection.cursor() if not ids: return 'end' for sale in Sale.browse(ids): stock_moves = [line.id for line in sale.production_moves] if stock_moves: cursor.execute(*stock_move_table.update( columns=[stock_move_table.state], values=['draft'], where=stock_move_table.id.in_(stock_moves) )) cursor.execute(*stock_move_table.delete( where=stock_move_table.id.in_(stock_moves)) ) for p in sale.productions: cursor = Transaction().connection.cursor() cursor.execute("UPDATE production SET state='waiting' WHERE id in (%s)" % (p.id)) Production.draft([p]) Production.cancel([p]) Production.delete([p]) return super(SaleForceDraft, self).transition_force_draft() class OrderStatusTime(ModelSQL, ModelView): "Sale Order Status Time" __name__ = 'sale.order_status.time' _rec_name = 'sale' sale = fields.Many2One('sale.sale', 'Sale', ondelete='CASCADE') created = fields.DateTime('Created') requested = fields.DateTime('Requested') commanded = fields.DateTime('commanded') dispatched = fields.DateTime('Dispatched') delivered = fields.DateTime('Delivered') rejected = fields.DateTime('Rejected') cancelled = fields.DateTime('Cancelled') class SaleLine(metaclass=PoolMeta): __name__ = 'sale.line' production = fields.Many2One('production', 'Production') status_order = fields.Selection(OPTIONS_STATUS, 'Status Order') without_task = fields.Boolean('Without Task') tasks = fields.One2Many('production.task', 'line', 'Tasks') @staticmethod def default_status_order(): return 'draft' @classmethod def mark_tasks_printed(cls, args): Task = Pool().get('production.task') task_ids = args.get('task_ids') tasks = Task.browse(task_ids) Task.write(list(tasks), {'state': 'commanded'}) @classmethod def get_data_command_and_task(cls, args): orders = cls.get_data_command(args) tasks = cls.get_data_tasks(args) return {'orders': orders, 'tasks': tasks} @classmethod def get_data_command(cls, args): Sale = Pool().get('sale.sale') Printer = Pool().get('sale.pos_printer') thirty_minutes_ago = str(datetime.now() - timedelta(minutes=30)) shop = args.get('shop') fields_printer = [ 'shop', 'name', 'host', 'interface', 'port', 'row_characters', 'categories.sequence', 'categories.category.name' ] printers = Printer.search_read(['shop', '=', shop], fields_names=fields_printer) printers = {p['id']: p for p in printers} dom = [ ("sale.shop", "=", shop), ("sale.state", "in", ("draft", "quotation")), ("status_order", "=", 'requested'), ("create_date", ">=", thirty_minutes_ago), ] if args.get('sale_id'): dom.append(('sale', '=', args['sale_id'])) fields = [ 'sale', 'product.name', 'product.template.printers', 'product.template.categories', 'quantity', 'note' ] lines = cls.search_read(dom, fields_names=fields) sale_ids = set(ln['sale'] for ln in lines) fields_sales = [ 'consumer.name', 'consumer.phone', 'consumer.address', 'consumer.notes', 'party.name', 'turn', 'number', 'invoice_number', 'position', 'salesman.rec_name', 'comment', 'delivery_charge', 'payment_term.name', 'delivery_amount', 'total_amount', 'shop.name', 'kind', 'table_assigned.name' ] sales = Sale.search_read(['id', 'in', sale_ids], fields_names=fields_sales) sales = { s['id']: { 'id': s['id'], 'consumer': s.get('consumer.'), 'turn': s['turn'], 'number': s['invoice_number'], 'sale_number': s['number'], 'position': s.get('position', ''), 'party': s.get('party.', {}).get('name') if s.get('party.') else '', 'kind': s['kind'], 'delivery_amount': s.get('delivery_amount', 0), 'salesman': s.get('salesman.').get('rec_name') if s.get('salesman.') else '', 'comment': s.get('comment', ''), 'payment_term': s.get('payment_term.').get('name', '') if s.get('payment_term.') else '', 'delivery_charge': s.get('delivery_charge', 0), 'total_amount': str(s['total_amount']), 'shop': s.get('shop.', {}).get('name', '') if s.get('shop.') else '', 'table_assigned': s.get('table_assigned.').get('name', '') if s.get('table_assigned.') else '', } for s in sales } orders = {} lines_mark_sended = [] for line in lines: sale_id = line['sale'] sale = sales[sale_id] printers_ = line['product.']['template.'].get('printers', []) if not printers_: lines_mark_sended.append(line['id']) continue value_line = { 'name': line['product.']['name'], 'quantity': str(line['quantity']), 'unit_price': int(0), # validate is this field is neccesary 'note': line['note'], 'id': line['id'] } categories = line['product.']['template.'].get('categories') for printer_id in printers_: printer = printers.get(printer_id) if not printer: continue key = f'{sale_id}_{printer_id}' if key not in orders: orders[key] = {**printer, **sale, 'lines': []} if len(printer.get('categories.')) > 1: orders[key]['lines'] = { c['sequence']: { 'name': c.get('category.', {}).get('name'), 'lines': []} for c in printer['categories.']} orders[key]['categories'] = {c['category.']['id']: c['sequence'] for c in printer['categories.']} if isinstance(orders[key]['lines'], list): orders[key]['lines'].append(value_line) else: key_id = str(orders[key]['categories'].get(categories[0], 'others')) if key_id == 'others' and 'others' not in orders[key]['lines']: orders[key]['lines']['others'] = {'name': 'OTROS', 'lines': []} orders[key]['lines'][key_id]['lines'].append(value_line) return list(orders.values()) @classmethod def get_data_tasks(cls, args): Task = Pool().get('production.task') thirty_minutes_ago = str(datetime.now() - timedelta(minutes=30)) shop = args['shop'] fields = [ 'sale.number', 'quantity', 'note', 'product.tasks.printers.shop', 'product.tasks.printers.name', 'product.tasks.printers.host', 'product.tasks.printers.interface', 'product.tasks.printers.port', 'product.tasks.printers.row_characters', 'product.tasks.name'] dom = [ ("sale.shop", "=", shop), ("sale.state", "in", ("draft", "quotation")), ("create_date", ">=", thirty_minutes_ago), ("without_task", "!=", True), ("tasks", '=', None) ] if args.get('sale_id'): dom.append(('sale', '=', args['sale_id'])) lines = cls.search_read( dom, fields_names=fields, order=[('sale', 'ASC'), ('id', 'DESC')]) to_create = [] lines_without_tasks = [] for line in lines: quantity = line['quantity'] note = line['note'] line_id = line['id'] sale_number = line['sale.']['number'] tasks = line['product.']['tasks.'] if not tasks: lines_without_tasks.append(line_id) for t in line['product.']['tasks.']: task_id = t['id'] for p in t['printers.']: if p['shop'] == shop: value = { 'quantity': quantity, 'note': note, 'line': line_id, 'name': t['name'], 'sale_number': sale_number, 'task': task_id, 'state': 'pending', 'printer': p['id']} to_create.append(value) if lines_without_tasks: lines_ = cls.browse(lines_without_tasks) cls.write(list(lines_), {'without_task': True}) Task.create(to_create) data = Task.get_tasks_to_print(args) return data @classmethod def delete(cls, lines): HistoryDelete = Pool().get('sale.line._history.delete') lines_to_create = [] lines_to_create_append = lines_to_create.append for line in lines: if line.order_sended: value = { 'line_id': line.id, 'product': line.product, 'quantity': line.quantity, 'date': line.sale.sale_date, 'order_status': line.sale.order_status, 'sale': line.sale.id, 'sale_state': line.sale.state, 'unit_price': line.unit_price, 'base_price': line.base_price, 'note': line.note, 'shop': line.sale.shop, 'salesman': line.sale.salesman, 'line_created': line.create_date } lines_to_create_append(value) super(SaleLine, cls).delete(lines) if lines_to_create: HistoryDelete.create(lines_to_create) class SaleLineHistoryDelete(ModelView, ModelSQL): 'Sale Line History Delete' __name__ = 'sale.line._history.delete' product = fields.Many2One('product.product', 'Product') line_id = fields.Char('Line id') order_status = fields.Char('Order Status') sale = fields.Many2One('sale.sale', 'Sale') sale_state = fields.Char('Sale State') quantity = fields.Float('Quantity', digits=(16, Eval('unit_digits', 2))) shop = fields.Many2One('sale.shop', 'Shop') unit_price = fields.Numeric('Unit Price', digits=price_digits) date = fields.Date('Date') base_price = fields.Numeric('Base Price', digits=price_digits) note = fields.Text('Note') salesman = fields.Many2One('company.employee', 'Salesman') line_created = fields.DateTime('Line Created') class SaleLineHistoryDeleteStart(ModelSQL, ModelView): 'Sale Line History Delete Start' __name__ = 'line_history.delete_start' company = fields.Many2One('company.company', 'Company', required=True) start_date = fields.Date('Date', required=True) end_date = fields.Date('Date', required=True) shop = fields.Many2One('sale.shop', 'Shop', required=True) @staticmethod def default_company(): return Transaction().context.get('company') @staticmethod def default_shop(): return Transaction().context.get('shop') @staticmethod def default_end_date(): Date = Pool().get('ir.date') return Date.today() @staticmethod def default_start_date(): Date = Pool().get('ir.date') today = Date.today() date_ = date(today.year, today.month, 1) return date_ class SaleLineHistoryDeleteWizard(Wizard): 'Sale Line History Delete' __name__ = 'line_history.delete_wizard' start = StateView( 'line_history.delete_start', 'sale_pos_frontend_rest.line_history_delete_view_form', [ Button('Cancel', 'end', 'tryton-cancel'), Button('Print', 'print_', 'tryton-ok', default=True), ]) print_ = StateReport('line_history.delete_report') def do_print_(self, action): report_context = { 'company': self.start.company.id, 'start_date': self.start.start_date, 'end_date': self.start.end_date, 'shop': self.start.shop.id, } return action, report_context def transition_print_(self): return 'end' class SaleLineHistoryDeleteReport(Report): 'Sale Line History Delete Report' __name__ = 'line_history.delete_report' @classmethod def get_context(cls, records, header, data): report_context = super().get_context(records, header, data) pool = Pool() History = pool.get('sale.line._history.delete') Company = pool.get('company.company') Shop = pool.get('sale.shop') domain = [ ('date', '>=', data['start_date']), ('date', '<=', data['end_date']), ] if data['shop']: domain.append(('shop', '=', data['shop'])) records = History.search_read(domain) record_ids = [r['id'] for r in records] records = cls._get_records(record_ids, 'sale.line._history.delete', data) company = Company(data['company']) report_context['company'] = company report_context['shop_name'] = Shop.name report_context['records'] = records return report_context class SaleSquareBoxGlobal(SaleSquareBox): 'Sale Square Box Global' __name__ = 'sale_pos_frontend_rest.sale_square_box_global' @classmethod def __setup__(cls): super(SaleSquareBoxGlobal, cls).__setup__() cls.print_ = StateReport('sale_pos_frontend_rest.sale_square_box_global_report') class SaleSquareBoxGlobalReport(Report): 'Square Box Global Report' __name__ = 'sale_pos_frontend_rest.sale_square_box_global_report' @classmethod def __setup__(cls): super(SaleSquareBoxGlobalReport, cls).__setup__() @classmethod def get_stament_cash(cls, statement): Statement = Pool().get('account.statement') if statement: value = { 'statement': Statement(statement['id']), 'base': statement['total_money'] or 0, 'bills': sum(k['amount'] for k in statement['count_money.'] if float(k['bill']) >= 1000), 'coins': sum(k['amount'] for k in statement['count_money.'] if float(k['bill']) < 1000) } return value @classmethod def get_context(cls, records, header, data): report_context = super().get_context(records, header, data) pool = Pool() Invoice = pool.get('account.invoice') Company = pool.get('company.company') Device = pool.get('sale.device') company = Company(data['company']) Statement = pool.get('account.statement') Shop = pool.get('sale.shop') # User = pool.get('res.user') dom_statement = [ ('date', '=', data['date']), ] devices = Device.search([('shop', '=', data['shop'])]) device_ids = [d.id for d in devices] dom_statement.append(('sale_device', 'in', device_ids)) if data['turn']: dom_statement.append(('turn', '=', int(data['turn']))) fields_statement = ['name', 'create_date', 'journal.kind', 'balance', 'count_money.bill', 'count_money.quantity', 'count_money.amount', 'total_money'] cash = None statements = Statement.search_read(dom_statement, fields_names=fields_statement) lst_statements = [] balance_statements = [] for st in statements: kind = st['journal.']['kind'] if kind == 'cash': cash = st else: balance_statements.append(st['balance']) lst_statements.append(st) dom_invoices = [ ('company', '=', data['company']), ('invoice_date', '=', data['date']), ('type', '=', 'out'), ('shop', '=', data['shop']), ] if data.get('turn'): dom_invoices.append(('turn', '=', int(data['turn']))) fields_inv = ['number', 'invoice_type', 'total_amount', 'state', 'payment_term.payment_type', 'sales.residual_amount', 'payment_term.rec_name', 'party.name', 'reference'] invoices = Invoice.search_read(dom_invoices, fields_names=fields_inv) pos = [] electronic = [] cancelled = [] credits = [] invs = [] pos_append = pos.append electronic_append = electronic.append cancelled_append = cancelled.append credits_append = credits.append invs_append = invs.append for invoice in invoices: residual_amount = invoice['sales.'][0]['residual_amount'] if residual_amount > 0: invoice['residual_amount'] = residual_amount credits_append(residual_amount) invs_append(invoice) if invoice['state'] == 'cancelled': cancelled_append((invoice['total_amount'], invoice)) elif invoice['invoice_type'] == '1': electronic_append(invoice['total_amount']) else: pos_append(invoice['total_amount']) report_context['total_sale'] = sum(pos) + sum(electronic) report_context['pos'] = sum(pos) report_context['electronic'] = sum(electronic) report_context['cash'] = cls.get_stament_cash(cash) report_context['credits'] = sum(credits) report_context['invoice_credits'] = invs report_context['statements'] = lst_statements report_context['balance_statements'] = balance_statements report_context['data'] = data report_context['company'] = company report_context['shop'] = Shop(data['shop']) return report_context