mirror of
https://github.com/OCA/pms.git
synced 2025-01-29 00:17:45 +02:00
[IMP] allow invoicing several partners from folio (#64)
field partner_invoice_id (m2o)->partner_invoice_ids(m2m)
This commit is contained in:
@@ -212,18 +212,22 @@ class PmsFolio(models.Model):
|
||||
tracking=True,
|
||||
compute="_compute_amount",
|
||||
)
|
||||
partner_invoice_id = fields.Many2one(
|
||||
"res.partner",
|
||||
string="Invoice Address",
|
||||
compute="_compute_partner_invoice_id",
|
||||
partner_invoice_ids = fields.Many2many(
|
||||
string="Billing addresses",
|
||||
comodel_name="res.partner",
|
||||
relation="pms_folio_partner_rel",
|
||||
column1="folio",
|
||||
column2="partner",
|
||||
compute="_compute_partner_invoice_ids",
|
||||
store=True,
|
||||
readonly=False,
|
||||
help="Invoice address for current group.",
|
||||
)
|
||||
partner_invoice_state_id = fields.Many2one(related="partner_invoice_id.state_id")
|
||||
partner_invoice_country_id = fields.Many2one(
|
||||
related="partner_invoice_id.country_id"
|
||||
)
|
||||
# REVIEW THIS
|
||||
# partner_invoice_state_id = fields.Many2one(related="partner_invoice_id.state_id")
|
||||
# partner_invoice_country_id = fields.Many2one(
|
||||
# related="partner_invoice_id.country_id"
|
||||
# )
|
||||
fiscal_position_id = fields.Many2one(
|
||||
"account.fiscal.position", string="Fiscal Position"
|
||||
)
|
||||
@@ -477,11 +481,12 @@ class PmsFolio(models.Model):
|
||||
folio.user_id = (folio.partner_id.user_id.id or self.env.uid,)
|
||||
|
||||
@api.depends("partner_id")
|
||||
def _compute_partner_invoice_id(self):
|
||||
self.partner_invoice_id = False
|
||||
def _compute_partner_invoice_ids(self):
|
||||
for folio in self:
|
||||
folio.partner_invoice_ids = False
|
||||
addr = folio.partner_id.address_get(["invoice"])
|
||||
folio.partner_invoice_id = addr["invoice"]
|
||||
if not addr["invoice"] in folio.partner_invoice_ids.ids:
|
||||
folio.partner_invoice_ids = [(4, addr["invoice"])]
|
||||
|
||||
@api.depends("partner_id")
|
||||
def _compute_payment_term_id(self):
|
||||
@@ -885,7 +890,7 @@ class PmsFolio(models.Model):
|
||||
)
|
||||
record.checkin_partner_pending_count = sum(mapped_checkin_partner_count)
|
||||
|
||||
def _prepare_invoice(self):
|
||||
def _prepare_invoice(self, partner_invoice_id=False):
|
||||
"""
|
||||
Prepare the dict of values to create the new invoice for a folio.
|
||||
This method may be overridden to implement custom invoice generation
|
||||
@@ -912,7 +917,9 @@ class PmsFolio(models.Model):
|
||||
# 'medium_id': self.medium_id.id,
|
||||
# 'source_id': self.source_id.id,
|
||||
"invoice_user_id": self.user_id and self.user_id.id,
|
||||
"partner_id": self.partner_invoice_id.id,
|
||||
"partner_id": partner_invoice_id
|
||||
if partner_invoice_id
|
||||
else self.partner_invoice_ids[0],
|
||||
"partner_bank_id": self.company_id.partner_id.bank_ids[:1].id,
|
||||
"journal_id": journal.id, # company comes from the journal
|
||||
"invoice_origin": self.name,
|
||||
@@ -986,12 +993,13 @@ class PmsFolio(models.Model):
|
||||
final=False,
|
||||
date=None,
|
||||
lines_to_invoice=False,
|
||||
partner_invoice_id=False,
|
||||
):
|
||||
"""
|
||||
Create the invoice associated to the Folio.
|
||||
:param grouped: if True, invoices are grouped by Folio id.
|
||||
If False, invoices are grouped by
|
||||
(partner_invoice_id, currency)
|
||||
(partner_invoice_ids, currency)
|
||||
:param final: if True, refunds will be generated if necessary
|
||||
:param lines_to_invoice: invoice specific lines dict(key=id, value=qty).
|
||||
if False, invoice all
|
||||
@@ -1011,7 +1019,9 @@ class PmsFolio(models.Model):
|
||||
0 if line.display_type else line.qty_to_invoice
|
||||
)
|
||||
invoice_vals_list = self.get_invoice_vals_list(
|
||||
final=final, lines_to_invoice=lines_to_invoice
|
||||
final=final,
|
||||
lines_to_invoice=lines_to_invoice,
|
||||
partner_invoice_id=partner_invoice_id,
|
||||
)
|
||||
|
||||
if not invoice_vals_list:
|
||||
@@ -1118,7 +1128,9 @@ class PmsFolio(models.Model):
|
||||
)
|
||||
return moves
|
||||
|
||||
def get_invoice_vals_list(self, final=False, lines_to_invoice=False):
|
||||
def get_invoice_vals_list(
|
||||
self, final=False, lines_to_invoice=False, partner_invoice_id=False
|
||||
):
|
||||
precision = self.env["decimal.precision"].precision_get(
|
||||
"Product Unit of Measure"
|
||||
)
|
||||
@@ -1130,7 +1142,7 @@ class PmsFolio(models.Model):
|
||||
down_payments = order.env["folio.sale.line"]
|
||||
|
||||
# Invoice values.
|
||||
invoice_vals = order._prepare_invoice()
|
||||
invoice_vals = order._prepare_invoice(partner_invoice_id=partner_invoice_id)
|
||||
|
||||
# Invoice line values (keep only necessary sections).
|
||||
invoice_lines_vals = []
|
||||
|
||||
@@ -6,9 +6,11 @@
|
||||
<t t-set="address">
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<t t-if="doc.partner_invoice_id != doc.partner_id">
|
||||
<t
|
||||
t-if="len(doc.partner_invoice_ids)==1 and doc.partner_id != doc.partner_invoice_ids[0]"
|
||||
>
|
||||
<div
|
||||
t-field="doc.partner_invoice_id"
|
||||
t-field="doc.partner_invoice_ids[0]"
|
||||
t-options='{"widget": "contact", "fields": ["address", "name", "phone"], "no_marker": True, "phone_icons": True}'
|
||||
/>
|
||||
</t>
|
||||
|
||||
@@ -132,6 +132,52 @@ class TestPmsFolioInvoice(TestHotel):
|
||||
"The status after an invoicing is not correct",
|
||||
)
|
||||
|
||||
def test_invoice_partial_folio_diferent_partners(self):
|
||||
# ARRANGE
|
||||
self.create_common_scenario()
|
||||
r1 = self.env["pms.reservation"].create(
|
||||
{
|
||||
"pms_property_id": self.property.id,
|
||||
"checkin": datetime.datetime.now(),
|
||||
"checkout": datetime.datetime.now() + datetime.timedelta(days=3),
|
||||
"adults": 2,
|
||||
"room_type_id": self.room_type_double.id,
|
||||
"partner_id": self.env.ref("base.res_partner_12").id,
|
||||
}
|
||||
)
|
||||
dict_lines = dict()
|
||||
# qty to 1 to 1st folio sale line
|
||||
dict_lines[
|
||||
r1.folio_id.sale_line_ids.filtered(lambda l: not l.display_type)[0].id
|
||||
] = 1
|
||||
r1.folio_id._create_invoices(
|
||||
lines_to_invoice=dict_lines,
|
||||
partner_invoice_id=self.env.ref("base.res_partner_1"),
|
||||
)
|
||||
|
||||
# test does not work without invalidating cache
|
||||
self.env["account.move"].invalidate_cache()
|
||||
|
||||
self.assertNotEqual(
|
||||
"invoiced",
|
||||
r1.folio_id.invoice_status,
|
||||
"The status after a partial invoicing is not correct",
|
||||
)
|
||||
|
||||
# qty to 2 to 1st folio sale line
|
||||
dict_lines[
|
||||
r1.folio_id.sale_line_ids.filtered(lambda l: not l.display_type)[0].id
|
||||
] = 2
|
||||
r1.folio_id._create_invoices(
|
||||
lines_to_invoice=dict_lines,
|
||||
partner_invoice_id=self.env.ref("base.res_partner_12"),
|
||||
)
|
||||
self.assertNotEqual(
|
||||
r1.folio_id.move_ids.mapped("partner_id")[0],
|
||||
r1.folio_id.move_ids.mapped("partner_id")[1],
|
||||
"The status after an invoicing is not correct",
|
||||
)
|
||||
|
||||
def test_invoice_partial_folio_wrong_qtys(self):
|
||||
# ARRANGE
|
||||
self.create_common_scenario()
|
||||
|
||||
@@ -381,7 +381,7 @@
|
||||
</div>
|
||||
<group>
|
||||
<field
|
||||
name="partner_invoice_id"
|
||||
name="partner_invoice_ids"
|
||||
string="Contact Invoiced"
|
||||
/>
|
||||
</group>
|
||||
@@ -484,7 +484,7 @@
|
||||
<field name="arch" type="xml">
|
||||
<search string="Tables Detail">
|
||||
<field name="partner_id" />
|
||||
<field name="partner_invoice_id" />
|
||||
<field name="partner_invoice_ids" />
|
||||
<field name="agency_id" />
|
||||
<filter
|
||||
name="to_invoice"
|
||||
@@ -506,7 +506,7 @@
|
||||
<filter
|
||||
string="Invoice Contact"
|
||||
name="group_invoice_contact"
|
||||
context="{'group_by':'partner_invoice_id'}"
|
||||
context="{'group_by':'partner_invoice_ids'}"
|
||||
/>
|
||||
<filter
|
||||
string="Tour Operator"
|
||||
|
||||
@@ -49,6 +49,20 @@ class FolioAdvancePaymentInv(models.TransientModel):
|
||||
sale_order = self.env["pms.folio"].browse(self._context.get("active_id"))
|
||||
return sale_order.currency_id
|
||||
|
||||
@api.model
|
||||
def _default_partner_invoice_id(self):
|
||||
if self._context.get("active_model") == "pms.folio" and self._context.get(
|
||||
"active_id", False
|
||||
):
|
||||
folio = self.env["pms.folio"].browse(self._context.get("active_id", []))
|
||||
return folio.partner_invoice_ids[0]
|
||||
|
||||
partner_invoice_id = fields.Many2one(
|
||||
comodel_name="res.partner",
|
||||
string="Billing contact",
|
||||
default=_default_partner_invoice_id,
|
||||
)
|
||||
|
||||
advance_payment_method = fields.Selection(
|
||||
[
|
||||
("delivered", "Regular invoice"),
|
||||
@@ -116,7 +130,9 @@ class FolioAdvancePaymentInv(models.TransientModel):
|
||||
"invoice_origin": order.name,
|
||||
"invoice_user_id": order.user_id.id,
|
||||
"narration": order.note,
|
||||
"partner_id": order.partner_invoice_id.id,
|
||||
"partner_id": self.partner_invoice_id
|
||||
if self.partner_invoice_id
|
||||
else order.partner_invoice_id.id,
|
||||
"currency_id": order.pricelist_id.currency_id.id,
|
||||
"payment_reference": order.reference,
|
||||
"invoice_payment_term_id": order.payment_term_id.id,
|
||||
@@ -211,6 +227,9 @@ class FolioAdvancePaymentInv(models.TransientModel):
|
||||
folios._create_invoices(
|
||||
final=self.deduct_down_payments,
|
||||
lines_to_invoice=lines_to_invoice,
|
||||
partner_invoice_id=self.partner_invoice_id
|
||||
if self.partner_invoice_id
|
||||
else False,
|
||||
)
|
||||
else:
|
||||
# Create deposit product if necessary
|
||||
|
||||
@@ -83,6 +83,7 @@
|
||||
<group>
|
||||
<field name="bill_services" widget="boolean_toggle" />
|
||||
<field name="bill_rooms" widget="boolean_toggle" />
|
||||
<field name="partner_invoice_id" />
|
||||
</group>
|
||||
</group>
|
||||
<footer>
|
||||
|
||||
Reference in New Issue
Block a user