Initialize v18 branch

Rename *_usability modules to *_usability_akretion
This commit is contained in:
Alexis de Lattre
2024-12-24 10:11:21 +01:00
parent 9913924202
commit 13744fc404
264 changed files with 50 additions and 87 deletions

View File

@@ -0,0 +1,7 @@
from . import res_users
from . import res_partner
from . import res_partner_bank
from . import res_company
from . import ir_mail_server
from . import ir_model
from . import ir_model_fields

View File

@@ -0,0 +1,35 @@
# Copyright 2015-2022 Akretion France (http://www.akretion.com/)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, models
import logging
logger = logging.getLogger(__name__)
class IrMailServer(models.Model):
_inherit = "ir.mail_server"
@api.model
def send_email(
self, message, mail_server_id=None, smtp_server=None, smtp_port=None,
smtp_user=None, smtp_password=None, smtp_encryption=None,
smtp_ssl_certificate=None, smtp_ssl_private_key=None,
smtp_debug=False, smtp_session=None):
# Start copy from native method
smtp_from, smtp_to_list, message = self._prepare_email_message(
message, smtp_session)
# End copy from native method
logger.info(
"Sending email from '%s' to '%s' Cc '%s' Bcc '%s' "
"with subject '%s'",
smtp_from, message.get('To'), message.get('Cc'),
message.get('Bcc'), message.get('Subject'))
return super().send_email(
message, mail_server_id=mail_server_id,
smtp_server=smtp_server, smtp_port=smtp_port,
smtp_user=smtp_user, smtp_password=smtp_password,
smtp_encryption=smtp_encryption, smtp_ssl_certificate=smtp_ssl_certificate,
smtp_ssl_private_key=smtp_ssl_private_key, smtp_debug=smtp_debug,
smtp_session=smtp_session)

View File

@@ -0,0 +1,16 @@
# Copyright 2019-2022 Akretion France (http://www.akretion.com/)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, models
class IrModel(models.Model):
_inherit = 'ir.model'
@api.depends('name', 'model')
def name_get(self):
res = []
for rec in self:
res.append((rec.id, '%s (%s)' % (rec.name, rec.model)))
return res

View File

@@ -0,0 +1,16 @@
# Copyright 2024 Akretion France (http://www.akretion.com/)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, models
class IrModelFields(models.Model):
_inherit = 'ir.model.fields'
@api.depends('name', 'field_description')
def name_get(self):
res = []
for rec in self:
res.append((rec.id, '%s (%s)' % (rec.field_description, rec.name)))
return res

View File

@@ -0,0 +1,137 @@
# Copyright 2015-2022 Akretion France (http://www.akretion.com/)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, models, _
from odoo.tools.misc import format_amount
class ResCompany(models.Model):
_inherit = 'res.company'
@api.model
def generate_line(self, fields, options, icon=True, separator=' - '):
assert fields
assert options
content = []
for field in fields:
value = False
if isinstance(field, tuple) and len(field) == 2:
value = field[0]
label = field[1]
uicon = False
elif isinstance(field, str) and field in options:
value = options[field]['value']
label = options[field].get('label')
uicon = options[field].get('icon')
if value:
prefix = icon and uicon or label
if prefix:
content.append('%s %s' % (prefix, value))
else:
content.append(value)
line = separator.join(content)
return line
def _prepare_header_options(self):
self.ensure_one()
options = {
'phone': {
'value': self.phone,
# http://www.fileformat.info/info/unicode/char/1f4de/index.htm
'icon': '\U0001F4DE',
'label': _('Tel:'),
},
'email': {
'value': self.email,
# http://www.fileformat.info/info/unicode/char/2709/index.htm
'icon': '\u2709',
'label': _('E-mail:'),
},
'website': {
'value': self.website,
'icon': '\U0001f310',
'label': _('Website:'),
},
'vat': {
'value': self.vat,
'label': _('VAT:'),
},
'ape': {
'value': hasattr(self, 'ape') and self.ape or False,
'label': _('APE:'),
},
'siret': {
'value': hasattr(self, 'siret') and self.siret or False,
'label': _('SIRET:'),
},
'siren': {
'value': hasattr(self, 'siren') and self.siren or False,
'label': _('SIREN:'),
},
'rcs_siren': {
'value': hasattr(self, 'siren') and self.siren and self.company_registry and f"{self.company_registry} {self.siren}",
'label': 'RCS',
},
'eori': {
'value': self._get_eori(),
'label': _('EORI:'),
},
'capital': {
# 'capital_amount' added by base_company_extension
'value': hasattr(self, 'capital_amount') and self.capital_amount and format_amount(self.env, self.capital_amount, self.currency_id) or False,
'label': _('Capital:'),
},
}
# 'legal_type' added by base_company_extension
if hasattr(self, 'legal_type') and self.legal_type:
options['capital']['label'] = _('%s with a capital of') % self.legal_type
# 'fax' added by OCA/partner-contact module 'partner_fax'
if hasattr(self.partner_id, 'fax'):
options['fax'] = {
'value': self.partner_id.fax or False,
'icon': '\U0001F5B7',
'label': _('Fax:'),
}
return options
def _get_eori(self):
eori = False
if self.partner_id.country_id.code == 'FR' and hasattr(self, 'siret') and self.siret:
# Currently migrating from EORI-SIRET to EORI-SIREN :
# https://www.pwcavocats.com/fr/ealertes/ealertes-france/2023/avril/reforme-numero-eori-siren-siret.html
# But, for the moment, we continue to use EORI-SIRET
eori = f'FR{self.siret}'
return eori
def _report_company_legal_name(self):
'''Method inherited in the module base_company_extension'''
self.ensure_one()
return self.name
def _report_header_line_details(self):
"""This method is designed to be inherited"""
# I decided not to put email in the default header because only a few very small
# companies have a generic company email address
line_details = [['phone', 'website', 'rcs_siren', 'capital'], ['vat', 'siret', 'eori', 'ape']]
return line_details
# for reports
def _display_report_header(
self, line_details=None, icon=True, line_separator=' - '):
self.ensure_one()
if line_details is None:
line_details = self._report_header_line_details()
res = ''
address = self.partner_id._display_address(without_company=True)
address = address.replace('\n', ' - ')
line1 = '%s - %s' % (self._report_company_legal_name(), address)
lines = [line1]
options = self._prepare_header_options()
for details in line_details:
line = self.generate_line(
details, options, icon=icon, separator=line_separator)
lines.append(line)
res = '\n'.join(lines)
return res

