Merge pull request #208 from sbejaoui/12.0-mig-product_contract

[12.0][IMP] - Create contract on sale order order confirmation
This commit is contained in:
Bejaoui Souheil
2019-10-01 13:35:44 +02:00
committed by GitHub
54 changed files with 2649 additions and 1 deletions

View File

@@ -4,7 +4,7 @@
<menuitem <menuitem
id="menu_contract_sale" name="Contracts" id="menu_contract_sale" name="Contracts"
parent="sale.sale_order_menu" parent="sale.sale_order_menu"
action="contract.action_supplier_contract" action="contract.action_customer_contract"
sequence="2" sequence="2"
groups="sales_team.group_sale_salesman" groups="sales_team.group_sale_salesman"
/> />

View File

@@ -0,0 +1,73 @@
==========================
Contract Sale Payment Mode
==========================
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fcontract-lightgray.png?logo=github
:target: https://github.com/OCA/contract/tree/12.0/contract_sale_payment_mode
:alt: OCA/contract
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/contract-12-0/contract-12-0-contract_sale_payment_mode
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
:target: https://runbot.odoo-community.org/runbot/110/12.0
:alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
This module manages the payment mode from sale order to contract.
**Table of contents**
.. contents::
:local:
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/contract/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 <https://github.com/OCA/contract/issues/new?body=module:%20contract_sale_payment_mode%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
~~~~~~~
* ACSONE SA/NV
Contributors
~~~~~~~~~~~~
* Thomas Binsfeld <thomas.binsfeld@acsone.eu>
Maintainers
~~~~~~~~~~~
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
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.
This module is part of the `OCA/contract <https://github.com/OCA/contract/tree/12.0/contract_sale_payment_mode>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View File

@@ -0,0 +1,2 @@
from . import models
from . import tests

View File

@@ -0,0 +1,22 @@
# Copyright 2019 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
'name': 'Contract Sale Payment Mode',
'summary': """
This addon manages payment mode from sale order to contract.""",
'version': '12.0.1.0.0',
'license': 'AGPL-3',
'author': 'ACSONE SA/NV,Odoo Community Association (OCA)',
'website': 'https://acsone.eu/',
'depends': [
# OCA/bank-payment
'account_payment_sale',
# OCA/contract
'product_contract',
],
'data': [
],
'demo': [
],
}

View File

@@ -0,0 +1 @@
from . import sale_order

View File

@@ -0,0 +1,16 @@
# Copyright 2019 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, models
class SaleOrder(models.Model):
_inherit = 'sale.order'
@api.multi
def _prepare_contract_value(self, contract_template):
self.ensure_one()
vals = super(SaleOrder, self)._prepare_contract_value(
contract_template)
vals['payment_mode_id'] = self.payment_mode_id.id
return vals

View File

@@ -0,0 +1 @@
* Thomas Binsfeld <thomas.binsfeld@acsone.eu>

View File

@@ -0,0 +1 @@
This module manages the payment mode from sale order to contract.

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -0,0 +1,419 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.14: http://docutils.sourceforge.net/" />
<title>Contract Sale Payment Mode</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="contract-sale-payment-mode">
<h1 class="title">Contract Sale Payment Mode</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/contract/tree/12.0/contract_sale_payment_mode"><img alt="OCA/contract" src="https://img.shields.io/badge/github-OCA%2Fcontract-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/contract-12-0/contract-12-0-contract_sale_payment_mode"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/110/12.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p>This module manages the payment mode from sale order to contract.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#bug-tracker" id="id1">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id2">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id3">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id4">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="id5">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#id1">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/contract/issues">GitHub Issues</a>.
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
<a class="reference external" href="https://github.com/OCA/contract/issues/new?body=module:%20contract_sale_payment_mode%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#id2">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#id3">Authors</a></h2>
<ul class="simple">
<li>ACSONE SA/NV</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#id4">Contributors</a></h2>
<ul class="simple">
<li>Thomas Binsfeld &lt;<a class="reference external" href="mailto:thomas.binsfeld&#64;acsone.eu">thomas.binsfeld&#64;acsone.eu</a>&gt;</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#id5">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>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.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/contract/tree/12.0/contract_sale_payment_mode">OCA/contract</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1 @@
from . import test_sale_order

View File

@@ -0,0 +1,21 @@
# Copyright 2018 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo.addons.product_contract.tests.test_sale_order import TestSaleOrder
class TestSaleOrderPaymentMode(TestSaleOrder):
def setUp(self):
super(TestSaleOrderPaymentMode, self).setUp()
self.payment_mode = self.env['account.payment.mode'].search(
[], limit=1
)
self.sale.payment_mode_id = self.payment_mode
def test_action_confirm_with_payment_mode(self):
self.test_action_confirm()
self.assertEqual(
self.sale.order_line.mapped('contract_id.payment_mode_id'),
self.payment_mode,
)

View File

@@ -0,0 +1,66 @@
.. 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
================
Product Contract
================
This module adds support for products to be linked to contract templates.
It also adds functionality to automatically create a contract, from the template,
when a ``sale.order`` contains a product that implements a contract.
Usage
=====
To use this module, you need to:
#. Go to Sales -> Products and select or create a product.
#. Check "Is a contract" and select the contract template related to the
product
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/110/10.0
Known issues / Roadmap
======================
* None
Bug Tracker
===========
Bugs are tracked on `GitHub Issues
<https://github.com/OCA/contract/issues>`_. In case of trouble, please
check there if your issue has already been reported. If you spotted it first,
help us smash it by providing 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
------------
* Ted Salmon <tsalmon@laslabs.com>
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.

View File

@@ -0,0 +1,4 @@
# Copyright 2017 LasLabs Inc.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import models

View File

@@ -0,0 +1,24 @@
# Copyright 2017 LasLabs Inc.
# Copyright 2018 ACSONE SA/NV.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
'name': 'Recurring - Product Contract',
'version': '12.0.2.0.0',
'category': 'Contract Management',
'license': 'AGPL-3',
'author': "LasLabs, "
"ACSONE SA/NV, "
"Odoo Community Association (OCA)",
'website': 'https://github.com/oca/contract',
'depends': ['product', 'contract_sale'],
'data': [
'views/res_config_settings.xml',
'views/contract.xml',
'views/product_template.xml',
'views/sale_order.xml'
],
'installable': True,
'application': False,
"external_dependencies": {"python": ["dateutil"]},
}

View File

@@ -0,0 +1,51 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_contract
#
# Translators:
# OCA Transbot <transbot@odoo-community.org>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-04-27 02:40+0000\n"
"PO-Revision-Date: 2017-04-27 02:40+0000\n"
"Last-Translator: OCA Transbot <transbot@odoo-community.org>, 2017\n"
"Language-Team: German (https://www.transifex.com/oca/teams/23907/de/)\n"
"Language: de\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_sale_order_line_contract_id
msgid "Contract"
msgstr "Vertrag"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_contract_template_id
#: model:ir.model.fields,field_description:product_contract.field_product_template_contract_template_id
msgid "Contract Template"
msgstr ""
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_is_contract
#: model:ir.model.fields,field_description:product_contract.field_product_template_is_contract
msgid "Is a contract"
msgstr ""
#. module: product_contract
#: model:ir.model,name:product_contract.model_product_template
msgid "Product Template"
msgstr ""
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order
msgid "Sales Order"
msgstr ""
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order_line
msgid "Sales Order Line"
msgstr ""

