Initial commit: Odoo 18.0-20251222 extra-addons
Some checks failed
pre-commit / pre-commit (push) Has been cancelled
tests / Detect unreleased dependencies (push) Has been cancelled
tests / test with OCB (push) Has been cancelled
tests / test with Odoo (push) Has been cancelled

This commit is contained in:
tocmo0nlord
2026-03-13 20:43:25 +00:00
parent 36e847a7df
commit adbe430761
9472 changed files with 1265727 additions and 0 deletions

View File

@@ -0,0 +1,96 @@
=============================
Sale Partner Address Restrict
=============================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:c574c62a96fc07c9cabf9723539ae73dc9e513ecedf5eda026cb141aa4ee3c00
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |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%2Fsale--workflow-lightgray.png?logo=github
:target: https://github.com/OCA/sale-workflow/tree/18.0/sale_partner_address_restrict
:alt: OCA/sale-workflow
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/sale-workflow-18-0/sale-workflow-18-0-sale_partner_address_restrict
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/sale-workflow&target_branch=18.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
This module restricts the addresses to be used in the sales order form
to only addresses of the selected customer.
When managing dropship delivery addresses, a delivery address needs to
be created for the buyer main contact. You can then mark the checkbox
'Dropship Address' on the delivery address to prevent the buyer main
contact name to be displayed as part of the delivery address name.
**Table of contents**
.. contents::
:local:
Configuration
=============
- Go to Sales > Configuration > Settings > Quotation & Orders > Sale
Partner Address Restriction
- Check the box if you want to restrict available partners for Delivery
and Invoicing addresses to partners that belong to the selected
Customer.
If you are managing dropship delivery addresses, you can mark the
checkbox 'Dropship Address' in the addresses to prevent the parent
contact name to be displayed.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/sale-workflow/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/sale-workflow/issues/new?body=module:%20sale_partner_address_restrict%0Aversion:%2018.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
-------
* ForgeFlow
Contributors
------------
- Marina Alapont <marina.alapont@forgeflow.com>
- Denis Roussel denis.roussel@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/sale-workflow <https://github.com/OCA/sale-workflow/tree/18.0/sale_partner_address_restrict>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View File

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

View File

@@ -0,0 +1,23 @@
# Copyright 2024 ForgeFlow S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
"name": "Sale Partner Address Restrict",
"summary": "Restrict addresses domain in the sales order form"
" taking into account the partner selected",
"version": "18.0.1.0.0",
"category": "Sales",
"website": "https://github.com/OCA/sale-workflow",
"author": "ForgeFlow, Odoo Community Association (OCA)",
"license": "AGPL-3",
"installable": True,
"depends": [
"base_partition",
"sale",
],
"data": [
"views/sale_order_view.xml",
"views/res_config_settings.xml",
"views/res_partner_views.xml",
],
}

View File

@@ -0,0 +1,33 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_partner_address_restrict
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-08-26 12:06+0000\n"
"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
"Language-Team: none\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"
"X-Generator: Weblate 5.6.2\n"
#. module: sale_partner_address_restrict
#. odoo-python
#: code:addons/sale_partner_address_restrict/models/sale_order.py:0
#, python-format
msgid ""
"Invoice and shipping addresses must be child addresses of the selected "
"partner or the selected partner itself."
msgstr ""
"Gli indirizzi di fatturazione e di spedizione devono essere indirizzi figli "
"del partner selezionato o del partner selezionato stesso."
#. module: sale_partner_address_restrict
#: model:ir.model,name:sale_partner_address_restrict.model_sale_order
msgid "Sales Order"
msgstr "Ordine di vendita"

View File

