Skip to content

Commit

Permalink
Merge PR #755 into 13.0
Browse files Browse the repository at this point in the history
Signed-off-by simahawk
  • Loading branch information
OCA-git-bot committed Aug 2, 2021
2 parents 6fd5684 + f15e7de commit 4c28f6c
Show file tree
Hide file tree
Showing 44 changed files with 804 additions and 0 deletions.
1 change: 1 addition & 0 deletions account_invoice_base_invoicing_mode/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
13 changes: 13 additions & 0 deletions account_invoice_base_invoicing_mode/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright 2020 Camptocamp
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "Account Invoice Base Invoicing Mode",
"version": "13.0.1.0.0",
"summary": "Base module for handling multiple invoicing mode",
"author": "Camptocamp, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/account-invoicing",
"license": "AGPL-3",
"category": "Accounting & Finance",
"depends": ["account", "queue_job", "sale"],
"data": ["views/res_partner.xml"],
}
4 changes: 4 additions & 0 deletions account_invoice_base_invoicing_mode/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from . import account_invoice
from . import queue_job
from . import res_partner
from . import sale_order
15 changes: 15 additions & 0 deletions account_invoice_base_invoicing_mode/models/account_invoice.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright 2020 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)

from odoo import models

from odoo.addons.queue_job.job import job, related_action


class AccountMove(models.Model):
_inherit = "account.move"

@job(default_channel="root.invoice_validation")
@related_action(action="related_action_open_invoice")
def _validate_invoice(self):
return self.sudo().action_post()
35 changes: 35 additions & 0 deletions account_invoice_base_invoicing_mode/models/queue_job.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Copyright 2020 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)

from odoo import _, models


class QueueJob(models.Model):
_inherit = "queue.job"

def related_action_open_invoice(self):
"""Open a form view with the invoice related to the job."""
self.ensure_one()
model_name = self.model_name
records = self.env[model_name].browse(self.record_ids).exists()
if not records:
return None
action = {
"name": _("Related Record"),
"type": "ir.actions.act_window",
"view_type": "form",
"view_mode": "form",
"res_model": records._name,
}
if len(records) == 1:
action["res_id"] = records.id
else:
action.update(
{
"name": _("Related Records"),
"view_mode": "tree,form",
"view_id": "account.view_invoice_tree",
"domain": [("id", "in", records.ids)],
}
)
return action
15 changes: 15 additions & 0 deletions account_invoice_base_invoicing_mode/models/res_partner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright 2020 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)

from odoo import fields, models


class ResPartner(models.Model):
_inherit = "res.partner"

invoicing_mode = fields.Selection([("standard", "Standard")], default="standard")
one_invoice_per_order = fields.Boolean(
"One invoice per order",
default=False,
help="Do not group sale order into one invoice.",
)
10 changes: 10 additions & 0 deletions account_invoice_base_invoicing_mode/models/sale_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Copyright 2020 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)

from odoo import fields, models


class SaleOrder(models.Model):
_inherit = "sale.order"

invoicing_mode = fields.Selection(related="partner_invoice_id.invoicing_mode")
3 changes: 3 additions & 0 deletions account_invoice_base_invoicing_mode/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
* `Camptocamp <https://www.camptocamp.com>`_:

* Thierry Ducrest <[email protected]>
9 changes: 9 additions & 0 deletions account_invoice_base_invoicing_mode/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
This is a base module for implementing different invoicing mode for customers.
It adds a selection field `invoicing_mode` in the Accounting tab of the partner
with a default value (Odoo standard invoicing mode).
But it serves no purpose installed on its own.

The following modules use it to install specific invoicing mode :

* `account_invoice_mode_at_shipping`
* `account_invoice_mode_monthly`
7 changes: 7 additions & 0 deletions account_invoice_base_invoicing_mode/readme/ROADMAP.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
On the version 13.0 PR it has been discussed to rename the modules like this:

* account_invoice_base_invoicing_mode -> partner_invoicing_mode
* account_invoice_mode_monthly -> partner_invoicing_mode_monthly
* account_invoice_mode_at_shipping -> partner_invoicing_mode_at_shipping