View File

@@ -0,0 +1,52 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_contract
#
# Translators:
# OCA Transbot <transbot@odoo-community.org>, 2017
# enjolras <yo@miguelrevilla.com>, 2018
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-02-10 03:15+0000\n"
"PO-Revision-Date: 2018-02-10 03:15+0000\n"
"Last-Translator: enjolras <yo@miguelrevilla.com>, 2018\n"
"Language-Team: Spanish (https://www.transifex.com/oca/teams/23907/es/)\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_sale_order_line_contract_id
msgid "Contract"
msgstr "Contrato"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_contract_template_id
#: model:ir.model.fields,field_description:product_contract.field_product_template_contract_template_id
msgid "Contract Template"
msgstr "Plantilla de contrato"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_is_contract
#: model:ir.model.fields,field_description:product_contract.field_product_template_is_contract
msgid "Is a contract"
msgstr "Es un contrato"
#. module: product_contract
#: model:ir.model,name:product_contract.model_product_template
msgid "Product Template"
msgstr "Plantilla de producto"
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order
msgid "Sales Order"
msgstr "Pedido de venta"
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order_line
msgid "Sales Order Line"
msgstr "Línea de pedido de venta"

View File

@@ -0,0 +1,51 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_contract
#
# Translators:
# Jarmo Kortetjärvi <jarmo.kortetjarvi@gmail.com>, 2018
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-03-10 01:44+0000\n"
"PO-Revision-Date: 2018-03-10 01:44+0000\n"
"Last-Translator: Jarmo Kortetjärvi <jarmo.kortetjarvi@gmail.com>, 2018\n"
"Language-Team: Finnish (https://www.transifex.com/oca/teams/23907/fi/)\n"
"Language: fi\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_sale_order_line_contract_id
msgid "Contract"
msgstr "Contract"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_contract_template_id
#: model:ir.model.fields,field_description:product_contract.field_product_template_contract_template_id
msgid "Contract Template"
msgstr "Sopimusmalli"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_is_contract
#: model:ir.model.fields,field_description:product_contract.field_product_template_is_contract
msgid "Is a contract"
msgstr ""
#. module: product_contract
#: model:ir.model,name:product_contract.model_product_template
msgid "Product Template"
msgstr ""
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order
msgid "Sales Order"
msgstr ""
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order_line
msgid "Sales Order Line"
msgstr ""

View File

@@ -0,0 +1,53 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_contract
#
# Translators:
# leemannd <denis.leemann@camptocamp.com>, 2017
# David BEAL, 2018
# Fabien Bourgeois <fabien@yaltik.com>, 2018
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-05-19 02:01+0000\n"
"PO-Revision-Date: 2018-05-19 02:01+0000\n"
"Last-Translator: Fabien Bourgeois <fabien@yaltik.com>, 2018\n"
"Language-Team: French (https://www.transifex.com/oca/teams/23907/fr/)\n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_sale_order_line_contract_id
msgid "Contract"
msgstr "Contrat"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_contract_template_id
#: model:ir.model.fields,field_description:product_contract.field_product_template_contract_template_id
msgid "Contract Template"
msgstr "Modèle de contrat"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_is_contract
#: model:ir.model.fields,field_description:product_contract.field_product_template_is_contract
msgid "Is a contract"
msgstr ""
#. module: product_contract
#: model:ir.model,name:product_contract.model_product_template
msgid "Product Template"
msgstr ""
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order
msgid "Sales Order"
msgstr "Vente"
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order_line
msgid "Sales Order Line"
msgstr ""

View File

@@ -0,0 +1,52 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_contract
#
# Translators:
# Ashish Deshmukh <ashish.p.deshmukh@gmail.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-08-17 01:05+0000\n"
"PO-Revision-Date: 2017-08-17 01:05+0000\n"
"Last-Translator: Ashish Deshmukh <ashish.p.deshmukh@gmail.com>, 2017\n"
"Language-Team: Hindi (India) (https://www.transifex.com/oca/teams/23907/"
"hi_IN/)\n"
"Language: hi_IN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_sale_order_line_contract_id
msgid "Contract"
msgstr "अनुबंध"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_contract_template_id
#: model:ir.model.fields,field_description:product_contract.field_product_template_contract_template_id
msgid "Contract Template"
msgstr "अनुबंध टेम्पलेट"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_is_contract
#: model:ir.model.fields,field_description:product_contract.field_product_template_is_contract
msgid "Is a contract"
msgstr "एक अनुबंध है"
#. module: product_contract
#: model:ir.model,name:product_contract.model_product_template
msgid "Product Template"
msgstr "प्रोडक्ट टेम्पलेट"
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order
msgid "Sales Order"
msgstr "बिक्री आदेश"
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order_line
msgid "Sales Order Line"
msgstr "बिक्री आदेश पंक्ति"

View File

@@ -0,0 +1,52 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_contract
#
# Translators:
# Bole <bole@dajmi5.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-02-10 03:15+0000\n"
"PO-Revision-Date: 2018-02-10 03:15+0000\n"
"Last-Translator: Bole <bole@dajmi5.com>, 2017\n"
"Language-Team: Croatian (https://www.transifex.com/oca/teams/23907/hr/)\n"
"Language: hr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_sale_order_line_contract_id
msgid "Contract"
msgstr "Ugovor"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_contract_template_id
#: model:ir.model.fields,field_description:product_contract.field_product_template_contract_template_id
msgid "Contract Template"
msgstr "Predložak ugovora"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_is_contract
#: model:ir.model.fields,field_description:product_contract.field_product_template_is_contract
msgid "Is a contract"
msgstr "Je ugovor"
#. module: product_contract
#: model:ir.model,name:product_contract.model_product_template
msgid "Product Template"
msgstr "Predložak proizvoda"
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order
msgid "Sales Order"
msgstr "Ponuda"
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order_line
msgid "Sales Order Line"
msgstr "Stavka ponude"

View File

@@ -0,0 +1,54 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_contract
#
# Translators:
# OCA Transbot <transbot@odoo-community.org>, 2017
# Bole <bole@dajmi5.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-06-17 01:39+0000\n"
"PO-Revision-Date: 2017-06-17 01:39+0000\n"
"Last-Translator: Bole <bole@dajmi5.com>, 2017\n"
"Language-Team: Croatian (Croatia) (https://www.transifex.com/oca/teams/23907/"
"hr_HR/)\n"
"Language: hr_HR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_sale_order_line_contract_id
msgid "Contract"
msgstr "Ugovor"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_contract_template_id
#: model:ir.model.fields,field_description:product_contract.field_product_template_contract_template_id
msgid "Contract Template"
msgstr "Predložak ugovora"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_is_contract
#: model:ir.model.fields,field_description:product_contract.field_product_template_is_contract
msgid "Is a contract"
msgstr "Je ugovor"
#. module: product_contract
#: model:ir.model,name:product_contract.model_product_template
msgid "Product Template"
msgstr "Predložak proizvoda"
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order
msgid "Sales Order"
msgstr "Prodajni nalog"
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order_line
msgid "Sales Order Line"
msgstr "Stavka prodajnog naloga"

View File

