[WIP] Invoice WorkFlow

This commit is contained in:
Dario Lodeiros
2019-01-21 10:38:06 +01:00
parent 9e1bf442b3
commit d901ac98f5
3 changed files with 91 additions and 52 deletions

View File

@@ -2,7 +2,10 @@
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields, api, _
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT
from odoo.tools import (
float_is_zero,
float_compare,
DEFAULT_SERVER_DATE_FORMAT)
from datetime import timedelta
from odoo.exceptions import ValidationError
from odoo.addons import decimal_precision as dp
@@ -48,7 +51,6 @@ class HotelService(models.Model):
@api.model
def _default_folio_id(self):
import wdb; wdb.set_trace()
if 'folio_id' in self._context:
return self._context['folio_id']
return False
@@ -59,15 +61,11 @@ class HotelService(models.Model):
Compute the quantity to invoice. If the invoice policy is order, the quantity to invoice is
calculated from the ordered quantity. Otherwise, the quantity delivered is used.
"""
pass
#~ for line in self:
#~ if line.folio_id.state in ['confirm', 'done']:
#~ if line.room_type_id.product_id.invoice_policy == 'order':
#~ line.qty_to_invoice = line.nights - line.qty_invoiced
#~ else:
#~ line.qty_to_invoice = line.qty_delivered - line.qty_invoiced
#~ else:
#~ line.qty_to_invoice = 0
for line in self:
if line.folio_id.state not in ['draft']:
line.qty_to_invoice = line.product_qty - line.qty_invoiced
else:
line.qty_to_invoice = 0
@api.depends('invoice_line_ids.invoice_id.state', 'invoice_line_ids.quantity')
def _get_invoice_qty(self):
@@ -77,16 +75,15 @@ class HotelService(models.Model):
a refund made would automatically decrease the invoiced quantity, then there is a risk of reinvoicing
it automatically, which may not be wanted at all. That's why the refund has to be created from the SO
"""
pass
#~ for line in self:
#~ qty_invoiced = 0.0
#~ for invoice_line in line.invoice_line_ids:
#~ if invoice_line.invoice_id.state != 'cancel':
#~ if invoice_line.invoice_id.type == 'out_invoice':
#~ qty_invoiced += invoice_line.uom_id._compute_quantity(invoice_line.quantity, line.product_uom)
#~ elif invoice_line.invoice_id.type == 'out_refund':
#~ qty_invoiced -= invoice_line.uom_id._compute_quantity(invoice_line.quantity, line.product_uom)
#~ line.qty_invoiced = qty_invoiced
for line in self:
qty_invoiced = 0.0
for invoice_line in line.invoice_line_ids:
if invoice_line.invoice_id.state != 'cancel':
if invoice_line.invoice_id.type == 'out_invoice':
qty_invoiced += invoice_line.uom_id._compute_quantity(invoice_line.quantity, line.product_id.uom_id)
elif invoice_line.invoice_id.type == 'out_refund':
qty_invoiced -= invoice_line.uom_id._compute_quantity(invoice_line.quantity, line.product_id.uom_id)
line.qty_invoiced = qty_invoiced
@api.depends('product_qty', 'qty_to_invoice', 'qty_invoiced')
def _compute_invoice_status(self):
@@ -103,20 +100,16 @@ class HotelService(models.Model):
is removed from the list.
- invoiced: the quantity invoiced is larger or equal to the quantity ordered.
"""
pass
#~ precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
#~ for line in self:
#~ if line.state not in ('sale', 'done'):
#~ line.invoice_status = 'no'
#~ elif not float_is_zero(line.qty_to_invoice, precision_digits=precision):
#~ line.invoice_status = 'to invoice'
#~ elif line.state == 'sale' and line.product_id.invoice_policy == 'order' and\
#~ float_compare(line.qty_delivered, line.product_uom_qty, precision_digits=precision) == 1:
#~ line.invoice_status = 'upselling'
#~ elif float_compare(line.qty_invoiced, line.product_uom_qty, precision_digits=precision) >= 0:
#~ line.invoice_status = 'invoiced'
#~ else:
#~ line.invoice_status = 'no'
precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
for line in self:
if line.folio_id.state in ('draft'):
line.invoice_status = 'no'
elif not float_is_zero(line.qty_to_invoice, precision_digits=precision):
line.invoice_status = 'to invoice'
elif float_compare(line.qty_invoiced, line.product_qty, precision_digits=precision) >= 0:
line.invoice_status = 'invoiced'
else:
line.invoice_status = 'no'
name = fields.Char('Service description', required=True)
sequence = fields.Integer(string='Sequence', default=10)

View File

@@ -170,6 +170,26 @@ class FolioAdvancePaymentInv(models.TransientModel):
subtype_id=self.env.ref('mail.mt_note').id)
return invoice
@api.model
def _validate_invoices(self, invoice):
invoice.action_invoice_open()
payment_ids = self.folio_ids.mapped('payment_ids.id')
domain = [('account_id', '=', invoice.account_id.id),
('payment_id', 'in', payment_ids), ('reconciled', '=', False),
'|', ('amount_residual', '!=', 0.0),
('amount_residual_currency', '!=', 0.0)]
if invoice.type in ('out_invoice', 'in_refund'):
domain.extend([('credit', '>', 0), ('debit', '=', 0)])
type_payment = _('Outstanding credits')
else:
domain.extend([('credit', '=', 0), ('debit', '>', 0)])
type_payment = _('Outstanding debits')
info = {'title': '', 'outstanding': True, 'content': [], 'invoice_id': invoice.id}
lines = self.env['account.move.line'].search(domain)
currency_id = invoice.currency_id
for line in lines:
invoice.assign_outstanding_credit(line.id)
@api.multi
def create_invoices(self):
inv_obj = self.env['account.invoice']
@@ -185,6 +205,8 @@ class FolioAdvancePaymentInv(models.TransientModel):
invoice = inv_obj.create(inv_data)
for line in self.line_ids:
line.invoice_line_create(invoice.id, line.qty)
self._validate_invoices(invoice)
elif self.advance_payment_method == 'all':
pass
#Group lines by tax_ids
@@ -291,17 +313,19 @@ class FolioAdvancePaymentInv(models.TransientModel):
description = folio.name + ' ' + reservation.room_type_id.name + ' (' + \
reservation.board_service_room_id.hotel_board_service_id.name + ')' \
if board_service else folio.name + ' ' + reservation.room_type_id.name
invoice_lines[group_key] = {
'description' : description,
'reservation_id': reservation.id,
'room_type_id': reservation.room_type_id,
'product_id': self.env['product.product'].browse(
reservation.room_type_id.product_id.id),
'discount': day.discount,
'price_unit': day.price + extra_price,
'reservation_line_ids': []
}
invoice_lines[group_key][('reservation_line_ids')].append((4,day.id))
if group_key not in invoice_lines:
invoice_lines[group_key] = {
'description' : description,
'reservation_id': reservation.id,
'room_type_id': reservation.room_type_id,
'product_id': self.env['product.product'].browse(
reservation.room_type_id.product_id.id),
'discount': day.discount,
'price_unit': day.price + extra_price,
'reservation_line_ids': [(4, day.id)]
}
else:
invoice_lines[group_key][('reservation_line_ids')].append((4,day.id))
for group_key in invoice_lines:
vals.append((0, False, invoice_lines[group_key]))
self.line_ids = vals
@@ -368,7 +392,12 @@ class LineAdvancePaymentInv(models.TransientModel):
product_id = fields.Many2one('product.product', string='Down Payment Product',
domain=[('type', '=', 'service')])
qty = fields.Integer('Quantity')
price_unit = fields.Float('Price')
price_unit = fields.Float('Price Unit')
price_total = fields.Float('Price Total', compute='_compute_price_total')
price_tax = fields.Float('Price Tax', compute='_compute_price_total')
price_subtotal = fields.Float('Price Subtotal',
compute='_compute_price_total',
store=True)
advance_inv_id = fields.Many2one('folio.advance.payment.inv')
price_room = fields.Float(compute='_compute_price_room')
discount = fields.Float(
@@ -384,9 +413,25 @@ class LineAdvancePaymentInv(models.TransientModel):
'hotel.reservation.line',
string='Reservation Lines')
@api.depends('qty', 'price_unit', 'discount')
def _compute_price_total(self):
for record in self:
origin = record.reservation_id if record.reservation_id.id else record.service_id
amount_line = record.price_unit * record.qty
if amount_line > 0:
product = record.product_id
price = amount_line * (1 - (record.discount or 0.0) * 0.01)
taxes = origin.tax_ids.compute_all(price, origin.currency_id, 1, product=product)
record.update({
'price_tax': sum(t.get('amount', 0.0) for t in taxes.get('taxes', [])),
'price_total': taxes['total_included'],
'price_subtotal': taxes['total_excluded'],
})
def _compute_price_room(self):
for record in self:
record.price_room = self.reservation_line_ids[0].price
if record.reservation_id:
record.price_room = record.reservation_line_ids[0].price
def _compute_folio_id(self):
for record in self:
@@ -426,7 +471,6 @@ class LineAdvancePaymentInv(models.TransientModel):
if fpos:
account = fpos.map_account(account)
vals = {
'name': line.description,
'sequence': origin.sequence,
'origin': origin.name,
'account_id': account.id,
@@ -441,13 +485,14 @@ class LineAdvancePaymentInv(models.TransientModel):
}
if line.reservation_id:
vals.update({
'name': line.description + ' (' + line.description_dates + ')',
'invoice_id': invoice_id,
'reservation_ids': [(6, 0, [origin.id])],
'reservation_line_ids': [(6, 0, line.reservation_line_ids.ids)]
})
import wdb; wdb.set_trace()
elif line.service_id:
vals.update({
'name': line.description,
'invoice_id': invoice_id,
'service_ids': [(6, 0, [origin.id])]
})

View File

@@ -53,15 +53,16 @@
<field name="service_id"
options="{'no_create': True,'no_open': True}"/>
<field name="description" />
<field name="description_dates" readonly="1" />
<field name="description_dates" readonly="1" force_save="1"/>
<field name="reservation_line_ids"
widget="many2many_tags" string="Nights"
domain="[('reservation_id','=',reservation_id),
('price','=', price_room)]"
options="{'no_create': True,'no_open': True}"/>
<field name="qty" />
<field name="discount" />
<field name="price_unit" />
<field name="discount" />
<field name="price_total" />
</tree>
</field>
</group>