47 Commits

Author SHA1 Message Date
Boris Gallet
872969d43a [MIG] partner_favorite/: Migration to 16.0 2024-02-22 15:50:19 +01:00
Stéphan Sainléger
cc897e65a9 [NEW] partner_favorite: transfer add-on
from repo
https://git.myceliandre.fr/OCA/partner-contact/commits/branch/nj-12.0-partner_gogocarto_export_api
2023-09-22 12:36:46 +02:00
Stéphan Sainléger
a5993e3786 [FIX] partner_profiles: correct unlink() for position profiles 2023-09-20 15:09:43 +02:00
Stéphan Sainléger
eba51e1654 [IMP] partner_profiles_geolocalize_usability: add sync data function
inherits sync_admin_and_public_data function on res.partner to
synchronise partner latitude and longitude from main to public profiles.
2023-09-20 15:09:43 +02:00
Stéphan Sainléger
4e18b41b70 [IMP] partner_profiles: add sync function for admin and public data 2023-09-20 15:09:43 +02:00
Stéphan Sainléger
edfb018ed3 [MIG] partner_profiles_gogocarto_export: migrate generic functions
Migrates generic geolocation functionalities to partner_profiles_geolocalize_usability
2023-09-20 15:09:43 +02:00
Stéphan Sainléger
127d8484b4 [MIG] partner_gogocarto_export_api: migrate generic fonctionalities
Migrates generic geolocation functionnalities to add-on partner_geolocalize_usability
2023-09-20 15:09:43 +02:00
Stéphan Sainléger
d2e558f13e [NEW] partner_profiles_geolocalize_usability: create add-on 2023-09-20 15:09:43 +02:00
Stéphan Sainléger
ac95e1537c [NEW] partner_geolocalize_usability: create add-on 2023-09-20 15:09:43 +02:00
Stéphan Sainléger
7a43a39e4f [NEW] partner_profiles_gogocarto_export: create add-on 2023-09-20 15:09:43 +02:00
Stéphan Sainléger
597340ff98 [IMP] partner_profiles: add ids to public and position groups 2023-09-20 15:09:43 +02:00
Stéphan Sainléger
102df5b9ef [FIX] partner_gogocarto_export_api: fix gogocarto config icon 2023-09-20 15:09:43 +02:00
Stéphan Sainléger
87e02a7180 [IMP] partner_gogocarto_export_api: refactor gogocarto parser 2023-09-20 15:09:43 +02:00
Stéphan Sainléger
65940d54ab [IMP] partner_gogocarto_export_api: refactor config settings view 2023-09-20 15:09:43 +02:00
Stéphan Sainléger
a559fa9e42 [IMP] partner_gogocarto_export_api: add README.rst
and update __manifest__.py
2023-09-20 15:09:43 +02:00
Stéphan Sainléger
f5a597fa84 [I18N] partner_gogocarto_export_api: add french translations 2023-09-20 15:09:43 +02:00
Stéphan Sainléger
2c2e2ef12b [IMP] partner_gogocarto_export_api: refactor partner form view 2023-09-20 15:09:43 +02:00
Stéphan Sainléger
33ec7a728c [IMP] partner_gogocarto_export_api: add .gitignore 2023-09-20 15:09:43 +02:00
Stéphan Sainléger
de273ec571 [NEW] partner_gogocarto_export_api: create add-on
Transfers add-on partner_gogocarto_export_api from OCA partner-contact repo
2023-09-20 15:09:43 +02:00
Stéphan Sainléger
9325c02b53 [I18N] partner_profiles_portal: improve french translations 2023-06-28 16:38:18 +02:00
Stéphan Sainléger
cdcea7ec60 [IMP] partner_profiles: apply migration only on contact type partner 2023-06-28 16:38:18 +02:00
Stéphan Sainléger
d51b9b6d08 [IMP] partner_profiles_portal: add required asterisk in portal forms 2023-06-28 16:38:18 +02:00
Stéphan Sainléger
783faf9f61 [IMP] partner_profiles_portal: remove position profile frm child_ids 2023-06-28 16:38:18 +02:00
Stéphan Sainléger
49f73b86a7 [IMP] partner_profiles: remove position profiles from child_ids 2023-06-28 16:38:18 +02:00
Stéphan Sainléger
0f10de644e [IMP] partner_profiles_portal: improve /my/account name field label 2023-06-28 16:38:18 +02:00
Stéphan Sainléger
8d72f56edc [I18N] partner_profiles_portal: modify profiles french translations
"Profil principal" -> "Fiche administrative"
"Profil public" -> "Coordonnées publiques"
"Profil position" -> "Fonction"
2023-06-28 16:38:18 +02:00
Stéphan Sainléger
124625f74c [I18N] partner_profiles: modify profile name french translations
"Profil principal" -> "Fiche administrative"
"Profil public" -> "Coordonnées publiques"
"Profil position" -> "Fonction"
2023-06-28 16:38:18 +02:00
Stéphan Sainléger
072cdf8978 [FIX] partner_profiles_portal: fix portal boolean fields handling 2023-06-27 17:31:24 +02:00
Stéphan Sainléger
29af98aac3 [IMP] partner_profiles: sync active field values between profiles
Change in main profile is synchronized in public and position profiles.
Change in public profile is sy,chronized in main and position profiles.
Change in position profile is NOT synchronized in main and public profiles.
2023-06-27 17:31:24 +02:00
Stéphan Sainléger
cda7190cff [IMP] partner_profiles: add profile in partner kanban view 2023-06-27 17:31:24 +02:00
Stéphan Sainléger
43d21befbf [IMP] partner_profiles_portal: add positions details in portal
Adds several portal views to consult all the positions of a structure,
and their details.
2023-06-27 17:31:24 +02:00
Stéphan Sainléger
95ddef62c3 [IMP] partner_profiles_portal: add website page edition slots 2023-06-27 17:31:24 +02:00
Stéphan Sainléger
019019aa93 [IMP] partner_profiles: clarify position profiles display
separates the notebook pages of the child_ids and the position
profiles in both company and individual partner form views.
2023-06-27 17:31:24 +02:00
Stéphan Sainléger
9438f19140 [IMP] partner_profiles_portal: refactor position profil creation 2023-06-27 17:31:24 +02:00
Stéphan Sainléger
a4c1c467c5 [IMP] partner_profiles: refactoring of position profile creation 2023-06-27 17:31:24 +02:00
Stéphan Sainléger
379b598754 [IMP] partner_profiles: prevent company type edit in several cases
Prevents the modification of the company type of res.partner:
- if partner is a public or a position profile
- if the partner has position profiles attached

Also synchronize the company type between main and public profiles.
2023-06-27 17:31:24 +02:00
Stéphan Sainléger
c95d20d7a1 [I18N] partner_profiles_portal: update french translations 2023-06-27 17:31:24 +02:00
Stéphan Sainléger
e994a2c407 [I18N] partner_profiles: update french translations 2023-06-27 17:31:24 +02:00
Stéphan Sainléger
0c81c36d30 [IMP] partner_profiles_portal: hide My structures button for company users 2023-06-27 17:31:24 +02:00
Stéphan Sainléger
bba6775f07 [IMP] partner_profiles_portal: add odoo user in partner form view 2023-06-27 17:31:24 +02:00
Stéphan Sainléger
bf5eeb0d32 [IMP] partner_profiles: remove useless fields in position form view 2023-06-27 17:31:24 +02:00
Stéphan Sainléger
859d672633 [IMP] partner_profiles_portal: new portal structures data management
refactors the way a portal user can edit the data of the structures he
is affiliated with.
All main, public and position profiles data are gathered in one
"structure" form.
Adds several navigation improvement (back to structures list,
validation message, ...)
2023-06-27 17:31:24 +02:00
Stéphan Sainléger
5c16620fe6 [IMP] partner_profiles_portal: refactoring of user information
Merge the main and public information edition in /my/account portal
page.
2023-06-27 17:31:24 +02:00
Stéphan Sainléger
4401cfab79 [IMP] partner_profiles: remove useless fields in public profile view
Hides from the partner public form view the fields and data not
considered as relevant for public profile. The public profile aims to
protect the contact data, but not to replace the other ones which are
considered as "administrative" data.
2023-06-27 17:31:24 +02:00
Stéphan Sainléger
2e63b1216f [IMP] partner_profiles: delete profiles when main partner deleted
When a main partner is unlinked, all the linked profiles (public
profile and position profiles) are deleted.
2023-06-27 17:31:24 +02:00
Stéphan Sainléger
6e227a83d4 [IMP] partner_profiles: filter public profiles in name_search answer 2023-06-27 17:31:24 +02:00
Stéphan Sainléger
2162312fb1 [FIX] partner_profiles: add missing add-on dependency 2023-06-27 17:31:24 +02:00
96 changed files with 4295 additions and 771 deletions

View File

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

View File

@@ -0,0 +1,21 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
'name': 'Partner Favorite',
'summary': "Add favorite star on Partner, and filter for favorite",
'version': "16.0.1.0.0",
'author': "Nicolas JEUDY, "
"Myceliandre, "
"Lokavaluto, "
"Odoo Community Association (OCA)",
'license': "AGPL-3",
'maintainer': 'Nicolas JEUDY',
'category': 'Extra Tools',
'website': 'https://odoo-community.org/',
'depends': ['base'],
'data': [
'views/res_partner.xml',
],
'auto_install': False,
'installable': True,
}

View File

@@ -0,0 +1,45 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * partner_favorite
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-05-10 20:53+0000\n"
"PO-Revision-Date: 2021-05-10 20:53+0000\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: partner_favorite
#: model:ir.model,name:partner_favorite.model_res_partner
msgid "Contact"
msgstr "Contact"
#. module: partner_favorite
#: model:ir.model.fields,help:partner_favorite.field_res_partner__is_favorite
#: model:ir.model.fields,help:partner_favorite.field_res_users__is_favorite
msgid "Display this partner with favorite filter"
msgstr "Afficher les partenaires favoris"
#. module: partner_favorite
#: model:ir.model.fields,field_description:partner_favorite.field_res_partner__favorite_user_ids
#: model:ir.model.fields,field_description:partner_favorite.field_res_users__favorite_user_ids
msgid "Members"
msgstr "Membres"
#. module: partner_favorite
#: model_terms:ir.ui.view,arch_db:partner_favorite.view_partner_search_favorite
msgid "My Favorites"
msgstr "Mes favoris"
#. module: partner_favorite
#: model:ir.model.fields,field_description:partner_favorite.field_res_partner__is_favorite
#: model:ir.model.fields,field_description:partner_favorite.field_res_users__is_favorite
msgid "Show Favorite Partner"
msgstr "Afficher les partenaire favoris"

View File

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

View File

@@ -0,0 +1,39 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import logging
from odoo import fields, models
_logger = logging.getLogger(__name__)
class ResPartner(models.Model):
"""Adds last name and first name; name becomes a stored function field."""
_inherit = 'res.partner'
def _compute_is_favorite(self):
for partner in self:
partner.is_favorite = self.env.user in partner.favorite_user_ids
def _inverse_is_favorite(self):
favorite_partners = not_fav_partners = self.env['res.partner']
for partner in self:
if self.env.user in partner.favorite_user_ids:
favorite_partners |= partner
else:
not_fav_partners |= partner
# partner User has no write access for partner.
not_fav_partners.write({'favorite_user_ids': [(4, self.env.uid)]})
favorite_partners.write({'favorite_user_ids': [(3, self.env.uid)]})
def _get_default_favorite_user_ids(self):
return [(6, 0, [self.env.uid])]
favorite_user_ids = fields.Many2many(
'res.users', 'partner_favorite_user_rel', 'partner_id', 'user_id',
default=_get_default_favorite_user_ids,
string='Members')
is_favorite = fields.Boolean(
compute='_compute_is_favorite',
inverse='_inverse_is_favorite',
string='Show Favorite Partner',
help="Display this partner with favorite filter")

View File

@@ -0,0 +1 @@
N/A

View File

@@ -0,0 +1 @@
* Nicolas JEUDY <https://github.com/njeudy>

View File

@@ -0,0 +1,2 @@
This module was written to extend the functionality of contacts to support
having favorite mechanism.

View File

@@ -0,0 +1 @@
* add filters

View File

@@ -0,0 +1 @@
After installing this module you can select a partner as favorite and filter on "My favorite".

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_partner_form_favorite" model="ir.ui.view">
<field name="name">Add favorite star</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.res_partner_kanban_view"/>
<field name="arch" type="xml">
<data>
<field name="type" position="after">
<field name="is_favorite"/>
</field>
<xpath expr="//strong/field[@name='display_name']" position="before">
<span class="o_right"><field name="is_favorite" widget="boolean_favorite" nolabel="1" force_save="1" /></span>
</xpath>
</data>
</field>
</record>
<record id="view_partner_search_favorite" model="ir.ui.view">
<field name="name">Add favorite star</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_res_partner_filter"/>
<field name="arch" type="xml">
<data>
<filter name="type_person" position="before">
<filter string="My Favorites" name="my_partners" domain="[('favorite_user_ids', 'in', uid)]"/>
<separator />
</filter>
</data>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,2 @@
*.*~
*pyc

View File

@@ -0,0 +1,56 @@
=============================
partner_geolocalize_usability
=============================
Brings several enhancements on geolocalize functionnalities
Installation
============
Use Odoo normal module installation procedure to install
``partner_geolocalize_usability``.
Description
===========
This module allows:
- to block or not the edition of partner_latitude and partner_longitude fields in partner form view.
- to massively trigger the geolocalize function
It also modify the partner form vieww for a better understanding of the geolocation data.
Configuration
=============
No configuration needed.
Known issues / Roadmap
======================
None yet.
Bug Tracker
===========
Bugs are tracked on `our issues website <https://github.com/elabore-coop/partner-tools/issues>`_. In case of
trouble, please check there if your issue has already been
reported. If you spotted it first, help us smashing it by providing a
detailed and welcomed feedback.
Credits
=======
Contributors
------------
* Stéphan Sainléger
Funders
-------
The development of this module has been financially supported by:
* Elabore (https://elabore.coop)
Maintainer
----------
This module is maintained by Elabore.

View File

@@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
from . import models
# from . import controllers
# from . import wizard

View File

@@ -0,0 +1,35 @@
# Copyright 2023 Stéphan Sainléger (Elabore)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "partner_geolocalize_usability",
"version": "12.0.1.0.0",
"author": "Elabore",
"website": "https://elabore.coop",
"maintainer": "Stéphan Sainléger",
"license": "AGPL-3",
"category": "Tools",
"summary": "Brings several enhancements on geolocalize functionnalities",
# any module necessary for this one to work correctly
"depends": [
"base",
"base_geolocalize"
],
"qweb": [],
"external_dependencies": {
"python": [],
},
# always loaded
"data": [
"views/res_partner.xml",
],
# only loaded in demonstration mode
"demo": [],
"js": [],
"css": [],
"installable": True,
# Install this module automatically if all dependency have been previously
# and independently installed. Used for synergetic or glue modules.
"auto_install": False,
"application": False,
}

View File

@@ -0,0 +1 @@
This directory should contain the *.po for Odoo translation.

View File

@@ -0,0 +1,39 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * partner_geolocalize_usability
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-09-12 13:48+0000\n"
"PO-Revision-Date: 2023-09-12 13:48+0000\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: partner_geolocalize_usability
#: model:ir.model,name:partner_geolocalize_usability.model_res_partner
msgid "Contact"
msgstr ""
#. module: partner_geolocalize_usability
#: model:ir.actions.server,name:partner_geolocalize_usability.geolocata_partner_action_server
#: model_terms:ir.ui.view,arch_db:partner_geolocalize_usability.partner_geolocalize_form_view
msgid "Geolocate"
msgstr "Géolocaliser"
#. module: partner_geolocalize_usability
#: model:ir.model.fields,field_description:partner_geolocalize_usability.field_res_partner__manual_geolocate
#: model:ir.model.fields,field_description:partner_geolocalize_usability.field_res_users__manual_geolocate
msgid "Geolocate yourself"
msgstr "Géolocaliser manuellement"
#. module: partner_geolocalize_usability
#: model_terms:ir.ui.view,arch_db:partner_geolocalize_usability.partner_geolocalize_form_view
msgid "Geolocation"
msgstr "Géolocalisation"

View File

@@ -0,0 +1,39 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * partner_geolocalize_usability
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-09-12 13:50+0000\n"
"PO-Revision-Date: 2023-09-12 13:50+0000\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: partner_geolocalize_usability
#: model:ir.model,name:partner_geolocalize_usability.model_res_partner
msgid "Contact"
msgstr ""
#. module: partner_geolocalize_usability
#: model:ir.actions.server,name:partner_geolocalize_usability.geolocata_partner_action_server
#: model_terms:ir.ui.view,arch_db:partner_geolocalize_usability.partner_geolocalize_form_view
msgid "Geolocate"
msgstr ""
#. module: partner_geolocalize_usability
#: model:ir.model.fields,field_description:partner_geolocalize_usability.field_res_partner__manual_geolocate
#: model:ir.model.fields,field_description:partner_geolocalize_usability.field_res_users__manual_geolocate
msgid "Geolocate yourself"
msgstr ""
#. module: partner_geolocalize_usability
#: model_terms:ir.ui.view,arch_db:partner_geolocalize_usability.partner_geolocalize_form_view
msgid "Geolocation"
msgstr ""

View File

@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import res_partner

View File

@@ -0,0 +1,12 @@
from odoo import models, fields, api
class ResPartner(models.Model):
_inherit = 'res.partner'
manual_geolocate = fields.Boolean('Geolocate yourself')
@api.multi
def geo_localize(self):
partners = self.filtered(lambda a: a.manual_geolocate == False)
return super(ResPartner, partners).geo_localize()

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record id="geolocata_partner_action_server" model="ir.actions.server">
<field name="name">Geolocate</field>
<field name="model_id" ref="model_res_partner" />
<field
name="binding_model_id" ref="model_res_partner" />
<field name="state">code</field>
<field name="code">records.geo_localize() </field>
</record>
<record model="ir.ui.view" id="partner_geolocalize_form_view">
<field name="name">partner.geolocalize.form</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form" />
<field name='priority'>99</field>
<field name="arch" type="xml">
<xpath expr="//page[@name='geo_location']" position="replace">
<page name="geolocalize" string="Geolocation">
<group colspan="2" col="2">
<separator string="Geolocation" colspan="2" />
<field name="manual_geolocate" />
<button
string="Geolocate"
name="geo_localize"
colspan="2"
icon="fa-check"
type="object" attrs="{'invisible':[('manual_geolocate', '=', True)]}" />
<field name="partner_latitude" attrs="{'readonly':[('manual_geolocate', '=', False)]}" />
<field name="partner_longitude" attrs="{'readonly':[('manual_geolocate', '=', False)]}" />
</group>
</page>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,2 @@
*.*~
*pyc

View File