@@ -0,0 +1,51 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_contract
#
# Translators:
# Lorenzo Battistini <lorenzo.battistini@agilebg.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-04-27 02:40+0000\n"
"PO-Revision-Date: 2017-04-27 02:40+0000\n"
"Last-Translator: Lorenzo Battistini <lorenzo.battistini@agilebg.com>, 2017\n"
"Language-Team: Italian (https://www.transifex.com/oca/teams/23907/it/)\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_sale_order_line_contract_id
msgid "Contract"
msgstr "Contratto"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_contract_template_id
#: model:ir.model.fields,field_description:product_contract.field_product_template_contract_template_id
msgid "Contract Template"
msgstr "Template di contratto"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_is_contract
#: model:ir.model.fields,field_description:product_contract.field_product_template_is_contract
msgid "Is a contract"
msgstr ""
#. module: product_contract
#: model:ir.model,name:product_contract.model_product_template
msgid "Product Template"
msgstr ""
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order
msgid "Sales Order"
msgstr ""
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order_line
msgid "Sales Order Line"
msgstr ""

View File

@@ -0,0 +1,52 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_contract
#
# Translators:
# Erwin van der Ploeg <erwin@odooexperts.nl>, 2017
# lfreeke <lfreeke@therp.nl>, 2018
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-01-06 03:17+0000\n"
"PO-Revision-Date: 2018-01-06 03:17+0000\n"
"Last-Translator: lfreeke <lfreeke@therp.nl>, 2018\n"
"Language-Team: Dutch (https://www.transifex.com/oca/teams/23907/nl/)\n"
"Language: nl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_sale_order_line_contract_id
msgid "Contract"
msgstr "Contract"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_contract_template_id
#: model:ir.model.fields,field_description:product_contract.field_product_template_contract_template_id
msgid "Contract Template"
msgstr "Contractsjabloon"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_is_contract
#: model:ir.model.fields,field_description:product_contract.field_product_template_is_contract
msgid "Is a contract"
msgstr "Is een contract"
#. module: product_contract
#: model:ir.model,name:product_contract.model_product_template
msgid "Product Template"
msgstr "Productsjabloon"
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order
msgid "Sales Order"
msgstr "Verkooporder"
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order_line
msgid "Sales Order Line"
msgstr "Verkooporderregel"

View File

@@ -0,0 +1,52 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_contract
#
# Translators:
# Peter Hageman <hageman.p@gmail.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-06-09 01:10+0000\n"
"PO-Revision-Date: 2017-06-09 01:10+0000\n"
"Last-Translator: Peter Hageman <hageman.p@gmail.com>, 2017\n"
"Language-Team: Dutch (Netherlands) (https://www.transifex.com/oca/"
"teams/23907/nl_NL/)\n"
"Language: nl_NL\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_sale_order_line_contract_id
msgid "Contract"
msgstr "Contract"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_contract_template_id
#: model:ir.model.fields,field_description:product_contract.field_product_template_contract_template_id
msgid "Contract Template"
msgstr "Contractsjabloon"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_is_contract
#: model:ir.model.fields,field_description:product_contract.field_product_template_is_contract
msgid "Is a contract"
msgstr "Is een contract"
#. module: product_contract
#: model:ir.model,name:product_contract.model_product_template
msgid "Product Template"
msgstr "Productsjabloon"
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order
msgid "Sales Order"
msgstr "Verkooporder"
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order_line
msgid "Sales Order Line"
msgstr "Verkooporderregel"

View File

@@ -0,0 +1,47 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_contract
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_sale_order_line_contract_id
msgid "Contract"
msgstr ""
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_contract_template_id
#: model:ir.model.fields,field_description:product_contract.field_product_template_contract_template_id
msgid "Contract Template"
msgstr ""
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_is_contract
#: model:ir.model.fields,field_description:product_contract.field_product_template_is_contract
msgid "Is a contract"
msgstr ""
#. module: product_contract
#: model:ir.model,name:product_contract.model_product_template
msgid "Product Template"
msgstr ""
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order
msgid "Sales Order"
msgstr ""
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order_line
msgid "Sales Order Line"
msgstr ""

View File

@@ -0,0 +1,51 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_contract
#
# Translators:
# Pedro Castro Silva <pedrocs@sossia.pt>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-07-15 01:24+0000\n"
"PO-Revision-Date: 2017-07-15 01:24+0000\n"
"Last-Translator: Pedro Castro Silva <pedrocs@sossia.pt>, 2017\n"
"Language-Team: Portuguese (https://www.transifex.com/oca/teams/23907/pt/)\n"
"Language: pt\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_sale_order_line_contract_id
msgid "Contract"
msgstr "Contrato"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_contract_template_id
#: model:ir.model.fields,field_description:product_contract.field_product_template_contract_template_id
msgid "Contract Template"
msgstr "Modelo de Contrato"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_is_contract
#: model:ir.model.fields,field_description:product_contract.field_product_template_is_contract
msgid "Is a contract"
msgstr "É um Contrato"
#. module: product_contract
#: model:ir.model,name:product_contract.model_product_template
msgid "Product Template"
msgstr "Modelo de Produto"
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order
msgid "Sales Order"
msgstr "Encomenda de Venda"
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order_line
msgid "Sales Order Line"
msgstr "Linha de Encomenda de Venda"

View File

@@ -0,0 +1,53 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_contract
#
# Translators:
# OCA Transbot <transbot@odoo-community.org>, 2017
# falexandresilva <falexandresilva@gmail.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-06-13 02:40+0000\n"
"PO-Revision-Date: 2017-06-13 02:40+0000\n"
"Last-Translator: falexandresilva <falexandresilva@gmail.com>, 2017\n"
"Language-Team: Portuguese (Brazil) (https://www.transifex.com/oca/"
"teams/23907/pt_BR/)\n"
"Language: pt_BR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_sale_order_line_contract_id
msgid "Contract"
msgstr "Contrato"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_contract_template_id
#: model:ir.model.fields,field_description:product_contract.field_product_template_contract_template_id
msgid "Contract Template"
msgstr ""
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_is_contract
#: model:ir.model.fields,field_description:product_contract.field_product_template_is_contract
msgid "Is a contract"
msgstr ""
#. module: product_contract
#: model:ir.model,name:product_contract.model_product_template
msgid "Product Template"
msgstr ""
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order
msgid "Sales Order"
msgstr "Pedido de compras"
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order_line
msgid "Sales Order Line"
msgstr ""

View File

@@ -0,0 +1,53 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_contract
#
# Translators:
# nek, 2018
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-03-17 03:26+0000\n"
"PO-Revision-Date: 2018-03-17 03:26+0000\n"
"Last-Translator: nek, 2018\n"
"Language-Team: Russian (https://www.transifex.com/oca/teams/23907/ru/)\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
"%100>=11 && n%100<=14)? 2 : 3);\n"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_sale_order_line_contract_id
msgid "Contract"
msgstr "Договор"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_contract_template_id
#: model:ir.model.fields,field_description:product_contract.field_product_template_contract_template_id
msgid "Contract Template"
msgstr "Шаблон Договора"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_is_contract
#: model:ir.model.fields,field_description:product_contract.field_product_template_is_contract
msgid "Is a contract"
msgstr "Это Договор"
#. module: product_contract
#: model:ir.model,name:product_contract.model_product_template
msgid "Product Template"
msgstr "Шаблон Продукта"
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order
msgid "Sales Order"
msgstr ""
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order_line
msgid "Sales Order Line"
msgstr ""

View File

