# This file is part of Presik. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from datetime import datetime, date from decimal import Decimal from trytond.i18n import gettext from trytond.pool import Pool, PoolMeta from trytond.pyson import Eval from trytond.report import Report from trytond.model import ModelView, fields from trytond.transaction import Transaction from trytond.exceptions import UserError from trytond.wizard import ( Wizard, StateView, Button, StateReport, StateTransition) _ZERO = Decimal(0) class Sale(metaclass=PoolMeta): __name__ = 'sale.sale' # folio = fields.Many2One('hotel.folio', 'Folio', states={ # 'readonly': True, # }) @classmethod def __setup__(cls): super(Sale, cls).__setup__() # _states = { # 'readonly': Eval('state') != 'draft', # } cls.state.selection.append(('transferred', 'Transferred')) @classmethod def transfer_to_folio(cls, sale_id, folio_id): sale, = cls.browse([sale_id]) Charge = Pool().get('hotel.folio.charge') Folio = Pool().get('hotel.folio') to_create = [] folio = Folio(folio_id) number = sale.number if folio.charges_blocked: raise UserError(gettext('hotel.msg_folio_charges_blocked')) if folio.registration_state == 'check_out': raise UserError(gettext('hotel.msg_folio_closed')) for line in sale.lines: unit_price = line.unit_price.quantize(Decimal('.01')) to_create.append({ 'folio': folio_id, 'product': line.product.id, 'description': line.description, 'quantity': line.quantity, 'date_service': line.sale.sale_date, 'unit_price': unit_price, 'kind': 'product', 'order': number, 'status': 'pending', 'origin': f'sale.line,{line.id}', }) charges_ids = Charge.create(to_create) # 'folio': folio_id, cls.write([sale], { 'state': 'transferred', 'invoice_method': 'manual', 'shipment_method': 'manual', 'reference': folio.booking.number, }) # FIXME: Add stock moves return 'ok' @classmethod def transfer_to_sale(cls, sale_id, target_sale_id): Line = Pool().get('sale.line') sale, = cls.browse([sale_id]) target, = cls.browse([target_sale_id]) for line in sale.lines: nwline, = Line.copy([line]) nwline.sale = target.id nwline.origin = f'sale.line,{line.id}' nwline.save() cls.write([sale], { 'state': 'transferred', 'invoice_method': 'manual', 'shipment_method': 'manual', 'reference': sale.number, }) # FIXME: Add stock moves return 'ok' class SaleLine(metaclass=PoolMeta): __name__ = 'sale.line' origin = fields.Reference('Origin', selection='get_origin', readonly=True) @classmethod def _get_origin(cls): 'Return list of Model names for origin Reference' return ['sale.line'] @classmethod def get_origin(cls): Model = Pool().get('ir.model') get_name = Model.get_name models = cls._get_origin() return [(None, '')] + [(m, get_name(m)) for m in models] class InvoiceIncomeDailyStart(ModelView): 'Invoice Income Daily Start' __name__ = 'hotel.invoice_income_daily.start' company = fields.Many2One('company.company', 'Company', required=True) invoice_date = fields.Date('Invoice Date', required=True) user = fields.Many2One('res.user', 'User', required=True) shop = fields.Many2One('sale.shop', 'Shop', required=True) # journal = fields.Many2One('account.statement.journal', 'Journal') @staticmethod def default_company(): return Transaction().context.get('company') @staticmethod def default_sale_date(): Date = Pool().get('ir.date') return Date.today() class InvoiceIncomeDaily(Wizard): 'Invoice Income Daily' __name__ = 'hotel.invoice_income_daily' start = StateView( 'hotel.invoice_income_daily.start', 'hotel.invoice_income_daily_start_view_form', [ Button('Cancel', 'end', 'tryton-cancel'), Button('Print', 'print_', 'tryton-ok', default=True), ]) print_ = StateReport('hotel.invoice_income_daily_report') def do_print_(self, action): report_context = { 'company': self.start.company.id, 'invoice_date': self.start.invoice_date, 'user': self.start.user.id, 'shop': self.start.shop.id, } return action, report_context def transition_print_(self): return 'end' class InvoiceIncomeDailyReport(Report): 'Invoice Income Daily Report' __name__ = 'hotel.invoice_income_daily_report' @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') company = Company(data['company']) Statement = pool.get('account.statement') Shop = pool.get('sale.shop') User = pool.get('res.user') shop = Shop(data['shop']) statements = Statement.search([ ('date', '=', data['invoice_date']), ('create_uid', '=', data['user']), ]) user = User(data['user']) records = [] advances = [] statements_ = [] total_advances = [] advances_cash = [] advances_electronic = [] total_statements = [] for statement in statements: st_amount = sum(li.amount for li in statement.lines) statements_.append({ 'id': statement.id, 'sale_device': statement.sale_device.name, 'journal': statement.journal.name, 'turn': statement.turn, 'total_amount': st_amount, 'state': statement.state, }) total_statements.append(st_amount) for li in statement.lines: sale = li.sale cash = 0 electronic = 0 if sale and not sale.invoice_number: for pline in sale.payments: if pline.statement.journal.kind == 'cash': advances_cash.append(pline.amount) cash = pline.amount else: electronic = pline.amount advances_electronic.append(pline.amount) advances.append({ 'number': sale.number, 'reference': sale.reference, 'party': sale.party.name, 'total_amount': pline.amount, 'cash': cash, 'electronic': electronic, }) total_advances.append(pline.amount) dom_ = [ ('company', '=', data['company']), ('invoice_date', '=', data['invoice_date']), ('shop', '=', data['shop']), ('number', '!=', None), ('state', 'in', ['posted', 'paid', 'canceled']), ('create_uid', '=', data['user']), ] invoices = Invoice.search(dom_, order=[('number', 'ASC')]) invoices_number = [] total_invoices_cash = [] total_invoices_electronic = [] total_invoices_credit = [] total_invoices_paid = [] total_invoices_amount = [] for invoice in invoices: invoices_number.append(invoice.number) cash = 0 electronic = 0 credit = 0 total_invoices_amount.append(invoice.total_amount) sale = invoice.sales[0] if not sale.payments: total_invoices_credit.append(invoice.amount_to_pay) credit = invoice.amount_to_pay else: for p in sale.payments: if p.statement.date == data['invoice_date']: if p.statement.journal.kind == 'cash': cash += p.amount total_invoices_cash.append(p.amount) else: electronic += p.amount total_invoices_electronic.append(p.amount) total_invoices_paid.append(p.amount) inv = { 'number': invoice.number, 'reference': invoice.reference, 'party': invoice.party.name, 'total_amount': invoice.total_amount, 'credit': credit, 'cash': cash, 'electronic': electronic, 'paid': cash + electronic, 'state': invoice.state_string, } records.append(inv) report_context['records'] = records report_context['advances'] = advances report_context['statements'] = statements_ report_context['date'] = data['invoice_date'] report_context['company'] = company report_context['shop'] = shop.name report_context['user'] = user.name report_context['print_date'] = datetime.now() report_context['total_invoices_amount'] = sum(total_invoices_amount) report_context['total_invoices_cash'] = sum(total_invoices_cash) report_context['total_invoices_electronic'] = sum(total_invoices_electronic) report_context['total_invoices_credit'] = sum(total_invoices_credit) report_context['total_invoices_paid'] = sum(total_invoices_paid) report_context['total_advances'] = sum(total_advances) report_context['advances_cash'] = sum(advances_cash) report_context['advances_electronic'] = sum(advances_electronic) report_context['total_statements'] = sum(total_statements) report_context['start_invoice'] = min(invoices_number) if invoices_number else '' report_context['end_invoice'] = max(invoices_number) if invoices_number else '' return report_context class InvoiceSimplifiedReport(Report): __name__ = 'account.invoice_simplified' @classmethod def get_context(cls, records, header, data): report_context = super().get_context(records, header, data) Company = Pool().get('company.company') categories = {} if records: record = records[0] for l in record.lines: cat = l.product.template.account_category taxes = '' for tax in cat.customer_taxes_used: taxes += tax.name + ' ' if cat.id not in categories.keys(): categories[cat.id] = { 'description': cat.name, 'amount': l.amount, 'taxes': taxes } else: categories[cat.id]['amount'] += l.amount record._lines = categories.values() report_context['company'] = Company(Transaction().context['company']) return report_context class SaleTransferStart(ModelView): 'Sale Transfer Start' __name__ = 'sale.transfer.start' kind = fields.Selection([ ('folio', 'Folio'), ('sale', 'Sale'), ], 'Kind', required=True) folio = fields.Many2One('hotel.folio', 'Folio', domain=[ ('registration_state', '=', 'check_in'), ('arrival_date', '<=', date.today()), ('departure_date', '>=', date.today()), ], states={ 'invisible': Eval('kind') != 'folio' }) sale = fields.Many2One('sale.sale', 'Sale', domain=[ ('state', '=', 'draft'), ('number', '!=', None), ], states={ 'invisible': Eval('kind') != 'sale' }) class SaleTransfer(Wizard): 'Sale Transfer' __name__ = 'sale.transfer' start = StateView( 'sale.transfer.start', 'hotel.sale_transfer_start_view_form', [ Button('Cancel', 'end', 'tryton-cancel'), Button('Ok', 'accept', 'tryton-ok', default=True), ]) accept = StateTransition() def transition_accept(self): Sale = Pool().get('sale.sale') sale_id = Transaction().context['active_id'] if self.start.kind == 'folio': Sale.transfer_to_folio(sale_id, self.start.folio.id) else: Sale.transfer_to_sale(sale_id, self.start.sale.id) return 'end'