View File

@@ -0,0 +1,138 @@
# Copyright 2015-2022 Akretion France (http://www.akretion.com/)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields, api, _
class ResPartner(models.Model):
_inherit = 'res.partner'
# tracking=True is handled in the 'mail' module, and base_usability
# doesn't depend on 'mail', so adding tracking on res.partner fields
# has been moved to mail_usability
ref = fields.Char(copy=False)
# For reports
name_title = fields.Char(
compute='_compute_name_title', string='Name with Title')
@api.depends('name', 'title')
def _compute_name_title(self):
for partner in self:
name_title = partner.name
if partner.title and not partner.is_company:
partner_lg = partner
# If prefer to read the lang of the partner than the lang
# of the context. That way, an English man will be displayed
# with his title in English whatever the environment
if partner.lang:
partner_lg = partner.with_context(lang=partner.lang)
title = partner_lg.title.shortcut or partner_lg.title.name
name_title = ' '.join([title, name_title])
partner.name_title = name_title
def _display_address(self, without_company=False):
'''Remove empty lines'''
res = super()._display_address(without_company=without_company)
while "\n\n" in res:
res = res.replace('\n\n', '\n')
return res
# for reports
def _display_full_address(
self,
details=['company', 'name', 'address', 'phone', 'mobile', 'email'],
icon=True):
self.ensure_one()
# To make the icons work with py3o with PDF export, on the py3o server:
# 1) sudo apt-get install fonts-symbola
# 2) start libreoffice in xvfb (don't use --headless) (To confirm)
if self.is_company:
company = self.name
name = False
name_no_title = False
title = False
title_short = False
else:
company = self.parent_id and self.parent_id.is_company and\
self.parent_id.name or False
name = self.name_title
name_no_title = self.name
title = self.title.name
title_short = self.title.shortcut
options = {
'name': {
'value': name,
},
'company': {
'value': company,
},
'title': {
'value': title,
},
'title_short': {
'value': title_short,
},
'name_no_title': {
'value': name_no_title,
},
'phone': {
'value': self.phone,
# http://www.fileformat.info/info/unicode/char/1f4de/index.htm
'icon': '\U0001F4DE',
'label': _('Tel:'),
},
'mobile': {
'value': self.mobile,
# http://www.fileformat.info/info/unicode/char/1f4f1/index.htm
'icon': '\U0001F4F1',
'label': _('Mobile:'),
},
'email': {
'value': self.email,
# http://www.fileformat.info/info/unicode/char/2709/index.htm
'icon': '\u2709',
'label': _('E-mail:'),
},
'website': {
'value': self.website,
# http://www.fileformat.info/info/unicode/char/1f310/index.htm
'icon': '\U0001f310',
'label': _('Website:'),
},
'address': {
'value': self._display_address(without_company=True),
},
'vat': {
'value': self.commercial_partner_id.vat,
'label': _('VAT Number:'),
},
'commercial_ref': {
'value': self.commercial_partner_id.ref,
'label': _('Customer Number:'),
},
'ref': {
'value': self.ref,
'label': _('Customer Number:'),
},
# Same with 'supplier_' prefix, to change the label
'supplier_commercial_ref': {
'value': self.commercial_partner_id.ref,
'label': _('Supplier Number:'),
},
'supplier_ref': {
'value': self.ref,
'label': _('Supplier Number:'),
},
}
res = []
for detail in details:
if options.get(detail) and options[detail]['value']:
entry = options[detail]
prefix = icon and entry.get('icon') or entry.get('label')
if prefix:
res.append('%s %s' % (prefix, entry['value']))
else:
res.append('%s' % entry['value'])
res = '\n'.join(res)
return res

View File

@@ -0,0 +1,14 @@
# Copyright 2015-2022 Akretion France (http://www.akretion.com/)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class ResPartnerBank(models.Model):
_inherit = 'res.partner.bank'
# In the 'base' module, they didn't put any string, so the bank name is
# displayed as 'Name', which the string of the related field it
# points to
bank_name = fields.Char(string='Bank Name')

View File

@@ -0,0 +1,34 @@
# Copyright 2018-2022 Akretion France (http://www.akretion.com/)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models, SUPERUSER_ID
import logging
from odoo.tools.misc import format_datetime
logger = logging.getLogger(__name__)
class ResUsers(models.Model):
_inherit = 'res.users'
@api.model
def _script_partners_linked_to_users_no_company(self):
if self.env.user.id != SUPERUSER_ID:
self = self.sudo()
logger.info(
'START to set company_id=False on partners related to users')
users = self.with_context(active_test=False).search([])
for user in users:
if user.partner_id.company_id:
user.partner_id.write({'company_id': False})
logger.info(
'Wrote company_id=False on user %s ID %d',
user.login, user.id)
logger.info(
'END setting company_id=False on partners related to users')
def _report_print_datetime(self, lang_code):
# Used to print current datetime in a report in the user's timezone
res = format_datetime(self.env, fields.Datetime.now(), lang_code=lang_code)
return res