@@ -0,0 +1,51 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_contract
#
# Translators:
# Ediz Duman <neps1192@gmail.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-04-21 01:48+0000\n"
"PO-Revision-Date: 2018-04-21 01:48+0000\n"
"Last-Translator: Ediz Duman <neps1192@gmail.com>, 2017\n"
"Language-Team: Turkish (https://www.transifex.com/oca/teams/23907/tr/)\n"
"Language: tr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_sale_order_line_contract_id
msgid "Contract"
msgstr "Sözleşme"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_contract_template_id
#: model:ir.model.fields,field_description:product_contract.field_product_template_contract_template_id
msgid "Contract Template"
msgstr "Sözleşme Şablonu"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_is_contract
#: model:ir.model.fields,field_description:product_contract.field_product_template_is_contract
msgid "Is a contract"
msgstr "Sözleşmeli"
#. module: product_contract
#: model:ir.model,name:product_contract.model_product_template
msgid "Product Template"
msgstr "Ürün Şablonu"
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order
msgid "Sales Order"
msgstr "Satış Siparişi"
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order_line
msgid "Sales Order Line"
msgstr "Satış Sipariş Satırı"

View File

@@ -0,0 +1,52 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_contract
#
# Translators:
# Ediz Duman <neps1192@gmail.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-04-27 02:40+0000\n"
"PO-Revision-Date: 2017-04-27 02:40+0000\n"
"Last-Translator: Ediz Duman <neps1192@gmail.com>, 2017\n"
"Language-Team: Turkish (Turkey) (https://www.transifex.com/oca/teams/23907/"
"tr_TR/)\n"
"Language: tr_TR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=1; plural=0;\n"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_sale_order_line_contract_id
msgid "Contract"
msgstr "Sözleşme"
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_contract_template_id
#: model:ir.model.fields,field_description:product_contract.field_product_template_contract_template_id
msgid "Contract Template"
msgstr ""
#. module: product_contract
#: model:ir.model.fields,field_description:product_contract.field_product_product_is_contract
#: model:ir.model.fields,field_description:product_contract.field_product_template_is_contract
msgid "Is a contract"
msgstr ""
#. module: product_contract
#: model:ir.model,name:product_contract.model_product_template
msgid "Product Template"
msgstr ""
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order
msgid "Sales Order"
msgstr ""
#. module: product_contract
#: model:ir.model,name:product_contract.model_sale_order_line
msgid "Sales Order Line"
msgstr ""

View File

@@ -0,0 +1,18 @@
# Copyright 2019 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
from openupgradelib import openupgrade
_logger = logging.getLogger(__name__)
def migrate(cr, version):
xmlids_to_rename = [
(
'product_contract.account_analytic_account_recurring_form_form',
'product_contract.contract_contract_customer_form_view',
)
]
openupgrade.rename_xmlids(cr, xmlids_to_rename)

View File

@@ -0,0 +1,11 @@
# Copyright 2017 LasLabs Inc.
# Copyright 2018 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import contract
from . import contract_line
from . import product_template
from . import sale_order
from . import sale_order_line
from . import res_company
from . import res_config_settings

View File

@@ -0,0 +1,39 @@
# Copyright 2018 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
from odoo.exceptions import AccessError
from odoo.tools.translate import _
class ContractContract(models.Model):
_inherit = 'contract.contract'
sale_order_count = fields.Integer(compute="_compute_sale_order_count")
@api.depends('contract_line_ids')
def _compute_sale_order_count(self):
for rec in self:
try:
order_count = len(
rec.contract_line_ids.mapped(
'sale_order_line_id.order_id'
)
)
except AccessError:
order_count = 0
rec.sale_order_count = order_count
@api.multi
def action_view_sales_orders(self):
self.ensure_one()
orders = self.contract_line_ids.mapped(
'sale_order_line_id.order_id'
)
return {
"name": _("Sales Orders"),
"view_mode": "tree,form",
"res_model": "sale.order",
"type": "ir.actions.act_window",
"domain": [("id", "in", orders.ids)],
}

View File

@@ -0,0 +1,64 @@
# Copyright 2017 LasLabs Inc.
# Copyright 2018 ACSONE SA/NV.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
class ContractLine(models.Model):
_inherit = 'contract.line'
_rec_name = 'display_name'
sale_order_line_id = fields.Many2one(
comodel_name="sale.order.line",
string="Sale Order Line",
required=False,
copy=False,
)
display_name = fields.Char(compute='_compute_display_name_2')
@api.multi
def _prepare_invoice_line(self, invoice_id=False):
res = super(ContractLine, self)._prepare_invoice_line(
invoice_id=invoice_id
)
if self.sale_order_line_id and res:
res['sale_line_ids'] = [(6, 0, [self.sale_order_line_id.id])]
return res
@api.multi
def _get_auto_renew_rule_type(self):
"""monthly last day don't make sense for auto_renew_rule_type"""
self.ensure_one()
if self.recurring_rule_type == "monthlylastday":
return "monthly"
return self.recurring_rule_type
@api.onchange('product_id')
def _onchange_product_id_recurring_info(self):
for rec in self:
rec.date_start = fields.Date.today()
if rec.product_id.is_contract:
rec.recurring_rule_type = rec.product_id.recurring_rule_type
rec.recurring_invoicing_type = (
rec.product_id.recurring_invoicing_type
)
rec.recurring_interval = 1
rec.is_auto_renew = rec.product_id.is_auto_renew
rec.auto_renew_interval = rec.product_id.default_qty
rec.auto_renew_rule_type = rec._get_auto_renew_rule_type()
rec.termination_notice_interval = (
rec.product_id.termination_notice_interval
)
rec.termination_notice_rule_type = (
rec.product_id.termination_notice_rule_type
)
@api.depends('name', 'date_start')
def _compute_display_name_2(self):
# FIXME: _compute_display_name depends on rec_name (display_name)
# and this trigger a WARNING : display_name depends on itself;
# please fix its decorator
for rec in self:
rec.display_name = ("%s - %s") % (rec.date_start, rec.name)

View File

@@ -0,0 +1,59 @@
# Copyright 2017 LasLabs Inc.
# Copyright 2018 ACSONE SA/NV.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
class ProductTemplate(models.Model):
_inherit = 'product.template'
is_contract = fields.Boolean('Is a contract')
contract_template_id = fields.Many2one(
comodel_name='contract.template', string='Contract Template'
)
default_qty = fields.Integer(string="Default Quantity", default=1)
recurring_rule_type = fields.Selection(
[
('daily', 'Day(s)'),
('weekly', 'Week(s)'),
('monthly', 'Month(s)'),
('monthlylastday', 'Month(s) last day'),
('yearly', 'Year(s)'),
],
default='monthly',
string='Invoice Every',
help="Specify Interval for automatic invoice generation.",
)
recurring_invoicing_type = fields.Selection(
[('pre-paid', 'Pre-paid'), ('post-paid', 'Post-paid')],
default='pre-paid',
string='Invoicing type',
help="Specify if process date is 'from' or 'to' invoicing date",
)
is_auto_renew = fields.Boolean(string="Auto Renew", default=False)
termination_notice_interval = fields.Integer(
default=1, string='Termination Notice Before'
)
termination_notice_rule_type = fields.Selection(
[('daily', 'Day(s)'), ('weekly', 'Week(s)'), ('monthly', 'Month(s)')],
default='monthly',
string='Termination Notice type',
)
@api.onchange('is_contract')
def _change_is_contract(self):
""" Clear the relation to contract_template_id when downgrading
product from contract
"""
if not self.is_contract:
self.contract_template_id = False
@api.constrains('is_contract', 'type')
def _check_contract_product_type(self):
"""
Contract product should be service type
"""
if self.is_contract and self.type != 'service':
raise ValidationError(_("Contract product should be service type"))

