361 lines
13 KiB
Python
361 lines
13 KiB
Python
# 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.sale,{sale_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.party.name
|
|
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'
|