@@ -0,0 +1,66 @@
============================
partner_gogocarto_export_api
============================
Gogocarto Export module, to export the partner data needed for a Gogocarto map.
This module allow the users to decide:
* the partners to be exported
* the fields exported for each partner (*name*, *partner_longitude* and *partner_lattitude* automatically exported)
Installation
============
Use Odoo normal module installation procedure to install
``partner_gogocarto_export_api``, all dependencies will be installed by default.
Configuration
=============
To export partners data:
#. Set the fields you want to export in Settings / Gogocarto.
#. Check the field *"Export to Gogocarto"* in the partner form view.
And use the link *https://yourodoo.com/web/<company_id>/get_http_gogocarto_elements* in Gogocarto server import configuration (*https://video.colibris-outilslibres.org/videos/watch/c74fc469-c822-4ab8-82a7-a2555e49e576*)
Known issues / Roadmap
======================
None yet.
Bug Tracker
===========
Bugs are tracked on `our issues website <https://github.com/elabore-coop/partner-tools/issues>`_. In case of
trouble, please check there if your issue has already been
reported. If you spotted it first, help us smashing it by providing a
detailed and welcomed feedback.
Credits
=======
Contributors
------------
* Stéphan SAINLEGER <https://github.com/stephansainleger>
* Chloé Migayrou <https://github.com/MigayrouChloe>
* Nicolas Jeudy <https://github.com/njeudy>
* Lokavaluto Teams <https://lokavaluto.fr>
Funders
-------
The development of this module has been financially supported by:
* Lokavaluto (https://lokavaluto.fr)
* Mycéliandre (https://myceliandre.fr)
* Elabore (https://elabore.coop)
Maintainer
----------
This module is maintained by Elabore and Lokavaluto.

View File

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

View File

@@ -0,0 +1,27 @@
{
'name': 'partner_gogocarto_export_api',
'summary': '''HTTP JSON api to send partner data for Gogocarto import''',
'license': 'AGPL-3',
'author': (
'Lokavaluto',
'Elabore'
),
'website': 'https://lokavaluto.fr',
'category': 'Localization',
'version': '12.0.2.0.0',
'depends': [
'base',
'contacts',
'base_geolocalize',
'partner_geolocalize_usability',
'base_jsonify',
],
'data': [
'views/gogocarto_partner.xml',
'views/gogocarto_config_settings_view.xml',
'views/res_company_view.xml',
],
'demo': [],
'installable': True,
'auto_install': False,
}

View File

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

View File

@@ -0,0 +1,29 @@
import json
import logging
from odoo import http
from odoo.http import Response, request
_logger = logging.getLogger(__name__)
class PartnerGogocartojs(http.Controller):
@http.route(
'/web/<company_id>/get_http_gogocarto_elements',
methods=['GET'],
type='http',
csrf=False,
auth="public",
website=True)
def get_gogocarto_elements_http(self, company_id):
data = self._jsonify_get_partner(company_id)
return Response(json.dumps(data))
def _jsonify_get_partner(self, company_id):
PartnerSudo = request.env['res.partner'].sudo()
parser = PartnerSudo._get_gogocarto_parser(company_id)
partners = PartnerSudo.with_context(force_company=company_id).search(
PartnerSudo._get_gogocarto_domain(company_id)
)
return partners.jsonify(parser)

View File

@@ -0,0 +1,73 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * partner_gogocarto_export_api
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-09-12 14:05+0000\n"
"PO-Revision-Date: 2023-09-12 14:05+0000\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: partner_gogocarto_export_api
#: model_terms:ir.ui.view,arch_db:partner_gogocarto_export_api.res_config_settings_view_form_gogocarto
msgid "Check the export on /web/{COMPANY_ID}/get_http_gogocarto_elements."
msgstr "Vérifiez l'export sur /web/{COMPANY_ID}/get_http_gogocarto_elements.\""
#. module: partner_gogocarto_export_api
#: model:ir.model,name:partner_gogocarto_export_api.model_res_company
msgid "Companies"
msgstr "Sociétés"
#. module: partner_gogocarto_export_api
#: model:ir.model,name:partner_gogocarto_export_api.model_res_config_settings
msgid "Config Settings"
msgstr "Paramètres de config"
#. module: partner_gogocarto_export_api
#: model:ir.model,name:partner_gogocarto_export_api.model_res_partner
msgid "Contact"
msgstr ""
#. module: partner_gogocarto_export_api
#: model:ir.model.fields,field_description:partner_gogocarto_export_api.field_res_company__export_gogocarto_fields
msgid "Export Gogocarto Fields"
msgstr "Champs exportés dans Gogocarto"
#. module: partner_gogocarto_export_api
#: model:ir.model.fields,field_description:partner_gogocarto_export_api.field_res_partner__in_gogocarto
#: model:ir.model.fields,field_description:partner_gogocarto_export_api.field_res_users__in_gogocarto
msgid "Export to Gogocarto"
msgstr "Exporter dans Gogocarto"
#. module: partner_gogocarto_export_api
#: model:ir.model.fields,field_description:partner_gogocarto_export_api.field_res_config_settings__export_gogocarto_fields
msgid "GogoCarto Exported fields"
msgstr "Champs exportés dans Gogocarto"
#. module: partner_gogocarto_export_api
#: model_terms:ir.ui.view,arch_db:partner_gogocarto_export_api.res_company_gogocarto_form_view
msgid "GogoCarto Setup"
msgstr "Gogocarto"
#. module: partner_gogocarto_export_api
#: model_terms:ir.ui.view,arch_db:partner_gogocarto_export_api.res_config_settings_view_form_gogocarto
msgid "Gogocarto"
msgstr ""
#. module: partner_gogocarto_export_api
#: model_terms:ir.ui.view,arch_db:partner_gogocarto_export_api.res_config_settings_view_form_gogocarto
msgid "Gogocarto export configuration"
msgstr "Configuration de l'export Gogocarto"
#. module: partner_gogocarto_export_api
#: model_terms:ir.ui.view,arch_db:partner_gogocarto_export_api.res_config_settings_view_form_gogocarto
msgid "Partner fields to export for Gogocarto map."
msgstr "Champs de contact à exporter vers Gogocarto."

View File

@@ -0,0 +1,73 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * partner_gogocarto_export_api
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-09-12 14:00+0000\n"
"PO-Revision-Date: 2023-09-12 14:00+0000\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: partner_gogocarto_export_api
#: model_terms:ir.ui.view,arch_db:partner_gogocarto_export_api.res_config_settings_view_form_gogocarto
msgid "Check the export on /web/{COMPANY_ID}/get_http_gogocarto_elements."
msgstr ""
#. module: partner_gogocarto_export_api
#: model:ir.model,name:partner_gogocarto_export_api.model_res_company
msgid "Companies"
msgstr ""
#. module: partner_gogocarto_export_api
#: model:ir.model,name:partner_gogocarto_export_api.model_res_config_settings
msgid "Config Settings"
msgstr ""
#. module: partner_gogocarto_export_api
#: model:ir.model,name:partner_gogocarto_export_api.model_res_partner
msgid "Contact"
msgstr ""
#. module: partner_gogocarto_export_api
#: model:ir.model.fields,field_description:partner_gogocarto_export_api.field_res_company__export_gogocarto_fields
msgid "Export Gogocarto Fields"
msgstr ""
#. module: partner_gogocarto_export_api
#: model:ir.model.fields,field_description:partner_gogocarto_export_api.field_res_partner__in_gogocarto
#: model:ir.model.fields,field_description:partner_gogocarto_export_api.field_res_users__in_gogocarto
msgid "Export to Gogocarto"
msgstr ""
#. module: partner_gogocarto_export_api
#: model:ir.model.fields,field_description:partner_gogocarto_export_api.field_res_config_settings__export_gogocarto_fields
msgid "GogoCarto Exported fields"
msgstr ""
#. module: partner_gogocarto_export_api
#: model_terms:ir.ui.view,arch_db:partner_gogocarto_export_api.res_company_gogocarto_form_view
msgid "GogoCarto Setup"
msgstr ""
#. module: partner_gogocarto_export_api
#: model_terms:ir.ui.view,arch_db:partner_gogocarto_export_api.res_config_settings_view_form_gogocarto
msgid "Gogocarto"
msgstr ""
#. module: partner_gogocarto_export_api
#: model_terms:ir.ui.view,arch_db:partner_gogocarto_export_api.res_config_settings_view_form_gogocarto
msgid "Gogocarto export configuration"
msgstr ""
#. module: partner_gogocarto_export_api
#: model_terms:ir.ui.view,arch_db:partner_gogocarto_export_api.res_config_settings_view_form_gogocarto
msgid "Partner fields to export for Gogocarto map."
msgstr ""

View File

@@ -0,0 +1,3 @@
from . import res_partner
from . import res_config_settings
from . import company

View File

@@ -0,0 +1,13 @@
from odoo import models, fields
class Company(models.Model):
_inherit = "res.company"
export_gogocarto_fields = fields.Many2many(
'ir.model.fields',
domain=[
('model_id', '=', 'res.partner'),
('name', 'not in', ['id', 'name', 'partner_longitude', 'partner_latitude'])
]
)

View File

@@ -0,0 +1,23 @@
import logging
from odoo import fields, models
_logger = logging.getLogger(__name__)
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
export_gogocarto_fields = fields.Many2many(
related='company_id.export_gogocarto_fields',
relation='ir.model.fields',
string='GogoCarto Exported fields',
readonly=False,
domain=[
('model_id', '=', 'res.partner'),
('name', 'not in', ['name',
'partner_longitude',
'partner_latitude',
'id'])
]
)

View File

@@ -0,0 +1,50 @@
from odoo import models, fields
class ResPartner(models.Model):
""" Inherits partner, adds Gogocarto fields in the partner form, and functions"""
_inherit = 'res.partner'
in_gogocarto = fields.Boolean('Export to Gogocarto')
def _get_gogocarto_domain(self, company_id):
# To OVERRIDE in sub_modules to customize the partner selection
return [('in_gogocarto', '=', True)]
def _get_generic_parser(self, fields):
parser = []
for field in fields:
if field.ttype in [
"boolean",
"char",
"integer",
"monetary",
"text",
"selection",
"float",
"date_time",
"date"]:
parser.append(field.name)
elif field.ttype in ["many2one", "one2many", "many2many"]:
parser.append((field.name, ['id', 'name']))
elif field.ttype == "binary":
continue
elif field.ttype == "html":
continue # Not developped so far
else:
continue
return parser
def _get_gogocarto_parser(self, company_id):
fields = self._get_export_fields(company_id)
parser = self._get_generic_parser(fields)
return parser
def _get_export_fields(self, company_id):
CompanySudo = self.env['res.company'].sudo().search([('id', '=', company_id)])
default_fields = self.env['ir.model.fields'].sudo().search([
('model_id', '=', 'res.partner'),
('name', 'in', ['id', 'name', 'partner_longitude', 'partner_latitude'])])
company_fields = CompanySudo.export_gogocarto_fields
export_fields = default_fields | company_fields
return export_fields

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="res_config_settings_view_form_gogocarto" model="ir.ui.view">
<field name="name">res.config.settings.view.form.inherit.gogocarto</field>
<field name="model">res.config.settings</field>
<field name="priority" eval="99" />
<field name="inherit_id" ref="base.res_config_settings_view_form" />
<field name="arch" type="xml">
<xpath expr="//div[hasclass('settings')]" position="inside">
<div class="app_settings_block" data-string="Gogocarto" string="Gogocarto"
data-key="partner_gogocarto_export_api">
<h2>Gogocarto export configuration</h2>
<div class="text-muted mt16 o_settings_container">
Check the export on /web/{COMPANY_ID}/get_http_gogocarto_elements.
</div>
<div class="row mt16 o_settings_container" id="gogocarto_selection_settings">
<div class="col-12 col-lg-6 o_setting_box" id="gogocarto_fields">
<div class="o_setting_right_pane">
<div class="text-muted">
Partner fields to export for Gogocarto map.
</div>
<div class="content-group">
<div class="mt16">
<field name="export_gogocarto_fields"
widget="many2many_tags"
options="{'no_create': True, 'no_open': True}" />
</div>
</div>
</div>
</div>
</div>
</div>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record model="ir.ui.view" id="partner_gogocarto_form_view">
<field name="name">partner.gogocarto.form</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="partner_geolocalize_usability.partner_geolocalize_form_view" />
<field name='priority'>99</field>
<field name="arch" type="xml">
<xpath expr="//page[@name='geolocalize']/group" position="inside">
<field name="in_gogocarto" />
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record model="ir.ui.view" id="res_company_gogocarto_form_view">
<field name="name">res_company.gogocarto.form</field>
<field name="model">res.company</field>
<field name="inherit_id" ref="base.view_company_form"/>
<field name='priority'>99</field>
<field name="arch" type="xml">
<xpath expr="//notebook" posiion="inside">
<page string="GogoCarto Setup" name="gogocarto">
<group>
<field name="export_gogocarto_fields"/>
</group>
</page>
</xpath>
</field>
</record>
</odoo>

View File

@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
from . import models
from . import wizard

View File

@@ -3,7 +3,7 @@
{
"name": "partner_profiles",
"version": "12.0.1.0.5",
"version": "12.0.2.5.1",
"author": "Elabore",
"website": "https://elabore.coop",
"maintainer": "Stéphan Sainléger",
@@ -14,6 +14,7 @@
"depends": [
"base",
"calendar",
"contacts",
"partner_contact_in_several_companies",
],
"qweb": [
@@ -25,8 +26,8 @@
# always loaded
"data": [
"security/ir.model.access.csv",
"wizard/create_position_profile.xml",
"views/res_partner_view.xml",
"views/calendar_event_view.xml",
"views/partner_profile_view.xml",
"data/partner_profile_data.xml",
"data/res_partner_data.xml",

View File

@@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-11-09 14:54+0000\n"
"PO-Revision-Date: 2022-11-09 14:54+0000\n"
"POT-Creation-Date: 2023-09-12 15:03+0000\n"
"PO-Revision-Date: 2023-09-12 15:03+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
@@ -15,10 +15,80 @@ msgstr ""
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_kanban_view
msgid "<span attrs=\"{'invisible': [('is_main_profile','=',False)]}\" style=\"color:#7c7bad;\">\n"
" <b>Main profile</b>\n"
" </span>\n"
" <span attrs=\"{'invisible': [('is_public_profile','=',False)]}\" style=\"color:#7c7bad;\">\n"
" <b>Public profile</b>\n"
" </span>\n"
" <span attrs=\"{'invisible': [('is_position_profile','=',False)]}\" style=\"color:#7c7bad;\">\n"
" <b>Position profile</b>\n"
" </span>"
msgstr "<span attrs=\"{'invisible': [('is_main_profile','=',False)]}\" style=\"color:#7c7bad;\">\n"
" <b>Fiche administrative</b>\n"
" </span>\n"
" <span attrs=\"{'invisible': [('is_public_profile','=',False)]}\" style=\"color:#7c7bad;\">\n"
" <b>Coordonnées publiques</b>\n"
" </span>\n"
" <span attrs=\"{'invisible': [('is_position_profile','=',False)]}\" style=\"color:#7c7bad;\">\n"
" <b>Fiche fonction</b>\n"
" </span>"
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Administrative Name"
msgstr "Nom Administratif"
msgid "<span>Please find here <strong>all the position profiles</strong> linked\n"
" to this main profile.</span>"
msgstr "<span>Vous trouverez ici <strong>toutes les fiches Fonction</strong> liés\n"
" à cette fiche administrative</span>"
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "<span>Please find here <strong>all the position profiles</strong> linked to\n"
" this main profile.</span>"
msgstr "<span>Vous trouverez ici <strong>toutes les fiches Fonction</strong> liés à\n"
" cette fiche administrative</span>"
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "<span>Please find here <strong>all</strong> the addresses linked with this\n"
" main profile. Adress creation from this tab <strong>only\n"
" generates new main profiles</strong>.</span>"
msgstr "<span>Vous trouverez ici <strong>toutes</strong> les adresses liées avec cette\n"
" fiche administrative. La création d'adresse depuis cet onglet <strong>génère\n"
" uniquement des profils principaux</strong>.</span>"
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "<span>Please find here <strong>all</strong> the addresses/contacts linked to\n"
" this main profile. Contact creation from this tab <strong>only\n"
" generates new main profiles</strong>.</span>"
msgstr "<span>Vous trouverez ici <strong>tou(te)s</strong> les adresses/contacts lié(e)s avec cette\n"
" fiche administrative. La création de contact depuis cet onglet <strong>génère\n"
" uniquement des profils principaux</strong>.</span>"
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.create_position_wizard_view_form
msgid "<span>You are about to create a <strong>Position Profile</strong> which\n"
" represents the role or the job of a person in a structure.</span>"
msgstr "<span>Vous allez créer une <strong>fiche Fonction</strong> qui\n"
" représente le rôle que tient une personne au sein d'une structure.</span>\""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Address"
msgstr "Adresse"
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.create_position_wizard_view_form
msgid "Cancel"
msgstr "Annuler"
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "City"
msgstr "Ville"
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
@@ -31,80 +101,149 @@ msgid "Contact"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Create Public Profile"
msgstr "Créer le profil public"
#: model:ir.model.fields,field_description:partner_profiles.field_res_partner__child_ids
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__child_ids
msgid "Contacts"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Country"
msgstr "Pays"
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.create_position_wizard_view_form
msgid "Create"
msgstr "Créer"
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Create New Position"
msgstr "Créer une nouvelle fonction"
#. module: partner_profiles
#: model:ir.actions.act_window,name:partner_profiles.action_create_position_profile_wizard
msgid "Create Position Profile"
msgstr "Créer une fiche Fonction"
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Create Public Profile"
msgstr "Ajouter des coordonnées publiques"
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.create_position_wizard_view_form
msgid "Create a position profile"
msgstr "Créer une fiche Fonction"
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__create_uid
#: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__create_uid
msgid "Created by"
msgstr "Créé par"
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__create_date
#: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__create_date
msgid "Created on"
msgstr "Créé le"
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__display_name
#: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__display_name
msgid "Display Name"
msgstr "Nom affiché"
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__email
msgid "Email"
msgstr "Courriel"
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__function
msgid "Function"
msgstr "Fonction"
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_res_partner__has_position
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__has_position
msgid "Has Position"
msgstr "A une position"
msgstr "A une fonction"
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__id
#: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__id
msgid "ID"
msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__is_company
msgid "Is Company"
msgstr "Est une société"
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_res_partner__is_main_profile
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__is_main_profile
msgid "Is Main Profile"
msgstr "Est un profil Principal"
msgstr "Est une fiche administrative"
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_res_partner__is_position_profile
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__is_position_profile
msgid "Is Position Profile"
msgstr "Est un profil Position"
msgstr "Est une fiche fontion"
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_res_partner__is_public_profile
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__is_public_profile
msgid "Is Public Profile"
msgstr "Est un profil Public"
msgstr "Est un fiche de coordonnées publiques"
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile____last_update
#: model:ir.model.fields,field_description:partner_profiles.field_partner_profile____last_update
msgid "Last Modified on"
msgstr "Dernière modification le"
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__write_uid
#: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__write_uid
msgid "Last Updated by"
msgstr "Dernière mise à jour par"
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__write_date
#: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__write_date
msgid "Last Updated on"
msgstr "Dernière mise à jour le"
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_res_partner__contact_id
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__contact_id
msgid "Main Contact"
msgstr "Fiche administrative"
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
#: model:partner.profile,name:partner_profiles.partner_profile_main
msgid "Main Profile"
msgstr "Profil principal"
msgstr "Fiche administrative"
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Mobile:"
msgstr "Mobile :"
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__name
msgid "Name"
msgstr "Nom"
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__comment
msgid "Notes"
msgstr "Commentaires"
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_res_partner__other_contact_ids
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__other_contact_ids
@@ -119,7 +258,6 @@ msgstr "Profiles de contact"
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_res_partner__partner_profile
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__partner_profile
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Partner profile"
msgstr "Profil de contact"
@@ -146,28 +284,105 @@ msgstr "Contact : Migration des Contacts standards aux Conctacts à profile"
#: model:ir.cron,cron_name:partner_profiles.ir_cron_generate_missing_public_profiles
#: model:ir.cron,name:partner_profiles.ir_cron_generate_missing_public_profiles
msgid "Partner: generate missing public profiles"
msgstr "Contact : Générer les profil publics manquant"
msgstr "Contact : Générer les fiches de coordonnées publiques manquantes"
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__partner_id
msgid "Person"
msgstr "Personne"
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__phone
msgid "Phone"
msgstr "Téléphone"
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Phone:"
msgstr "Téléphone :"
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
#: model:partner.profile,name:partner_profiles.partner_profile_position
msgid "Position Profile"
msgstr "Profil position"
msgstr "Fiche fonction"
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Positions"
msgstr "Fonctions"
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
#: model:partner.profile,name:partner_profiles.partner_profile_public
msgid "Public Profile"
msgstr "Profil public"
msgstr "Coordonnées publiques"
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_res_partner__public_profile_id
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__public_profile_id
msgid "Public profile"
msgstr "Profil public"
msgstr "Coordonnées publiques"
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__ref
msgid "Ref"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "State"
msgstr "État"
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Street 2..."
msgstr "Rue 2..."
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Street..."
msgstr "Rue..."
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__structure_id
msgid "Structure"
msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_res_partner__structure_position_ids
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__structure_position_ids
msgid "Structure's positions"
msgstr "Fonctions occupées dans la structures"
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Sync data"
msgstr "Synchroniser"
#. module: partner_profiles
#: model:ir.actions.server,name:partner_profiles.sync_public_data_action_server
msgid "Synchronize main and public data"
msgstr "Synchroniser les données publiques"
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_res_partner__to_migrate
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__to_migrate
msgid "To Migrate"
msgstr "A migrer"
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "ZIP"
msgstr "Code postal"
#. module: partner_profiles
#: model:ir.model,name:partner_profiles.model_create_position_profile
msgid "create Position Profile"
msgstr "créer une fiche fonction"
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "e.g. https://www.odoo.com"
msgstr "e.x. https://www.odoo.com"

View File

@@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-11-09 14:53+0000\n"
"PO-Revision-Date: 2022-11-09 14:53+0000\n"
"POT-Creation-Date: 2023-09-12 15:02+0000\n"
"PO-Revision-Date: 2023-09-12 15:02+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
@@ -15,9 +15,64 @@ msgstr ""
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_kanban_view
msgid "<span attrs=\"{'invisible': [('is_main_profile','=',False)]}\" style=\"color:#7c7bad;\">\n"
" <b>Main profile</b>\n"
" </span>\n"
" <span attrs=\"{'invisible': [('is_public_profile','=',False)]}\" style=\"color:#7c7bad;\">\n"
" <b>Public profile</b>\n"
" </span>\n"
" <span attrs=\"{'invisible': [('is_position_profile','=',False)]}\" style=\"color:#7c7bad;\">\n"
" <b>Position profile</b>\n"
" </span>"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Administrative Name"
msgid "<span>Please find here <strong>all the position profiles</strong> linked\n"
" to this main profile.</span>"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "<span>Please find here <strong>all the position profiles</strong> linked to\n"
" this main profile.</span>"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "<span>Please find here <strong>all</strong> the addresses linked with this\n"
" main profile. Adress creation from this tab <strong>only\n"
" generates new main profiles</strong>.</span>"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "<span>Please find here <strong>all</strong> the addresses/contacts linked to\n"
" this main profile. Contact creation from this tab <strong>only\n"
" generates new main profiles</strong>.</span>"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.create_position_wizard_view_form
msgid "<span>You are about to create a <strong>Position Profile</strong> which\n"
" represents the role or the job of a person in a structure.</span>"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Address"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.create_position_wizard_view_form
msgid "Cancel"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "City"
msgstr ""
#. module: partner_profiles
@@ -30,26 +85,70 @@ msgstr ""
msgid "Contact"
msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_res_partner__child_ids
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__child_ids
msgid "Contacts"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Country"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.create_position_wizard_view_form
msgid "Create"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Create New Position"
msgstr ""
#. module: partner_profiles
#: model:ir.actions.act_window,name:partner_profiles.action_create_position_profile_wizard
msgid "Create Position Profile"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Create Public Profile"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.create_position_wizard_view_form
msgid "Create a position profile"
msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__create_uid
#: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__create_uid
msgid "Created by"
msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__create_date
#: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__create_date
msgid "Created on"
msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__display_name
#: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__display_name
msgid "Display Name"
msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__email
msgid "Email"
msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__function
msgid "Function"
msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_res_partner__has_position
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__has_position
@@ -57,10 +156,16 @@ msgid "Has Position"
msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__id
#: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__id
msgid "ID"
msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__is_company
msgid "Is Company"
msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_res_partner__is_main_profile
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__is_main_profile
@@ -80,31 +185,50 @@ msgid "Is Public Profile"
msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile____last_update
#: model:ir.model.fields,field_description:partner_profiles.field_partner_profile____last_update
msgid "Last Modified on"
msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__write_uid
#: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__write_uid
msgid "Last Updated by"
msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__write_date
#: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__write_date
msgid "Last Updated on"
msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_res_partner__contact_id
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__contact_id
msgid "Main Contact"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
#: model:partner.profile,name:partner_profiles.partner_profile_main
msgid "Main Profile"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Mobile:"
msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__name
msgid "Name"
msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__comment
msgid "Notes"
msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_res_partner__other_contact_ids
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__other_contact_ids
@@ -119,7 +243,6 @@ msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_res_partner__partner_profile
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__partner_profile
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Partner profile"
msgstr ""
@@ -148,12 +271,32 @@ msgstr ""
msgid "Partner: generate missing public profiles"
msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__partner_id
msgid "Person"
msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__phone
msgid "Phone"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Phone:"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
#: model:partner.profile,name:partner_profiles.partner_profile_position
msgid "Position Profile"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Positions"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
#: model:partner.profile,name:partner_profiles.partner_profile_public
@@ -171,3 +314,60 @@ msgstr ""
msgid "Ref"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "State"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Street 2..."
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Street..."
msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__structure_id
msgid "Structure"
msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_res_partner__structure_position_ids
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__structure_position_ids
msgid "Structure's positions"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Sync data"
msgstr ""
#. module: partner_profiles
#: model:ir.actions.server,name:partner_profiles.sync_public_data_action_server
msgid "Synchronize main and public data"
msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_res_partner__to_migrate
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__to_migrate
msgid "To Migrate"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "ZIP"
msgstr ""
#. module: partner_profiles
#: model:ir.model,name:partner_profiles.model_create_position_profile
msgid "create Position Profile"
msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "e.g. https://www.odoo.com"
msgstr ""

View File

@@ -3,6 +3,7 @@
import logging
from odoo import _, api, fields, models
from odoo.exceptions import UserError
_logger = logging.getLogger(__name__)
@@ -18,6 +19,7 @@ class res_partner(models.Model):
translate=False,
readonly=False,
)
contact_id = fields.Many2one(ondelete="cascade")
is_main_profile = fields.Boolean(compute="_compute_profile_booleans", store=True)
is_public_profile = fields.Boolean(compute="_compute_profile_booleans", store=True)
is_position_profile = fields.Boolean(
@@ -31,13 +33,16 @@ class res_partner(models.Model):
compute="_compute_public_profile_id",
string="Public profile",
store=True,
ondelete="cascade",
)
# If current partner is Main partner, this field indicates what its position profiles are.
other_contact_ids = fields.One2many(
domain=[("is_position_profile", "=", True)]
)
child_ids = fields.One2many(
domain=[("is_position_profile", "=", False)]
)
structure_position_ids = fields.One2many('res.partner', 'parent_id', string="Structure's positions", domain=[('active', '=', True), ('is_position_profile', '=', True)])
@api.depends("partner_profile", "other_contact_ids")
def _compute_profile_booleans(self):
@@ -80,6 +85,19 @@ class res_partner(models.Model):
self.contact_type = "attached"
self.partner_profile = position_profile.id
@api.onchange("is_company")
def _onchange_is_company(self):
for partner in self:
if partner.is_main_profile:
if partner.has_position or partner.structure_position_ids.filtered(lambda c: c.is_position_profile):
raise UserError("You can not modify the partner company type when the parner has postion profiles associated. Please remove the position profiles before retrying.")
if partner.public_profile_id:
# public_partner = self.env["res.partner"].browse(partner.public_profile_id)[0]
values = {
"is_company": partner.is_company,
}
partner.public_profile_id.sudo().write(values)
@api.model
def create(self, vals):
"""Assume if not type, default is contact"""
@@ -117,6 +135,47 @@ class res_partner(models.Model):
res = super(res_partner, self).create(vals)
return res
@api.multi
def unlink(self):
for partner in self:
if partner.is_company:
# Delete position profiles linked to the company main profile
for position in partner.structure_position_ids:
position.unlink()
return super(res_partner, self).unlink()
@api.multi
def write(self, vals):
super(res_partner, self).write(vals)
if "active" in vals and not "sync_active" in vals:
self._sync_active_profiles()
def _sync_active_profiles(self):
"""Synchronize the active fields values between all the profiles of a partner.
Change in main profile is synchronized in public and position profiles.
Change in public profile is NOT synchronized in main and public profiles.
Change in position profile is NOT synchronized in main and public profiles."""
for partner in self:
if partner.is_main_profile:
# Sync public profile active value with main one
public_profile = partner.public_profile_id
if public_profile and (public_profile.active != partner.active):
public_profile.write({"active": partner.active, "sync_active": True})
# Sync position profiles active value with main one
positions = self.env["res.partner"].search(
[
("is_position_profile", "=", True),
("active", "!=", partner.active),
'|',
("contact_id", "=", partner.id),
("parent_id", "=", partner.id)
]
)
if len(positions) > 0:
for position in positions:
position.write({"active": partner.active, "sync_active": True})
@api.model
def search_position_partners(self, profile):
if profile:
@@ -147,7 +206,6 @@ class res_partner(models.Model):
if self.is_company:
fields = [
"name",
"function",
"phone",
"mobile",
"email",
@@ -158,7 +216,6 @@ class res_partner(models.Model):
"country_id",
"zip",
"is_company",
"lang",
]
else:
fields = ["name"]
@@ -189,6 +246,31 @@ class res_partner(models.Model):
when a partner is attached to him. """
return ['title']
@api.model
def name_search(self, name='', args=None, operator='ilike', limit=100):
""" Remove public profile partners from the name_search results"""
if not args:
args = [("is_public_profile", "=", False)]
else:
args.append(("is_public_profile", "=", False))
return super(res_partner, self).name_search(name, args, operator, limit)
@api.multi
def sync_admin_and_public_data(self):
for partner in self:
if partner.is_main_profile and partner.public_profile_id:
main_partner = partner
public_partner = partner.public_profile_id
elif partner.is_public_profile and partner.contact_id:
main_partner = partner.contact_id
public_partner = partner
public_fields = partner._get_public_profile_fields()
values = {}
for field_name in public_fields:
values[field_name] = main_partner._get_field_value(field_name)
public_partner.write(values)
##################################################################################
## Planned actions
##################################################################################
@@ -196,7 +278,7 @@ class res_partner(models.Model):
@api.model
def _cron_generate_missing_public_profiles(self):
partners = self.search(
[("is_main_profile", "=", True), ("public_profile_id", "=", False)]
[("is_main_profile", "=", True), ("public_profile_id", "=", False), ("type", "=", "contact")]
)
for partner in partners:
partner.create_public_profile()
@@ -211,7 +293,8 @@ class res_partner(models.Model):
search_values = [
("is_company", "=", is_company),
("active", "=", active),
("partner_profile", "=", False)
("partner_profile", "=", False),
("type", "=", "contact")
]
if id:
search_values.append(("id", "=", id))
@@ -262,6 +345,7 @@ class res_partner(models.Model):
def _get_main_partner_search_values(self, partner):
return [
("active", "=", True),
("type", "=", "contact"),
("is_main_profile", "=", True),
("is_company", "=", False),
"|",

View File

@@ -1,16 +0,0 @@
<?xml version="1.0"?>
<odoo>
<data>
<record id="partner_profiles_calendar_event_form_view" model="ir.ui.view">
<field name="name">partner.profiles.calendar.event.view</field>
<field name="model">calendar.event</field>
<field name="inherit_id" ref="calendar.view_calendar_event_form" />
<field name="sequence">99</field>
<field name="arch" type="xml">
<field name="partner_ids" position="attributes">
<attribute name="domain">[('is_public_profile', '=', False)]</attribute>
</field>
</field>
</record>
</data>
</odoo>

View File

@@ -42,57 +42,234 @@
<button type="object" name="create_public_profile"
string="Create Public Profile"
attrs="{'invisible': [('public_profile_id','!=',False)]}" />
<button string="Sync data"
name="sync_admin_and_public_data" type="object"
icon="fa-refresh"
attrs="{'invisible': [('public_profile_id','=',False)]}" />
</div>
</group>
</group>
</xpath>
<!-- ################ -->
<!-- NOTEBOOK UPDATES -->
<!-- ################ -->
<!-- page Contacts & Adresses -->
<xpath expr="//field[@name='child_ids']/.." position="attributes">
<attribute name="attrs">{'invisible': [('is_company','=', False)]}</attribute>
</xpath>
<xpath
expr="//field[@name='child_ids']/form/sheet/group/group/field[@name='contact_type']"
position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<xpath expr="//field[@name='child_ids']/form/sheet/group/group/field[@name='name']"
position="before">
<field name="is_position_profile" readonly="1" invisible="1" />
<field name="partner_profile" string="Partner profile" invisible="1" />
<xpath
expr="//field[@name='child_ids']" position="before">
<div class="alert alert-info" role="alert" style="margin-bottom:0px;"
attrs="{'invisible': [('is_company','=', False)]}">
<span>Please find here <strong>all</strong> the addresses/contacts linked to
this main profile. Contact creation from this tab <strong>only
generates new main profiles</strong>.</span>
</div>
<div class="alert alert-info" role="alert" style="margin-bottom:0px;"
attrs="{'invisible': [('is_company','=', True)]}">
<span>Please find here <strong>all</strong> the addresses linked with this
main profile. Adress creation from this tab <strong>only
generates new main profiles</strong>.</span>
</div>
</xpath>
<!-- page Structure's position -->
<xpath expr="//page[@name='other_position']" position="after">
<page name="strecture_positions" string="Positions"
attrs="{'invisible': [('is_company','=', False)]}">
<div class="alert alert-info" role="alert" style="margin-bottom:0px;">
<span>Please find here <strong>all the position profiles</strong> linked
to this main profile.</span>
</div>
<field name="structure_position_ids" mode="kanban"
domain="[('is_position_profile', '=', True)]">
<kanban create="false">
<field name="id" />
<field name="color" />
<field name="name" />
<field name="title" />
<field name="email" />
<field name="function" />
<field name="phone" />
<field name="mobile" />
<field name="image_small" />
<templates>
<t t-name="kanban-box">
<t t-set="color"
t-value="kanban_color(record.color.raw_value)" />
<div
t-att-class="color + (record.title.raw_value == 1 ? ' oe_kanban_color_alert' : '') + ' oe_kanban_global_click'">
<div class="o_kanban_image">
<img alt="" t-if="record.image_small.raw_value"
t-att-src="kanban_image('res.partner', 'image_small', record.id.raw_value)" />
</div>
<div class="oe_kanban_details">
<field name="name" />
<div t-if="record.function.raw_value">
<field name="function" />
</div>
<div t-if="record.email.raw_value">
<field name="email" widget="email" />
</div>
<div t-if="record.phone.raw_value">Phone: <field
name="phone" widget="phone" /></div>
<div t-if="record.mobile.raw_value">Mobile: <field
name="mobile" widget="phone" /></div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
<button name="%(action_create_position_profile_wizard)d"
string="Create New Position"
class="oe_highlight" type="action"
attrs="{'invisible': [('is_main_profile','=',False)]}" />
</page>
</xpath>
<!-- page Other Positions -->
<xpath expr="//page[@name='other_position']" position="attributes">
<attribute name="attrs">{'invisible': ['|', ('contact_id','!=',False),
('is_company','=',True)]}</attribute>
<attribute name="attrs">{'invisible': [('is_company','=',True)]}</attribute>
</xpath>
<xpath expr="//page[@name='other_position']/field[@name='other_contact_ids']/kanban"
position="attributes">
<attribute name="create">true</attribute>
<xpath expr="//page[@name='other_position']" position="attributes">
<attribute name="string">Positions</attribute>
</xpath>
<xpath expr="//page[@name='other_position']/field[@name='other_contact_ids']"
position="attributes">
<attribute name="context">{'default_partner_profile': 3, 'default_contact_id':
active_id, 'default_name': name, 'default_street': street,
'default_street2': street2, 'default_city': city, 'default_state_id':
state_id, 'default_zip': zip, 'default_country_id': country_id,
'default_supplier': supplier}</attribute>
<xpath expr="//page[@name='other_position']/field[@name='other_contact_ids']/form"
position="replace" />
<xpath expr="//field[@name='other_contact_ids']" position="before">
<div class="alert alert-info" role="alert" style="margin-bottom:0px;">
<span>Please find here <strong>all the position profiles</strong> linked to
this main profile.</span>
</div>
</xpath>
<xpath
expr="//field[@name='other_contact_ids']/form/sheet/group/group/field[@name='name']"
position="after">
<field name="is_position_profile" readonly="1" invisible="1" />
<field name="partner_profile" string="Partner profile" />
<field name="parent_id" widget="res_partner_many2one" placeholder="Company"
domain="[('is_company', '=', True),('is_main_profile','=', True)]"
context="{'default_partner_profile': 1, 'default_is_company': True, 'show_vat': True}" />
<xpath expr="//field[@name='other_contact_ids']" position="after">
<button name="%(action_create_position_profile_wizard)d"
string="Create New Position"
class="oe_highlight" type="action"
attrs="{'invisible': [('is_main_profile','=',False)]}" />
</xpath>
<!-- #################################### -->
<!-- PUBLIC AND POSITION PROFILES DISPLAY -->
<!-- #################################### -->
<xpath expr="//div[@name='button_box']" position="attributes">
<attribute name="attrs">{'invisible': ['|', ('is_public_profile','=', True),
('is_position_profile','=', True)]}</attribute>
</xpath>
<xpath expr="//field[@name='company_type']" position="attributes">
<attribute name="attrs">{'invisible': ['|', ('is_public_profile','=', True),
('is_position_profile','=', True)]}</attribute>
</xpath>
<xpath expr="//field[@name='image']" position="attributes">
<attribute name="attrs">{'invisible': ['|', ('is_public_profile','=', True),
('is_position_profile','=', True)]}</attribute>
</xpath>
<xpath expr="//notebook" position="attributes">
<attribute name="attrs">{'invisible': ['|', ('is_public_profile','=', True),
('is_position_profile','=', True)]}</attribute>
</xpath>
<xpath expr="//field[@name='type']/../.." position="attributes">
<attribute name="attrs">{'invisible': ['|', ('is_public_profile','=', True),
('is_position_profile','=', True)]}</attribute>
</xpath>
<!-- ###################### -->
<!-- PUBLIC PROFILE DISPLAY -->
<!-- ###################### -->
<xpath expr="//field[@name='type']/../.." position="after">
<group id="public_data" attrs="{'invisible': [('is_public_profile','=',False)]}">
<group>
<label for="street" string="Address" />
<div class="o_address_format">
<field name="street" placeholder="Street..."
class="o_address_street"
attrs="{'readonly': [('type', '=', 'contact'),('parent_id', '!=', False)]}" />
<field name="street2" placeholder="Street 2..."
class="o_address_street"
attrs="{'readonly': [('type', '=', 'contact'),('parent_id', '!=', False)]}" />
<field name="city" placeholder="City" class="o_address_city"
attrs="{'readonly': [('type', '=', 'contact'),('parent_id', '!=', False)]}" />
<field name="state_id" class="o_address_state" placeholder="State"
options='{"no_open": True}'
attrs="{'readonly': [('type', '=', 'contact'),('parent_id', '!=', False)]}"
context="{'country_id': country_id, 'zip': zip}" />
<field name="zip" placeholder="ZIP" class="o_address_zip"
attrs="{'readonly': [('type', '=', 'contact'),('parent_id', '!=', False)]}" />
<field name="country_id" placeholder="Country"
class="o_address_country"
options='{"no_open": True, "no_create": True}'
attrs="{'readonly': [('type', '=', 'contact'),('parent_id', '!=', False)]}" />
</div>
</group>
<group>
<field name="phone" widget="phone" />
<field name="mobile" widget="phone" />
<field name="email" widget="email" context="{'gravatar_image': True}" />
<field name="website" widget="url"
placeholder="e.g. https://www.odoo.com" />
</group>
</group>
</xpath>
<!-- ######################## -->
<!-- POSITION PROFILE DISPLAY -->
<!-- ######################## -->
<xpath expr="//field[@name='type']/../.." position="after">
<group id="position_data"
attrs="{'invisible': [('is_position_profile','=',False)]}">
<group>
<field name="function" />
</group>
<group>
<field name="phone" widget="phone" />
<field name="email" widget="email" context="{'gravatar_image': True}" />
</group>
<group>
<field name="comment" />
</group>
</group>
</xpath>
</field>
</record>
<record id="partner_profiles_kanban_view" model="ir.ui.view">
<field name="name">Partner Profiles Kanban View</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.res_partner_kanban_view" />
<field name="sequence">99</field>
<field name="arch" type="xml">
<xpath expr="//kanban" position="inside">
<field name="is_main_profile" />
<field name="is_public_profile" />
<field name="is_position_profile" />
</xpath>
<xpath
expr="//div[@class='oe_kanban_details']/div[hasclass('o_kanban_tags_section')]"
position="before">
<div>
<span attrs="{'invisible': [('is_main_profile','=',False)]}"
style="color:#7c7bad;">
<b>Main profile</b>
</span>
<span attrs="{'invisible': [('is_public_profile','=',False)]}"
style="color:#7c7bad;">
<b>Public profile</b>
</span>
<span attrs="{'invisible': [('is_position_profile','=',False)]}"
style="color:#7c7bad;">
<b>Position profile</b>
</span>
</div>
</xpath>
</field>
</record>
<record id="sync_public_data_action_server" model="ir.actions.server">
<field name="name">Synchronize main and public data</field>
<field name="model_id" ref="model_res_partner" />
<field name="groups_id" eval="[(4,ref('base.group_no_one'))]" />
<field name="state">code</field>
<field name="code">records.sync_admin_and_public_data() </field>
</record>
</data>
</odoo>

View File

@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import create_position_profile

View File

@@ -0,0 +1,66 @@
# Copyright 2022 Elabore (https://elabore.coop)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
class CreatePositionProfile(models.TransientModel):
_name = "create.position.profile"
_description = "create Position Profile"
@api.model
def _default_is_company(self):
return self.env['res.partner'].browse(self._context.get('active_ids')).is_company
@api.model
def _default_structure_id(self):
current_partner_id = self.env['res.partner'].browse(self._context.get('active_ids'))
if current_partner_id.is_company:
return current_partner_id.id
else:
return None
@api.model
def _default_partner_id(self):
current_partner_id = self.env['res.partner'].browse(self._context.get('active_ids'))
if not current_partner_id.is_company:
return current_partner_id.id
else:
return None
is_company = fields.Boolean('Is Company', default=_default_is_company)
structure_id = fields.Many2one('res.partner', string='Structure', domain="[('is_company', '=', True), ('is_main_profile', '=', True)]", default=_default_structure_id )
partner_id = fields.Many2one('res.partner', string='Person', domain="[('is_company', '=', False), ('is_main_profile', '=', True)]", default=_default_partner_id)
function = fields.Char('Function')
phone = fields.Char('Phone')
email = fields.Char('Email')
comment = fields.Text('Notes')
def _compute_position_profile_values(self):
values= {
"contact_id": self.partner_id.id,
"parent_id": self.structure_id.id,
"function": self.function,
"name": self.partner_id.name,
"phone": self.phone,
"email": self.email,
"comment" : self.comment,
"partner_profile": self.env.ref("partner_profiles.partner_profile_position").id
}
return values
@api.multi
def create_position_profile(self):
values = self._compute_position_profile_values()
position_partner_id = self.env["res.partner"].create(values)
view = self.env.ref("base.view_partner_form")
return {
"name": "Position Partner created",
"view_type": "form",
"view_mode": "form",
"view_id": view.id,
"res_model": "res.partner",
"type": "ir.actions.act_window",
"res_id": position_partner_id.id,
"context": self.env.context,
}

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="create_position_wizard_view_form" model="ir.ui.view">
<field name="name">create.position.wizard.view.form</field>
<field name="model">create.position.profile</field>
<field name="arch" type="xml">
<form string="Create a position profile">
<sheet>
<div class="alert alert-info" role="alert" style="margin-bottom:0px;">
<span>You are about to create a <strong>Position Profile</strong> which
represents the role or the job of a person in a structure.</span>
</div>
<group>
<field name="is_company" invisible="1" />
<field name="structure_id"
attrs="{'readonly': [('is_company','=',True)], 'required': [('is_company','=',False)]}" />
<field name="partner_id"
attrs="{'readonly': [('is_company','=',False)], 'required': [('is_company','=',True)]}" />
<field name="function" />
<field name="email" />
<field name="phone" />
<field name="comment" />
</group>
</sheet>
<footer>
<button string="Create" name="create_position_profile" type="object"
class="btn-primary" />
<button string="Cancel" class="btn-secondary" special="cancel" />
</footer>
</form>
</field>
</record>
<record id="action_create_position_profile_wizard" model="ir.actions.act_window">
<field name="name">Create Position Profile</field>
<field name="res_model">create.position.profile</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="view_id" ref="create_position_wizard_view_form" />
<field name="target">new</field>
</record>
<act_window name="Create Position Profile"
res_model="create.position.profile"
src_model="res.partner"
multi="True"
key2="client_action_multi"
view_mode="form"
id="action_create_position_profile_wizard" />
</odoo>

View File

@@ -0,0 +1,2 @@
*.*~
*pyc

View File

@@ -0,0 +1,53 @@
======================================
partner_profiles_geolocalize_usability
======================================
Adapt geolocalize usability to partner profiles logic
Installation
============
Use Odoo normal module installation procedure to install
``partner_profiles_geolocalize_usability``.
Description
===========
This module adds the geolocation data in the form view of public profiles.
Configuration
=============
No configuration needed.
Known issues / Roadmap
======================
None yet.
Bug Tracker
===========
Bugs are tracked on `our issues website <https://github.com/elabore-coop/partner-tools/issues>`_. In case of
trouble, please check there if your issue has already been
reported. If you spotted it first, help us smashing it by providing a
detailed and welcomed feedback.
Credits
=======
Contributors
------------
* Stéphan Sainléger
Funders
-------
The development of this module has been financially supported by:
* Elabore (https://elabore.coop)
Maintainer
----------
This module is maintained by Elabore.

View File

@@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
from . import models
# from . import controllers
# from . import wizard

View File

@@ -0,0 +1,38 @@
# Copyright 2023 Stéphan Sainléger (Elabore)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "partner_profiles_geolocalize_usability",
"version": "12.0.1.1.0",
"author": "Elabore",
"website": "https://elabore.coop",
"maintainer": "Stéphan Sainléger",
"license": "AGPL-3",
"category": "Tools",
"summary": "Adapt geolocalize usability to partner profiles logic",
# any module necessary for this one to work correctly
"depends": [
"base",
"partner_geolocalize_usability",
"partner_profiles",
],
"qweb": [
# "static/src/xml/*.xml",
],
"external_dependencies": {
"python": [],
},
# always loaded
"data": [
"views/res_partner.xml",
],
# only loaded in demonstration mode
"demo": [],
"js": [],
"css": [],
"installable": True,
# Install this module automatically if all dependency have been previously
# and independently installed. Used for synergetic or glue modules.
"auto_install": False,
"application": False,
}

View File

@@ -0,0 +1 @@
This directory should contain the *.po for Odoo translation.

View File

@@ -0,0 +1,22 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * partner_profiles_geolocalize_usability
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-09-12 13:52+0000\n"
"PO-Revision-Date: 2023-09-12 13:52+0000\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: partner_profiles_geolocalize_usability
#: model_terms:ir.ui.view,arch_db:partner_profiles_geolocalize_usability.partner_geolocalize_form_view_public
msgid "Geolocate"
msgstr "Géolocaliser"

View File

@@ -0,0 +1,22 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * partner_profiles_geolocalize_usability
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-09-12 13:51+0000\n"
"PO-Revision-Date: 2023-09-12 13:51+0000\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: partner_profiles_geolocalize_usability
#: model_terms:ir.ui.view,arch_db:partner_profiles_geolocalize_usability.partner_geolocalize_form_view_public
msgid "Geolocate"
msgstr ""

View File

@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import res_partner

View File

@@ -0,0 +1,23 @@
from odoo import models, api
class ResPartner(models.Model):
_inherit = 'res.partner'
@api.multi
def sync_admin_and_public_data(self):
super(ResPartner, self).sync_admin_and_public_data()
for partner in self:
if partner.is_main_profile and partner.public_profile_id:
main_partner = partner
public_partner = partner.public_profile_id
elif partner.is_public_profile and partner.contact_id:
main_partner = partner.contact_id
public_partner = partner
values = {
"manual_geolocate": main_partner.manual_geolocate,
"partner_latitude": main_partner.partner_latitude,
"partner_longitude": main_partner.partner_longitude,
}
public_partner.write(values)

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record model="ir.ui.view" id="partner_geolocalize_form_view_public">
<field name="name">partner.gogocarto.form.public</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="partner_profiles.partner_profiles_form_view" />
<field name='priority'>99</field>
<field name="arch" type="xml">
<xpath expr="//group[@id='public_data']" position="inside">
<group>
<field name="manual_geolocate" />
<button
string="Geolocate"
name="geo_localize"
colspan="2"
icon="fa-check"
type="object" attrs="{'invisible':[('manual_geolocate', '=', True)]}" />
<field name="partner_latitude" attrs="{'readonly':[('manual_geolocate', '=', False)]}" />
<field name="partner_longitude" attrs="{'readonly':[('manual_geolocate', '=', False)]}" />
</group>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,2 @@
*.*~
*pyc

View File

@@ -0,0 +1,56 @@
================================
partner_profiles_gogocarto_export
================================
Adapt data export for gogocarto to partner profiles logic
Installation
============
Use Odoo normal module installation procedure to install
``partner_profiles_gogocarto_export``.
Configuration
=============
To export public partners data:
#. Set the fields you want to export in Settings / Gogocarto, in the dedicated parameter for public profiles.
#. Check the field *"Export to Gogocarto"* in the partner form view of the main profile.
And use the link *https://yourodoo.com/web/<company_id>/get_http_gogocarto_elements* in Gogocarto server import configuration (*https://video.colibris-outilslibres.org/videos/watch/c74fc469-c822-4ab8-82a7-a2555e49e576*)
Known issues / Roadmap
======================
None yet.
Bug Tracker
===========
Bugs are tracked on `our issues website <https://github.com/elabore-coop/partner-tools/issues>`_. In case of
trouble, please check there if your issue has already been
reported. If you spotted it first, help us smashing it by providing a
detailed and welcomed feedback.
Credits
=======
Contributors
------------
* Stéphan Sainléger
Funders
-------
The development of this module has been financially supported by:
* Elabore (https://elabore.coop)
* Lokavaluto (https://lokavaluto.fr)
Maintainer
----------
This module is maintained by Elabore and Lokavaluto.

View File

@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import models

View File

@@ -0,0 +1,40 @@
# Copyright 2023 Stéphan Sainléger (Elabore)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "partner_profiles_gogocarto_export",
"version": "12.0.1.0.0",
"author": "Elabore",
"website": "https://elabore.coop",
"maintainer": "Stéphan Sainléger",
"license": "AGPL-3",
"category": "Tools",
"summary": "Adapt data export for gogocarto to partner profiles logic",
# any module necessary for this one to work correctly
"depends": [
"base",
"partner_gogocarto_export_api",
"partner_profiles",
"partner_profiles_geolocalize_usability",
],
"qweb": [
# "static/src/xml/*.xml",
],
"external_dependencies": {
"python": [],
},
# always loaded
"data": [
"views/config_settings_view.xml",
"views/res_company_view.xml",
],
# only loaded in demonstration mode
"demo": [],
"js": [],
"css": [],
"installable": True,
# Install this module automatically if all dependency have been previously
# and independently installed. Used for synergetic or glue modules.
"auto_install": False,
"application": False,
}

View File

@@ -0,0 +1 @@
This directory should contain the *.po for Odoo translation.

View File

@@ -0,0 +1,46 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * partner_profiles_gogocarto_export
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-09-12 14:02+0000\n"
"PO-Revision-Date: 2023-09-12 14:02+0000\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: partner_profiles_gogocarto_export
#: model:ir.model,name:partner_profiles_gogocarto_export.model_res_company
msgid "Companies"
msgstr "Sociétés"
#. module: partner_profiles_gogocarto_export
#: model:ir.model,name:partner_profiles_gogocarto_export.model_res_config_settings
msgid "Config Settings"
msgstr "Paramètres de config"
#. module: partner_profiles_gogocarto_export
#: model:ir.model,name:partner_profiles_gogocarto_export.model_res_partner
msgid "Contact"
msgstr "Contact"
#. module: partner_profiles_gogocarto_export
#: model:ir.model.fields,field_description:partner_profiles_gogocarto_export.field_res_company__export_gogocarto_public_fields
msgid "Export Gogocarto Public Fields"
msgstr "Export Gogocarto des champs publics"
#. module: partner_profiles_gogocarto_export
#: model:ir.model.fields,field_description:partner_profiles_gogocarto_export.field_res_config_settings__export_gogocarto_public_fields
msgid "GogoCarto Exported Public fields"
msgstr "Champs publics exportés dans Gogocarto"
#. module: partner_profiles_gogocarto_export
#: model_terms:ir.ui.view,arch_db:partner_profiles_gogocarto_export.res_config_settings_view_form_gogocarto_public
msgid "Partner public fields to export for Gogocarto map."
msgstr "Champs publics à exporter dans Gogocarto"

View File

@@ -0,0 +1,47 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * partner_profiles_gogocarto_export
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-09-12 14:08+0000\n"
"PO-Revision-Date: 2023-09-12 14:08+0000\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: partner_profiles_gogocarto_export
#: model:ir.model,name:partner_profiles_gogocarto_export.model_res_company
msgid "Companies"
msgstr ""
#. module: partner_profiles_gogocarto_export
#: model:ir.model,name:partner_profiles_gogocarto_export.model_res_config_settings
msgid "Config Settings"
msgstr ""
#. module: partner_profiles_gogocarto_export
#: model:ir.model,name:partner_profiles_gogocarto_export.model_res_partner
msgid "Contact"
msgstr ""
#. module: partner_profiles_gogocarto_export
#: model:ir.model.fields,field_description:partner_profiles_gogocarto_export.field_res_company__export_gogocarto_public_fields
msgid "Export Gogocarto Public Fields"
msgstr ""
#. module: partner_profiles_gogocarto_export
#: model:ir.model.fields,field_description:partner_profiles_gogocarto_export.field_res_config_settings__export_gogocarto_public_fields
msgid "GogoCarto Exported Public fields"
msgstr ""
#. module: partner_profiles_gogocarto_export
#: model_terms:ir.ui.view,arch_db:partner_profiles_gogocarto_export.res_config_settings_view_form_gogocarto_public
msgid "Partner public fields to export for Gogocarto map."
msgstr ""

View File

@@ -0,0 +1,3 @@
from . import res_config_settings
from . import company
from . import res_partner

View File

@@ -0,0 +1,14 @@
from odoo import models, fields
class Company(models.Model):
_inherit = "res.company"
export_gogocarto_public_fields = fields.Many2many(
'ir.model.fields',
relation='ir_model_fields_gogocarto_public',
domain=[
('model_id', '=', 'res.partner'),
('name', 'not in', ['id', 'name', 'partner_longitude', 'partner_latitude'])
]
)

View File

@@ -0,0 +1,23 @@
import logging
from odoo import fields, models
_logger = logging.getLogger(__name__)
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
export_gogocarto_public_fields = fields.Many2many(
related='company_id.export_gogocarto_public_fields',
relation='ir.model.fields',
string='GogoCarto Exported Public fields',
readonly=False,
domain=[
('model_id', '=', 'res.partner'),
('name', 'not in', ['name',
'partner_longitude',
'partner_latitude',
'id'])
]
)

View File

@@ -0,0 +1,29 @@
from odoo import models
import logging
class ResPartner(models.Model):
""" Inherits partner, adds Gogocarto public fields in the partner form, and functions"""
_inherit = 'res.partner'
def _get_gogocarto_domain(self, company_id):
# To OVERRIDE in sub_modules to customize the partner selection
res = super(ResPartner, self)._get_gogocarto_domain(company_id)
res.extend([('is_main_profile', '=', True)])
return res
def _get_gogocarto_parser(self, company_id):
parser = super(ResPartner, self)._get_gogocarto_parser(company_id)
public_fields = self._get_export_public_fields(company_id)
public_parser = self._get_generic_parser(public_fields)
parser.append(("public_profile_id", public_parser))
return parser
def _get_export_public_fields(self, company_id):
CompanySudo = self.env['res.company'].sudo().search([('id', '=', company_id)])
default_fields = self.env['ir.model.fields'].sudo().search([
('model_id', '=', 'res.partner'),
('name', 'in', ['id', 'name', 'partner_longitude', 'partner_latitude'])])
company_fields = CompanySudo.export_gogocarto_public_fields
export_fields = default_fields | company_fields
return export_fields

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="res_config_settings_view_form_gogocarto_public" model="ir.ui.view">
<field name="name">res.config.settings.view.form.inherit.gogocarto.public</field>
<field name="model">res.config.settings</field>
<field name="inherit_id"
ref="partner_gogocarto_export_api.res_config_settings_view_form_gogocarto" />
<field name="arch" type="xml">
<xpath expr="//div[@id='gogocarto_selection_settings']" position="inside">
<div class="col-12 col-lg-6 o_setting_box" id="gogocarto_public_fields">
<div class="o_setting_right_pane">
<div class="text-muted">
Partner public fields to export for Gogocarto map.
</div>
<div class="content-group">
<div class="mt16">
<field name="export_gogocarto_public_fields" widget="many2many_tags"
options="{'no_create': True, 'no_open': True}" />
</div>
</div>
</div>
</div>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record model="ir.ui.view" id="res_company_gogocarto_public_form_view">
<field name="name">res_company.gogocarto.public.form</field>
<field name="model">res.company</field>
<field name="inherit_id" ref="partner_gogocarto_export_api.res_company_gogocarto_form_view" />
<field name='priority'>99</field>
<field name="arch" type="xml">
<xpath expr="//page[@name='gogocarto']" position="inside">
<group>
<field name="export_gogocarto_public_fields" />
</group>
</xpath>
</field>
</record>
</odoo>

View File

@@ -2,3 +2,4 @@
from . import models
from . import controllers
from . import wizard

View File

@@ -3,7 +3,7 @@
{
"name": "partner_profiles_portal",
"version": "12.0.1.0.2",
"version": "12.0.2.5.1",
"author": "Elabore",
"website": "https://elabore.coop",
"maintainer": "Stéphan Sainléger",
@@ -26,9 +26,13 @@
"data": [
"security/members_security.xml",
"views/portal_home_template.xml",
"views/portal_my_profiles_template.xml",
"views/portal_partner_profile_template.xml",
"views/portal_my_structures_template.xml",
"views/portal_my_positions_template.xml",
"views/portal_partner_structure_template.xml",
"views/portal_partner_position_template.xml",
"views/portal_my_account.xml",
"views/res_partner_view.xml",
"wizard/create_position_profile.xml",
],
# only loaded in demonstration mode
"demo": [],

View File

@@ -1,4 +1,7 @@
# -*- coding: utf-8 -*-
from . import portal_my_profiles
from . import portal_partner_profile
from . import portal_my_structures
from . import portal_structure_profile
from . import portal_my_positions
from . import portal_position_profile
from . import portal_my_account

View File

@@ -0,0 +1,169 @@
# -*- coding: utf-8 -*-
import base64
from odoo import tools
from odoo.http import request, route
from odoo.addons.portal.controllers.portal import CustomerPortal
class CustomerPortalMyProfile(CustomerPortal):
def _get_mandatory_main_fields(self):
return ["main_name", "main_email"]
def _get_optional_main_fields(self):
return ["main_street", "main_street2", "main_city", "main_country_id", "main_phone", "main_mobile", "main_zip", "main_state_id", "main_website"]
def _get_mandatory_public_fields(self):
return ["public_name"]
def _get_optional_public_fields(self):
return ["public_email", "public_street", "public_street2", "public_city", "public_phone", "public_mobile", "public_zip", "public_website"]
def _get_special_fields(self):
return ["main_logo"]
def _get_main_boolean_account_fields(self):
'''Provides the fields for which we must check the presence
in form's kw to know the value to save in the partner field.
All of them MUST start with "main_".'''
fields = []
return fields
def _get_public_boolean_account_fields(self):
'''Provides the fields for which we must check the presence
in form's kw to know the value to save in the partner field.
All of them MUST start with "public_".'''
fields = []
return fields
def _transform_in_partner_fields(self, kw, profile_fields, prefix=""):
'''Transforms kw's values in res_partner fields and values'''
return {key[len(prefix):]: kw[key] for key in profile_fields if key in kw}
def _add_boolean_values(self, values, kw, boolean_fields, prefix=""):
for key in boolean_fields:
values.update(
{
key[len(prefix):]: kw.get(key, "off") == "on",
}
)
return values
def _retrieve_main_values(self, data):
main_fields = self._get_mandatory_main_fields() + self._get_optional_main_fields()
values = self._transform_in_partner_fields(data, main_fields, "main_")
boolean_fields = self._get_main_boolean_account_fields()
values = self._add_boolean_values(values, data, boolean_fields, "main_")
if 'main_logo' in data:
image = data.get('main_logo')
if image:
image = image.read()
image = base64.b64encode(image)
values.update({
'image': image
})
return values
def _retrieve_public_values(self, data):
public_fields = self._get_mandatory_public_fields() + self._get_optional_public_fields()
values = self._transform_in_partner_fields(data, public_fields, "public_")
boolean_fields = self._get_public_boolean_account_fields()
values = self._add_boolean_values(values, data, boolean_fields, "public_")
return values
def _get_page_opening_values(self):
# Just retrieve the values to display for Selection fields
countries = request.env["res.country"].sudo().search([])
states = request.env['res.country.state'].sudo().search([])
values = {
"countries": countries,
'states': states,
}
return values
@route(["/my/account"], type="http", auth="user", website=True)
def account(self, redirect=None, **post):
values = self._prepare_portal_layout_values()
user = request.env.user
partner = user.partner_id
public_partner = partner.public_profile_id
values.update({
'error': {},
'error_message': [],
})
if post and request.httprequest.method == 'POST':
error, error_message = self.details_form_validate(post)
values.update({'error': error, 'error_message': error_message})
values.update(post)
if not error:
# Save main profile values
values = self._retrieve_main_values(post)
partner.sudo().write(values)
# Save public profile values
public_values = self._retrieve_public_values(post)
if len(public_values) > 0:
public_partner.sudo().write(public_values)
# Email change generates a change of user's login
if post.get("main_email", user.login) != user.login:
user.login = post["main_email"]
return request.redirect("/web/session/logout")
if redirect:
return request.redirect(redirect)
return request.redirect('/my/home')
values.update(self._get_page_opening_values())
values.update({
'partner': partner,
'public_partner': public_partner,
'has_check_vat': hasattr(request.env['res.partner'], 'check_vat'),
'redirect': "/my/account?success=True",
'page_name': 'my_details',
})
response = request.render("portal.portal_my_details", values)
response.headers['X-Frame-Options'] = 'DENY'
return response
def details_form_validate(self, data):
error = dict()
error_message = []
# Validation
for field_name in self._get_mandatory_main_fields() + self._get_mandatory_public_fields():
if not data.get(field_name):
error[field_name] = 'missing'
# email validation
if data.get('main_email') and not tools.single_email_re.match(data.get('main_email')):
error["main_email"] = 'error'
error_message.append(_('Invalid Email! Please enter a valid email address.'))
if data.get('public_email') and not tools.single_email_re.match(data.get('public_email')):
error["public_email"] = 'error'
error_message.append(_('Invalid Public Email! Please enter a valid public email address.'))
# public name uniqueness
if data.get("public_name") and request.env["res.partner"].sudo().search(
[
("name", "=", data.get("public_name")),
("is_public_profile", "=", True),
("contact_id", "!=", request.env.user.partner_id.id),
]
):
error["public_name"] = "error"
error_message.append(
_("This public name is already used, please find an other idea.")
)
# error message for empty required fields
if [err for err in error.values() if err == 'missing']:
error_message.append('Some required fields are empty.')
unknown = [k for k in data if k not in self._get_mandatory_main_fields() + self._get_optional_main_fields() + self._get_mandatory_public_fields() + self._get_optional_public_fields() + self._get_special_fields()]
if unknown:
error['common'] = 'Unknown field'
error_message.append("Unknown field '%s'" % ','.join(unknown))
return error, error_message

View File

@@ -0,0 +1,80 @@
# Copyright 2020 Lokavaluto ()
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import http, _
from odoo.http import request
from odoo.addons.portal.controllers.portal import CustomerPortal, pager as portal_pager
class CustomerPortalMyPositions(CustomerPortal):
def _get_domain_my_positions(self, user):
if user.partner_id.structure_position_ids:
return [("id", "in", user.partner_id.structure_position_ids.ids),
("is_company", "=", False),
("is_position_profile", "=", True),
]
else:
return None
def _prepare_portal_layout_values(self):
values = super(CustomerPortalMyPositions, self)._prepare_portal_layout_values()
domain = self._get_domain_my_structures(request.env.user)
values["structure_count"] = request.env["res.partner"].search_count(domain) if domain else 0
return values
@http.route(
["/my/positions", "/my/positions/page/<int:page>"],
type="http",
auth="user",
website=True,
)
def portal_my_positions(
self, page=1, date_begin=None, date_end=None, sortby=None, **kw
):
values = self._prepare_portal_layout_values()
position = request.env["res.partner"]
domain = self._get_domain_my_positions(request.env.user)
searchbar_sortings = {
"name": {"label": _("Name"), "order": "name"},
"parent_id": {"label": _("Company"), "order": "parent_id"},
}
if not sortby:
sortby = "name"
order = searchbar_sortings[sortby]["order"]
# archive groups - Default Group By 'create_date'
archive_groups = self._get_archive_groups("res.partner", domain)
# structures count
position_count = position.search_count(domain) if domain else 0
# pager
pager = portal_pager(
url="/my/positions",
url_args={"sortby": sortby},
total=position_count,
page=page,
step=self._items_per_page,
)
# content according to pager and archive selected
positions = position.search(
domain,
order=order,
limit=self._items_per_page,
offset=pager["offset"],
) if domain else None
request.session["my_positions_history"] = positions.ids[:100] if positions else None
values.update(
{
"positions": positions,
"page_name": "position",
"archive_groups": archive_groups,
"default_url": "/my/positions",
"pager": pager,
"searchbar_sortings": searchbar_sortings,
"sortby": sortby,
}
)
return request.render("partner_profiles_portal.portal_my_positions", values)

View File

@@ -5,49 +5,38 @@ from odoo.http import request
from odoo.addons.portal.controllers.portal import CustomerPortal, pager as portal_pager
class CustomerPortalMyProfiles(CustomerPortal):
class CustomerPortalMyStructures(CustomerPortal):
def _get_domain_my_profiles(self, user):
def _get_domain_my_structures(self, user):
if user.partner_id.other_contact_ids:
main_profile_ids = user.partner_id.other_contact_ids.filtered(
"edit_structure_main_profile"
).mapped("parent_id")
public_profile_ids = user.partner_id.other_contact_ids.filtered(
"edit_structure_public_profile"
).mapped("parent_id.public_profile_id")
return [
"|",
"|",
("contact_id", "=", user.partner_id.id),
("id", "in", main_profile_ids.ids),
("id", "in", public_profile_ids.ids),
main_structure_ids = user.partner_id.other_contact_ids.mapped("parent_id")
return [("id", "in", main_structure_ids.ids),
("is_company", "=", True)
]
else:
return [("contact_id", "=", user.partner_id.id)]
return None
def _prepare_portal_layout_values(self):
values = super(CustomerPortalMyProfiles, self)._prepare_portal_layout_values()
values["profile_count"] = request.env["res.partner"].search_count(
self._get_domain_my_profiles(request.env.user)
)
values = super(CustomerPortalMyStructures, self)._prepare_portal_layout_values()
domain = self._get_domain_my_structures(request.env.user)
values["structure_count"] = request.env["res.partner"].search_count(domain) if domain else 0
return values
@http.route(
["/my/profiles", "/my/profiles/page/<int:page>"],
["/my/structures", "/my/structures/page/<int:page>"],
type="http",
auth="user",
website=True,
)
def portal_my_profiles(
def portal_my_structures(
self, page=1, date_begin=None, date_end=None, sortby=None, **kw
):
values = self._prepare_portal_layout_values()
profile = request.env["res.partner"]
domain = self._get_domain_my_profiles(request.env.user)
structure = request.env["res.partner"]
domain = self._get_domain_my_structures(request.env.user)
searchbar_sortings = {
"name": {"label": _("Name"), "order": "name"},
"partner_profile": {"label": _("Profile Type"), "order": "partner_profile"},
"parent_id": {"label": _("Company"), "order": "parent_id"},
}
if not sortby:
@@ -57,35 +46,35 @@ class CustomerPortalMyProfiles(CustomerPortal):
# archive groups - Default Group By 'create_date'
archive_groups = self._get_archive_groups("res.partner", domain)
# profiles count
profile_count = profile.search_count(domain)
# structures count
structure_count = structure.search_count(domain) if domain else 0
# pager
pager = portal_pager(
url="/my/profiles",
url="/my/structures",
url_args={"sortby": sortby},
total=profile_count,
total=structure_count,
page=page,
step=self._items_per_page,
)
# content according to pager and archive selected
profiles = profile.search(
structures = structure.search(
domain,
order=order,
limit=self._items_per_page,
offset=pager["offset"],
)
request.session["my_profiles_history"] = profiles.ids[:100]
) if domain else None
request.session["my_structures_history"] = structures.ids[:100] if structures else None
values.update(
{
"profiles": profiles,
"page_name": "profile",
"structures": structures,
"page_name": "structure",
"archive_groups": archive_groups,
"default_url": "/my/profiles",
"default_url": "/my/structures",
"pager": pager,
"searchbar_sortings": searchbar_sortings,
"sortby": sortby,
}
)
return request.render("partner_profiles_portal.portal_my_profiles", values)
return request.render("partner_profiles_portal.portal_my_structures", values)

View File

@@ -1,130 +0,0 @@
# Copyright 2020 Lokavaluto ()
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import http, tools, _
from odoo.exceptions import AccessError, MissingError
from odoo.http import request
from odoo.addons.portal.controllers.portal import CustomerPortal
class CustomerPortalPartnerProfile(CustomerPortal):
def _profile_get_page_view_values(self, profile, access_token, **kwargs):
values = {
"page_name": "profile",
"profile": profile,
}
return self._get_page_view_values(
profile, access_token, values, "my_profiles_history", False, **kwargs
)
def _details_profile_form_validate(self, data, profile_id):
error = dict()
error_message = []
# nickname uniqueness
if data.get("nickname") and request.env["res.partner"].sudo().search(
[
("name", "=", data.get("nickname")),
("partner_profile.ref", "=", "partner_profile_public"),
("id", "!=", profile_id),
]
):
error["nickname"] = "error"
error_message.append(
_("This nickname is already used, please find an other idea.")
)
# email validation
if data.get("email") and not tools.single_email_re.match(data.get("email")):
error["email"] = "error"
error_message.append(
_("Invalid Email! Please enter a valid email address.")
)
return error, error_message
def _get_profile_fields(self):
fields = [
"nickname",
"function",
"phone",
"mobile",
"email",
"website_url",
"street",
"street2",
"city",
"country_id",
"zipcode",
]
return fields
def _get_page_saving_values(self, profile, kw):
profile_fields = self._get_profile_fields()
values = {key: kw[key] for key in profile_fields if key in kw}
values.update(
{
"name": values.pop("nickname", profile.name),
"zip": values.pop("zipcode", ""),
"website": values.pop("website_url", ""),
}
)
return values
def _get_page_opening_values(self):
# Just retrieve the values to display for Selection fields
countries = request.env["res.country"].sudo().search([])
values = {
"countries": countries,
}
return values
@http.route(
["/my/profile/<int:profile_id>", "/my/profile/save"],
type="http",
auth="user",
website=True,
)
def portal_my_profile(
self, profile_id=None, access_token=None, redirect=None, **kw
):
# The following condition is to transform profile_id to an int, as it is sent as a string from the templace "portal_my_profile"
# TODO: find a better way to retrieve the profile_id at form submit step
if not isinstance(profile_id, int):
profile_id = int(profile_id)
# Check that the user has the right to see this profile
try:
profile_sudo = self._document_check_access(
"res.partner", profile_id, access_token
)
except (AccessError, MissingError):
return request.redirect("/my/profiles")
values = self._profile_get_page_view_values(profile_sudo, access_token, **kw)
values.update(
{
"error": {},
"error_message": [],
}
)
if kw and request.httprequest.method == "POST":
# the user has clicked in the Save button to save new data
error, error_message = self._details_profile_form_validate(kw, profile_id)
values.update({"error": error, "error_message": error_message})
values.update(kw)
if not error:
profile = request.env["res.partner"].browse(profile_id)
values = self._get_page_saving_values(profile, kw)
profile.sudo().write(values)
if redirect:
return request.redirect(redirect)
return request.redirect("/my/profiles")
# This is just the form page opening. We send all the data needed for the form fields
values.update(self._get_page_opening_values())
values.update(
{
"profile_id": profile_id, # Sent in order to retrieve it at submit time
"redirect": redirect
}
)
return request.render("partner_profiles_portal.portal_my_profile", values)

View File

@@ -0,0 +1,120 @@
# Copyright 2020 Lokavaluto ()
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import base64
from odoo import http, tools, _
from odoo.exceptions import AccessError, MissingError
from odoo.http import request
from odoo.addons.portal.controllers.portal import CustomerPortal
class CustomerPortalPositionProfile(CustomerPortal):
def _position_get_page_view_values(self, position, access_token, **kwargs):
values = {
"page_name": "position",
"position": position,
}
return self._get_page_view_values(
position, access_token, values, "my_positions_history", False, **kwargs
)
def _details_position_form_validate(self, data, position_id):
error = dict()
error_message = []
# email validation
if data.get("email") and not tools.single_email_re.match(data.get("email")):
error["email"] = "error"
error_message.append(
_("Invalid Email! Please enter a valid email address.")
)
return error, error_message
def _get_position_profile_fields(self):
'''Provides all the fields that must fill the structure's position profile of the user.
All of them MUST start with "position_".'''
fields = [
"function",
"phone",
"email",
"edit_structure_profiles",
]
return fields
def _get_position_boolean_fields(self):
'''Provides the fields for which we must check the presence
in form's kw to know the value to save in the partner field.'''
fields = ["edit_structure_profiles"]
return fields
def _transform_fields(self, kw, profile_fields):
'''Transforms kw's values in res_partner fields and values'''
return {key: kw[key] for key in profile_fields if key in kw}
def _get_page_saving_position_values(self, kw):
profile_fields = self._get_position_profile_fields()
values = self._transform_fields(kw, profile_fields)
# Boolean fields are not returned in "kw" if their value in the form is False.
# Then we have to check their presence to determine which value to save in the partner.
boolean_fields = self._get_position_boolean_fields()
for key in boolean_fields:
values.update(
{
key: kw.get(key, "off") == "on"
}
)
return values
@http.route(
["/my/position/<int:position_id>", "/my/position/save"],
type="http",
auth="user",
website=True,
)
def portal_my_position(
self,position_id=None, access_token=None, redirect=None, **kw
):
# The following condition is to transform profile_id to an int, as it is sent as a string from the templace "portal_my_profile"
# TODO: find a better way to retrieve the profile_id at form submit step
if not isinstance(position_id, int):
position_id = int(position_id)
# Check that the user has the right to see this profile
try:
position_sudo = self._document_check_access(
"res.partner", position_id, access_token
)
except (AccessError, MissingError):
return request.redirect("/my/positions")
position_profile = request.env["res.partner"].browse(position_id)
values = self._position_get_page_view_values(position_sudo, access_token, **kw)
values.update(
{
"error": {},
"error_message": [],
}
)
if kw and request.httprequest.method == "POST":
# the user has clicked in the Save button to save new data
error, error_message = self._details_position_form_validate(kw, position_id)
values.update({"error": error, "error_message": error_message})
values.update(kw)
if not error:
# Update position profile
new_values = self._get_page_saving_position_values(kw)
position_profile.sudo().write(new_values)
# End of updates
if redirect:
return request.redirect(redirect)
return request.redirect("/my/positions")
# This is just the form page opening. We send all the data needed for the form fields
values.update(
{
"position_id": position_id, # Sent in order to retrieve it at submit time
"position": position_profile,
"redirect": "/my/position/" + str(position_id) + "?success=True"
}
)
return request.render("partner_profiles_portal.portal_position", values)

View File

@@ -0,0 +1,234 @@
# Copyright 2020 Lokavaluto ()
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import base64
from odoo import http, tools, _
from odoo.exceptions import AccessError, MissingError
from odoo.http import request
from odoo.addons.portal.controllers.portal import CustomerPortal
class CustomerPortalStructureProfile(CustomerPortal):
def _structure_get_page_view_values(self, structure, access_token, **kwargs):
values = {
"page_name": "structure",
"structure": structure,
}
return self._get_page_view_values(
structure, access_token, values, "my_structures_history", False, **kwargs
)
def _details_structure_form_validate(self, data, structure_id):
error = dict()
error_message = []
# public name uniqueness
if data.get("public_name") and request.env["res.partner"].sudo().search(
[
("name", "=", data.get("public_name")),
("is_public_profile", "=", True),
("contact_id", "!=", structure_id),
]
):
error["public_name"] = "error"
error_message.append(
_("This public name is already used, please find an other idea.")
)
# email validation
if data.get("email") and not tools.single_email_re.match(data.get("email")):
error["email"] = "error"
error_message.append(
_("Invalid Email! Please enter a valid email address.")
)
return error, error_message
def _get_main_profile_fields(self):
'''Provides all the fields that must fill the structure's main profile.
All of them MUST start with "main_".'''
fields = [
"main_name",
"main_street",
"main_street2",
"main_zip",
"main_city",
"main_country_id",
"main_phone",
"main_mobile",
"main_email",
"main_website",
]
return fields
def _get_main_boolean_structure_fields(self):
'''Provides the fields for which we must check the presence
in form's kw to know the value to save in the partner field.
All of them MUST start with "main_".'''
fields = []
return fields
def _get_public_profile_fields(self):
'''Provides all the fields that must fill the structure's public profile.
All of them MUST start with "public_".'''
fields = [
"public_name",
"public_street2",
"public_street",
"public_zip",
"public_city",
"public_phone",
"public_mobile",
"public_email",
"public_website",
]
return fields
def _get_public_boolean_structure_fields(self):
'''Provides the fields for which we must check the presence
in form's kw to know the value to save in the partner field.
All of them MUST start with "public_".'''
fields = []
return fields
def _get_position_profile_fields(self):
'''Provides all the fields that must fill the structure's position profile of the user.
All of them MUST start with "position_".'''
fields = [
"position_function",
"position_phone",
"position_email",
]
return fields
def _get_position_boolean_structure_fields(self):
'''Provides the fields for which we must check the presence
in form's kw to know the value to save in the partner field.
All of them MUST start with "position_".'''
fields = []
return fields
def _transform_in_res_partner_fields(self, kw, profile_fields, prefix=""):
'''Transforms kw's values in res_partner fields and values'''
return {key[len(prefix):]: kw[key] for key in profile_fields if key in kw}
def _add_boolean_values(self, values, kw, boolean_fields, prefix=""):
for key in boolean_fields:
values.update(
{
key[len(prefix):]: kw.get(key, "off") == "on",
}
)
return values
def _get_page_saving_main_structure_values(self, kw):
profile_fields = self._get_main_profile_fields()
values = self._transform_in_res_partner_fields(kw, profile_fields, "main_")
boolean_fields = self._get_main_boolean_structure_fields()
values = self._add_boolean_values(values, kw, boolean_fields, "main_")
if 'logo' in kw:
image = kw.get('logo')
if image:
image = image.read()
image = base64.b64encode(image)
values.update({
'image': image
})
return values
def _get_page_saving_public_structure_values(self, kw):
profile_fields = self._get_public_profile_fields()
values = self._transform_in_res_partner_fields(kw, profile_fields, "public_")
boolean_fields = self._get_public_boolean_structure_fields()
values = self._add_boolean_values(values, kw, boolean_fields, "public_")
return values
def _get_page_saving_position_structure_values(self, kw):
profile_fields = self._get_position_profile_fields()
values = self._transform_in_res_partner_fields(kw, profile_fields, "position_")
boolean_fields = self._get_position_boolean_structure_fields()
values = self._add_boolean_values(values, kw, boolean_fields, "position_")
return values
def _get_page_opening_values(self):
# Just retrieve the values to display for Selection fields
countries = request.env["res.country"].sudo().search([])
values = {
"countries": countries,
}
return values
@http.route(
["/my/structure/<int:structure_id>", "/my/structure/save"],
type="http",
auth="user",
website=True,
)
def portal_my_structure(
self,structure_id=None, access_token=None, redirect=None, **kw
):
# The following condition is to transform profile_id to an int, as it is sent as a string from the templace "portal_my_profile"
# TODO: find a better way to retrieve the profile_id at form submit step
if not isinstance(structure_id, int):
structure_id = int(structure_id)
# Check that the user has the right to see this profile
try:
structure_sudo = self._document_check_access(
"res.partner", structure_id, access_token
)
except (AccessError, MissingError):
return request.redirect("/my/structures")
Partner = request.env["res.partner"]
partner_id = request.env.user.partner_id
main_profile = Partner.browse(structure_id)
public_profile = Partner.browse(main_profile.public_profile_id.id)
position_profile = Partner.search(
[
("parent_id", "=", structure_id),
("contact_id", "=", partner_id.id),
("is_position_profile", "=", True),
("active", "=", True)
],
limit=1
)[0]
values = self._structure_get_page_view_values(structure_sudo, access_token, **kw)
values.update(
{
"error": {},
"error_message": [],
}
)
if kw and request.httprequest.method == "POST":
# the user has clicked in the Save button to save new data
error, error_message = self._details_structure_form_validate(kw, structure_id)
values.update({"error": error, "error_message": error_message})
values.update(kw)
if not error:
# Update main profile
new_values = self._get_page_saving_main_structure_values(kw)
main_profile.sudo().write(new_values)
# Update public profile
new_values = self._get_page_saving_public_structure_values(kw)
public_profile.sudo().write(new_values)
# Update position profile
new_values = self._get_page_saving_position_structure_values(kw)
position_profile.sudo().write(new_values)
# End of updates
if redirect:
return request.redirect(redirect)
return request.redirect("/my/structures")
# This is just the form page opening. We send all the data needed for the form fields
can_edit_structure = partner_id in main_profile.can_edit_structure_profiles_ids
values.update(self._get_page_opening_values())
values.update(
{
"structure_id": structure_id, # Sent in order to retrieve it at submit time
"public_profile": public_profile,
"position_profile": position_profile,
"can_edit_structure": can_edit_structure,
"redirect": "/my/structure/" + str(structure_id) + "?success=True"
}
)
return request.render("partner_profiles_portal.portal_structure", values)

View File

@@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-01-03 10:08+0000\n"
"PO-Revision-Date: 2023-01-03 10:08+0000\n"
"POT-Creation-Date: 2023-06-13 14:02+0000\n"
"PO-Revision-Date: 2023-06-13 14:02+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
@@ -16,166 +16,282 @@ msgstr ""
"Plural-Forms: \n"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles
msgid "<b>Main profiles :</b>\n"
" internal and private profiles, used for membership management and internal communication.\n"
" <br/>\n"
" <b>Public profiles :</b>\n"
" profiles that might be available to tierce applications (annuary for instance)."
msgstr "<b>Profils Principaux :</b>\n"
" Profils internes et privés, utilisés pour la gestion des adhésions et la communication interne.\n"
" <br/>\n"
" <b>Profils Publics :</b>\n"
" Profils diffusés à des applications tierces (annuaire, porte-monnaie électronique ou cartographie par exemple)."
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
msgid "'s position in the structure"
msgstr " - Fonction dans la structure"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles
msgid "<b>Public profile :</b>\n"
" profiles that might be available to tierce applications (annuary for instance).\n"
" <br/>\n"
" <b>Position profiles :</b>\n"
" profiles that indicate your belonging to an organization, and the role you have in."
msgstr "<b>Profils Publics :</b>\n"
" Profils diffusés à des applications tierces (annuaire, porte-monnaie électronique ou cartographie par exemple).\n"
" <br/>\n"
" <b>Profils Position :</b>\n"
" Profils qui indiquent votre appartenance à une organisation, et votre rôle dans cette dernière."
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "<i class=\"fa fa-fw fa-check-circle\"/> Data saved!"
msgstr "<i class=\"fa fa-fw fa-check-circle\"/> Données enregistrées!"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
msgid "<br/>\n"
" Contact information"
msgstr "<br/>\n"
" Informations de contact"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "<i>Current logo/picture:</i>"
msgstr "<i>Logo/image actuel :</i>"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
msgid "<br/>\n"
" Job position"
msgstr "<br/>\n"
" Poste occupé"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "<i>Current logo:</i>"
msgstr "<i>Logo actuel :</i>"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles
msgid "<br/>\n"
" My organizations' profiles"
msgstr "<br/>\n"
" Mes profils position"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "<i>New logo/picture:</i>"
msgstr "<i>Nouveau logo/image :</i>"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles
msgid "<br/>\n"
" My profiles"
msgstr "<br/>\n"
" Mes profils"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "<i>New logo:</i>"
msgstr "<i>Nouveau logo :</i>"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles
msgid "<span class=\"d-none d-md-inline\">Profile name</span>"
msgstr "<span class=\"d-none d-md-inline\">Nom du Profile</span>"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "<small>- Modification causes log out. Sign in just after!</small>"
msgstr "<small>- La modification entraîne une déconnexion. Reconnectez-vous ensuite !</small>"
#. module: partner_profiles_portal
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_partner__can_edit_main_profile_ids
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_users__can_edit_main_profile_ids
msgid "Can edit main profile"
msgstr "Peut éditer le profil principal"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_positions
msgid "<span class=\"d-none d-md-inline\">Function</span>"
msgstr "<span class=\"d-none d-md-inline\">Fonction occupée</span>"
#. module: partner_profiles_portal
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_partner__can_edit_public_profile_ids
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_users__can_edit_public_profile_ids
msgid "Can edit public profile"
msgstr "Peux éditer le profil public"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_positions
msgid "<span class=\"d-none d-md-inline\">Person name</span>"
msgstr "<span class=\"d-none d-md-inline\">Nom</span>"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_structures
msgid "<span class=\"d-none d-md-inline\">Structure name</span>"
msgstr "<span class=\"d-none d-md-inline\">Nom de la structure</span>"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
msgid "<span class=\"fa fa-arrow-left\"/> Back to my positions list"
msgstr "<span class=\"fa fa-arrow-left\"/> Retour à la liste des fonctions"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "<span class=\"fa fa-arrow-left\"/> Back to my structures list"
msgstr "<span class=\"fa fa-arrow-left\"/> Retour à la liste de mes structures"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
msgid "Access rights"
msgstr "Droits d'accès"
#. module: partner_profiles_portal
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_partner__odoo_user_id
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_users__odoo_user_id
msgid "Associated Odoo user"
msgstr "Utilisateur Odoo associé"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.partner_profiles_form_view
msgid "Associated User"
msgstr "Utilisateur associé"
#. module: partner_profiles_portal
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_partner__can_edit_structure_profiles_ids
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_users__can_edit_structure_profiles_ids
msgid "Can edit struture profiles"
msgstr "Peut éditer les profils de la structure"
#. module: partner_profiles_portal
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_partner__child_main_contact_ids
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_users__child_main_contact_ids
msgid "Can read structure profiles"
msgstr "Peut lire les profiles de la structure"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "City"
msgstr "Ville"
#. module: partner_profiles_portal
#: code:addons/partner_profiles_portal/controllers/portal_my_profiles.py:51
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles
#, python-format
msgid "Company"
msgstr "Société"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "City:"
msgstr "Ville :"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_home_profile_menu
msgid "Consult my profiles"
msgstr "Consulter mes profils"
#: code:addons/partner_profiles_portal/controllers/portal_my_positions.py:40
#: code:addons/partner_profiles_portal/controllers/portal_my_profiles.py:51
#: code:addons/partner_profiles_portal/controllers/portal_my_structures.py:40
#, python-format
msgid "Company"
msgstr ""
#. module: partner_profiles_portal
#: model:ir.model,name:partner_profiles_portal.model_res_partner
msgid "Contact"
msgstr "Contact"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Contact information"
msgstr "Information de contact"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Country"
msgstr "Pays"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Country..."
msgstr "Pays..."
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Country:"
msgstr "Pays :"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Email"
msgstr "Courriel"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Email Pro:"
msgstr "Courriel pro :"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Email:"
msgstr "Courriel :"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Function:"
msgstr "Fonction occupée :"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Image"
msgstr ""
#. module: partner_profiles_portal
#: code:addons/partner_profiles_portal/controllers/portal_my_account.py:115
#: code:addons/partner_profiles_portal/controllers/portal_partner_profile.py:40
#: code:addons/partner_profiles_portal/controllers/portal_partner_profile.py:46
#: code:addons/partner_profiles_portal/controllers/portal_position_profile.py:28
#: code:addons/partner_profiles_portal/controllers/portal_structure_profile.py:41
#, python-format
msgid "Invalid Email! Please enter a valid email address."
msgstr "L'email n'est pas valide, merci de renseigner un email valide !"
#. module: partner_profiles_portal
#: code:addons/partner_profiles_portal/models/res_partner.py:14
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_partner__edit_structure_main_profile
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_users__edit_structure_main_profile
#: code:addons/partner_profiles_portal/controllers/portal_my_account.py:118
#, python-format
msgid "Manage structure's main profile"
msgstr "Gère le profil principal de la structure"
msgid "Invalid Public Email! Please enter a valid public email address."
msgstr "L'email public n'est pas valide, merci de renseigner un email valide !"
#. module: partner_profiles_portal
#: code:addons/partner_profiles_portal/models/res_partner.py:17
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_partner__edit_structure_public_profile
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_users__edit_structure_public_profile
#, python-format
msgid "Manage structure's public profile"
msgstr "Gère le profil public de la structure"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Logo:"
msgstr "Logo :"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
msgid "Manage\n"
" the structure's profiles"
msgstr "Gère les profils de la structure"
#. module: partner_profiles_portal
#: model:ir.model.fields,field_description:partner_profiles_portal.field_create_position_profile__edit_structure_profiles
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_partner__edit_structure_profiles
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_users__edit_structure_profiles
msgid "Manage structure's profiles"
msgstr "Gère les profiles de la structure"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Mobile"
msgstr "Portable"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Mobile:"
msgstr "Mobile :"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
msgid "My Position Details"
msgstr "Détail de la fonction"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_positions
msgid "My Positions"
msgstr "Mon équipe"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "My Structure Details"
msgstr "Informations de ma structure"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_structures
msgid "My Structures"
msgstr "Mes Structures"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_home_profile_menu
msgid "Modify my account"
msgstr "Modifier mon compte"
msgid "My information"
msgstr "Mes informations"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_home_profile_menu
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_positions
msgid "My positions"
msgstr "Mon équipe"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_home_profile_menu
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_structures
msgid "My structures"
msgstr "Mes structures"
#. module: partner_profiles_portal
#: code:addons/partner_profiles_portal/controllers/portal_my_positions.py:39
#: code:addons/partner_profiles_portal/controllers/portal_my_profiles.py:49
#: code:addons/partner_profiles_portal/controllers/portal_my_structures.py:39
#, python-format
msgid "Name"
msgstr "Name"
msgstr "Nom"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
msgid "Name / Nickname"
msgstr "Nom / Pseudo"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Name /\n"
" Nickname"
msgstr "Nom /\n"
" Surnom"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Name:"
msgstr "Nom :"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Phone"
msgstr "Téléphone"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles
msgid "Position"
msgstr "Position"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Phone Pro:"
msgstr "Téléphone pro :"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Phone:"
msgstr "Téléphone :"
#. module: partner_profiles_portal
#: code:addons/partner_profiles_portal/controllers/portal_my_profiles.py:50
@@ -184,56 +300,159 @@ msgid "Profile Type"
msgstr "Type de profil"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles
msgid "Profile type"
msgstr "Type de profil"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Public contact information"
msgstr "Information publiques de contact"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles
msgid "Profiles"
msgstr "Profils"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Public information"
msgstr "Informations publiques"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
msgid "Save\n"
" <span class=\"fa fa-long-arrow-right\"/>"
msgstr "Enregistrer\n"
" <span class=\"fa fa-long-arrow-right\"/>"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Public name:"
msgstr "Nom public :"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Save"
msgstr "Sauvegarder"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "State /\n"
" Province"
msgstr "État /\n"
" Province"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Street"
msgstr "Rue"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Street 2"
msgstr "Rue 2"
msgstr "Rue (complément)"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles
msgid "There are no profiles."
msgstr "Il n'y a pas de profils"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Street:"
msgstr "Rue :"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "The following information are public information that might be\n"
" used in tierce applications (annuary for instance).<br/> You\n"
" can customize them (and be anonymous for instance) to publicly\n"
" show whatever you need or want."
msgstr "Les informations suivantes sont des informations publiques qui peuvent être\n"
" visibles dans des applications tierces (annuaires par exemple).<br/> Vous\n"
" pouvez les personnaliser (et vous rendre anonyme par exemple) pour montrer\n"
" publiquement ce que vous souhaitez ou avez besoin."
#. module: partner_profiles_portal
#: code:addons/partner_profiles_portal/controllers/portal_partner_profile.py:33
#: code:addons/partner_profiles_portal/controllers/portal_partner_profile.py:39
#, python-format
msgid "This nickname is already used, please find an other idea."
msgstr "The Pseudo est déjà utilisé, merci d'en trouver un autre."
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
#: code:addons/partner_profiles_portal/controllers/portal_my_account.py:130
#: code:addons/partner_profiles_portal/controllers/portal_structure_profile.py:34
#, python-format
msgid "This public name is already used, please find an other idea."
msgstr "The nom public est déjà utilisé, merci d'en trouver un autre."
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Website"
msgstr "Site Web"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Website:"
msgstr "Site Web :"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_structures
msgid "You are not linked with any structure."
msgstr "Vous n'êtes lié à aucune structure."
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_positions
msgid "You do not have any positions in your structure."
msgstr "Vous n'avez pas de fonctions occupées dans votre structure."
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_home_profile_menu
msgid "Your Details"
msgstr "Vos détails"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
msgid "Zip / Postal Code"
msgstr "Code postal"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Structure's name"
msgstr "Nom de la structure"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Firstname and Lastname"
msgstr "Prénom et Nom"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Your position in the structure"
msgstr "Votre fonction dans la structure"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Zip /\n"
" Postal Code:"
msgstr "ZIP /\n"
" Code postal :"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Zip / Postal\n"
" Code"
msgstr "ZIP / Code\n"
" Postal"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Zip / Postal\n"
" Code:"
msgstr "Zip / Code\n"
" Postal :"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Zip / Postal Code"
msgstr "Zip / Code postal"
#. module: partner_profiles_portal
#: model:ir.model,name:partner_profiles_portal.model_create_position_profile
msgid "create Position Profile"
msgstr "créer une fiche fonction"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "details"
msgstr "détails"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "e.g. https://odoo.com"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "select..."
msgstr "sélectionner..."

View File

@@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-01-03 10:07+0000\n"
"PO-Revision-Date: 2023-01-03 10:07+0000\n"
"POT-Creation-Date: 2023-06-13 13:59+0000\n"
"PO-Revision-Date: 2023-06-13 13:59+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
@@ -16,79 +16,111 @@ msgstr ""
"Plural-Forms: \n"
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles
msgid "<b>Main profiles :</b>\n"
" internal and private profiles, used for membership management and internal communication.\n"
" <br/>\n"
" <b>Public profiles :</b>\n"
" profiles that might be available to tierce applications (annuary for instance)."
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
msgid "'s position in the structure"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles
msgid "<b>Public profile :</b>\n"
" profiles that might be available to tierce applications (annuary for instance).\n"
" <br/>\n"
" <b>Position profiles :</b>\n"
" profiles that indicate your belonging to an organization, and the role you have in."
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "<i class=\"fa fa-fw fa-check-circle\"/> Data saved!"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
msgid "<br/>\n"
" Contact information"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "<i>Current logo/picture:</i>"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
msgid "<br/>\n"
" Job position"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "<i>Current logo:</i>"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles
msgid "<br/>\n"
" My organizations' profiles"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "<i>New logo/picture:</i>"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles
msgid "<br/>\n"
" My profiles"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "<i>New logo:</i>"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles
msgid "<span class=\"d-none d-md-inline\">Profile name</span>"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "<small>- Modification causes log out. Sign in just after!</small>"
msgstr ""
#. module: partner_profiles_portal
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_partner__can_edit_main_profile_ids
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_users__can_edit_main_profile_ids
msgid "Can edit main profile"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_positions
msgid "<span class=\"d-none d-md-inline\">Function</span>"
msgstr ""
#. module: partner_profiles_portal
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_partner__can_edit_public_profile_ids
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_users__can_edit_public_profile_ids
msgid "Can edit public profile"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_positions
msgid "<span class=\"d-none d-md-inline\">Person name</span>"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_structures
msgid "<span class=\"d-none d-md-inline\">Structure name</span>"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
msgid "<span class=\"fa fa-arrow-left\"/> Back to my positions list"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "<span class=\"fa fa-arrow-left\"/> Back to my structures list"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
msgid "Access rights"
msgstr ""
#. module: partner_profiles_portal
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_partner__odoo_user_id
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_users__odoo_user_id
msgid "Associated Odoo user"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.partner_profiles_form_view
msgid "Associated User"
msgstr ""
#. module: partner_profiles_portal
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_partner__can_edit_structure_profiles_ids
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_users__can_edit_structure_profiles_ids
msgid "Can edit struture profiles"
msgstr ""
#. module: partner_profiles_portal
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_partner__child_main_contact_ids
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_users__child_main_contact_ids
msgid "Can read structure profiles"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "City"
msgstr ""
#. module: partner_profiles_portal
#: code:addons/partner_profiles_portal/controllers/portal_my_profiles.py:51
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles
#, python-format
msgid "Company"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "City:"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_home_profile_menu
msgid "Consult my profiles"
#: code:addons/partner_profiles_portal/controllers/portal_my_positions.py:40
#: code:addons/partner_profiles_portal/controllers/portal_my_profiles.py:51
#: code:addons/partner_profiles_portal/controllers/portal_my_structures.py:40
#, python-format
msgid "Company"
msgstr ""
#. module: partner_profiles_portal
@@ -97,72 +129,179 @@ msgid "Contact"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Contact information"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Country"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Country..."
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Country:"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Email"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Email Pro:"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Email:"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Function:"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Image"
msgstr ""
#. module: partner_profiles_portal
#: code:addons/partner_profiles_portal/controllers/portal_my_account.py:115
#: code:addons/partner_profiles_portal/controllers/portal_partner_profile.py:40
#: code:addons/partner_profiles_portal/controllers/portal_partner_profile.py:46
#: code:addons/partner_profiles_portal/controllers/portal_position_profile.py:28
#: code:addons/partner_profiles_portal/controllers/portal_structure_profile.py:41
#, python-format
msgid "Invalid Email! Please enter a valid email address."
msgstr ""
#. module: partner_profiles_portal
#: code:addons/partner_profiles_portal/controllers/portal_my_account.py:118
#, python-format
msgid "Invalid Public Email! Please enter a valid public email address."
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Logo:"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
msgid "Manage\n"
" the structure's profiles"
msgstr ""
#. module: partner_profiles_portal
#: code:addons/partner_profiles_portal/models/res_partner.py:14
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_partner__edit_structure_main_profile
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_users__edit_structure_main_profile
#, python-format
msgid "Manage structure's main profile"
msgstr ""
#. module: partner_profiles_portal
#: model:ir.model.fields,field_description:partner_profiles_portal.field_create_position_profile__edit_structure_profiles
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_partner__edit_structure_profiles
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_users__edit_structure_profiles
msgid "Manage structure's profiles"
msgstr ""
#. module: partner_profiles_portal
#: code:addons/partner_profiles_portal/models/res_partner.py:17
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_partner__edit_structure_public_profile
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_users__edit_structure_public_profile
#, python-format
msgid "Manage structure's public profile"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Mobile"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_home_profile_menu
msgid "Modify my account"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Mobile:"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
msgid "My Position Details"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_positions
msgid "My Positions"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "My Structure Details"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_structures
msgid "My Structures"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_home_profile_menu
msgid "My information"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_home_profile_menu
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_positions
msgid "My positions"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_home_profile_menu
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_structures
msgid "My structures"
msgstr ""
#. module: partner_profiles_portal
#: code:addons/partner_profiles_portal/controllers/portal_my_positions.py:39
#: code:addons/partner_profiles_portal/controllers/portal_my_profiles.py:49
#: code:addons/partner_profiles_portal/controllers/portal_my_structures.py:39
#, python-format
msgid "Name"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
msgid "Name / Nickname"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Name /\n"
" Nickname"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Name:"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Phone"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles
msgid "Position"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Phone Pro:"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Phone:"
msgstr ""
#. module: partner_profiles_portal
@@ -172,55 +311,152 @@ msgid "Profile Type"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles
msgid "Profile type"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Public contact information"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles
msgid "Profiles"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Public information"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
msgid "Save\n"
" <span class=\"fa fa-long-arrow-right\"/>"
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Public name:"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Save"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "State /\n"
" Province"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Street"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Street 2"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles
msgid "There are no profiles."
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Street:"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "The following information are public information that might be\n"
" used in tierce applications (annuary for instance).<br/> You\n"
" can customize them (and be anonymous for instance) to publicly\n"
" show whatever you need or want."
msgstr ""
#. module: partner_profiles_portal
#: code:addons/partner_profiles_portal/controllers/portal_partner_profile.py:33
#: code:addons/partner_profiles_portal/controllers/portal_partner_profile.py:39
#, python-format
msgid "This nickname is already used, please find an other idea."
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
#: code:addons/partner_profiles_portal/controllers/portal_my_account.py:130
#: code:addons/partner_profiles_portal/controllers/portal_structure_profile.py:34
#, python-format
msgid "This public name is already used, please find an other idea."
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Website"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Website:"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_structures
msgid "You are not linked with any structure."
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_positions
msgid "You do not have any positions in your structure."
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_home_profile_menu
msgid "Your Details"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profile
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Structure's name"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Firstname and Lastname"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Your position in the structure"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Zip /\n"
" Postal Code:"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Zip / Postal\n"
" Code"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Zip / Postal\n"
" Code:"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Zip / Postal Code"
msgstr ""
#. module: partner_profiles_portal
#: model:ir.model,name:partner_profiles_portal.model_create_position_profile
msgid "create Position Profile"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "details"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "e.g. https://odoo.com"
msgstr ""
#. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "select..."
msgstr ""

View File

@@ -10,44 +10,50 @@ _logger = logging.getLogger(__name__)
class res_partner(models.Model):
_inherit = "res.partner"
edit_structure_main_profile = fields.Boolean(
string=_("Manage structure's main profile")
edit_structure_profiles = fields.Boolean(
string="Manage structure's profiles"
)
edit_structure_public_profile = fields.Boolean(
string=_("Manage structure's public profile")
)
can_edit_main_profile_ids = fields.Many2many(
can_edit_structure_profiles_ids = fields.Many2many(
"res.partner",
relation="res_partner_main_profile_rel",
column1="partner_id",
column2="profile_id",
store=True,
compute="_compute_can_edit",
string="Can edit main profile",
compute="_compute_can_read_edit",
string="Can edit struture profiles",
)
can_edit_public_profile_ids = fields.Many2many(
child_main_contact_ids = fields.Many2many(
"res.partner",
relation="res_partner_public_profile_rel",
relation="res_partner_child_contacts_rel",
column1="partner_id",
column2="profile_id",
store=True,
compute="_compute_can_edit",
string="Can edit public profile",
compute="_compute_can_read_edit",
string="Can read structure profiles",
)
odoo_user_id = fields.Many2one(
"res.users",
compute="_compute_odoo_user_id",
string="Associated Odoo user",
store=True,
)
@api.depends(
"other_contact_ids",
"other_contact_ids.edit_structure_main_profile",
"other_contact_ids.edit_structure_public_profile",
"child_ids",
"child_ids.edit_structure_main_profile",
"child_ids.edit_structure_public_profile",
"other_contact_ids.edit_structure_profiles",
"structure_position_ids",
"structure_position_ids.edit_structure_profiles",
)
def _compute_can_edit(self):
def _compute_can_read_edit(self):
for partner in self:
partner.can_edit_main_profile_ids = partner.child_ids.filtered(
"edit_structure_main_profile"
).mapped("contact_id")
partner.can_edit_public_profile_ids = partner.child_ids.filtered(
"edit_structure_public_profile"
partner.can_edit_structure_profiles_ids = partner.structure_position_ids.filtered(
"edit_structure_profiles"
).mapped("contact_id")
partner.child_main_contact_ids = partner.structure_position_ids.mapped("contact_id")
@api.depends("user_ids")
def _compute_odoo_user_id(self):
for partner in self:
partner.odoo_user_id = self.env["res.users"].search(
[("partner_id", "=", partner.id)], limit=1
)

View File

@@ -1,11 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record model="ir.rule" id="res_partner_portal_members_rule">
<field name="name">res_partner: portal: read/write access on my profiles</field>
<record model="ir.rule" id="res_partner_portal_members_read_rule">
<field name="name">res_partner: portal: read access on my structures</field>
<field name="model_id" ref="base.model_res_partner" />
<field name="domain_force">['|','|',('contact_id', '=', user.partner_id.id),
('can_edit_main_profile_ids', 'in', [user.partner_id.id]),
('contact_id.can_edit_public_profile_ids', 'in', [user.partner_id.id])]</field>
('child_main_contact_ids', 'in', [user.partner_id.id]),
('contact_id.child_main_contact_ids', 'in', [user.partner_id.id])]</field>
<field name="groups" eval="[(4, ref('base.group_portal'))]" />
<field name="perm_read" eval="True" />
<field name="perm_write" eval="False" />
<field name="perm_create" eval="False" />
<field name="perm_unlink" eval="False" />
</record>
<record model="ir.rule" id="res_partner_portal_members_write_rule">
<field name="name">res_partner: portal: write access on my structures</field>
<field name="model_id" ref="base.model_res_partner" />
<field name="domain_force">['|','|',('contact_id', '=', user.partner_id.id),
('can_edit_structure_profiles_ids', 'in', [user.partner_id.id]),
('contact_id.can_edit_structure_profiles_ids', 'in', [user.partner_id.id])]</field>
<field name="groups" eval="[(4, ref('base.group_portal'))]" />
<field name="perm_read" eval="True" />
<field name="perm_write" eval="True" />

View File

@@ -1,22 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="portal_my_home_profile_menu" name="Portal My Home: Profile Menu" inherit_id="portal.portal_layout" priority="40">
<template id="portal_my_home_profile_menu" name="Portal My Home: Profile Menu"
inherit_id="portal.portal_layout" priority="40">
<xpath expr="//div[hasclass('o_portal_my_details')]" position="replace">
<div class="o_portal_my_details">
<h4>Your Details </h4>
<hr class="mt-1 mb-0" />
<div class="mb8" t-field="user_id.partner_id" t-options="{&quot;widget&quot;: &quot;contact&quot;, &quot;fields&quot;: [&quot;email&quot;, &quot;phone&quot;, &quot;address&quot;, &quot;name&quot;]}" />
<div class="mb8" t-field="user_id.partner_id"
t-options="{&quot;widget&quot;: &quot;contact&quot;, &quot;fields&quot;: [&quot;email&quot;, &quot;phone&quot;, &quot;address&quot;, &quot;name&quot;]}" />
<div name="profiles_management">
<a t-attf-href="/my/account">
<button class="btn btn-primary mb8">
Modify my account
</button>
</a>
<a t-attf-href="/my/profiles">
<button class="btn btn-primary mb8">
Consult my profiles
</button>
</a>
<div id="account">
<a t-attf-href="/my/account">
<button class="btn btn-primary mb8">
My information
</button>
</a>
</div>
<div
id="structures" t-if="not user_id.partner_id.is_company">
<a t-attf-href="/my/structures">
<button class="btn btn-primary mb8">
My structures
</button>
</a>
</div>
<div
id="positions" t-if="user_id.partner_id.is_company">
<a t-attf-href="/my/positions">
<button class="btn btn-primary mb8">
My positions
</button>
</a>
</div>
</div>
</div>
</xpath>

View File

@@ -0,0 +1,243 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="portal_my_details_profiles" inherit_id="portal.portal_my_details"
name="User profiles details">
<xpath expr="//form" position="replace">
<div class="oe_structure" id="oe_structure_portal_my_details_1" />
<form action="/my/account" method="post" enctype="multipart/form-data">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()" />
<div class="row o_portal_details">
<div class="col-lg-12">
<div id="messages" class="col-lg-12">
<div t-if="success" class="alert alert-success">
<i class="fa fa-fw fa-check-circle" /> Data saved! </div>
<div t-if="error_message" class="alert alert-danger" role="alert">
<t t-foreach="error_message" t-as="err">
<t t-esc="err" />
<br />
</t>
</div>
</div>
<div class="row" id="name">
<div
t-attf-class="form-group #{error.get('main_name') and 'o_has_error' or ''} col-xl-12">
<label t-if="partner.is_company" class="col-form-label"
for="main_name">Structure's name</label>
<label t-if="not partner.is_company" class="col-form-label"
for="main_name">Firstname and Lastname</label>
<label class="text-danger"> *</label>
<input type="text" name="main_name" required="True"
t-attf-class="form-control #{error.get('main_name') and 'is-invalid' or ''}"
t-att-value="main_name or partner.name" />
</div>
</div>
<div id="logo">
<label class="col-form-label">Image</label>
<div class="row">
<div t-attf-class="col-xl-2">
<i>Current logo/picture:</i>
<div name="image" t-field="partner.image"
t-options="{&quot;widget&quot;: &quot;image&quot;, &quot;preview_image&quot;: &quot;image_512&quot;, &quot;class&quot;: &quot;d-block mx-auto mb16&quot;}" />
</div>
<div class="form-group form-field form-field-binary"
data-model-field="false" data-optional="true"
t-attf-class="col-xl-2">
<i>New logo/picture:</i>
<i>
<input type="file" name="main_logo" multiple="false"
data-show-upload="true" data-show-caption="true"
accept="image/*" />
</i>
</div>
</div>
</div>
<div id="contact">
<br />
<h3>
Contact information
</h3>
<div class="row" id="email">
<div
t-attf-class="form-group #{error.get('main_email') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="main_email">Email</label>
<label class="text-danger"> *</label>
<small>- Modification causes log out. Sign in just after!</small>
<input type="email" name="main_email" required="True"
t-attf-class="form-control #{error.get('main_email') and 'is-invalid' or ''}"
t-att-value="main_email or partner.email" />
</div>
</div>
<div class="row" id="adress">
<div
t-attf-class="form-group #{error.get('main_street') and 'o_has_error' or ''} col-xl-12">
<label class="col-form-label" for="main_street">Street</label>
<input type="text" name="main_street"
t-attf-class="form-control #{error.get('main_street') and 'is-invalid' or ''}"
t-att-value="main_street or partner.street" />
<input type="text" name="main_street2"
t-attf-class="form-control #{error.get('main_street2') and 'is-invalid' or ''}"
t-att-value="main_street2 or partner.street2" />
</div>
<div
t-attf-class="form-group #{error.get('main_zip') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="main_zip">Zip / Postal Code</label>
<input type="text" name="main_zip"
t-attf-class="form-control #{error.get('zip') and 'is-invalid' or ''}"
t-att-value="main_zip or partner.zip" />
</div>
<div
t-attf-class="form-group #{error.get('main_city') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="main_city">City</label>
<input type="text" name="main_city"
t-attf-class="form-control #{error.get('main_city') and 'is-invalid' or ''}"
t-att-value="main_city or partner.city" />
</div>
<div
t-attf-class="form-group #{error.get('main_country_id') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="main_country_id">Country</label>
<label class="text-danger"> *</label>
<select name="main_country_id" required="True"
t-attf-class="form-control #{error.get('main_country_id') and 'is-invalid' or ''}">
<option value="">Country...</option>
<t t-foreach="countries or []" t-as="country">
<option t-att-value="country.id"
t-att-selected="country.id == int(main_country_id) if main_country_id else country.id == partner.country_id.id">
<t t-esc="country.name" />
</option>
</t>
</select>
</div>
<div
t-attf-class="form-group #{error.get('main_state_id') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="main_state_id">State /
Province</label>
<select name="main_state_id"
t-attf-class="form-control #{error.get('state_id') and 'is-invalid' or ''}">
<option value="">select...</option>
<t t-foreach="states or []" t-as="state">
<option t-att-value="state.id" style="display:none;"
t-att-data-country_id="state.country_id.id"
t-att-selected="state.id == partner.state_id.id">
<t t-esc="state.name" />
</option>
</t>
</select>
</div>
</div>
<div class="row" id="other_contact_data">
<div
t-attf-class="form-group #{error.get('main_phone') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="main_phone">Phone</label>
<input type="tel" name="main_phone"
t-attf-class="form-control #{error.get('main_phone') and 'is-invalid' or ''}"
t-att-value="main_phone or partner.phone" />
</div>
<div
t-attf-class="form-group #{error.get('main_mobile') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="main_mobile">Mobile</label>
<input type="tel" name="main_mobile"
t-attf-class="form-control #{error.get('main_mobile') and 'is-invalid' or ''}"
t-att-value="main_mobile or partner.mobile" />
</div>
<div
t-attf-class="form-group #{error.get('main_website') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="main_website">Website</label>
<input type="text" name="main_website"
t-attf-class="form-control #{error.get('main_website') and 'is-invalid' or ''}"
t-att-value="main_website or partner.website" />
</div>
</div>
</div>
<br />
<div class="s_card card bg-white w-100" id="public">
<h3 class="card-header">
Public information
</h3>
<div class="card-body">
<p> The following information are public information that might be
used in tierce applications (annuary for instance).<br /> You
can customize them (and be anonymous for instance) to publicly
show whatever you need or want. </p>
<div class="row">
<div
t-attf-class="form-group #{error.get('public_name') and 'o_has_error' or ''} col-xl-12">
<label class="col-form-label" for="public_name">Name /
Nickname</label>
<label class="text-danger"> *</label>
<input type="text" name="public_name" required="True"
t-attf-class="form-control #{error.get('public_name') and 'is-invalid' or ''}"
t-att-value="public_name or public_partner.name" />
</div>
<div
t-attf-class="form-group #{error.get('public_street') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="public_street">Street</label>
<input type="text" name="public_street"
t-attf-class="form-control #{error.get('public_street') and 'is-invalid' or ''}"
t-att-value="public_street or public_partner.street" />
<input type="text" name="public_street2"
t-attf-class="form-control #{error.get('public_street2') and 'is-invalid' or ''}"
t-att-value="public_street2 or public_partner.street2" />
</div>
<div
t-attf-class="form-group #{error.get('public_zip') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="public_zip">Zip / Postal
Code</label>
<input type="text" name="public_zip"
t-attf-class="form-control #{error.get('public_zip') and 'is-invalid' or ''}"
t-att-value="public_zip or public_partner.zip" />
</div>
<div
t-attf-class="form-group #{error.get('public_city') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="public_city">City</label>
<input type="text" name="public_city"
t-attf-class="form-control #{error.get('public_city') and 'is-invalid' or ''}"
t-att-value="public_city or public_partner.city" />
</div>
</div>
<div class="row">
<div
t-attf-class="form-group #{error.get('public_phone') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="public_phone">Phone</label>
<input type="tel" name="public_phone"
t-attf-class="form-control #{error.get('public_phone') and 'is-invalid' or ''}"
t-att-value="public_phone or public_partner.phone" />
</div>
<div
t-attf-class="form-group #{error.get('public_mobile') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="public_mobile">Mobile</label>
<input type="tel" name="public_mobile"
t-attf-class="form-control #{error.get('public_mobile') and 'is-invalid' or ''}"
t-att-value="public_mobile or public_partner.mobile" />
</div>
<div
t-attf-class="form-group #{error.get('public_email') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="public_email">Email</label>
<input type="email" name="public_email"
t-attf-class="form-control #{error.get('public_email') and 'is-invalid' or ''}"
t-att-value="public_email or public_partner.email" />
</div>
<div
t-attf-class="form-group #{error.get('public_website') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="public_website">Website</label>
<input type="text" name="public_website"
t-attf-class="form-control #{error.get('public_website') and 'is-invalid' or ''}"
t-att-value="public_website or public_partner.website" />
</div>
</div>
</div>
</div>
<input type="hidden" name="redirect" t-att-value="redirect" />
<div style="text-align:right;">
<button type="submit"
class="btn btn-primary ">Save
</button>
</div>
</div>
</div>
</form>
<div class="oe_structure" id="oe_structure_portal_my_details_2" />
</xpath>
</template>
</odoo>

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="portal_my_positions" name="My Positions">
<t t-call="portal.portal_layout">
<t t-set="breadcrumbs_searchbar" t-value="True" />
<t t-call="portal.portal_searchbar">
<t t-set="title">My Positions</t>
</t>
<h3>
My positions
</h3>
<div class="oe_position" id="oe_position_portal_my_positions_1" />
<t t-if="not positions">
<div class="alert alert-warning mt8" role="alert">
You do not have any positions in your structure.
</div>
</t>
<t t-if="positions" t-call="portal.portal_table">
<thead>
<tr class="active">
<th>
<span class='d-none d-md-inline'>Person name</span>
</th>
<th>
<span class='d-none d-md-inline'>Function</span>
</th>
</tr>
</thead>
<tbody>
<tr t-foreach="positions" t-as="position">
<td>
<a t-attf-href="/my/position/#{position.id}?{{ keep_query() }}">
<span t-field="position.name" />
</a>
</td>
<td>
<span t-field="position.function" />
</td>
</tr>
</tbody>
</t>
</t>
</template>
</odoo>

View File

@@ -1,97 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="portal_my_profiles" name="My Profiles">
<t t-call="portal.portal_layout">
<t t-set="breadcrumbs_searchbar" t-value="True" />
<t t-call="portal.portal_searchbar">
<t t-set="title">Profiles</t>
</t>
<div class="oe_structure" id="oe_structure_portal_my_profiles_1" />
<t t-if="not profiles">
<div class="alert alert-warning mt8" role="alert">
There are no profiles.
</div>
</t>
<h3>
<br />
My profiles
</h3>
<t t-if="profiles" t-call="portal.portal_table">
<thead>
<tr class="active">
<th>
<span class='d-none d-md-inline'>Profile name</span>
</th>
<th class="text-right">Profile type</th>
<th class="text-right">Position</th>
<th class="text-right">Company</th>
</tr>
</thead>
<tbody>
<tr t-foreach="profiles" t-as="profile">
<t t-if="not profile.is_company">
<td>
<a t-attf-href="/my/profile/#{profile.id}?{{ keep_query() }}">
<span t-field="profile.name" />
</a>
</td>
<td class="text-right">
<span t-field="profile.partner_profile" />
</td>
<td class="text-right">
<span t-field="profile.function" />
</td>
<td class="text-right">
<span t-field="profile.parent_id" />
</td>
</t>
</tr>
</tbody>
</t>
<p style="font-style:italic; font-size:smaller">
<b>Public profile :</b>
profiles that might be available to tierce applications (annuary for instance).
<br />
<b>Position profiles :</b>
profiles that indicate your belonging to an organization, and the role you have in.
</p>
<h3>
<br />
My organizations' profiles
</h3>
<t t-if="profiles" t-call="portal.portal_table">
<thead>
<tr class="active">
<th>
<span class='d-none d-md-inline'>Profile name</span>
</th>
<th class="text-right">Profile type</th>
</tr>
</thead>
<tbody>
<tr t-foreach="profiles" t-as="profile">
<t t-if="profile.is_company">
<td>
<a t-attf-href="/my/profile/#{profile.id}?{{ keep_query() }}">
<span t-field="profile.name" />
</a>
</td>
<td class="text-right">
<span t-field="profile.partner_profile" />
</td>
</t>
</tr>
</tbody>
</t>
<p style="font-style:italic; font-size:smaller">
<b>Main profiles :</b>
internal and private profiles, used for membership management and internal communication.
<br />
<b>Public profiles :</b>
profiles that might be available to tierce applications (annuary for instance).
</p>
<div class="oe_structure" id="oe_structure_portal_my_profiles_2" />
</t>
</template>
</odoo>

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="portal_my_structures" name="My Structures">
<t t-call="portal.portal_layout">
<t t-set="breadcrumbs_searchbar" t-value="True" />
<t t-call="portal.portal_searchbar">
<t t-set="title">My Structures</t>
</t>
<h3>
My structures
</h3>
<div class="oe_structure" id="oe_structure_portal_my_structures_1" />
<t t-if="not structures">
<div class="alert alert-warning mt8" role="alert">
You are not linked with any structure.
</div>
</t>
<t t-if="structures" t-call="portal.portal_table">
<thead>
<tr class="active">
<th>
<span class='d-none d-md-inline'>Structure name</span>
</th>
</tr>
</thead>
<tbody>
<tr t-foreach="structures" t-as="structure">
<td>
<a t-attf-href="/my/structure/#{structure.id}?{{ keep_query() }}">
<span t-field="structure.name" />
</a>
</td>
</tr>
</tbody>
</t>
</t>
</template>
</odoo>

View File

@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="portal_position" name="Position Details">
<t t-call="portal.portal_layout">
<t t-set="o_portal_fullwidth_alert" groups="profile.group_profile_user">
<t t-call="portal.portal_back_in_edit_mode">
<t t-set="backend_url"
t-value="'/web#return_label=Website&amp;model=res.partner&amp;id=%s&amp;view_type=form' % (position.id)" />
</t>
</t>
<t t-set="additional_title">My Position Details</t>
<div style="text-align:right">
<br />
<a href="/my/positions">
<span class="fa fa-arrow-left" /> Back to my positions list </a>
</div>
<form action="/my/position/save" method="post" enctype="multipart/form-data">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()" />
<div class="row o_portal_details">
<div class="col-lg-12">
<h1 style="text-align: center;">
<span t-field="position.name" /> details </h1>
<div t-if="success" class="alert alert-success py-1 mb-2">
<i class="fa fa-fw fa-check-circle" /> Data saved! </div>
<div t-if="error_message" role="alert" class="col-lg-12 alert alert-danger">
<t t-foreach="error_message" t-as="err">
<t t-esc="err" />
<br />
</t>
</div>
<!-- ##################### -->
<!-- POSITION PROFILE DATA -->
<!-- ##################### -->
<div>
<br />
<h3>
<span t-field="position.name" />'s position in the structure </h3>
<div class="row" id="position_function">
<div
t-attf-class="form-group #{error.get('function') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="function">Function: </label>
<input type="text" name="function"
t-attf-class="form-control #{error.get('function') and 'is-invalid' or ''}"
t-att-value="function or position.function" />
</div>
</div>
<div class="row" id="position_contact">
<div
t-attf-class="form-group #{error.get('email') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="email">Email Pro: </label>
<input type="email" name="email"
t-attf-class="form-control #{error.get('email') and 'is-invalid' or ''}"
t-att-value="email or position.email" />
</div>
<div
t-attf-class="form-group #{error.get('phone') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="phone">Phone Pro: </label>
<input type="tel" name="phone"
t-attf-class="form-control #{error.get('phone') and 'is-invalid' or ''}"
t-att-value="phone or position.phone" />
</div>
</div>
</div>
<div id="position_access_rights">
<br />
<h3>
Access rights </h3>
<div id="edit_structure_profiles"
t-attf-class="form-group #{error.get('edit_structure_profiles') and 'o_has_error' or ''} col-xl-6">
<input type="checkbox" name="edit_structure_profiles"
t-att-checked="edit_structure_profiles or position.edit_structure_profiles" />
<label class="col-form-label" for="edit_structure_profiles">Manage
the structure's profiles</label>
</div>
</div>
<br />
<input type="hidden" name="position_id" t-att-value="position_id" />
<input type="hidden" name="redirect" t-att-value="redirect" />
<div style="text-align:right;">
<button type="submit"
class="btn btn-primary ">Save
</button>
</div>
</div>
</div>
</form>
<div style="text-align:right">
<br />
<a href="/my/positions">
<span class="fa fa-arrow-left" /> Back to my positions list </a>
</div>
</t>
</template>
</odoo>

View File

@@ -1,189 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="portal_my_profile" name="My Profile">
<t t-call="portal.portal_layout">
<t t-set="o_portal_fullwidth_alert" groups="profile.group_profile_user">
<t t-call="portal.portal_back_in_edit_mode">
<t t-set="backend_url" t-value="'/web#return_label=Website&amp;model=res.partner&amp;id=%s&amp;view_type=form' % (profile.id)" />
</t>
</t>
<t t-call="portal.portal_record_layout">
<t t-set="card_header">
<h5 class="mb-0">
<strong>
<span t-field="profile.name" />
</strong>
<small class="text-muted">
-
<span t-field="profile.partner_profile" />
</small>
</h5>
<div t-if="profile.is_position_profile">
<h5 class="mb-0">
<span t-field="profile.parent_id" />
</h5>
<br />
<ul class="col-12 col-md-6 pb-2" style="list-style-type:none">
<li>
<span t-field="profile.street" />
</li>
<li>
<span t-field="profile.zip" />
</li>
<li>
<span t-field="profile.city" />
</li>
<li>
<span t-field="profile.country_id" />
</li>
</ul>
</div>
</t>
<t t-set="card_body">
<div class="oe_structure" id="oe_structure_portal_my_profile_1" />
<!-- Body for Position partner profiles-->
<div t-if="profile.is_position_profile">
<form action="/my/profile/save" method="post">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()" />
<div class="row o_portal_details">
<div class="col-lg-12">
<div class="col-lg-12">
<div t-if="error_message" class="alert alert-danger" role="alert">
<t t-foreach="error_message" t-as="err">
<t t-esc="err" />
<br />
</t>
</div>
</div>
<h3>
<br />
Job position
</h3>
<div class="row">
<div t-attf-class="form-group #{error.get('function') and 'o_has_error' or ''} col-xl-12">
<input type="text" name="function" t-attf-class="form-control #{error.get('function') and 'is-invalid' or ''}" t-att-value="function or profile.function" />
</div>
</div>
<h3>
<br />
Contact information
</h3>
<div class="row">
<div t-attf-class="form-group #{error.get('phone') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="phone">Phone</label>
<input type="tel" name="phone" t-attf-class="form-control #{error.get('phone') and 'is-invalid' or ''}" t-att-value="phone or profile.phone" />
</div>
<div t-attf-class="form-group #{error.get('mobile') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="mobile">Mobile</label>
<input type="tel" name="mobile" t-attf-class="form-control #{error.get('mobile') and 'is-invalid' or ''}" t-att-value="mobile or profile.mobile" />
</div>
<div t-attf-class="form-group #{error.get('email') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="email">Email</label>
<input type="email" name="email" t-attf-class="form-control #{error.get('email') and 'is-invalid' or ''}" t-att-value="email or profile.email" />
</div>
<div t-attf-class="form-group #{error.get('website_url') and 'o_has_error' or ''}col-xl-6">
<label class="col-form-label" for="website_url">Website</label>
<input type="text" name="website_url" t-attf-class="form-control #{error.get('website') and 'is-invalid' or ''}" t-att-value="website_url or profile.website" />
</div>
</div>
<input type="hidden" name="profile_id" t-att-value="profile_id" />
<input type="hidden" name="redirect" t-att-value="redirect" />
<div class="clearfix">
<button type="submit" class="btn btn-primary float-right mb32 ">
Save
<span class="fa fa-long-arrow-right" />
</button>
</div>
</div>
</div>
</form>
</div>
<!-- Body for Public partner profiles-->
<div t-if="profile.is_main_profile or profile.is_public_profile">
<form action="/my/profile/save" method="post">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()" />
<div class="row o_portal_details">
<div class="col-lg-12">
<div name="errors" class="col-lg-12">
<div t-if="error_message" class="alert alert-danger" role="alert">
<t t-foreach="error_message" t-as="err">
<t t-esc="err" />
<br />
</t>
</div>
</div>
<div name="nickname" class="row">
<div t-attf-class="form-group #{error.get('nickname') and 'o_has_error' or ''} col-xl-12">
<label class="col-form-label" for="nickname">Name / Nickname</label>
<input type="text" name="nickname" t-attf-class="form-control #{error.get('nickname') and 'is-invalid' or ''}" t-att-value="nickname or profile.name" />
</div>
</div>
<h3>
<br />
Contact information
</h3>
<div name="contact_info_1" class="row">
<div name="street" t-attf-class="form-group #{error.get('street') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="street">Street</label>
<input type="text" name="street" t-attf-class="form-control #{error.get('street') and 'is-invalid' or ''}" t-att-value="street or profile.street" />
</div>
<div name="street2" t-attf-class="form-group #{error.get('street2') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="street2">Street 2</label>
<input type="text" name="street2" t-attf-class="form-control #{error.get('street2') and 'is-invalid' or ''}" t-att-value="street2 or profile.street2" />
</div>
<div name="zip" t-attf-class="form-group #{error.get('zipcode') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="zipcode">Zip / Postal Code</label>
<input type="text" name="zipcode" t-attf-class="form-control #{error.get('zipcode') and 'is-invalid' or ''}" t-att-value="zipcode or profile.zip" />
</div>
<div name="city" t-attf-class="form-group #{error.get('city') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="city">City</label>
<input type="text" name="city" t-attf-class="form-control #{error.get('city') and 'is-invalid' or ''}" t-att-value="city or profile.city" />
</div>
<div name="country" t-attf-class="form-group #{error.get('country_id') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="country_id">Country</label>
<select name="country_id" t-attf-class="form-control">
<option value="">Country...</option>
<t t-foreach="countries or []" t-as="country">
<option t-att-value="country.id" t-att-selected="country.id == int(country_id) if country_id else country.id == profile.country_id.id">
<t t-esc="country.name" />
</option>
</t>
</select>
</div>
</div>
<div name="contact_info_2" class="row">
<div name="phone" t-attf-class="form-group #{error.get('phone') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="phone">Phone</label>
<input type="tel" name="phone" t-attf-class="form-control #{error.get('phone') and 'is-invalid' or ''}" t-att-value="phone or profile.phone" />
</div>
<div name="mobile" t-attf-class="form-group #{error.get('mobile') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="mobile">Mobile</label>
<input type="tel" name="mobile" t-attf-class="form-control #{error.get('mobile') and 'is-invalid' or ''}" t-att-value="mobile or profile.mobile" />
</div>
<div name="email" t-attf-class="form-group #{error.get('email') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="email">Email</label>
<input type="email" name="email" t-attf-class="form-control #{error.get('email') and 'is-invalid' or ''}" t-att-value="email or profile.email" />
</div>
<div name="website" t-attf-class="form-group #{error.get('website_url') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="website_url">Website</label>
<input type="text" name="website_url" t-attf-class="form-control #{error.get('website_url') and 'is-invalid' or ''}" t-att-value="website_url or profile.website" />
</div>
</div>
<input type="hidden" name="profile_id" t-att-value="profile_id" />
<input type="hidden" name="redirect" t-att-value="redirect" />
<div class="clearfix">
<button type="submit" class="btn btn-primary float-right mb32 ">
Save
<span class="fa fa-long-arrow-right" />
</button>
</div>
</div>
</div>
</form>
</div>
<div class="oe_structure" id="oe_structure_portal_my_profile_2" />
</t>
</t>
</t>
</template>
</odoo>

View File

@@ -0,0 +1,318 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="portal_structure" name="Structure Details">
<t t-call="portal.portal_layout">
<t t-set="o_portal_fullwidth_alert" groups="profile.group_profile_user">
<t t-call="portal.portal_back_in_edit_mode">
<t t-set="backend_url"
t-value="'/web#return_label=Website&amp;model=res.partner&amp;id=%s&amp;view_type=form' % (structure.id)" />
</t>
</t>
<t t-set="additional_title">My Structure Details</t>
<div style="text-align:right">
<br />
<a href="/my/structures">
<span class="fa fa-arrow-left" /> Back to my structures list </a>
</div>
<form action="/my/structure/save" method="post" enctype="multipart/form-data">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()" />
<div class="row o_portal_details">
<div class="col-lg-12">
<h1 style="text-align: center;">
<span t-field="structure.name" /> details </h1>
<div t-if="success" class="alert alert-success py-1 mb-2">
<i class="fa fa-fw fa-check-circle" /> Data saved! </div>
<div t-if="error_message" role="alert" class="col-lg-12 alert alert-danger">
<t t-foreach="error_message" t-as="err">
<t t-esc="err" />
<br />
</t>
</div>
<!-- ################# -->
<!-- MAIN PROFILE DATA -->
<!-- ################# -->
<div class="row">
<div id="name"
t-attf-class="form-group #{error.get('main_name') and 'o_has_error' or ''} col-xl-12">
<label class="col-form-label" for="main_name">Name: </label>
<label class="text-danger"> *</label>
<input t-if="can_edit_structure" type="text" name="main_name"
required="True"
t-attf-class="form-control #{error.get('main_name') and 'is-invalid' or ''}"
t-att-value="main_name or structure.name" />
<span t-if="not can_edit_structure" t-field="structure.name" />
</div>
<div t-attf-class="col-xl-12" id="logo">
<label class="col-form-label">Logo: </label>
<div class="row">
<div t-attf-class="col-xl-2">
<i>Current logo:</i>
<div name="image" t-field="structure.image"
t-options="{&quot;widget&quot;: &quot;image&quot;, &quot;preview_image&quot;: &quot;image_512&quot;, &quot;class&quot;: &quot;d-block mx-auto mb16&quot;}" />
</div>
<div class="form-group form-field form-field-binary"
data-model-field="false" data-optional="true"
t-attf-class="col-xl-2" t-if="can_edit_structure">
<i>New logo:</i>
<i>
<input type="file" name="logo" multiple="false"
data-show-upload="true" data-show-caption="true"
accept="image/*" />
</i>
</div>
</div>
</div>
</div>
<div id="contact">
<br />
<h3>
Contact information
</h3>
<div class="row" id="adress">
<div
t-attf-class="form-group #{error.get('main_street') and 'o_has_error' or ''} col-xl-12">
<label class="col-form-label" for="main_street">Street: </label>
<input t-if="can_edit_structure" type="text" name="main_street"
placeholder="Street"
t-attf-class="form-control #{error.get('main_street') and 'is-invalid' or ''}"
t-att-value="main_street or structure.street" />
<span t-if="not can_edit_structure" t-field="structure.street" />
<input t-if="can_edit_structure" type="text" name="main_street2"
placeholder="Street 2 "
t-attf-class="form-control #{error.get('main_street2') and 'is-invalid' or ''}"
t-att-value="main_street2 or structure.street2" />
<span t-if="not can_edit_structure"> - </span>
<span t-if="not can_edit_structure" t-field="structure.street2" />
</div>
<div
t-attf-class="form-group #{error.get('main_zip') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="main_zip">Zip /
Postal Code: </label>
<input t-if="can_edit_structure" type="text" name="main_zip"
t-attf-class="form-control #{error.get('main_zip') and 'is-invalid' or ''}"
t-att-value="main_zip or structure.zip" />
<span t-if="not can_edit_structure" t-field="structure.zip" />
</div>
<div
t-attf-class="form-group #{error.get('main_city') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="main_city">City: </label>
<input t-if="can_edit_structure" type="text" name="main_city"
t-attf-class="form-control #{error.get('main_city') and 'is-invalid' or ''}"
t-att-value="main_city or structure.city" />
<span t-if="not can_edit_structure" t-field="structure.city" />
</div>
<div
t-attf-class="form-group #{error.get('main_country_id') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="main_country_id">Country: </label>
<select t-if="can_edit_structure" name="main_country_id"
t-attf-class="form-control #{error.get('main_country_id') and 'is-invalid' or ''}">
<option value="">Country...</option>
<t t-foreach="countries or []" t-as="country">
<option t-att-value="country.id"
t-att-selected="country.id == int(main_country_id) if main_country_id else country.id == structure.country_id.id">
<t t-esc="country.name" />
</option>
</t>
</select>
<span t-if="not can_edit_structure"
t-field="structure.country_id" />
</div>
</div>
<div class="row" id="other_contact_data">
<div
t-attf-class="form-group #{error.get('main_phone') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="main_phone">Phone: </label>
<input t-if="can_edit_structure" type="tel" name="main_phone"
t-attf-class="form-control #{error.get('main_phone') and 'is-invalid' or ''}"
t-att-value="main_phone or structure.phone" />
<span t-if="not can_edit_structure" t-field="structure.phone" />
</div>
<div
t-attf-class="form-group #{error.get('main_mobile') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="main_mobile">Mobile: </label>
<input t-if="can_edit_structure" type="tel" name="main_mobile"
t-attf-class="form-control #{error.get('main_mobile') and 'is-invalid' or ''}"
t-att-value="main_mobile or structure.mobile" />
<span t-if="not can_edit_structure" t-field="structure.mobile" />
</div>
<div
t-attf-class="form-group #{error.get('main_email') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="main_email">Email: </label>
<input t-if="can_edit_structure" type="email" name="main_email"
required="True"
t-attf-class="form-control #{error.get('main_email') and 'is-invalid' or ''}"
t-att-value="main_email or structure.email" />
<span t-if="not can_edit_structure" t-field="structure.email" />
</div>
<div
t-attf-class="form-group #{error.get('main_website') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="main_website">Website: </label>
<input t-if="can_edit_structure" type="text" name="main_website"
placeholder="e.g. https://odoo.com"
t-attf-class="form-control #{error.get('main_website') and 'is-invalid' or ''}"
t-att-value="main_website or structure.website" />
<span t-if="not can_edit_structure" t-field="structure.website" />
</div>
</div>
</div>
<!-- ##################### -->
<!-- POSITION PROFILE DATA -->
<!-- ##################### -->
<div id="position_data">
<br />
<h3>
Your position in the structure
</h3>
<div class="row" id="position_function">
<div
t-attf-class="form-group #{error.get('position_function') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="position_function">Function: </label>
<input type="text" name="position_function"
t-attf-class="form-control #{error.get('position_function') and 'is-invalid' or ''}"
t-att-value="position_function or position_profile.function" />
</div>
</div>
<div class="row" id="position_contact">
<div
t-attf-class="form-group #{error.get('position_email') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="position_email">Email Pro: </label>
<input type="email" name="position_email"
t-attf-class="form-control #{error.get('position_email') and 'is-invalid' or ''}"
t-att-value="position_email or position_profile.email" />
</div>
<div
t-attf-class="form-group #{error.get('position_phone') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="position_phone">Phone Pro: </label>
<input type="tel" name="position_phone"
t-attf-class="form-control #{error.get('position_phone') and 'is-invalid' or ''}"
t-att-value="position_phone or position_profile.phone" />
</div>
</div>
</div>
<br />
<!-- ################### -->
<!-- PUBLIC PROFILE DATA -->
<!-- ################### -->
<div class="s_card card bg-white w-100" id="public">
<h3 class="card-header">
Public contact information
</h3>
<div class="card-body">
<p> The following information are public information that might be
used in tierce applications (annuary for instance).<br /> You
can customize them (and be anonymous for instance) to publicly
show whatever you need or want. </p>
<div class="row">
<div
t-attf-class="form-group #{error.get('public_name') and 'o_has_error' or ''} col-xl-12">
<label class="col-form-label" for="public_name">Public name: </label>
<label class="text-danger"> *</label>
<input t-if="can_edit_structure" type="text"
name="public_name" required="True"
t-attf-class="form-control #{error.get('public_name') and 'is-invalid' or ''}"
t-att-value="public_name or public_profile.name" />
<span t-if="not can_edit_structure"
t-field="public_profile.name" />
</div>
<div
t-attf-class="form-group #{error.get('public_street') and 'o_has_error' or ''} col-xl-12">
<label class="col-form-label" for="public_street">Street: </label>
<input t-if="can_edit_structure" type="text"
name="public_street" placeholder="Street"
t-attf-class="form-control #{error.get('public_street') and 'is-invalid' or ''}"
t-att-value="public_street or public_profile.street" />
<span t-if="not can_edit_structure"
t-field="public_profile.street" />
<input t-if="can_edit_structure" type="text"
name="public_street2"
placeholder="Street 2"
t-attf-class="form-control #{error.get('public_street2') and 'is-invalid' or ''}"
t-att-value="public_street2 or public_profile.street2" />
<span t-if="not can_edit_structure"> - </span>
<span t-if="not can_edit_structure"
t-field="public_profile.street2" />
</div>
<div
t-attf-class="form-group #{error.get('public_zip') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="public_zip">Zip / Postal
Code: </label>
<input t-if="can_edit_structure" type="text"
name="public_zip"
t-attf-class="form-control #{error.get('public_zip') and 'is-invalid' or ''}"
t-att-value="public_zip or public_profile.zip" />
<span t-if="not can_edit_structure"
t-field="public_profile.zip" />
</div>
<div
t-attf-class="form-group #{error.get('public_city') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="public_city">City: </label>
<input t-if="can_edit_structure" type="text"
name="public_city"
t-attf-class="form-control #{error.get('public_city') and 'is-invalid' or ''}"
t-att-value="public_city or public_profile.city" />
<span t-if="not can_edit_structure"
t-field="public_profile.city" />
</div>
</div>
<div class="row">
<div
t-attf-class="form-group #{error.get('public_phone') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="public_phone">Phone: </label>
<input t-if="can_edit_structure" type="tel"
name="public_phone"
t-attf-class="form-control #{error.get('public_phone') and 'is-invalid' or ''}"
t-att-value="public_phone or public_profile.phone" />
<span t-if="not can_edit_structure"
t-field="public_profile.phone" />
</div>
<div
t-attf-class="form-group #{error.get('public_mobile') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="public_mobile">Mobile: </label>
<input t-if="can_edit_structure" type="tel"
name="public_mobile"
t-attf-class="form-control #{error.get('public_mobile') and 'is-invalid' or ''}"
t-att-value="public_mobile or public_profile.mobile" />
<span t-if="not can_edit_structure"
t-field="public_profile.mobile" />
</div>
<div
t-attf-class="form-group #{error.get('public_email') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="public_email">Email: </label>
<input t-if="can_edit_structure" type="email"
name="public_email"
t-attf-class="form-control #{error.get('public_email') and 'is-invalid' or ''}"
t-att-value="public_email or public_profile.email" />
<span t-if="not can_edit_structure"
t-field="public_profile.email" />
</div>
<div
t-attf-class="form-group #{error.get('public_website') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="public_website">Website: </label>
<input t-if="can_edit_structure" type="text"
name="public_website"
t-attf-class="form-control #{error.get('public_website') and 'is-invalid' or ''}"
t-att-value="public_website or public_profile.website" />
<span t-if="not can_edit_structure"
t-field="public_profile.website" />
</div>
</div>
</div>
</div>
<input type="hidden" name="structure_id" t-att-value="structure_id" />
<input type="hidden" name="redirect" t-att-value="redirect" />
<div style="text-align:right;">
<button type="submit"
class="btn btn-primary ">Save
</button>
</div>
</div>
</div>
</form>
<div style="text-align:right">
<br />
<a href="/my/structures">
<span class="fa fa-arrow-left" /> Back to my structures list </a>
</div>
</t>
</template>
</odoo>

View File

@@ -8,24 +8,17 @@
<field name="sequence">99</field>
<field name="arch" type="xml">
<!-- Main display -->
<xpath expr="//group[@name='profile_status']/field[@name='contact_id']"
position="before">
<field name="odoo_user_id" string="Associated User" readonly="1"
attrs="{'invisible': [('is_main_profile','=',False)]}" />
</xpath>
<xpath expr="//group[@name='profile_status']" position="after">
<group name="structure_access_rights" attrs="{'invisible': ['|', ('is_position_profile','=',False), ('parent_id','=',False)]}">
<field name="edit_structure_main_profile" />
<field name="edit_structure_public_profile" />
<group name="structure_access_rights"
attrs="{'invisible': ['|', ('is_position_profile','=',False), ('parent_id','=',False)]}">
<field name="edit_structure_profiles" />
</group>
</xpath>
<!-- page Contacts & Adresses -->
<xpath expr="//field[@name='child_ids']/form/sheet/group/group/field[@name='comment']" position="before">
<field name="edit_structure_main_profile" attrs="{'invisible': [('is_position_profile','=',False)]}" />
<field name="edit_structure_public_profile" attrs="{'invisible': [('is_position_profile','=',False)]}" />
</xpath>
<!-- page Other Positions -->
<xpath expr="//field[@name='other_contact_ids']/form/sheet/group/group/field[@name='parent_id']" position="after">
<field name="edit_structure_main_profile" attrs="{'invisible': [('is_position_profile','=',False)]}" />
<field name="edit_structure_public_profile" attrs="{'invisible': [('is_position_profile','=',False)]}" />
</xpath>
</field>
</record>
</data>

View File

@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import create_position_profile

View File

@@ -0,0 +1,20 @@
# Copyright 2022 Elabore (https://elabore.coop)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
class CreatePositionProfile(models.TransientModel):
_inherit = "create.position.profile"
edit_structure_profiles = fields.Boolean(
string="Manage structure's profiles"
)
def _compute_position_profile_values(self):
values = super(CreatePositionProfile, self)._compute_position_profile_values()
values.update(
{
"edit_structure_profiles": self.edit_structure_profiles
}
)
return values

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="inherit_create_position_wizard_view_form" model="ir.ui.view">
<field name="name">create.position.wizard.view.form.inherit</field>
<field name="model">create.position.profile</field>
<field name="inherit_id" ref="partner_profiles.create_position_wizard_view_form" />
<field name="arch" type="xml">
<xpath expr="//field[@name='phone']" position="after">
<field name="edit_structure_profiles" />
</xpath>
</field>
</record>
</odoo>