View File

@@ -0,0 +1,14 @@
# Copyright 2019 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class ResCompany(models.Model):
_inherit = 'res.company'
create_contract_at_sale_order_confirmation = fields.Boolean(
string="Automatically Create Contracts At Sale Order Confirmation",
default=True,
)

View File

@@ -0,0 +1,14 @@
# Copyright 2019 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
create_contract_at_sale_order_confirmation = fields.Boolean(
related="company_id.create_contract_at_sale_order_confirmation",
readonly=False
)

View File

@@ -0,0 +1,118 @@
# Copyright 2017 LasLabs Inc.
# Copyright 2018 ACSONE SA/NV.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import fields, api, models
class SaleOrder(models.Model):
_inherit = 'sale.order'
is_contract = fields.Boolean(
string='Is a contract', compute='_compute_is_contract'
)
contract_count = fields.Integer(compute='_compute_contract_count')
need_contract_creation = fields.Boolean(
compute='_compute_need_contract_creation'
)
@api.depends('order_line.contract_id', 'state')
def _compute_need_contract_creation(self):
for rec in self:
if rec.state in ('sale', 'done'):
line_to_create_contract = rec.order_line.filtered(
lambda r: not r.contract_id and r.product_id.is_contract
)
line_to_update_contract = rec.order_line.filtered(
lambda r: r.contract_id
and r.product_id.is_contract
and r
not in r.contract_id.contract_line_ids.mapped(
'sale_order_line_id'
)
)
if line_to_create_contract or line_to_update_contract:
rec.need_contract_creation = True
@api.depends('order_line')
def _compute_is_contract(self):
self.is_contract = any(self.order_line.mapped('is_contract'))
@api.multi
def _prepare_contract_value(self, contract_template):
self.ensure_one()
return {
'name': '{template_name}: {sale_name}'.format(
template_name=contract_template.name, sale_name=self.name
),
'partner_id': self.partner_id.id,
'contract_template_id': contract_template.id,
'user_id': self.user_id.id,
'payment_term_id': self.payment_term_id.id,
'fiscal_position_id': self.fiscal_position_id.id,
'invoice_partner_id': self.partner_invoice_id.id,
}
@api.multi
def action_create_contract(self):
contract_model = self.env['contract.contract']
contracts = self.env['contract.contract']
for rec in self.filtered('is_contract'):
line_to_create_contract = rec.order_line.filtered(
lambda r: not r.contract_id and r.product_id.is_contract
)
line_to_update_contract = rec.order_line.filtered(
lambda r: r.contract_id
and r.product_id.is_contract
and r
not in r.contract_id.contract_line_ids.mapped(
'sale_order_line_id'
)
)
for contract_template in line_to_create_contract.mapped(
'product_id.contract_template_id'
):
order_lines = line_to_create_contract.filtered(
lambda r, template=contract_template:
r.product_id.contract_template_id == template
)
contract = contract_model.create(
rec._prepare_contract_value(contract_template)
)
contracts |= contract
contract._onchange_contract_template_id()
order_lines.create_contract_line(contract)
order_lines.write({'contract_id': contract.id})
for line in line_to_update_contract:
line.create_contract_line(line.contract_id)
return contracts
@api.multi
def action_confirm(self):
""" If we have a contract in the order, set it up """
self.filtered(
lambda order: (
order.company_id.create_contract_at_sale_order_confirmation
)
).action_create_contract()
return super(SaleOrder, self).action_confirm()
@api.multi
@api.depends("order_line")
def _compute_contract_count(self):
for rec in self:
rec.contract_count = len(rec.order_line.mapped('contract_id'))
@api.multi
def action_show_contracts(self):
self.ensure_one()
action = self.env.ref(
"contract.action_customer_contract"
).read()[0]
contracts = (
self.env['contract.line']
.search([('sale_order_line_id', 'in', self.order_line.ids)])
.mapped('contract_id')
)
action["domain"] = [("id", "in", contracts.ids)]
return action

View File

