Files
pms/hotel/wizard/folio_make_invoice_advance.py
2019-01-16 17:28:59 +01:00

263 lines
12 KiB
Python

# Part of Odoo. See LICENSE file for full copyright and licensing details.
import time
from odoo import api, fields, models, _
import odoo.addons.decimal_precision as dp
from odoo.exceptions import UserError
class FolioAdvancePaymentInv(models.TransientModel):
_name = "folio.advance.payment.inv"
_description = "Folios Advance Payment Invoice"
@api.model
def _count(self):
return len(self._context.get('active_ids', []))
@api.model
def _get_advance_payment_method(self):
return 'all'
@api.model
def _default_product_id(self):
product_id = self.env['ir.default'].sudo().get('sale.config.settings',
'deposit_product_id_setting')
return self.env['product.product'].browse(product_id)
@api.model
def _default_deposit_account_id(self):
return self._default_product_id().property_account_income_id
@api.model
def _default_deposit_taxes_id(self):
return self._default_product_id().taxes_id
advance_payment_method = fields.Selection([
('all', 'Invoiceable lines (deduct down payments)'),
('percentage', 'Down payment (percentage)'),
('fixed', 'Down payment (fixed amount)')
], string='What do you want to invoice?', default=_get_advance_payment_method,
required=True)
count = fields.Integer(default=_count, string='# of Orders')
folio_ids = fields.Many2many("hotel.folio", string="Folios",
help="Folios grouped")
group_folios = fields.Boolean('Group Folios')
line_ids = fields.One2many('line.advance.inv',
'advance_inv_id',
string="Invoice Lines")
view_detail = fields.Boolean('View Detail')
#Advance Payment
product_id = fields.Many2one('product.product', string='Down Payment Product',
domain=[('type', '=', 'service')], default=_default_product_id)
amount = fields.Float('Down Payment Amount',
digits=dp.get_precision('Account'),
help="The amount to be invoiced in advance, taxes excluded.")
deposit_account_id = fields.Many2one("account.account", string="Income Account",
domain=[('deprecated', '=', False)],
help="Account used for deposits",
default=_default_deposit_account_id)
deposit_taxes_id = fields.Many2many("account.tax", string="Customer Taxes",
help="Taxes used for deposits",
default=_default_deposit_taxes_id)
@api.onchange('advance_payment_method')
def onchange_advance_payment_method(self):
if self.advance_payment_method == 'percentage':
return {'value': {'amount': 0}}
return {}
@api.multi
def _create_invoice(self, order, so_line, amount):
inv_obj = self.env['account.invoice']
ir_property_obj = self.env['ir.property']
account_id = False
if self.product_id.id:
account_id = self.product_id.property_account_income_id.id \
or self.product_id.categ_id.property_account_income_categ_id.id
if not account_id:
inc_acc = ir_property_obj.get('property_account_income_categ_id', 'product.category')
account_id = order.fiscal_position_id.map_account(inc_acc).id if inc_acc else False
if not account_id:
raise UserError(
_('There is no income account defined for this product: "%s". You may have to install a chart of account from Accounting app, settings menu.') %
(self.product_id.name,))
if self.amount <= 0.00:
raise UserError(_('The value of the down payment amount must be positive.'))
context = {'lang': order.partner_id.lang}
if self.advance_payment_method == 'percentage':
amount = order.amount_untaxed * self.amount / 100
name = _("Down payment of %s%%") % (self.amount,)
else:
amount = self.amount
name = _('Down Payment')
del context
taxes = self.product_id.taxes_id.filtered(
lambda r: not order.company_id or r.company_id == order.company_id)
if order.fiscal_position_id and taxes:
tax_ids = order.fiscal_position_id.map_tax(taxes).ids
else:
tax_ids = taxes.ids
invoice = inv_obj.create({
'name': order.client_order_ref or order.name,
'origin': order.name,
'type': 'out_invoice',
'reference': False,
'account_id': order.partner_id.property_account_receivable_id.id,
'partner_id': order.partner_invoice_id.id,
'partner_shipping_id': order.partner_shipping_id.id,
'invoice_line_ids': [(0, 0, {
'name': name,
'origin': order.name,
'account_id': account_id,
'price_unit': amount,
'quantity': 1.0,
'discount': 0.0,
'uom_id': self.product_id.uom_id.id,
'product_id': self.product_id.id,
'sale_line_ids': [(6, 0, [so_line.id])],
'invoice_line_tax_ids': [(6, 0, tax_ids)],
'account_analytic_id': order.project_id.id or False,
})],
'currency_id': order.pricelist_id.currency_id.id,
'payment_term_id': order.payment_term_id.id,
'fiscal_position_id': order.fiscal_position_id.id \
or order.partner_id.property_account_position_id.id,
'team_id': order.team_id.id,
'user_id': order.user_id.id,
'comment': order.note,
})
invoice.compute_taxes()
invoice.message_post_with_view(
'mail.message_origin_link',
values={'self': invoice, 'origin': order},
subtype_id=self.env.ref('mail.mt_note').id)
return invoice
@api.multi
def create_invoices(self):
folios = self.env['hotel.folio'].browse(self._context.get('active_ids', []))
if self.advance_payment_method == 'delivered':
folios.action_invoice_create()
elif self.advance_payment_method == 'all':
folios.action_invoice_create()
else:
# Create deposit product if necessary
if not self.product_id:
vals = self._prepare_deposit_product()
self.product_id = self.env['product.product'].create(vals)
self.env['ir.default'].sudo().set(
'sale.config.settings',
'deposit_product_id_setting',
self.product_id.id)
sale_line_obj = self.env['sale.order.line']
for order in sale_orders:
if self.advance_payment_method == 'percentage':
amount = order.amount_untaxed * self.amount / 100
else:
amount = self.amount
if self.product_id.invoice_policy != 'order':
raise UserError(_('The product used to invoice a down payment should have an invoice policy set to "Ordered quantities". Please update your deposit product to be able to create a deposit invoice.'))
if self.product_id.type != 'service':
raise UserError(_("The product used to invoice a down payment should be of type 'Service'. Please use another product or update this product."))
taxes = self.product_id.taxes_id.filtered(
lambda r: not order.company_id or r.company_id == order.company_id)
if order.fiscal_position_id and taxes:
tax_ids = order.fiscal_position_id.map_tax(taxes).ids
else:
tax_ids = taxes.ids
context = {'lang': order.partner_id.lang}
so_line = sale_line_obj.create({
'name': _('Advance: %s') % (time.strftime('%m %Y'),),
'price_unit': amount,
'product_uom_qty': 0.0,
'order_id': order.id,
'discount': 0.0,
'product_uom': self.product_id.uom_id.id,
'product_id': self.product_id.id,
'tax_id': [(6, 0, tax_ids)],
})
del context
self._create_invoice(order, so_line, amount)
if self._context.get('open_invoices', False):
return sale_orders.action_view_invoice()
return {'type': 'ir.actions.act_window_close'}
def _prepare_deposit_product(self):
return {
'name': 'Down payment',
'type': 'service',
'invoice_policy': 'order',
'property_account_income_id': self.deposit_account_id.id,
'taxes_id': [(6, 0, self.deposit_taxes_id.ids)],
}
@api.onchange('view_detail')
def prepare_reservation_invoice_lines(self):
vals = []
folios = self.env['hotel.folio'].browse(self._context.get('active_ids', []))
for folio in folios:
folio_name = folio.name
for reservation in folio.room_lines:
reservation_name = reservation.name
unit_price = False
discount = False
qty = 0
for day in reservation.reservation_line_ids.sorted('date'):
if day.price == unit_price and day.discount == discount:
date_to = day.date
qty += 1
else:
if unit_price:
vals.append((0, False, {
'date_from': date_from,
'date_to': date_to,
'room_type_id': reservation.room_type_id,
'product_id': self.env['product.product'].browse(
reservation.room_type_id.product_id.id
),
'qty': qty,
'discount': discount,
'unit_price': unit_price
}))
qty = 1
unit_price = day.price
date_from = day.date
date_to = day.date
vals.append((0, False, {
'date_from': date_from,
'date_to': date_to,
'room_type_id': reservation.room_type_id,
'product_id': self.env['product.product'].browse(
reservation.room_type_id.product_id.id
),
'qty': qty,
'discount': discount,
'unit_price': unit_price
}))
self.line_ids = vals
class LineAdvancePaymentInv(models.TransientModel):
_name = "line.advance.inv"
_description = "Lines Advance Invoice"
date_from = fields.Date('From')
date_to = fields.Date('To')
room_type_id = fields.Many2one('hotel.room.type')
product_id = fields.Many2one('product.product', string='Down Payment Product',
domain=[('type', '=', 'service')])
qty = fields.Integer('Quantity')
unit_price = fields.Float('Price')
advance_inv_id = fields.Many2one('folio.advance.payment.inv')
discount = fields.Float(
string='Discount (%)',
digits=dp.get_precision('Discount'), default=0.0)
to_invoice = fields.Boolean('To Invoice')