It would be great to do it, during the version 14.0 migration.
16 changes: 16 additions & 0 deletions account_invoice_base_invoicing_mode/views/res_partner.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="view_partner_property_form" model="ir.ui.view">
<field name="name">view_partner_property_form_base_invoicing_mode</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="account.view_partner_property_form" />
<field name="arch" type="xml">
<xpath expr="//page[@name='accounting']/group" position="inside">
<group name="invoicing_mode">
<field name="invoicing_mode" />
<field name="one_invoice_per_order" />
</group>
</xpath>
</field>
</record>
</odoo>
2 changes: 2 additions & 0 deletions account_invoice_mode_at_shipping/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import models
from . import tests
12 changes: 12 additions & 0 deletions account_invoice_mode_at_shipping/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Copyright 2020 Camptocamp
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "Account Invoice Mode At Shipping",
"version": "13.0.1.0.0",
"summary": "Create invoices automatically when goods are shipped.",
"author": "Camptocamp, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/account-invoicing",
"license": "AGPL-3",
"category": "Accounting & Finance",
"depends": ["account", "account_invoice_base_invoicing_mode", "queue_job", "stock"],
}
3 changes: 3 additions & 0 deletions account_invoice_mode_at_shipping/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import res_partner
from . import stock_move
from . import stock_picking
10 changes: 10 additions & 0 deletions account_invoice_mode_at_shipping/models/res_partner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Copyright 2020 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)

from odoo import fields, models


class ResPartner(models.Model):
_inherit = "res.partner"

invoicing_mode = fields.Selection(selection_add=([("at_shipping", "At Shipping")]))
19 changes: 19 additions & 0 deletions account_invoice_mode_at_shipping/models/stock_move.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright 2020 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)

from odoo import models


class StockMove(models.Model):
_inherit = "stock.move"

def _get_related_invoices(self):
""" Overridden from stock_account to return the customer invoices
related to this stock move.
"""
invoices = super()._get_related_invoices()
line_invoices = self.mapped("sale_line_id.order_id.invoice_ids").filtered(
lambda x: x.state == "posted"
)
invoices |= line_invoices
return invoices
53 changes: 53 additions & 0 deletions account_invoice_mode_at_shipping/models/stock_picking.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Copyright 2020 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)

from odoo import _, models

from odoo.addons.queue_job.job import job


class StockPicking(models.Model):
_inherit = "stock.picking"

def action_done(self):
res = super().action_done()

for picking in self:
if picking._invoice_at_shipping():
picking.with_delay()._invoicing_at_shipping()
return res

def _invoice_at_shipping(self):
"""Check if picking must be invoiced at shipping."""
self.ensure_one()
return (
self.picking_type_code == "outgoing"
and self.sale_id.partner_invoice_id.invoicing_mode == "at_shipping"
)

@job(default_channel="root.invoice_at_shipping")
def _invoicing_at_shipping(self):
self.ensure_one()
sales = self.env["sale.order"].browse()
# Filter out non invoicable sales order
for sale in self._get_sales_order_to_invoice():
if sale._get_invoiceable_lines():
sales |= sale
# Split invoice creation on partner sales grouping on invoice settings
sales_one_invoice_per_order = sales.filtered(
"partner_invoice_id.one_invoice_per_order"
)
invoices = self.env["account.move"].browse()
if sales_one_invoice_per_order:
invoices |= sales_one_invoice_per_order._create_invoices(grouped=True)
sales_many_invoice_per_order = sales - sales_one_invoice_per_order
if sales_many_invoice_per_order:
invoices |= sales_many_invoice_per_order._create_invoices(grouped=False)
for invoice in invoices:
invoice.with_delay()._validate_invoice()
return invoices or _("Nothing to invoice.")

def _get_sales_order_to_invoice(self):
return self.mapped("move_lines.sale_line_id.order_id").filtered(
lambda r: r._get_invoiceable_lines()
)
3 changes: 3 additions & 0 deletions account_invoice_mode_at_shipping/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
* `Camptocamp <https://www.camptocamp.com>`_:

* Thierry Ducrest <[email protected]>
4 changes: 4 additions & 0 deletions account_invoice_mode_at_shipping/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
This module allows to select a `At shipping` invoicing mode for a customer.
It is based on `account_invoice_base_invoicing_mode`.
When this mode is selected the customer will be invoiced automatically on
delivery of the goods.
1 change: 1 addition & 0 deletions account_invoice_mode_at_shipping/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import test_invoice_mode_at_shipping
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Copyright 2020 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)