@@ -0,0 +1,248 @@
# Copyright 2017 LasLabs Inc.
# Copyright 2017 ACSONE SA/NV.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
class SaleOrderLine(models.Model):
_inherit = 'sale.order.line'
is_contract = fields.Boolean(
string='Is a contract', related="product_id.is_contract"
)
contract_id = fields.Many2one(
comodel_name='contract.contract', string='Contract', copy=False
)
contract_template_id = fields.Many2one(
comodel_name='contract.template',
string='Contract Template',
related='product_id.product_tmpl_id.contract_template_id',
readonly=True,
)
recurring_rule_type = fields.Selection(
[
('daily', 'Day(s)'),
('weekly', 'Week(s)'),
('monthly', 'Month(s)'),
('monthlylastday', 'Month(s) last day'),
('yearly', 'Year(s)'),
],
default='monthly',
string='Invoice Every',
copy=False,
)
recurring_invoicing_type = fields.Selection(
[('pre-paid', 'Pre-paid'), ('post-paid', 'Post-paid')],
default='pre-paid',
string='Invoicing type',
help="Specify if process date is 'from' or 'to' invoicing date",
copy=False,
)
date_start = fields.Date(string='Date Start')
date_end = fields.Date(string='Date End')
contract_line_id = fields.Many2one(
comodel_name="contract.line",
string="Contract Line to replace",
required=False,
copy=False,
)
@api.multi
def _get_auto_renew_rule_type(self):
"""monthly last day don't make sense for auto_renew_rule_type"""
self.ensure_one()
if self.recurring_rule_type == "monthlylastday":
return "monthly"
return self.recurring_rule_type
@api.onchange('product_id')
def onchange_product(self):
contract_line_model = self.env['contract.line']
for rec in self:
if rec.product_id.is_contract:
rec.product_uom_qty = rec.product_id.default_qty
rec.recurring_rule_type = rec.product_id.recurring_rule_type
rec.recurring_invoicing_type = (
rec.product_id.recurring_invoicing_type
)
rec.date_start = rec.date_start or fields.Date.today()
rec.date_end = (
rec.date_start
+ contract_line_model.get_relative_delta(
rec._get_auto_renew_rule_type(),
int(rec.product_uom_qty),
)
- relativedelta(days=1)
)
@api.onchange('date_start', 'product_uom_qty', 'recurring_rule_type')
def onchange_date_start(self):
contract_line_model = self.env['contract.line']
for rec in self.filtered('product_id.is_contract'):
if not rec.date_start:
rec.date_end = False
else:
rec.date_end = (
rec.date_start
+ contract_line_model.get_relative_delta(
rec._get_auto_renew_rule_type(),
int(rec.product_uom_qty),
)
- relativedelta(days=1)
)
@api.multi
def _prepare_contract_line_values(
self, contract, predecessor_contract_line_id=False
):
"""
:param contract: related contract
:param predecessor_contract_line_id: contract line to replace id
:return: new contract line dict
"""
self.ensure_one()
recurring_next_date = self.env[
'contract.line'
]._compute_first_recurring_next_date(
self.date_start or fields.Date.today(),
self.recurring_invoicing_type,
self.recurring_rule_type,
1,
)
termination_notice_interval = (
self.product_id.termination_notice_interval
)
termination_notice_rule_type = (
self.product_id.termination_notice_rule_type
)
return {
'sequence': self.sequence,
'product_id': self.product_id.id,
'name': self.name,
# The quantity on the generated contract line is 1, as it
# correspond to the most common use cases:
# - quantity on the SO line = number of periods sold and unit
# price the price of one period, so the
# total amount of the SO corresponds to the planned value
# of the contract; in this case the quantity on the contract
# line must be 1
# - quantity on the SO line = number of hours sold,
# automatic invoicing of the actual hours through a variable
# quantity formula, in which case the quantity on the contract
# line is not used
# Other use cases are easy to implement by overriding this method.
'quantity': 1.0,
'uom_id': self.product_uom.id,
'price_unit': self.price_unit,
'discount': self.discount,
'date_end': self.date_end,
'date_start': self.date_start or fields.Date.today(),
'recurring_next_date': recurring_next_date,
'recurring_interval': 1,
'recurring_invoicing_type': self.recurring_invoicing_type,
'recurring_rule_type': self.recurring_rule_type,
'is_auto_renew': self.product_id.is_auto_renew,
'auto_renew_interval': self.product_uom_qty,
'auto_renew_rule_type': self._get_auto_renew_rule_type(),
'termination_notice_interval': termination_notice_interval,
'termination_notice_rule_type': termination_notice_rule_type,
'contract_id': contract.id,
'sale_order_line_id': self.id,
'predecessor_contract_line_id': predecessor_contract_line_id,
}
@api.multi
def create_contract_line(self, contract):
contract_line_model = self.env['contract.line']
contract_line = self.env['contract.line']
predecessor_contract_line = False
for rec in self:
if rec.contract_line_id:
# If the upsell/downsell line start at the same date or before
# the contract line to replace supposed to start, we cancel
# the one to be replaced. Otherwise we stop it.
if rec.date_start <= rec.contract_line_id.date_start:
# The contract will handel the contract line integrity
# An exception will be raised if we try to cancel an
# invoiced contract line
rec.contract_line_id.cancel()
elif (
not rec.contract_line_id.date_end
or rec.date_start <= rec.contract_line_id.date_end
):
rec.contract_line_id.stop(
rec.date_start - relativedelta(days=1)
)
predecessor_contract_line = rec.contract_line_id
if predecessor_contract_line:
new_contract_line = contract_line_model.create(
rec._prepare_contract_line_values(
contract, predecessor_contract_line.id
)
)
predecessor_contract_line.successor_contract_line_id = (
new_contract_line
)
else:
new_contract_line = contract_line_model.create(
rec._prepare_contract_line_values(contract)
)
contract_line |= new_contract_line
return contract_line
@api.constrains('contract_id')
def _check_contract_sale_partner(self):
for rec in self:
if rec.contract_id:
if rec.order_id.partner_id != rec.contract_id.partner_id:
raise ValidationError(
_(
"Sale Order and contract should be "
"linked to the same partner"
)
)
@api.constrains('product_id', 'contract_id')
def _check_contract_sale_contract_template(self):
for rec in self:
if rec.contract_id:
if (
rec.contract_id.contract_template_id
and rec.contract_template_id
!= rec.contract_id.contract_template_id
):
raise ValidationError(
_("Contract product has different contract template")
)
def _compute_invoice_status(self):
res = super(SaleOrderLine, self)._compute_invoice_status()
for line in self.filtered('contract_id'):
line.invoice_status = 'no'
return res
@api.multi
def invoice_line_create(self, invoice_id, qty):
return super(
SaleOrderLine, self.filtered(lambda l: not l.contract_id)
).invoice_line_create(invoice_id, qty)
@api.depends(
'qty_invoiced',
'qty_delivered',
'product_uom_qty',
'order_id.state',
'product_id.is_contract',
)
def _get_to_invoice_qty(self):
"""
sale line linked to contracts must not be invoiced from sale order
"""
res = super()._get_to_invoice_qty()
self.filtered('product_id.is_contract').update({'qty_to_invoice': 0.0})
return res

View File

@@ -0,0 +1,2 @@
* Ted Salmon <tsalmon@laslabs.com>
* Souheil Bejaoui <souheil.bejaoui@acsone.eu>

View File

@@ -0,0 +1,5 @@
This module adds support for products to be linked to contract templates.
A contract is created on ``sale.order`` confirmation for each different template used in sale order line where recurrence details are set too.
Contract product are ignored on invoicing process and pass to nothing to invoice directly.

View File

@@ -0,0 +1,6 @@
To use this module, you need to:
#. Go to Sales -> Products and select or create a product.
#. Check "Is a contract" and select the contract template related to the
product
#. Define default recurrence rules

View File

@@ -0,0 +1,6 @@
# Copyright 2017 LasLabs Inc.
# Copyright 2018 ACSONE SA/NV.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import test_product
from . import test_sale_order

View File

@@ -0,0 +1,33 @@
# Copyright 2017 LasLabs Inc.
# Copyright 2018 ACSONE SA/NV.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo.tests.common import TransactionCase
from odoo.exceptions import ValidationError
class TestProductTemplate(TransactionCase):
def setUp(self):
super(TestProductTemplate, self).setUp()
self.service_product = self.env.ref('product.product_product_1')
self.consu_product = self.env.ref('product.product_product_5')
self.contract = self.env['contract.template'].create(
{'name': 'Test'}
)
def test_change_is_contract(self):
""" It should verify that the contract_template_id is removed
when is_contract is False """
self.service_product.is_contract = True
self.service_product.contract_template_id = self.contract.id
self.service_product.is_contract = False
self.service_product.product_tmpl_id._change_is_contract()
self.assertEquals(len(self.service_product.contract_template_id), 0)
def test_check_contract_product_type(self):
"""
It should raise ValidationError on change of is_contract to True
for consu product
"""
with self.assertRaises(ValidationError):
self.consu_product.is_contract = True

View File