@@ -0,0 +1,85 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * sale_partner_address_restrict
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 18.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: sale_partner_address_restrict
#: model_terms:ir.ui.view,arch_db:sale_partner_address_restrict.res_config_settings_view_form
msgid "Address restriction"
msgstr ""
#. module: sale_partner_address_restrict
#: model:ir.model.fields,help:sale_partner_address_restrict.field_res_company__sale_partner_address_restriction
#: model:ir.model.fields,help:sale_partner_address_restrict.field_res_config_settings__sale_partner_address_restriction
msgid ""
"Check this box if you want to restrict partner addresses selection in sale "
"orders. They should depends on the Customer filled in."
msgstr ""
#. module: sale_partner_address_restrict
#: model_terms:ir.ui.view,arch_db:sale_partner_address_restrict.res_config_settings_view_form
msgid ""
"Check this if you want to restrict the address selection to contacts of same"
" company."
msgstr ""
#. module: sale_partner_address_restrict
#: model:ir.model,name:sale_partner_address_restrict.model_res_company
msgid "Companies"
msgstr ""
#. module: sale_partner_address_restrict
#: model:ir.model,name:sale_partner_address_restrict.model_res_config_settings
msgid "Config Settings"
msgstr ""
#. module: sale_partner_address_restrict
#: model:ir.model,name:sale_partner_address_restrict.model_res_partner
msgid "Contact"
msgstr ""
#. module: sale_partner_address_restrict
#: model:ir.model.fields,field_description:sale_partner_address_restrict.field_res_partner__is_dropship_address
#: model:ir.model.fields,field_description:sale_partner_address_restrict.field_res_users__is_dropship_address
msgid "Dropship Address"
msgstr ""
#. module: sale_partner_address_restrict
#. odoo-python
#: code:addons/sale_partner_address_restrict/models/sale_order.py:0
msgid ""
"Invoice and shipping addresses must be child addresses of the selected "
"partner or the selected partner itself."
msgstr ""
#. module: sale_partner_address_restrict
#: model:ir.model.fields,field_description:sale_partner_address_restrict.field_sale_order__partner_address_restriction_domain
msgid "Partner Address Restriction Domain"
msgstr ""
#. module: sale_partner_address_restrict
#: model:ir.model.fields,field_description:sale_partner_address_restrict.field_res_company__sale_partner_address_restriction
#: model:ir.model.fields,field_description:sale_partner_address_restrict.field_res_config_settings__sale_partner_address_restriction
msgid "Sale Partner Address Restriction"
msgstr ""
#. module: sale_partner_address_restrict
#: model:ir.model,name:sale_partner_address_restrict.model_sale_order
msgid "Sales Order"
msgstr ""
#. module: sale_partner_address_restrict
#: model:ir.model.fields,help:sale_partner_address_restrict.field_sale_order__partner_address_restriction_domain
msgid ""
"This is the computed domain to filter delivery and invoicing addresses."
msgstr ""

View File

@@ -0,0 +1,4 @@
from . import sale_order
from . import res_company
from . import res_partner
from . import res_config_settings

View File

@@ -0,0 +1,13 @@
# Copyright 2024 ACSONE SA/NV
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models
class ResCompany(models.Model):
_inherit = "res.company"
sale_partner_address_restriction = fields.Boolean(
help="Check this box if you want to restrict partner addresses selection "
"in sale orders. They should depends on the Customer filled in."
)

View File

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

View File

@@ -0,0 +1,16 @@
# Copyright 2025 ForgeFlow S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from odoo import fields, models
class ResPartner(models.Model):
_inherit = "res.partner"
is_dropship_address = fields.Boolean(string="Dropship Address")
def _get_complete_name(self):
res = super()._get_complete_name()
if not self.is_dropship_address or not self.name or not self.type == "delivery":
return res
return self.name.strip()

View File

@@ -0,0 +1,49 @@
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
class SaleOrder(models.Model):
_inherit = "sale.order"
partner_address_restriction_domain = fields.Binary(
compute="_compute_partner_address_restriction_domain",
help="This is the computed domain to filter delivery and invoicing addresses.",
)
@api.depends("partner_id", "company_id.sale_partner_address_restriction")
def _compute_partner_address_restriction_domain(self):
for activated, activated_sales in self.partition(
lambda sale: sale.company_id.sale_partner_address_restriction
).items():
if not activated:
activated_sales.partner_address_restriction_domain = [(1, "=", 1)]
continue
for company, sales in activated_sales.partition("company_id").items():
for sale in sales:
sale.partner_address_restriction_domain = [
("commercial_partner_id", "=", sale.partner_id.id),
"|",
("company_id", "=", False),
("company_id", "=", company.id),
]
@api.constrains("partner_id", "partner_invoice_id", "partner_shipping_id")
def _check_partner_addresses(self):
for order in self:
if (
order.company_id.sale_partner_address_restriction
and order.partner_id
and (
(order.partner_invoice_id.commercial_partner_id != order.partner_id)
or (
order.partner_shipping_id.commercial_partner_id
!= order.partner_id
)
)
):
raise ValidationError(
_(
"Invoice and shipping addresses must be child addresses"
" of the selected partner or the selected partner itself."
)
)