from odoo.tests.common import SavepointCase


class TestInvoiceModeAtShipping(SavepointCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
cls.partner = cls.env.ref("base.res_partner_1")
cls.product = cls.env.ref("product.product_delivery_01")
cls.so1 = cls.env["sale.order"].create(
{
"partner_id": cls.partner.id,
"partner_invoice_id": cls.partner.id,
"partner_shipping_id": cls.partner.id,
"order_line": [
(
0,
0,
{
"name": "Line one",
"product_id": cls.product.id,
"product_uom_qty": 4,
"product_uom": cls.product.uom_id.id,
"price_unit": 123,
},
)
],
"pricelist_id": cls.env.ref("product.list0").id,
}
)
stock_location = cls.env.ref("stock.stock_location_stock")
inventory = cls.env["stock.inventory"].create(
{
"name": "Test Inventory",
"product_ids": [(6, 0, cls.product.ids)],
"state": "confirm",
"line_ids": [
(
0,
0,
{
"product_qty": 100,
"location_id": stock_location.id,
"product_id": cls.product.id,
"product_uom_id": cls.product.uom_id.id,
},
)
],
}
)
inventory.action_validate()

def test_invoice_created_at_shipping(self):
"""Check that an invoice is created when goods are shipped."""
self.partner.invoicing_mode = "at_shipping"
self.so1.action_confirm()
for picking in self.so1.picking_ids:
for line in picking.move_lines:
line.quantity_done = line.product_uom_qty
picking.action_assign()
picking.with_context(test_queue_job_no_delay=True).button_validate()
self.assertEqual(len(self.so1.invoice_ids), 1)
self.assertEqual(self.so1.invoice_ids.state, "posted")

def test_invoice_not_created_at_shipping(self):
"""Check that an invoice is not created when goods are shipped."""
self.partner.invoicing_mode = "standard"
self.so1.action_confirm()
for picking in self.so1.picking_ids:
for line in picking.move_lines:
line.quantity_done = line.product_uom_qty
picking.action_assign()
picking.button_validate()
self.assertEqual(len(self.so1.invoice_ids), 0)
2 changes: 2 additions & 0 deletions account_invoice_mode_monthly/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import models
from . import tests
13 changes: 13 additions & 0 deletions account_invoice_mode_monthly/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright 2020 Camptocamp
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "Account Invoice Mode Monthly",
"version": "13.0.1.0.0",
"summary": "Create invoices automatically on a monthly basis.",
"author": "Camptocamp, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/account-invoicing",
"license": "AGPL-3",
"category": "Accounting & Finance",
"depends": ["account", "account_invoice_base_invoicing_mode", "queue_job", "sale"],
"data": ["data/ir_cron.xml", "views/res_config_settings_views.xml"],
}
18 changes: 18 additions & 0 deletions account_invoice_mode_monthly/data/ir_cron.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo noupdate="1">
<record forcecreate="True" id="ir_cron_generate_monthly_invoice" model="ir.cron">
<field name="name">Generate Monthly Invoices</field>
<field eval="True" name="active" />
<field name="user_id" ref="base.user_root" />
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field eval="False" name="doall" />
<field name="model_id" ref="model_sale_order" />
<field name="code">model.cron_generate_monthly_invoices()</field>
<field
name="nextcall"
eval="(DateTime.now().replace(hour=1,minute=0).strftime('%Y-%m-%d %H:%M:%S'))"
/>
</record>
</odoo>
4 changes: 4 additions & 0 deletions account_invoice_mode_monthly/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from . import res_company
from . import res_config_settings
from . import res_partner
from . import sale_order
21 changes: 21 additions & 0 deletions account_invoice_mode_monthly/models/res_company.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Copyright 2020 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html)

from odoo import fields, models


class ResCompany(models.Model):
_inherit = "res.company"

invoicing_mode_monthly_day_todo = fields.Integer(
"Invoicing Day",
default="31",
help="Day of the month to execute the invoicing. For a number higher"
"than the number of days in a month, the invoicing will be"
"executed on the last day of the month.",
)
invoicing_mode_monthly_last_execution = fields.Datetime(
string="Last execution",
help="Last execution of monthly invoicing.",
readonly=True,
)
Loading

0 comments on commit 4c28f6c

Please sign in to comment.