@@ -0,0 +1,315 @@
# Copyright 2017 LasLabs Inc.
# Copyright 2018 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from dateutil.relativedelta import relativedelta
from odoo.tests.common import TransactionCase
from odoo.exceptions import ValidationError
from odoo.fields import Date
class TestSaleOrder(TransactionCase):
def setUp(self):
super(TestSaleOrder, self).setUp()
self.product1 = self.env.ref('product.product_product_1')
self.product2 = self.env.ref('product.product_product_2')
self.sale = self.env.ref('sale.sale_order_2')
self.contract_template1 = self.env['contract.template'].create(
{'name': 'Template 1'}
)
self.contract_template2 = self.env['contract.template'].create(
{
'name': 'Template 2',
'contract_line_ids': [
(
0,
0,
{
'product_id': self.product2.id,
'name': 'Services from #START# to #END#',
'quantity': 1,
'uom_id': self.product2.uom_id.id,
'price_unit': 100,
'discount': 50,
'recurring_rule_type': 'yearly',
'recurring_interval': 1,
},
)
],
}
)
self.product1.write(
{
'is_contract': True,
'default_qty': 12,
'recurring_rule_type': "monthlylastday",
'contract_template_id': self.contract_template1.id,
}
)
self.product2.write(
{
'is_contract': True,
'contract_template_id': self.contract_template2.id,
}
)
self.order_line1 = self.sale.order_line.filtered(
lambda l: l.product_id == self.product1
)
self.order_line1.date_start = '2018-01-01'
self.order_line1.product_uom_qty = 12
pricelist = self.sale.partner_id.property_product_pricelist.id
self.contract = self.env["contract.contract"].create(
{
"name": "Test Contract 2",
"partner_id": self.sale.partner_id.id,
"pricelist_id": pricelist,
"contract_type": "sale",
"contract_template_id": self.contract_template1.id,
"contract_line_ids": [
(
0,
0,
{
"product_id": self.product1.id,
"name": "Services from #START# to #END#",
"quantity": 1,
"uom_id": self.product1.uom_id.id,
"price_unit": 100,
"discount": 50,
"recurring_rule_type": "monthly",
"recurring_interval": 1,
"date_start": "2016-02-15",
"recurring_next_date": "2016-02-29",
},
)
],
}
)
self.contract_line = self.contract.contract_line_ids[0]
def test_compute_is_contract(self):
"""Sale Order should have is_contract true if one of its lines is
contract"""
self.assertTrue(self.sale.is_contract)
def test_action_confirm(self):
""" It should create a contract for each contract template used in
order_line """
self.order_line1.onchange_product()
self.sale.action_confirm()
contracts = self.sale.order_line.mapped('contract_id')
self.assertEqual(len(contracts), 2)
self.assertEqual(
self.order_line1.contract_id.contract_template_id,
self.contract_template1,
)
contract_line = self.order_line1.contract_id.contract_line_ids
self.assertEqual(contract_line.date_start, Date.to_date('2018-01-01'))
self.assertEqual(contract_line.date_end, Date.to_date('2018-12-31'))
self.assertEqual(
contract_line.recurring_next_date, Date.to_date('2018-01-31')
)
def test_sale_order_invoice_status(self):
"""
sale line linked to contracts must not be invoiced from sale order
"""
self.sale.action_confirm()
self.assertEqual(self.order_line1.invoice_status, 'no')
invoice = self.order_line1.contract_id.recurring_create_invoice()
self.assertTrue(invoice)
self.assertEqual(self.order_line1.invoice_qty, 1)
self.assertEqual(self.order_line1.qty_to_invoice, 0)
def test_action_confirm_without_contract_creation(self):
""" It should create a contract for each contract template used in
order_line """
self.sale.company_id.create_contract_at_sale_order_confirmation = False
self.order_line1.onchange_product()
self.sale.action_confirm()
self.assertEqual(len(self.sale.order_line.mapped('contract_id')), 0)
self.assertTrue(self.sale.need_contract_creation)
self.sale.action_create_contract()
self.assertEqual(len(self.sale.order_line.mapped('contract_id')), 2)
self.assertFalse(self.sale.need_contract_creation)
self.assertEqual(
self.order_line1.contract_id.contract_template_id,
self.contract_template1,
)
contract_line = self.order_line1.contract_id.contract_line_ids
self.assertEqual(contract_line.date_start, Date.to_date('2018-01-01'))
self.assertEqual(contract_line.date_end, Date.to_date('2018-12-31'))
self.assertEqual(
contract_line.recurring_next_date, Date.to_date('2018-01-31')
)
def test_sale_contract_count(self):
"""It should count contracts as many different contract template used
in order_line"""
self.order_line1.onchange_product()
self.sale.action_confirm()
self.assertEqual(self.sale.contract_count, 2)
def test_onchange_product(self):
""" It should get recurrence invoicing info to the sale line from
its product """
self.order_line1.onchange_product()
self.assertEqual(
self.order_line1.recurring_rule_type,
self.product1.recurring_rule_type,
)
self.assertEqual(
self.order_line1.recurring_invoicing_type,
self.product1.recurring_invoicing_type,
)
self.assertEqual(self.order_line1.date_end, Date.to_date('2018-12-31'))
def test_check_contract_sale_partner(self):
"""Can't link order line to a partner contract different then the
order one"""
contract2 = self.env['contract.contract'].create(
{
'name': 'Contract',
'contract_template_id': self.contract_template2.id,
'partner_id': self.sale.partner_id.id,
}
)
with self.assertRaises(ValidationError):
self.order_line1.contract_id = contract2
def test_check_contract_sale_contract_template(self):
"""Can't link order line to a contract with different contract
template then the product one"""
contract1 = self.env['contract.contract'].create(
{
'name': 'Contract',
'partner_id': self.env.user.partner_id.id,
'contract_template_id': self.contract_template1.id,
}
)
with self.assertRaises(ValidationError):
self.order_line1.contract_id = contract1
def test_no_contract_proudct(self):
"""it should create contract for only product contract"""
self.product1.is_contract = False
self.sale.action_confirm()
self.assertFalse(self.order_line1.contract_id)
def test_sale_order_line_invoice_status(self):
"""Sale order line for contract product should have nothing to
invoice as status"""
self.order_line1.onchange_product()
self.sale.action_confirm()
self.assertEqual(self.order_line1.invoice_status, 'no')
def test_sale_order_invoice_status(self):
"""Sale order with only contract product should have nothing to
invoice status directtly"""
self.sale.order_line.filtered(
lambda line: not line.product_id.is_contract
).unlink()
self.order_line1.onchange_product()
self.sale.action_confirm()
self.assertEqual(self.sale.invoice_status, 'no')
def test_sale_order_create_invoice(self):
"""Should not invoice contract product on sale order create invoice"""
self.product2.is_contract = False
self.product2.invoice_policy = 'order'
self.order_line1.onchange_product()
self.sale.action_confirm()
self.sale.action_invoice_create()
self.assertEqual(len(self.sale.invoice_ids), 1)
invoice_line = self.sale.invoice_ids.invoice_line_ids.filtered(
lambda line: line.product_id.is_contract
)
self.assertEqual(len(invoice_line), 0)
def test_link_contract_invoice_to_sale_order(self):
"""It should link contract invoice to sale order"""
self.order_line1.onchange_product()
self.sale.action_confirm()
invoice = self.order_line1.contract_id.recurring_create_invoice()
self.assertTrue(invoice in self.sale.invoice_ids)
def test_contract_upsell(self):
"""Should stop contract line at sale order line start date"""
self.order_line1.contract_id = self.contract
self.order_line1.contract_line_id = self.contract_line
self.contract_line.date_end = Date.today() + relativedelta(months=4)
self.contract_line.is_auto_renew = True
self.order_line1.date_start = "2018-06-01"
self.order_line1.onchange_product()
self.sale.action_confirm()
self.assertEqual(
self.contract_line.date_end, Date.to_date("2018-05-31")
)
self.assertFalse(self.contract_line.is_auto_renew)
new_contract_line = self.env['contract.line'].search(
[('sale_order_line_id', '=', self.order_line1.id)]
)
self.assertEqual(
self.contract_line.successor_contract_line_id, new_contract_line
)
self.assertEqual(
new_contract_line.predecessor_contract_line_id, self.contract_line
)
def test_contract_upsell_2(self):
"""Should stop contract line at sale order line start date"""
self.order_line1.contract_id = self.contract
self.order_line1.contract_line_id = self.contract_line
self.contract_line.write(
{
'date_start': "2018-06-01",
'recurring_next_date': "2018-06-01",
'date_end': False,
}
)
self.order_line1.date_start = "2018-06-01"
self.order_line1.onchange_product()
self.sale.action_confirm()
self.assertFalse(self.contract_line.date_end)
self.assertTrue(self.contract_line.is_canceled)
def test_onchange_product_id_recurring_info(self):
self.product2.write(
{
'recurring_rule_type': 'monthly',
'recurring_invoicing_type': 'pre-paid',
'is_auto_renew': True,
'default_qty': 12,
'termination_notice_interval': '6',
'termination_notice_rule_type': 'weekly',
}
)
self.contract_line.write(
{
'date_start': Date.today(),
'date_end': Date.today() + relativedelta(years=1),
'recurring_next_date': Date.today(),
'product_id': self.product2.id,
}
)
self.contract_line._onchange_product_id_recurring_info()
self.assertEqual(self.contract_line.recurring_rule_type, 'monthly')
self.assertEqual(
self.contract_line.recurring_invoicing_type, 'pre-paid'
)
self.assertEqual(self.contract_line.recurring_interval, 1)
self.assertEqual(self.contract_line.is_auto_renew, True)
self.assertEqual(self.contract_line.auto_renew_interval, 12)
self.assertEqual(self.contract_line.auto_renew_rule_type, 'monthly')
self.assertEqual(self.contract_line.termination_notice_interval, 6)
self.assertEqual(
self.contract_line.termination_notice_rule_type, 'weekly'
)
def test_action_show_contracts(self):
self.sale.action_confirm()
action = self.sale.action_show_contracts()
self.assertEqual(
self.env['contract.contract'].search(action['domain']),
self.sale.order_line.mapped('contract_id'),
)

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2018 ACSONE SA/NV.
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-->
<odoo>
<record id="contract_contract_customer_form_view"
model="ir.ui.view">
<field name="model">contract.contract</field>
<field name="inherit_id"
ref="contract.contract_contract_customer_form_view"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='button_box']" position="inside">
<button class="oe_stat_button" name="action_view_sales_orders"
type="object" icon="fa-edit"
attrs="{'invisible': [('sale_order_count', '=', 0)]}">
<div class="o_field_widget o_stat_info">
<span class="o_stat_value">
<field name="sale_order_count"/>
</span>
<span class="o_stat_text">Sale Orders</span>
</div>
</button>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2017 LasLabs Inc.
Copyright 2018 ACSONE SA/NV.
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-->
<odoo>
<record id="product_template_form_contract_view" model="ir.ui.view">
<field name="name">account.invoice.select.contract</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_form_view"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='options']" position="inside">
<div attrs="{'invisible': [('type', '!=', 'service')],}">
<field name="is_contract"/>
<label for="is_contract"/>
</div>
</xpath>
<xpath expr="//notebook" position="inside">
<page string="Contract"
name="contract"
attrs="{'invisible': [('is_contract', '=', False)],}">
<group>
<field name="contract_template_id"
attrs="{'required':[('is_contract', '=', True)]}"/>
</group>
<group name="recurrence_info">
<group>
<field name="recurring_rule_type"/>
</group>
<group>
<field name="default_qty"/>
<field name="recurring_invoicing_type"
attrs="{'invisible': [('recurring_rule_type', '=', 'monthlylastday')]}"/>
</group>
</group>
<group>
<field name="is_auto_renew"/>
<label for="termination_notice_interval" attrs="{'invisible': [('is_auto_renew', '=', False)],
'required':[('is_contract', '=', True)]}"/>
<div attrs="{'invisible': [('is_auto_renew', '=', False)],
'required':[('is_auto_renew', '=', True)]}">
<field name="termination_notice_interval"
class="oe_inline" nolabel="1"/>
<field name="termination_notice_rule_type"
class="oe_inline" nolabel="1"/>
</div>
</group>
</page>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2019 ACSONE SA/NV
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record model="ir.ui.view" id="res_config_settings_form_view">
<field name="name">res.config.settings.form (in product_contract)
</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="sale.res_config_settings_view_form"/>
<field name="arch" type="xml">
<xpath expr="//div[@id='sales_settings_invoicing_policy']/.."
position="inside">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane">
<field name="create_contract_at_sale_order_confirmation"/>
</div>
<div class="o_setting_right_pane">
<label for="create_contract_at_sale_order_confirmation"/>
<div class="text-muted">
Automatically Create Contracts At Sale Order Confirmation
</div>
</div>
</div>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,87 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2018 ACSONE SA/NV.
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-->
<odoo>
<record id="view_order_form" model="ir.ui.view">
<field name="name">sale.order.form (in product_contract)</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<xpath expr="//header" position="inside">
<field name="need_contract_creation" invisible="1"/>
<button name="action_create_contract"
string="Create Contracts"
type="object"
class="oe_highlight" attrs="{'invisible': [('need_contract_creation', '=', False)]}"/>
</xpath>
<xpath expr="//div[@name='button_box']" position="inside">
<button name="action_show_contracts"
type="object" icon="fa-book"
class="oe_stat_button"
attrs="{'invisible': ['|', ('is_contract', '!=', True), ('state', 'not in', ['sale', 'done'])]}">
<field string="Contracts"
name="contract_count"
widget="statinfo"/>
</button>
</xpath>
<xpath expr="//field[@name='order_line']" position="before">
<field name="is_contract" invisible="1"/>
</xpath>
<xpath expr="//field[@name='order_line']/form//field[@name='product_id']"
position="after">
<field name="contract_template_id" invisible="1"/>
<field name="contract_id"
options='{"no_create": True}'
attrs="{'invisible': [('is_contract', '=', False)]}"
domain="['|',('contract_template_id','=',contract_template_id),
('contract_template_id','=',False),
('partner_id','=',parent.partner_id),
('recurring_invoices','=',True),
]"/>
<field name="contract_line_id"
attrs="{'invisible': [('is_contract', '=', False)]}"
domain="[('contract_id','=',contract_id)]"/>
</xpath>
<xpath expr="//field[@name='order_line']/form//field[@name='tax_id']/parent::group"
position="after">
<field name="is_contract" invisible="1"/>
<separator colspan="4" string="Recurrence Invoicing"
attrs="{'invisible': [('is_contract', '=', False)]}"/>
<group attrs="{'invisible': [('is_contract', '=', False)]}">
<field name="recurring_rule_type"/>
</group>
<group attrs="{'invisible': [('is_contract', '=', False)]}">
<field name="recurring_invoicing_type"
attrs="{'invisible': [('recurring_rule_type', '=', 'monthlylastday')]}"/>
</group>
<group attrs="{'invisible': [('is_contract', '=', False)]}">
<field name="date_start"
attrs="{'required': [('is_contract', '=', True)]}"/>
</group>
<group attrs="{'invisible': [('is_contract', '=', False)]}">
<field name="date_end" attrs="{'required': [('is_contract', '=', True)]}"/>
</group>
</xpath>
<xpath expr="//field[@name='order_line']/tree//field[@name='price_total']"
position="after">
<field name="date_start"
attrs="{'column_invisible': [('parent.is_contract', '=', False)]}"/>
<field name="date_end"
attrs="{'column_invisible': [('parent.is_contract', '=', False)]}"/>
</xpath>
<xpath expr="//field[@name='order_line']/tree"
position="attributes">
<attribute name="editable"/>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1 @@
../../../../contract_sale_payment_mode

View File

@@ -0,0 +1,6 @@
import setuptools
setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)

View File

@@ -0,0 +1 @@
../../../../product_contract

View File

@@ -0,0 +1,6 @@
import setuptools
setuptools.setup(
setup_requires=['setuptools-odoo'],
odoo_addon=True,
)