forked from OCA/sale-workflow
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[10.0][ADD] sale_order_invoicing_finished_task: New module (OCA#500)
* [10.0][ADD] sale_order_invoicing_finished_task: New module * [10.0][IMP] sale_order_invoicing_finished_task: Toggle invoiceable flag in task. * [10.0][FIX] sale_order_invoicing_finished_task: Not invoiceable status * [10.0][IMP] sale_order_invoicing_finished_task: check invoice policy * Add files for README * Update README.rst * Change some format issues in README * Change license to AGPL and improve readme * Update __manifest__.py Add Camptocamp as author * [10.0][FIX] sale_order_invoicing_finished_task: Overwrite create and write methods because the stage_id field onchange not trigger in a form view with statusbar widget * [10.0][IMP] sale_order_invoicing_finished_task: Add tests
- Loading branch information
1 parent
f18e687
commit 6223c3c
Showing
15 changed files
with
500 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg | ||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html | ||
:alt: License: AGPL-3 | ||
|
||
================================== | ||
Sale Order Invoicing Finished Task | ||
================================== | ||
|
||
The requirement of this module is to give the possibility in the task to indicate if a task is available to invoice or not. This means by default even the task is not finished you could set it as invoiceable. | ||
|
||
As an option you can relate to a Proyect Stage ( ``project.task.type`` ) this control. For example if you want to assign Invoiceable to stage ``Done`` always | ||
|
||
Usage | ||
===== | ||
|
||
To use this module, you need to: | ||
|
||
1. Go to Sales -> Product and create a service product | ||
|
||
2. In the product go to Invoicing tab and select (1) An invocing policy (2) Track | ||
service must be create a task and tack hours (3) Set Invoicing finished task | ||
checkbox and save | ||
|
||
|
||
.. image:: static/description/product_view_invoicefinishedtask.png | ||
|
||
|
||
3. Go to Sales -> Sale orders -> Create a new one. Add a customer y the product | ||
you have created | ||
4. Confirm the sales order, it will create you a proyect and a task | ||
5. Go to the task and you will find a smartbutton called Not invoiceable, when | ||
you press the button you will indicate that the task can be invoiced | ||
|
||
.. image:: static/description/task_view_invoicefinishedtask.png | ||
|
||
6. Optional: if you want to use project stages to control this Go To Proyect -> Settings -> Stage -> You have to set true the field Invoiceable in the stages that you consider are invoiceable. Event to use stages for this functionality you can also set it manually in the task whenever you want. | ||
|
||
You can try it in:' | ||
|
||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas | ||
:alt: Try me on Runbot | ||
:target: https://runbot.odoo-community.org/runbot/167/10.0 | ||
|
||
Bug Tracker | ||
=========== | ||
|
||
Bugs are tracked on `GitHub Issues | ||
<https://github.com/OCA/167/issues>`_. In case of trouble, please | ||
check there if your issue has already been reported. If you spotted it first, | ||
help us smashing it by providing a detailed and welcomed feedback. | ||
|
||
Credits | ||
======= | ||
|
||
Images | ||
------ | ||
|
||
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/ | ||
blob/master/template/module/static/description/icon.svg>`_. | ||
|
||
|
||
Contributors | ||
------------ | ||
|
||
* Denis Leemann <[email protected]> | ||
* Sergio Teruel <[email protected]> | ||
* Carlos Dauden <[email protected]> | ||
|
||
Maintainer | ||
---------- | ||
|
||
.. image:: https://odoo-community.org/logo.png | ||
:alt: Odoo Community Association | ||
:target: https://odoo-community.org | ||
|
||
This module is maintained by the OCA. | ||
|
||
OCA, or the Odoo Community Association, is a nonprofit organization whose | ||
mission is to support the collaborative development of Odoo features and | ||
promote its widespread use. | ||
|
||
To contribute to this module, please visit https://odoo-community.org. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
from . import models |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# -*- coding: utf-8 -*- | ||
# Copyright 2017 Sergio Teruel <[email protected]> | ||
# Copyright 2017 Carlos Dauden <[email protected]> | ||
# Copyright 2017 Camptocamp SA | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). | ||
|
||
{ | ||
"name": "Sale Order Invoicing Finished Task", | ||
"summary": "Control invoice order lines if his task has been finished", | ||
"version": "10.0.1.0.0", | ||
"category": "Sales", | ||
"website": "https://github.com/OCA/sale-workflow", | ||
"author": "Tecnativa, " | ||
"Camptocamp, " | ||
"Odoo Community Association (OCA)", | ||
"license": "AGPL-3", | ||
"application": False, | ||
"installable": True, | ||
"depends": [ | ||
"sale_timesheet", | ||
], | ||
"data": [ | ||
"views/product_view.xml", | ||
"views/project_view.xml", | ||
], | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
from . import product | ||
from . import project | ||
from . import sale_order |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# -*- coding: utf-8 -*- | ||
# Copyright 2017 Sergio Teruel <[email protected]> | ||
# Copyright 2017 Carlos Dauden <[email protected]> | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
from odoo import fields, models | ||
|
||
|
||
class ProductTemplate(models.Model): | ||
_inherit = 'product.template' | ||
|
||
invoicing_finished_task = fields.Boolean( | ||
help='Invoice the order lines only when the task is in folded stage', | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
# -*- coding: utf-8 -*- | ||
# Copyright 2017 Camptocamp SA | ||
# Copyright 2017 Sergio Teruel <[email protected]> | ||
# Copyright 2017 Carlos Dauden <[email protected]> | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
from odoo import _, api, fields, models | ||
from odoo.exceptions import ValidationError, UserError | ||
|
||
|
||
class ProjectTaskType(models.Model): | ||
_inherit = 'project.task.type' | ||
|
||
invoiceable = fields.Boolean( | ||
string='Invoiceable', | ||
) | ||
|
||
|
||
class ProjectTask(models.Model): | ||
_inherit = 'project.task' | ||
|
||
invoiceable = fields.Boolean( | ||
string='Invoiceable', | ||
) | ||
invoicing_finished_task = fields.Boolean( | ||
related='sale_line_id.product_id.invoicing_finished_task', | ||
readonly=True, | ||
) | ||
|
||
@api.onchange('stage_id') | ||
def _onchange_stage_id(self): | ||
for task in self: | ||
if task.invoicing_finished_task and \ | ||
task.stage_id.invoiceable and\ | ||
not task.invoiceable: | ||
task.invoiceable = True | ||
|
||
@api.multi | ||
def toggle_invoiceable(self): | ||
for task in self: | ||
# We dont' want to modify when the related SOLine is invoiced | ||
if (not task.sale_line_id or | ||
task.sale_line_id.state in ('done', 'cancel') or | ||
task.sale_line_id.invoice_status in ('invoiced',)): | ||
raise UserError(_("You cannot modify the status if there is " | ||
"no Sale Order Line or if it has been " | ||
"invoiced.")) | ||
task.invoiceable = not task.invoiceable | ||
|
||
@api.multi | ||
def write(self, vals): | ||
for task in self: | ||
if (vals.get('sale_line_id') and | ||
task.sale_line_id.state in ('done', 'cancel')): | ||
raise ValidationError(_('You cannot modify the Sale Order ' | ||
'Line of the task once it is invoiced') | ||
) | ||
res = super(ProjectTask, self).write(vals) | ||
# Onchange stage_id field is not triggered with statusbar widget | ||
if 'stage_id' in vals: | ||
self._onchange_stage_id() | ||
return res | ||
|
||
@api.model | ||
def create(self, vals): | ||
SOLine = self.env['sale.order.line'] | ||
so_line = SOLine.browse(vals.get('sale_line_id')) | ||
# We don't want to add a project.task to an already invoiced line | ||
if so_line and so_line.state in ('done', 'cancel'): | ||
raise ValidationError(_('You cannot add a task to and invoiced ' | ||
'Sale Order Line')) | ||
# Onchange stage_id field is not triggered with statusbar widget | ||
if 'sale_line_id' in vals: | ||
stage = self.env['project.task.type'].browse(vals['stage_id']) | ||
if so_line.product_id.invoicing_finished_task and \ | ||
stage.invoiceable: | ||
vals['invoiceable'] = True | ||
return super(ProjectTask, self).create(vals) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# -*- coding: utf-8 -*- | ||
# Copyright 2017 Sergio Teruel <[email protected]> | ||
# Copyright 2017 Carlos Dauden <[email protected]> | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
from odoo import api, fields, models | ||
|
||
|
||
class SaleOrder(models.Model): | ||
_inherit = 'sale.order' | ||
|
||
@api.depends('state', 'order_line.invoice_status', | ||
'order_line.task_ids.invoiceable') | ||
def _get_invoiced(self): | ||
super(SaleOrder, self)._get_invoiced() | ||
for order in self: | ||
if not all(order.tasks_ids.mapped('invoiceable')): | ||
order.update({ | ||
'invoice_status': 'no', | ||
}) | ||
|
||
|
||
class SaleOrderLine(models.Model): | ||
_inherit = 'sale.order.line' | ||
|
||
task_ids = fields.One2many( | ||
comodel_name='project.task', | ||
inverse_name='sale_line_id', | ||
string='Tasks', | ||
) | ||
|
||
@api.depends('qty_invoiced', 'qty_delivered', 'product_uom_qty', | ||
'order_id.state', 'task_ids.invoiceable') | ||
def _get_to_invoice_qty(self): | ||
lines = self.filtered( | ||
lambda x: (x.product_id.type == 'service' and | ||
x.product_id.invoicing_finished_task and | ||
x.product_id.track_service == 'task') | ||
) | ||
for line in lines: | ||
if all(line.task_ids.mapped('invoiceable')): | ||
if line.product_id.invoice_policy == 'order': | ||
line.qty_to_invoice = ( | ||
line.product_uom_qty - line.qty_invoiced) | ||
else: | ||
line.qty_to_invoice = ( | ||
line.qty_delivered - line.qty_invoiced) | ||
else: | ||
line.qty_to_invoice = 0.0 | ||
super(SaleOrderLine, self - lines)._get_to_invoice_qty() |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions
9
sale_order_invoicing_finished_task/static/description/icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+55.2 KB
...invoicing_finished_task/static/description/product_view_invoicefinishedtask.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+53 KB
...er_invoicing_finished_task/static/description/task_view_invoicefinishedtask.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# -*- coding: utf-8 -*- | ||
# Copyright 2017 Sergio Teruel <[email protected]> | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). | ||
|
||
from . import test_sale_order_invoicing_finished_task |
Oops, something went wrong.