28 Commits

Author SHA1 Message Date
Stéphan Sainléger
10f1185e5a [I18N] partner_profiles_portal: improve french translations 2023-06-28 15:31:54 +02:00
Stéphan Sainléger
b839b8379f [IMP] partner_profiles: apply migration only on contact type partner 2023-06-28 15:31:54 +02:00
Stéphan Sainléger
6e55e69918 [IMP] partner_profiles_portal: add required asterisk in portal forms 2023-06-28 15:31:54 +02:00
Stéphan Sainléger
6e277c0a29 [IMP] partner_profiles_portal: remove position profile frm child_ids 2023-06-28 15:31:54 +02:00
Stéphan Sainléger
3e9f6f62e8 [IMP] partner_profiles: remove position profiles from child_ids 2023-06-28 15:31:54 +02:00
Stéphan Sainléger
83433f7856 [IMP] partner_profiles_portal: improve /my/account name field label 2023-06-28 15:31:54 +02:00
Stéphan Sainléger
eb6658d10f [I18N] partner_profiles_portal: modify profiles french translations
"Profil principal" -> "Fiche administrative"
"Profil public" -> "Coordonnées publiques"
"Profil position" -> "Fonction"
2023-06-28 15:31:54 +02:00
Stéphan Sainléger
b2d77fa926 [I18N] partner_profiles: modify profile name french translations
"Profil principal" -> "Fiche administrative"
"Profil public" -> "Coordonnées publiques"
"Profil position" -> "Fonction"
2023-06-28 15:31:54 +02:00
Stéphan Sainléger
eb25ed7d0b [FIX] partner_profiles_portal: fix portal boolean fields handling 2023-06-27 14:30:54 +02:00
Stéphan Sainléger
b7496f99b5 [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 14:30:54 +02:00
Stéphan Sainléger
8e48fde08f [IMP] partner_profiles: add profile in partner kanban view 2023-06-27 14:30:54 +02:00
Stéphan Sainléger
b1161bc709 [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 14:30:54 +02:00
Stéphan Sainléger
5d6d5668e3 [IMP] partner_profiles_portal: add website page edition slots 2023-06-27 14:30:54 +02:00
Stéphan Sainléger
f262aad42a [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 14:30:54 +02:00
Stéphan Sainléger
4ce4709767 [IMP] partner_profiles_portal: refactor position profil creation 2023-06-27 14:30:54 +02:00
Stéphan Sainléger
97e3dd5c04 [IMP] partner_profiles: refactoring of position profile creation 2023-06-27 14:30:54 +02:00
Stéphan Sainléger
dd184128af [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 14:30:54 +02:00
Stéphan Sainléger
7fbbb4f396 [I18N] partner_profiles_portal: update french translations 2023-06-27 14:30:54 +02:00
Stéphan Sainléger
e0849d3d81 [I18N] partner_profiles: update french translations 2023-06-26 15:01:00 +02:00
Stéphan Sainléger
d8077861ac [IMP] partner_profiles_portal: hide My structures button for company users 2023-06-26 15:01:00 +02:00
Stéphan Sainléger
69bcbc788e [IMP] partner_profiles_portal: add odoo user in partner form view 2023-06-26 15:01:00 +02:00
Stéphan Sainléger
ffec9795e6 [IMP] partner_profiles: remove useless fields in position form view 2023-06-26 15:01:00 +02:00
Stéphan Sainléger
56bec1eed7 [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-26 15:01:00 +02:00
Stéphan Sainléger
69de81a9e0 [IMP] partner_profiles_portal: refactoring of user information
Merge the main and public information edition in /my/account portal
page.
2023-06-26 15:01:00 +02:00
Stéphan Sainléger
6f7629aba8 [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-26 15:01:00 +02:00
Stéphan Sainléger
eb21e1914e [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-26 15:01:00 +02:00
Stéphan Sainléger
ffff6e683c [IMP] partner_profiles: filter public profiles in name_search answer 2023-04-18 18:11:51 +02:00
Stéphan Sainléger
9d7d859cb1 [FIX] partner_profiles: add missing add-on dependency 2023-03-21 15:37:53 +01:00
35 changed files with 2941 additions and 770 deletions

View File

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

View File

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

View File

@@ -6,8 +6,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Odoo Server 12.0\n" "Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-11-09 14:54+0000\n" "POT-Creation-Date: 2023-06-13 15:25+0000\n"
"PO-Revision-Date: 2022-11-09 14:54+0000\n" "PO-Revision-Date: 2023-06-13 15:25+0000\n"
"Last-Translator: <>\n" "Last-Translator: <>\n"
"Language-Team: \n" "Language-Team: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@@ -15,10 +15,80 @@ msgstr ""
"Content-Transfer-Encoding: \n" "Content-Transfer-Encoding: \n"
"Plural-Forms: \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 #. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view #: 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"
msgstr "Nom Administratif" " 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 #. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view #: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
@@ -31,80 +101,149 @@ msgid "Contact"
msgstr "" msgstr ""
#. module: partner_profiles #. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view #: model:ir.model.fields,field_description:partner_profiles.field_res_partner__child_ids
msgid "Create Public Profile" #: model:ir.model.fields,field_description:partner_profiles.field_res_users__child_ids
msgstr "Créer le profil public" msgid "Contacts"
msgstr ""
#. module: partner_profiles #. 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 #: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__create_uid
msgid "Created by" msgid "Created by"
msgstr "Créé par" msgstr "Créé par"
#. module: partner_profiles #. 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 #: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__create_date
msgid "Created on" msgid "Created on"
msgstr "Créé le" msgstr "Créé le"
#. module: partner_profiles #. 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 #: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__display_name
msgid "Display Name" msgid "Display Name"
msgstr "Nom affiché" 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 #. 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_partner__has_position
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__has_position #: model:ir.model.fields,field_description:partner_profiles.field_res_users__has_position
msgid "Has Position" msgid "Has Position"
msgstr "A une position" msgstr "A une fonction"
#. module: partner_profiles #. 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 #: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__id
msgid "ID" msgid "ID"
msgstr "" 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 #. 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_partner__is_main_profile
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__is_main_profile #: model:ir.model.fields,field_description:partner_profiles.field_res_users__is_main_profile
msgid "Is Main Profile" msgid "Is Main Profile"
msgstr "Est un profil Principal" msgstr "Est une fiche administrative"
#. module: partner_profiles #. 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_partner__is_position_profile
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__is_position_profile #: model:ir.model.fields,field_description:partner_profiles.field_res_users__is_position_profile
msgid "Is Position Profile" msgid "Is Position Profile"
msgstr "Est un profil Position" msgstr "Est une fiche fontion"
#. module: partner_profiles #. 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_partner__is_public_profile
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__is_public_profile #: model:ir.model.fields,field_description:partner_profiles.field_res_users__is_public_profile
msgid "Is Public Profile" msgid "Is Public Profile"
msgstr "Est un profil Public" msgstr "Est un fiche de coordonnées publiques"
#. module: partner_profiles #. 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 #: model:ir.model.fields,field_description:partner_profiles.field_partner_profile____last_update
msgid "Last Modified on" msgid "Last Modified on"
msgstr "Dernière modification le" msgstr "Dernière modification le"
#. module: partner_profiles #. 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 #: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__write_uid
msgid "Last Updated by" msgid "Last Updated by"
msgstr "Dernière mise à jour par" msgstr "Dernière mise à jour par"
#. module: partner_profiles #. 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 #: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__write_date
msgid "Last Updated on" msgid "Last Updated on"
msgstr "Dernière mise à jour le" 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 #. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view #: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
#: model:partner.profile,name:partner_profiles.partner_profile_main #: model:partner.profile,name:partner_profiles.partner_profile_main
msgid "Main Profile" 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 #. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__name #: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__name
msgid "Name" msgid "Name"
msgstr "Nom" 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 #. 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_partner__other_contact_ids
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__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 #. 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_partner__partner_profile
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__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" msgid "Partner profile"
msgstr "Profil de contact" msgstr "Profil de contact"
@@ -146,28 +284,95 @@ 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,cron_name:partner_profiles.ir_cron_generate_missing_public_profiles
#: model:ir.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" 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 #. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view #: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
#: model:partner.profile,name:partner_profiles.partner_profile_position #: model:partner.profile,name:partner_profiles.partner_profile_position
msgid "Position Profile" 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 #. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view #: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
#: model:partner.profile,name:partner_profiles.partner_profile_public #: model:partner.profile,name:partner_profiles.partner_profile_public
msgid "Public Profile" msgid "Public Profile"
msgstr "Profil public" msgstr "Coordonnées publiques"
#. module: partner_profiles #. 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_partner__public_profile_id
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__public_profile_id #: model:ir.model.fields,field_description:partner_profiles.field_res_users__public_profile_id
msgid "Public profile" msgid "Public profile"
msgstr "Profil public" msgstr "Coordonnées publiques"
#. module: partner_profiles #. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__ref #: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__ref
msgid "Ref" msgid "Ref"
msgstr "" 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: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 "" msgstr ""
"Project-Id-Version: Odoo Server 12.0\n" "Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-11-09 14:53+0000\n" "POT-Creation-Date: 2023-06-13 15:24+0000\n"
"PO-Revision-Date: 2022-11-09 14:53+0000\n" "PO-Revision-Date: 2023-06-13 15:24+0000\n"
"Last-Translator: <>\n" "Last-Translator: <>\n"
"Language-Team: \n" "Language-Team: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@@ -15,9 +15,64 @@ msgstr ""
"Content-Transfer-Encoding: \n" "Content-Transfer-Encoding: \n"
"Plural-Forms: \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 #. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view #: 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 "" msgstr ""
#. module: partner_profiles #. module: partner_profiles
@@ -30,26 +85,70 @@ msgstr ""
msgid "Contact" msgid "Contact"
msgstr "" 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 #. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view #: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Create Public Profile" msgid "Create Public Profile"
msgstr "" msgstr ""
#. module: partner_profiles #. 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 #: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__create_uid
msgid "Created by" msgid "Created by"
msgstr "" msgstr ""
#. module: partner_profiles #. 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 #: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__create_date
msgid "Created on" msgid "Created on"
msgstr "" msgstr ""
#. module: partner_profiles #. 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 #: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__display_name
msgid "Display Name" msgid "Display Name"
msgstr "" 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 #. 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_partner__has_position
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__has_position #: model:ir.model.fields,field_description:partner_profiles.field_res_users__has_position
@@ -57,10 +156,16 @@ msgid "Has Position"
msgstr "" msgstr ""
#. module: partner_profiles #. 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 #: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__id
msgid "ID" msgid "ID"
msgstr "" 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 #. 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_partner__is_main_profile
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__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 "" msgstr ""
#. module: partner_profiles #. 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 #: model:ir.model.fields,field_description:partner_profiles.field_partner_profile____last_update
msgid "Last Modified on" msgid "Last Modified on"
msgstr "" msgstr ""
#. module: partner_profiles #. 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 #: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__write_uid
msgid "Last Updated by" msgid "Last Updated by"
msgstr "" msgstr ""
#. module: partner_profiles #. 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 #: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__write_date
msgid "Last Updated on" msgid "Last Updated on"
msgstr "" 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 #. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view #: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
#: model:partner.profile,name:partner_profiles.partner_profile_main #: model:partner.profile,name:partner_profiles.partner_profile_main
msgid "Main Profile" msgid "Main Profile"
msgstr "" msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Mobile:"
msgstr ""
#. module: partner_profiles #. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__name #: model:ir.model.fields,field_description:partner_profiles.field_partner_profile__name
msgid "Name" msgid "Name"
msgstr "" msgstr ""
#. module: partner_profiles
#: model:ir.model.fields,field_description:partner_profiles.field_create_position_profile__comment
msgid "Notes"
msgstr ""
#. module: partner_profiles #. 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_partner__other_contact_ids
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__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 #. 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_partner__partner_profile
#: model:ir.model.fields,field_description:partner_profiles.field_res_users__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" msgid "Partner profile"
msgstr "" msgstr ""
@@ -148,12 +271,32 @@ msgstr ""
msgid "Partner: generate missing public profiles" msgid "Partner: generate missing public profiles"
msgstr "" 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 #. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view #: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
#: model:partner.profile,name:partner_profiles.partner_profile_position #: model:partner.profile,name:partner_profiles.partner_profile_position
msgid "Position Profile" msgid "Position Profile"
msgstr "" msgstr ""
#. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
msgid "Positions"
msgstr ""
#. module: partner_profiles #. module: partner_profiles
#: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view #: model_terms:ir.ui.view,arch_db:partner_profiles.partner_profiles_form_view
#: model:partner.profile,name:partner_profiles.partner_profile_public #: model:partner.profile,name:partner_profiles.partner_profile_public
@@ -171,3 +314,50 @@ msgstr ""
msgid "Ref" msgid "Ref"
msgstr "" 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: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 import logging
from odoo import _, api, fields, models from odoo import _, api, fields, models
from odoo.exceptions import UserError
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@@ -18,6 +19,7 @@ class res_partner(models.Model):
translate=False, translate=False,
readonly=False, readonly=False,
) )
contact_id = fields.Many2one(ondelete="cascade")
is_main_profile = fields.Boolean(compute="_compute_profile_booleans", store=True) is_main_profile = fields.Boolean(compute="_compute_profile_booleans", store=True)
is_public_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( is_position_profile = fields.Boolean(
@@ -31,13 +33,16 @@ class res_partner(models.Model):
compute="_compute_public_profile_id", compute="_compute_public_profile_id",
string="Public profile", string="Public profile",
store=True, store=True,
ondelete="cascade",
) )
# If current partner is Main partner, this field indicates what its position profiles are. # If current partner is Main partner, this field indicates what its position profiles are.
other_contact_ids = fields.One2many( other_contact_ids = fields.One2many(
domain=[("is_position_profile", "=", True)] 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") @api.depends("partner_profile", "other_contact_ids")
def _compute_profile_booleans(self): def _compute_profile_booleans(self):
@@ -80,6 +85,19 @@ class res_partner(models.Model):
self.contact_type = "attached" self.contact_type = "attached"
self.partner_profile = position_profile.id 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 @api.model
def create(self, vals): def create(self, vals):
"""Assume if not type, default is contact""" """Assume if not type, default is contact"""
@@ -117,6 +135,47 @@ class res_partner(models.Model):
res = super(res_partner, self).create(vals) res = super(res_partner, self).create(vals)
return res 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 self.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 @api.model
def search_position_partners(self, profile): def search_position_partners(self, profile):
if profile: if profile:
@@ -147,7 +206,6 @@ class res_partner(models.Model):
if self.is_company: if self.is_company:
fields = [ fields = [
"name", "name",
"function",
"phone", "phone",
"mobile", "mobile",
"email", "email",
@@ -158,7 +216,6 @@ class res_partner(models.Model):
"country_id", "country_id",
"zip", "zip",
"is_company", "is_company",
"lang",
] ]
else: else:
fields = ["name"] fields = ["name"]
@@ -189,6 +246,15 @@ class res_partner(models.Model):
when a partner is attached to him. """ when a partner is attached to him. """
return ['title'] 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)
################################################################################## ##################################################################################
## Planned actions ## Planned actions
################################################################################## ##################################################################################
@@ -196,7 +262,7 @@ class res_partner(models.Model):
@api.model @api.model
def _cron_generate_missing_public_profiles(self): def _cron_generate_missing_public_profiles(self):
partners = self.search( 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: for partner in partners:
partner.create_public_profile() partner.create_public_profile()
@@ -211,7 +277,8 @@ class res_partner(models.Model):
search_values = [ search_values = [
("is_company", "=", is_company), ("is_company", "=", is_company),
("active", "=", active), ("active", "=", active),
("partner_profile", "=", False) ("partner_profile", "=", False),
("type", "=", "contact")
] ]
if id: if id:
search_values.append(("id", "=", id)) search_values.append(("id", "=", id))
@@ -262,6 +329,7 @@ class res_partner(models.Model):
def _get_main_partner_search_values(self, partner): def _get_main_partner_search_values(self, partner):
return [ return [
("active", "=", True), ("active", "=", True),
("type", "=", "contact"),
("is_main_profile", "=", True), ("is_main_profile", "=", True),
("is_company", "=", False), ("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

@@ -47,50 +47,213 @@
</group> </group>
</xpath> </xpath>
<!-- ################ -->
<!-- NOTEBOOK UPDATES -->
<!-- ################ -->
<!-- page Contacts & Adresses --> <!-- page Contacts & Adresses -->
<xpath expr="//field[@name='child_ids']/.." position="attributes">
<attribute name="attrs">{'invisible': [('is_company','=', False)]}</attribute>
</xpath>
<xpath <xpath
expr="//field[@name='child_ids']/form/sheet/group/group/field[@name='contact_type']" expr="//field[@name='child_ids']/form/sheet/group/group/field[@name='contact_type']"
position="attributes"> position="attributes">
<attribute name="invisible">1</attribute> <attribute name="invisible">1</attribute>
</xpath> </xpath>
<xpath expr="//field[@name='child_ids']/form/sheet/group/group/field[@name='name']" <xpath
position="before"> expr="//field[@name='child_ids']" position="before">
<field name="is_position_profile" readonly="1" invisible="1" /> <div class="alert alert-info" role="alert" style="margin-bottom:0px;"
<field name="partner_profile" string="Partner profile" invisible="1" /> 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> </xpath>
<!-- page Other Positions --> <!-- page Other Positions -->
<xpath expr="//page[@name='other_position']" position="attributes"> <xpath expr="//page[@name='other_position']" position="attributes">
<attribute name="attrs">{'invisible': ['|', ('contact_id','!=',False), <attribute name="attrs">{'invisible': [('is_company','=',True)]}</attribute>
('is_company','=',True)]}</attribute>
</xpath> </xpath>
<xpath expr="//page[@name='other_position']/field[@name='other_contact_ids']/kanban" <xpath expr="//page[@name='other_position']" position="attributes">
position="attributes"> <attribute name="string">Positions</attribute>
<attribute name="create">true</attribute>
</xpath> </xpath>
<xpath expr="//page[@name='other_position']/field[@name='other_contact_ids']" <xpath expr="//page[@name='other_position']/field[@name='other_contact_ids']/form"
position="attributes"> position="replace" />
<attribute name="context">{'default_partner_profile': 3, 'default_contact_id': <xpath expr="//field[@name='other_contact_ids']" position="before">
active_id, 'default_name': name, 'default_street': street, <div class="alert alert-info" role="alert" style="margin-bottom:0px;">
'default_street2': street2, 'default_city': city, 'default_state_id': <span>Please find here <strong>all the position profiles</strong> linked to
state_id, 'default_zip': zip, 'default_country_id': country_id, this main profile.</span>
'default_supplier': supplier}</attribute> </div>
</xpath>
<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 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 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>
<xpath <xpath
expr="//field[@name='other_contact_ids']/form/sheet/group/group/field[@name='name']" expr="//div[@class='oe_kanban_details']/div[hasclass('o_kanban_tags_section')]"
position="after"> position="before">
<field name="is_position_profile" readonly="1" invisible="1" /> <div>
<field name="partner_profile" string="Partner profile" /> <span attrs="{'invisible': [('is_main_profile','=',False)]}"
<field name="parent_id" widget="res_partner_many2one" placeholder="Company" style="color:#7c7bad;">
domain="[('is_company', '=', True),('is_main_profile','=', True)]" <b>Main profile</b>
context="{'default_partner_profile': 1, 'default_is_company': True, 'show_vat': True}" /> </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> </xpath>
</field> </field>
</record> </record>

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

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

View File

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

View File

@@ -1,4 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from . import portal_my_profiles from . import portal_my_structures
from . import portal_partner_profile 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 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: if user.partner_id.other_contact_ids:
main_profile_ids = user.partner_id.other_contact_ids.filtered( main_structure_ids = user.partner_id.other_contact_ids.mapped("parent_id")
"edit_structure_main_profile" return [("id", "in", main_structure_ids.ids),
).mapped("parent_id") ("is_company", "=", True)
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),
] ]
else: else:
return [("contact_id", "=", user.partner_id.id)] return None
def _prepare_portal_layout_values(self): def _prepare_portal_layout_values(self):
values = super(CustomerPortalMyProfiles, self)._prepare_portal_layout_values() values = super(CustomerPortalMyStructures, self)._prepare_portal_layout_values()
values["profile_count"] = request.env["res.partner"].search_count( domain = self._get_domain_my_structures(request.env.user)
self._get_domain_my_profiles(request.env.user) values["structure_count"] = request.env["res.partner"].search_count(domain) if domain else 0
)
return values return values
@http.route( @http.route(
["/my/profiles", "/my/profiles/page/<int:page>"], ["/my/structures", "/my/structures/page/<int:page>"],
type="http", type="http",
auth="user", auth="user",
website=True, website=True,
) )
def portal_my_profiles( def portal_my_structures(
self, page=1, date_begin=None, date_end=None, sortby=None, **kw self, page=1, date_begin=None, date_end=None, sortby=None, **kw
): ):
values = self._prepare_portal_layout_values() values = self._prepare_portal_layout_values()
profile = request.env["res.partner"] structure = request.env["res.partner"]
domain = self._get_domain_my_profiles(request.env.user) domain = self._get_domain_my_structures(request.env.user)
searchbar_sortings = { searchbar_sortings = {
"name": {"label": _("Name"), "order": "name"}, "name": {"label": _("Name"), "order": "name"},
"partner_profile": {"label": _("Profile Type"), "order": "partner_profile"},
"parent_id": {"label": _("Company"), "order": "parent_id"}, "parent_id": {"label": _("Company"), "order": "parent_id"},
} }
if not sortby: if not sortby:
@@ -57,35 +46,35 @@ class CustomerPortalMyProfiles(CustomerPortal):
# archive groups - Default Group By 'create_date' # archive groups - Default Group By 'create_date'
archive_groups = self._get_archive_groups("res.partner", domain) archive_groups = self._get_archive_groups("res.partner", domain)
# profiles count # structures count
profile_count = profile.search_count(domain) structure_count = structure.search_count(domain) if domain else 0
# pager # pager
pager = portal_pager( pager = portal_pager(
url="/my/profiles", url="/my/structures",
url_args={"sortby": sortby}, url_args={"sortby": sortby},
total=profile_count, total=structure_count,
page=page, page=page,
step=self._items_per_page, step=self._items_per_page,
) )
# content according to pager and archive selected # content according to pager and archive selected
profiles = profile.search( structures = structure.search(
domain, domain,
order=order, order=order,
limit=self._items_per_page, limit=self._items_per_page,
offset=pager["offset"], offset=pager["offset"],
) ) if domain else None
request.session["my_profiles_history"] = profiles.ids[:100] request.session["my_structures_history"] = structures.ids[:100] if structures else None
values.update( values.update(
{ {
"profiles": profiles, "structures": structures,
"page_name": "profile", "page_name": "structure",
"archive_groups": archive_groups, "archive_groups": archive_groups,
"default_url": "/my/profiles", "default_url": "/my/structures",
"pager": pager, "pager": pager,
"searchbar_sortings": searchbar_sortings, "searchbar_sortings": searchbar_sortings,
"sortby": sortby, "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 "" msgstr ""
"Project-Id-Version: Odoo Server 12.0\n" "Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-01-03 10:08+0000\n" "POT-Creation-Date: 2023-06-13 14:02+0000\n"
"PO-Revision-Date: 2023-01-03 10:08+0000\n" "PO-Revision-Date: 2023-06-13 14:02+0000\n"
"Last-Translator: <>\n" "Last-Translator: <>\n"
"Language-Team: \n" "Language-Team: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@@ -16,166 +16,282 @@ msgstr ""
"Plural-Forms: \n" "Plural-Forms: \n"
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
msgid "<b>Main profiles :</b>\n" msgid "'s position in the structure"
" internal and private profiles, used for membership management and internal communication.\n" msgstr " - Fonction dans la structure"
" <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)."
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "<b>Public profile :</b>\n" #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
" profiles that might be available to tierce applications (annuary for instance).\n" #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
" <br/>\n" msgid "<i class=\"fa fa-fw fa-check-circle\"/> Data saved!"
" <b>Position profiles :</b>\n" msgstr "<i class=\"fa fa-fw fa-check-circle\"/> Données enregistrées!"
" 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."
#. module: partner_profiles_portal #. 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 "<br/>\n" msgid "<i>Current logo/picture:</i>"
" Contact information" msgstr "<i>Logo/image actuel :</i>"
msgstr "<br/>\n"
" Informations de contact"
#. module: partner_profiles_portal #. 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 "<br/>\n" msgid "<i>Current logo:</i>"
" Job position" msgstr "<i>Logo actuel :</i>"
msgstr "<br/>\n"
" Poste occupé"
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "<br/>\n" msgid "<i>New logo/picture:</i>"
" My organizations' profiles" msgstr "<i>Nouveau logo/image :</i>"
msgstr "<br/>\n"
" Mes profils position"
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "<br/>\n" msgid "<i>New logo:</i>"
" My profiles" msgstr "<i>Nouveau logo :</i>"
msgstr "<br/>\n"
" Mes profils"
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "<span class=\"d-none d-md-inline\">Profile name</span>" msgid "<small>- Modification causes log out. Sign in just after!</small>"
msgstr "<span class=\"d-none d-md-inline\">Nom du Profile</span>" msgstr "<small>- La modification entraîne une déconnexion. Reconnectez-vous ensuite !</small>"
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_partner__can_edit_main_profile_ids #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_positions
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_users__can_edit_main_profile_ids msgid "<span class=\"d-none d-md-inline\">Function</span>"
msgid "Can edit main profile" msgstr "<span class=\"d-none d-md-inline\">Fonction occupée</span>"
msgstr "Peut éditer le profil principal"
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_partner__can_edit_public_profile_ids #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_positions
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_users__can_edit_public_profile_ids msgid "<span class=\"d-none d-md-inline\">Person name</span>"
msgid "Can edit public profile" msgstr "<span class=\"d-none d-md-inline\">Nom</span>"
msgstr "Peux éditer le profil public"
#. module: partner_profiles_portal #. 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" msgid "City"
msgstr "Ville" msgstr "Ville"
#. module: partner_profiles_portal #. 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_structure
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles msgid "City:"
#, python-format msgstr "Ville :"
msgid "Company"
msgstr "Société"
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_home_profile_menu #: code:addons/partner_profiles_portal/controllers/portal_my_positions.py:40
msgid "Consult my profiles" #: code:addons/partner_profiles_portal/controllers/portal_my_profiles.py:51
msgstr "Consulter mes profils" #: code:addons/partner_profiles_portal/controllers/portal_my_structures.py:40
#, python-format
msgid "Company"
msgstr ""
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model:ir.model,name:partner_profiles_portal.model_res_partner #: model:ir.model,name:partner_profiles_portal.model_res_partner
msgid "Contact" msgid "Contact"
msgstr "Contact" msgstr ""
#. module: partner_profiles_portal #. 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" msgid "Country"
msgstr "Pays" msgstr "Pays"
#. module: partner_profiles_portal #. 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..." msgid "Country..."
msgstr "Pays..." msgstr "Pays..."
#. module: partner_profiles_portal #. 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" msgid "Email"
msgstr "Courriel" msgstr "Courriel"
#. module: partner_profiles_portal #. 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: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 #, python-format
msgid "Invalid Email! Please enter a valid email address." msgid "Invalid Email! Please enter a valid email address."
msgstr "L'email n'est pas valide, merci de renseigner un email valide !" msgstr "L'email n'est pas valide, merci de renseigner un email valide !"
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: code:addons/partner_profiles_portal/models/res_partner.py:14 #: code:addons/partner_profiles_portal/controllers/portal_my_account.py:118
#: 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 #, python-format
msgid "Manage structure's main profile" msgid "Invalid Public Email! Please enter a valid public email address."
msgstr "Gère le profil principal de la structure" msgstr "L'email public n'est pas valide, merci de renseigner un email valide !"
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: code:addons/partner_profiles_portal/models/res_partner.py:17 #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_partner__edit_structure_public_profile msgid "Logo:"
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_users__edit_structure_public_profile msgstr "Logo :"
#, python-format
msgid "Manage structure's public profile"
msgstr "Gère le profil public de la structure"
#. module: partner_profiles_portal #. 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" 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 #. 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_home_profile_menu
msgid "Modify my account" msgid "My information"
msgstr "Modifier mon compte" msgstr "Mes informations"
#. module: partner_profiles_portal #. 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_profiles.py:49
#: code:addons/partner_profiles_portal/controllers/portal_my_structures.py:39
#, python-format #, python-format
msgid "Name" msgid "Name"
msgstr "Name" msgstr "Nom"
#. module: partner_profiles_portal #. 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 "Name / Nickname" msgid "Name /\n"
msgstr "Nom / Pseudo" " Nickname"
msgstr "Nom /\n"
" Surnom"
#. module: partner_profiles_portal #. 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" msgid "Phone"
msgstr "Téléphone" msgstr "Téléphone"
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
msgid "Position" #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgstr "Position" 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 #. module: partner_profiles_portal
#: code:addons/partner_profiles_portal/controllers/portal_my_profiles.py:50 #: code:addons/partner_profiles_portal/controllers/portal_my_profiles.py:50
@@ -184,56 +300,159 @@ msgid "Profile Type"
msgstr "Type de profil" msgstr "Type de profil"
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Profile type" msgid "Public contact information"
msgstr "Type de profil" msgstr "Information publiques de contact"
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Profiles" msgid "Public information"
msgstr "Profils" msgstr "Informations publiques"
#. module: partner_profiles_portal #. 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 "Save\n" msgid "Public name:"
" <span class=\"fa fa-long-arrow-right\"/>" msgstr "Nom public :"
msgstr "Enregistrer\n"
" <span class=\"fa fa-long-arrow-right\"/>"
#. module: partner_profiles_portal #. 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" msgid "Street"
msgstr "Rue" msgstr "Rue"
#. module: partner_profiles_portal #. 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" msgid "Street 2"
msgstr "Rue 2" msgstr "Rue (complément)"
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "There are no profiles." msgid "Street:"
msgstr "Il n'y a pas de profils" 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 #. 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:33
#: code:addons/partner_profiles_portal/controllers/portal_partner_profile.py:39
#, python-format #, python-format
msgid "This nickname is already used, please find an other idea." msgid "This nickname is already used, please find an other idea."
msgstr "The Pseudo est déjà utilisé, merci d'en trouver un autre." msgstr "The Pseudo est déjà utilisé, merci d'en trouver un autre."
#. module: partner_profiles_portal #. 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" msgid "Website"
msgstr "Site Web" 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 #. 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_home_profile_menu
msgid "Your Details" msgid "Your Details"
msgstr "Vos détails" msgstr "Vos détails"
#. module: partner_profiles_portal #. 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 "Zip / Postal Code" msgid "Structure's name"
msgstr "Code postal" 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 "" msgstr ""
"Project-Id-Version: Odoo Server 12.0\n" "Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-01-03 10:07+0000\n" "POT-Creation-Date: 2023-06-13 13:59+0000\n"
"PO-Revision-Date: 2023-01-03 10:07+0000\n" "PO-Revision-Date: 2023-06-13 13:59+0000\n"
"Last-Translator: <>\n" "Last-Translator: <>\n"
"Language-Team: \n" "Language-Team: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@@ -16,79 +16,111 @@ msgstr ""
"Plural-Forms: \n" "Plural-Forms: \n"
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
msgid "<b>Main profiles :</b>\n" msgid "'s position in the structure"
" 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 "" msgstr ""
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "<b>Public profile :</b>\n" #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
" profiles that might be available to tierce applications (annuary for instance).\n" #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
" <br/>\n" msgid "<i class=\"fa fa-fw fa-check-circle\"/> Data saved!"
" <b>Position profiles :</b>\n"
" profiles that indicate your belonging to an organization, and the role you have in."
msgstr "" msgstr ""
#. module: partner_profiles_portal #. 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 "<br/>\n" msgid "<i>Current logo/picture:</i>"
" Contact information"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. 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 "<br/>\n" msgid "<i>Current logo:</i>"
" Job position"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "<br/>\n" msgid "<i>New logo/picture:</i>"
" My organizations' profiles"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "<br/>\n" msgid "<i>New logo:</i>"
" My profiles"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "<span class=\"d-none d-md-inline\">Profile name</span>" msgid "<small>- Modification causes log out. Sign in just after!</small>"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_partner__can_edit_main_profile_ids #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_positions
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_users__can_edit_main_profile_ids msgid "<span class=\"d-none d-md-inline\">Function</span>"
msgid "Can edit main profile"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_partner__can_edit_public_profile_ids #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_positions
#: model:ir.model.fields,field_description:partner_profiles_portal.field_res_users__can_edit_public_profile_ids msgid "<span class=\"d-none d-md-inline\">Person name</span>"
msgid "Can edit public profile"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. 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" msgid "City"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. 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_structure
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles msgid "City:"
#, python-format
msgid "Company"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_home_profile_menu #: code:addons/partner_profiles_portal/controllers/portal_my_positions.py:40
msgid "Consult my profiles" #: 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 "" msgstr ""
#. module: partner_profiles_portal #. module: partner_profiles_portal
@@ -97,72 +129,179 @@ msgid "Contact"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. 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" msgid "Country"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. 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..." msgid "Country..."
msgstr "" msgstr ""
#. module: partner_profiles_portal #. 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" msgid "Email"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. 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: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 #, python-format
msgid "Invalid Email! Please enter a valid email address." msgid "Invalid Email! Please enter a valid email address."
msgstr "" 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 #. module: partner_profiles_portal
#: code:addons/partner_profiles_portal/models/res_partner.py:14 #: 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 #, python-format
msgid "Manage structure's main profile" msgid "Manage structure's main profile"
msgstr "" 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 #. module: partner_profiles_portal
#: code:addons/partner_profiles_portal/models/res_partner.py:17 #: 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 #, python-format
msgid "Manage structure's public profile" msgid "Manage structure's public profile"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. 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" msgid "Mobile"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. 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_structure
msgid "Modify my account" msgid "Mobile:"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. 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_profiles.py:49
#: code:addons/partner_profiles_portal/controllers/portal_my_structures.py:39
#, python-format #, python-format
msgid "Name" msgid "Name"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. 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 "Name / Nickname" msgid "Name /\n"
" Nickname"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. 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" msgid "Phone"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_position
msgid "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 "" msgstr ""
#. module: partner_profiles_portal #. module: partner_profiles_portal
@@ -172,55 +311,152 @@ msgid "Profile Type"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "Profile type" msgid "Public contact information"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_details_profiles
msgid "Profiles" msgid "Public information"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. 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 "Save\n" msgid "Public name:"
" <span class=\"fa fa-long-arrow-right\"/>"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. 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" msgid "Street"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. 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" msgid "Street 2"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. module: partner_profiles_portal
#: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_my_profiles #: model_terms:ir.ui.view,arch_db:partner_profiles_portal.portal_structure
msgid "There are no profiles." 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 "" msgstr ""
#. module: partner_profiles_portal #. 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:33
#: code:addons/partner_profiles_portal/controllers/portal_partner_profile.py:39
#, python-format #, python-format
msgid "This nickname is already used, please find an other idea." msgid "This nickname is already used, please find an other idea."
msgstr "" msgstr ""
#. module: partner_profiles_portal #. 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" msgid "Website"
msgstr "" 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 #. 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_home_profile_menu
msgid "Your Details" msgid "Your Details"
msgstr "" msgstr ""
#. module: partner_profiles_portal #. 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" msgid "Zip / Postal Code"
msgstr "" 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): class res_partner(models.Model):
_inherit = "res.partner" _inherit = "res.partner"
edit_structure_main_profile = fields.Boolean( edit_structure_profiles = fields.Boolean(
string=_("Manage structure's main profile") string="Manage structure's profiles"
) )
edit_structure_public_profile = fields.Boolean( can_edit_structure_profiles_ids = fields.Many2many(
string=_("Manage structure's public profile")
)
can_edit_main_profile_ids = fields.Many2many(
"res.partner", "res.partner",
relation="res_partner_main_profile_rel", relation="res_partner_main_profile_rel",
column1="partner_id", column1="partner_id",
column2="profile_id", column2="profile_id",
store=True, store=True,
compute="_compute_can_edit", compute="_compute_can_read_edit",
string="Can edit main profile", string="Can edit struture profiles",
) )
can_edit_public_profile_ids = fields.Many2many( child_main_contact_ids = fields.Many2many(
"res.partner", "res.partner",
relation="res_partner_public_profile_rel", relation="res_partner_child_contacts_rel",
column1="partner_id", column1="partner_id",
column2="profile_id", column2="profile_id",
store=True, store=True,
compute="_compute_can_edit", compute="_compute_can_read_edit",
string="Can edit public profile", 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( @api.depends(
"other_contact_ids", "other_contact_ids",
"other_contact_ids.edit_structure_main_profile", "other_contact_ids.edit_structure_profiles",
"other_contact_ids.edit_structure_public_profile", "structure_position_ids",
"child_ids", "structure_position_ids.edit_structure_profiles",
"child_ids.edit_structure_main_profile",
"child_ids.edit_structure_public_profile",
) )
def _compute_can_edit(self): def _compute_can_read_edit(self):
for partner in self: for partner in self:
partner.can_edit_main_profile_ids = partner.child_ids.filtered( partner.can_edit_structure_profiles_ids = partner.structure_position_ids.filtered(
"edit_structure_main_profile" "edit_structure_profiles"
).mapped("contact_id")
partner.can_edit_public_profile_ids = partner.child_ids.filtered(
"edit_structure_public_profile"
).mapped("contact_id") ).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"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <odoo>
<record model="ir.rule" id="res_partner_portal_members_rule"> <record model="ir.rule" id="res_partner_portal_members_read_rule">
<field name="name">res_partner: portal: read/write access on my profiles</field> <field name="name">res_partner: portal: read access on my structures</field>
<field name="model_id" ref="base.model_res_partner" /> <field name="model_id" ref="base.model_res_partner" />
<field name="domain_force">['|','|',('contact_id', '=', user.partner_id.id), <field name="domain_force">['|','|',('contact_id', '=', user.partner_id.id),
('can_edit_main_profile_ids', 'in', [user.partner_id.id]), ('child_main_contact_ids', 'in', [user.partner_id.id]),
('contact_id.can_edit_public_profile_ids', 'in', [user.partner_id.id])]</field> ('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="groups" eval="[(4, ref('base.group_portal'))]" />
<field name="perm_read" eval="True" /> <field name="perm_read" eval="True" />
<field name="perm_write" eval="True" /> <field name="perm_write" eval="True" />

View File

@@ -1,23 +1,38 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <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"> <xpath expr="//div[hasclass('o_portal_my_details')]" position="replace">
<div class="o_portal_my_details"> <div class="o_portal_my_details">
<h4>Your Details </h4> <h4>Your Details </h4>
<hr class="mt-1 mb-0" /> <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"> <div name="profiles_management">
<div id="account">
<a t-attf-href="/my/account"> <a t-attf-href="/my/account">
<button class="btn btn-primary mb8"> <button class="btn btn-primary mb8">
Modify my account My information
</button> </button>
</a> </a>
<a t-attf-href="/my/profiles"> </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"> <button class="btn btn-primary mb8">
Consult my profiles My structures
</button> </button>
</a> </a>
</div> </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> </div>
</xpath> </xpath>
</template> </template>

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="sequence">99</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<!-- Main display --> <!-- 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"> <xpath expr="//group[@name='profile_status']" position="after">
<group name="structure_access_rights" attrs="{'invisible': ['|', ('is_position_profile','=',False), ('parent_id','=',False)]}"> <group name="structure_access_rights"
<field name="edit_structure_main_profile" /> attrs="{'invisible': ['|', ('is_position_profile','=',False), ('parent_id','=',False)]}">
<field name="edit_structure_public_profile" /> <field name="edit_structure_profiles" />
</group> </group>
</xpath> </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> </field>
</record> </record>
</data> </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>