View File

@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"

View File

@@ -0,0 +1,6 @@
- Go to Sales \> Configuration \> Settings \> Quotation & Orders \> Sale Partner Address Restriction
- Check the box if you want to restrict available partners for Delivery and Invoicing addresses to
partners that belong to the selected Customer.
If you are managing dropship delivery addresses, you can mark the checkbox 'Dropship Address'
in the addresses to prevent the parent contact name to be displayed.

View File

@@ -0,0 +1,2 @@
- Marina Alapont \<<marina.alapont@forgeflow.com>\>
- Denis Roussel <denis.roussel@acsone.eu>

View File

@@ -0,0 +1,7 @@
This module restricts the addresses to be used in the sales order form to only
addresses of the selected customer.
When managing dropship delivery addresses, a delivery address needs to be created
for the buyer main contact. You can then mark the checkbox 'Dropship Address' on
the delivery address to prevent the buyer main contact name to be displayed as
part of the delivery address name.

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -0,0 +1,443 @@
<!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: https://docutils.sourceforge.io/" />
<title>Sale Partner Address Restrict</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/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: gray; } /* 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, pre.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="sale-partner-address-restrict">
<h1 class="title">Sale Partner Address Restrict</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:c574c62a96fc07c9cabf9723539ae73dc9e513ecedf5eda026cb141aa4ee3c00
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" 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 image-reference" 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 image-reference" href="https://github.com/OCA/sale-workflow/tree/18.0/sale_partner_address_restrict"><img alt="OCA/sale-workflow" src="https://img.shields.io/badge/github-OCA%2Fsale--workflow-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/sale-workflow-18-0/sale-workflow-18-0-sale_partner_address_restrict"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/sale-workflow&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module restricts the addresses to be used in the sales order form
to only addresses of the selected customer.</p>
<p>When managing dropship delivery addresses, a delivery address needs to
be created for the buyer main contact. You can then mark the checkbox
Dropship Address on the delivery address to prevent the buyer main
contact name to be displayed as part of the delivery address name.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#configuration" id="toc-entry-1">Configuration</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-2">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-3">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-4">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-5">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-6">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="configuration">
<h1><a class="toc-backref" href="#toc-entry-1">Configuration</a></h1>
<ul class="simple">
<li>Go to Sales &gt; Configuration &gt; Settings &gt; Quotation &amp; Orders &gt; Sale
Partner Address Restriction</li>
<li>Check the box if you want to restrict available partners for Delivery
and Invoicing addresses to partners that belong to the selected
Customer.</li>
</ul>
<p>If you are managing dropship delivery addresses, you can mark the
checkbox Dropship Address in the addresses to prevent the parent
contact name to be displayed.</p>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-2">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/sale-workflow/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 to smash it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/sale-workflow/issues/new?body=module:%20sale_partner_address_restrict%0Aversion:%2018.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="#toc-entry-3">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#toc-entry-4">Authors</a></h2>
<ul class="simple">
<li>ForgeFlow</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-5">Contributors</a></h2>
<ul class="simple">
<li>Marina Alapont &lt;<a class="reference external" href="mailto:marina.alapont&#64;forgeflow.com">marina.alapont&#64;forgeflow.com</a>&gt;</li>
<li>Denis Roussel <a class="reference external" href="mailto:denis.roussel&#64;acsone.eu">denis.roussel&#64;acsone.eu</a></li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-6">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/sale-workflow/tree/18.0/sale_partner_address_restrict">OCA/sale-workflow</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,91 @@
from odoo.exceptions import ValidationError
from odoo.tests import Form
from odoo.addons.base.tests.common import BaseCommon
class TestSaleOrder(BaseCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.partner1 = cls.env["res.partner"].create({"name": "Test Partner 1"})
cls.child_1 = cls.env["res.partner"].create(
{"name": "Child 1", "parent_id": cls.partner1.id, "type": "delivery"}
)
cls.child_2 = cls.env["res.partner"].create(
{"name": "Child 2", "parent_id": cls.partner1.id}
)
cls.partner2 = cls.env["res.partner"].create({"name": "Test Partner 2"})
cls.partner3 = cls.env["res.partner"].create({"name": "Test Partner 3"})
cls.env.user.groups_id += cls.env.ref("account.group_delivery_invoice_address")
cls.env.company.sale_partner_address_restriction = True
def test_sale_order_address_domain(self):
order_form = Form(self.env["sale.order"])
order_form.partner_id = self.partner1
sale_order = order_form.save()
expected_domain = [
("commercial_partner_id", "=", sale_order.partner_id.id),
"|",
("company_id", "=", False),
("company_id", "=", sale_order.company_id.id),
]
partners = self.env["res.partner"].search(expected_domain)
self.assertEqual(len(partners), 3)
with Form(sale_order) as sale_order:
sale_order.partner_id = self.partner2
expected_domain = [
("commercial_partner_id", "=", sale_order.partner_id.id),
"|",
("company_id", "=", False),
("company_id", "=", sale_order.company_id.id),
]
partners = self.env["res.partner"].search(expected_domain)
self.assertEqual(len(partners), 1)
def test_sale_order_partner_unallowed(self):
order_form = Form(self.env["sale.order"])
order_form.partner_id = self.partner1
sale_order = order_form.save()
with self.assertRaises(ValidationError):
with Form(sale_order) as sale_order:
sale_order.partner_shipping_id = self.partner3
def test_sale_order_partner_allowed(self):
self.env.company.sale_partner_address_restriction = False
order_form = Form(self.env["sale.order"])
order_form.partner_id = self.partner1
sale_order = order_form.save()
with Form(sale_order) as sale_order:
sale_order.partner_shipping_id = self.partner3
def test_sale_order_address_constraint(self):
with self.assertRaises(ValidationError):
self.env["sale.order"].create(
{
"partner_id": self.partner1.id,
"partner_invoice_id": self.partner2.id,
"partner_shipping_id": self.child_2.id,
}
)
def test_sale_order_address_no_constraint(self):
self.env.company.sale_partner_address_restriction = False
self.env["sale.order"].create(
{
"partner_id": self.partner1.id,
"partner_invoice_id": self.partner2.id,
"partner_shipping_id": self.child_2.id,
}
)
def test_dropship_delivery_address(self):
self.assertIn(self.partner1.name, self.child_1.display_name)
self.child_1.is_dropship_address = True
self.child_1._compute_display_name()
self.assertNotIn(self.partner1.name, self.child_1.display_name)

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2025 ACSONE SA/NV
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="res_config_settings_view_form" model="ir.ui.view">
<field name="name">res.config.settings.view.form.inherit.sale</field>
<field name="model">res.config.settings</field>
<field name="priority" eval="10" />
<field name="inherit_id" ref="base.res_config_settings_view_form" />
<field name="arch" type="xml">
<setting id="quotation_validity_days" position="after">
<setting
id="sale_partner_address_restrict"
help="Check this if you want to restrict the address selection to contacts of same company."
title="Address restriction"
>
<field name="sale_partner_address_restriction" />
</setting>
</setting>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="view_partner_form" model="ir.ui.view">
<field
name="name"
>res.partner.form - sale_partner_address_restrict_dropshipping</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form" />
<field name="arch" type="xml">
<xpath expr="//group/group[//field[@name='vat']]" position="inside">
<field
name="is_dropship_address"
invisible="type != 'delivery' or not parent_id"
/>
</xpath>
<xpath
expr="//notebook/page[@name='contact_addresses']//form//field[@name='name']"
position="after"
>
<field name="is_dropship_address" invisible="type != 'delivery'" />
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2023 ACSONE SA/NV
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="view_order_form" model="ir.ui.view">
<field name="name">sale.order.form (in partner_invoicing_mode)</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form" />
<field name="arch" type="xml">
<field name="partner_id" position="after">
<field name="partner_address_restriction_domain" invisible="1" />
</field>
<field name="partner_invoice_id" position="attributes">
<attribute name="domain">partner_address_restriction_domain</attribute>
</field>
<field name="partner_shipping_id" position="attributes">
<attribute name="domain">partner_address_restriction_domain</attribute>
</field>
</field>
</record>
</odoo>