3 Commits

10 changed files with 370 additions and 11 deletions

View File

@@ -3,7 +3,7 @@
{ {
"name": "account_budget_forecast", "name": "account_budget_forecast",
"version": "14.0.1.3.0", "version": "14.0.1.4.0",
"author": "Elabore", "author": "Elabore",
"maintainer": "False", "maintainer": "False",
"website": "False", "website": "False",

View File

@@ -12,43 +12,43 @@ class AccountAnalyticAccount(models.Model):
"budget.forecast", "budget.forecast",
"analytic_id", "analytic_id",
domain=[("budget_category", "=", "manpower")], domain=[("budget_category", "=", "manpower")],
copy=True, copy=False,
) )
budget_forecast_material_ids = fields.One2many( budget_forecast_material_ids = fields.One2many(
"budget.forecast", "budget.forecast",
"analytic_id", "analytic_id",
domain=[("budget_category", "=", "material")], domain=[("budget_category", "=", "material")],
copy=True, copy=False,
) )
budget_forecast_equipment_ids = fields.One2many( budget_forecast_equipment_ids = fields.One2many(
"budget.forecast", "budget.forecast",
"analytic_id", "analytic_id",
domain=[("budget_category", "=", "equipment")], domain=[("budget_category", "=", "equipment")],
copy=True, copy=False,
) )
budget_forecast_subcontractors_ids = fields.One2many( budget_forecast_subcontractors_ids = fields.One2many(
"budget.forecast", "budget.forecast",
"analytic_id", "analytic_id",
domain=[("budget_category", "=", "subcontractors")], domain=[("budget_category", "=", "subcontractors")],
copy=True, copy=False,
) )
budget_forecast_delivery_ids = fields.One2many( budget_forecast_delivery_ids = fields.One2many(
"budget.forecast", "budget.forecast",
"analytic_id", "analytic_id",
domain=[("budget_category", "=", "delivery")], domain=[("budget_category", "=", "delivery")],
copy=True, copy=False,
) )
budget_forecast_miscellaneous_ids = fields.One2many( budget_forecast_miscellaneous_ids = fields.One2many(
"budget.forecast", "budget.forecast",
"analytic_id", "analytic_id",
domain=[("budget_category", "=", "miscellaneous")], domain=[("budget_category", "=", "miscellaneous")],
copy=True, copy=False,
) )
budget_forecast_unplanned_ids = fields.One2many( budget_forecast_unplanned_ids = fields.One2many(
"budget.forecast", "budget.forecast",
"analytic_id", "analytic_id",
domain=[("budget_category", "=", "unplanned")], domain=[("budget_category", "=", "unplanned")],
copy=True, copy=False,
) )
project_section_budget_ids = fields.One2many( project_section_budget_ids = fields.One2many(
"budget.forecast", "budget.forecast",

View File

@@ -2,6 +2,8 @@
from odoo import models, fields, _, api from odoo import models, fields, _, api
from odoo.exceptions import Warning from odoo.exceptions import Warning
import logging
_logger = logging.getLogger(__name__)
class SaleOrder(models.Model): class SaleOrder(models.Model):
@@ -49,9 +51,12 @@ class SaleOrder(models.Model):
name = self.analytic_account_id.name.replace(self.name, record.name) name = self.analytic_account_id.name.replace(self.name, record.name)
else: else:
name = "%s: %s" % (self.analytic_account_id.name, record.name) name = "%s: %s" % (self.analytic_account_id.name, record.name)
record.analytic_account_id = self.analytic_account_id.copy( try:
default=dict(name=name) copied_account = self.analytic_account_id.copy(default={"name": name})
) if copied_account:
record.analytic_account_id = copied_account
except Exception as e:
_logger.error("Failed to copy analytic account for sale order %s: %s", self.name, e)
return record return record

View File

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

View File

@@ -0,0 +1,66 @@
{
'name': 'Import chart of accounts',
'version': '14.0.1.1.0',
'summary': 'while importing the accounts chart, only update account name of existing accounts and automatise settings for new accounts',
'description': """
Installation
============
Install import_chart_of_accounts, all dependencies will be installed by default.
Description
=============
Pendant l'import, chaque ligne est comparée aux comptes comptables présents dans Odoo
- Si le compte comptable existe déjà dans bdd, seul le nom du compte comptable est mis à jour
- Un compte comptable est déjà existant si les 6 premiers chiffres du code comptable sont identique (par ex: le compte 120000 et 12000000 sont les mêmes comptes)
- Si le compte comptable n'existe pas dans bdd, il est créé.
- Un compte similaire est recherché dans la bdd à partir des 3 premier chiffres du code comptable.
- On recherche tous les comptes qui ont les 3 premiers chiffres de son code en commun avec celui du compte nouvellement créé
- Parmi ces comptes, le compte du lequel les paramètres seront copiés sur le nouveau compte est celui au numéro de code le plus bas.
- On enregistre la valeur des variables 'type' et 'reconcilition' du compte "similaire" dans le nouveau compte comptable
- S'il n'existe "compte similaire" pour ce nouveau compte, aucun paramétrage n'est ajouté lors de l'import
Exemple :
J'importe le compte comptable 607730 Epicerie divers
Ce compte comptable n'existe pas déjà dans Odoo, il est créé.
Pour le configurer automatiquement, on se fonde sur un compte similaire dans Odoo et avec le code le plus bas parmis les comptes similaires
Ici il s'agit de 607000 Achats de marchandise:
Il a pour Type Charges car c'est une compte de charges et Autoriser le lettrage est à False.
Le compte 607730 Epicerie divers sera donc enregistré dans Odoo avec le même paramétrage.
Usage
=====
Pour importer le plan comptable :
Aller dans l'App Facturation
Menu Configuration > Comptabilité > Importer le plan comptable
Un assistant permettant le téléversement d'un plan comptable apparaît.
Le fichier téléversé doit être au format CSV uniquement.
Il ne doit comporter que deux colonnes :
- La première colonne doit s'appeler 'code' pour le numéro de compte comptable
- La deuxième colonne doit s'appeler 'name' pour le nom du compte comptable
""",
'author': '',
'website': '',
'license': 'AGPL-3',
'category': '',
'depends': [
'account'
],
'data': [
'wizard/import_coa_wizard_views.xml',
'security/ir.model.access.csv'
],
'installable': True,
'application': False,
'assets': {
}
}

View File

@@ -0,0 +1,168 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * import_chart_of_accounts
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-05-29 10:27+0000\n"
"PO-Revision-Date: 2024-05-29 10:27+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: import_chart_of_accounts
#: model_terms:ir.ui.view,arch_db:import_chart_of_accounts.import_coa_wizard_view
msgid "<strong>Exemple :</strong>"
msgstr ""
#. module: import_chart_of_accounts
#: model_terms:ir.ui.view,arch_db:import_chart_of_accounts.import_coa_wizard_view
msgid "Accounts chart CSV Import Wizard"
msgstr "Importer un plan comptable"
#. module: import_chart_of_accounts
#: model:ir.model.fields,field_description:import_chart_of_accounts.field_import_coa_wizard__coa_file
msgid "CSV File"
msgstr "Fichier CSV"
#. module: import_chart_of_accounts
#: model_terms:ir.ui.view,arch_db:import_chart_of_accounts.import_coa_wizard_view
msgid "Cancel"
msgstr "Annuler"
#. module: import_chart_of_accounts
#: model_terms:ir.ui.view,arch_db:import_chart_of_accounts.import_coa_wizard_view
msgid "Ce compte comptable n'existe pas déjà dans Odoo, il est créé."
msgstr ""
#. module: import_chart_of_accounts
#: model:ir.model.fields,field_description:import_chart_of_accounts.field_import_coa_wizard__create_uid
msgid "Created by"
msgstr ""
#. module: import_chart_of_accounts
#: model:ir.model.fields,field_description:import_chart_of_accounts.field_import_coa_wizard__create_date
msgid "Created on"
msgstr ""
#. module: import_chart_of_accounts
#: model:ir.model.fields,field_description:import_chart_of_accounts.field_import_coa_wizard__display_name
msgid "Display Name"
msgstr ""
#. module: import_chart_of_accounts
#: model:ir.model.fields,field_description:import_chart_of_accounts.field_import_coa_wizard__filename
msgid "Filename"
msgstr ""
#. module: import_chart_of_accounts
#: model:ir.model.fields,field_description:import_chart_of_accounts.field_import_coa_wizard__id
msgid "ID"
msgstr ""
#. module: import_chart_of_accounts
#: model_terms:ir.ui.view,arch_db:import_chart_of_accounts.import_coa_wizard_view
msgid ""
"Ici il s'agit de <strong>607000 Achats de marchandise</strong>:<br/>\n"
" Il a pour <strong>Type</strong> Charges car c'est une compte de charges et <strong>Autoriser le lettrage</strong> est à False.<br/>\n"
" Le compte 607730 Epicerie divers sera donc enregistré dans Odoo avec le même paramétrage,<br/>\n"
" c'est-à-dire avec un type Charge et une non autorisation du lettrage"
msgstr ""
#. module: import_chart_of_accounts
#: model_terms:ir.ui.view,arch_db:import_chart_of_accounts.import_coa_wizard_view
msgid "Il ne doit comporter que <strong>deux colonnes</strong>"
msgstr ""
#. module: import_chart_of_accounts
#: model_terms:ir.ui.view,arch_db:import_chart_of_accounts.import_coa_wizard_view
msgid "Import"
msgstr "Importer"
#. module: import_chart_of_accounts
#: model_terms:ir.ui.view,arch_db:import_chart_of_accounts.import_coa_wizard_view
msgid "J'importe le compte comptable <strong>607730 Epicerie divers</strong>"
msgstr ""
#. module: import_chart_of_accounts
#: model_terms:ir.ui.view,arch_db:import_chart_of_accounts.import_coa_wizard_view
msgid ""
"La deuxième colonne doit s'appeler <strong>name</strong> pour le nom du "
"compte comptable"
msgstr ""
#. module: import_chart_of_accounts
#: model_terms:ir.ui.view,arch_db:import_chart_of_accounts.import_coa_wizard_view
msgid ""
"La première colonne doit s'appeler <strong>code</strong> pour le numéro de "
"compte comptable"
msgstr ""
#. module: import_chart_of_accounts
#: model:ir.model.fields,field_description:import_chart_of_accounts.field_import_coa_wizard____last_update
msgid "Last Modified on"
msgstr ""
#. module: import_chart_of_accounts
#: model:ir.model.fields,field_description:import_chart_of_accounts.field_import_coa_wizard__write_uid
msgid "Last Updated by"
msgstr ""
#. module: import_chart_of_accounts
#: model:ir.model.fields,field_description:import_chart_of_accounts.field_import_coa_wizard__write_date
msgid "Last Updated on"
msgstr ""
#. module: import_chart_of_accounts
#: model_terms:ir.ui.view,arch_db:import_chart_of_accounts.import_coa_wizard_view
msgid "Le fichier téléversé doit être au <strong>format CSV</strong>"
msgstr ""
#. module: import_chart_of_accounts
#: model_terms:ir.ui.view,arch_db:import_chart_of_accounts.import_coa_wizard_view
msgid ""
"Pendant l'import, chaque ligne est comparée aux comptes comptables présents "
"dans Odoo"
msgstr ""
#. module: import_chart_of_accounts
#: model_terms:ir.ui.view,arch_db:import_chart_of_accounts.import_coa_wizard_view
msgid "Pour importer le plan comptable :"
msgstr ""
#. module: import_chart_of_accounts
#: model_terms:ir.ui.view,arch_db:import_chart_of_accounts.import_coa_wizard_view
msgid ""
"Pour le configurer automatiquement, on se fonde sur le compte le plus proche"
" dans Odoo"
msgstr ""
#. module: import_chart_of_accounts
#: model_terms:ir.ui.view,arch_db:import_chart_of_accounts.import_coa_wizard_view
msgid ""
"Si le compte comptable existe déjà dans bdd, seul le nom du compte comptable"
" est mis à jour"
msgstr ""
#. module: import_chart_of_accounts
#: model_terms:ir.ui.view,arch_db:import_chart_of_accounts.import_coa_wizard_view
msgid ""
"Si le compte comptable n'existe pas dans bdd, il est créé. Puis un compte similaire est recherché dans la bdd,\n"
" <br/>le compte comptable nouvellement créé aura le même type et la même autorisation de lettrage."
msgstr ""
#. module: import_chart_of_accounts
#: model:ir.actions.act_window,name:import_chart_of_accounts.action_import_coa_wizard
#: model:ir.ui.menu,name:import_chart_of_accounts.import_coa_menu
msgid "Upload Chart Of Accounts"
msgstr "Importer un plan comptable"
#. module: import_chart_of_accounts
#: model:ir.model,name:import_chart_of_accounts.model_import_coa_wizard
msgid "import.coa.wizard"
msgstr ""

View File

@@ -0,0 +1,2 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_import_coa_wizard,access.import.coa.wizard,model_import_coa_wizard,account.group_account_manager,1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_import_coa_wizard access.import.coa.wizard model_import_coa_wizard account.group_account_manager 1 1 1 0

View File

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

View File

@@ -0,0 +1,50 @@
from odoo import models, fields, api, exceptions, _
import csv
import base64
from io import StringIO
from odoo.exceptions import UserError
class ImportCoaWizard(models.TransientModel):
_name = 'import.coa.wizard'
coa_file = fields.Binary(string='CSV File', required=True)
filename = fields.Char(string='Filename')
def import_plan_comptable(self):
self.ensure_one()
if not self.coa_file:
raise UserError("Please upload a file.")
if self.filename and not self.filename.lower().endswith('.csv'):
raise UserError("Import COA Wizard only supports CSV")
file_content = base64.b64decode(self.coa_file).decode('utf-8')
csv_file = StringIO(file_content)
csv_reader = csv.DictReader(csv_file)
required_columns = ['code', 'name']
if not all(column in csv_reader.fieldnames for column in required_columns):
raise UserError(f"The CSV file must contain the following columns: {', '.join(required_columns)}")
data_to_import = [row for row in csv_reader]
for record_data in data_to_import:
# the account is already existing in Odoo if the 6 first digits are identicales
existing_line = self.find_account_with_same_firsts_digits(record_data['code'][:6])
if existing_line:
existing_line.write(record_data)
else:
# the closest account already existing in Odoo has the first tree digits identicales
closest_account = self.find_account_with_same_firsts_digits(record_data['code'][:3])
if closest_account :
record_data['user_type_id'] = closest_account.user_type_id.id
record_data['reconcile'] = closest_account.reconcile
new_account = self.env['account.account'].create(record_data)
return {
"type": "ir.actions.act_window",
"res_model": "account.account",
"view_mode": "list"
}
def find_account_with_same_firsts_digits(self, code_prefix):
return self.env['account.account'].search([('code', '=like', f'{code_prefix}%')],limit=1)

View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="import_coa_wizard_view" model="ir.ui.view">
<field name="name">import.coa.wizard.view</field>
<field name="model">import.coa.wizard</field>
<field name="arch" type="xml">
<form string="Accounts chart CSV Import Wizard">
<group name="help-import" colspan="1" col="1">
<div colspan="2">
<p>Pour importer le plan comptable :
<ul>
<li>Le fichier téléversé doit être au <strong>format CSV</strong></li>
<li>Il ne doit comporter que <strong>deux colonnes</strong></li>
<li>La première colonne doit s'appeler <strong>code</strong> pour le numéro de compte comptable</li>
<li>La deuxième colonne doit s'appeler <strong>name</strong> pour le nom du compte comptable</li>
</ul>
</p>
<br/>
<p>Pendant l'import, chaque ligne est comparée aux comptes comptables présents dans Odoo
<ul>
<li>Si le compte comptable existe déjà dans bdd, seul le nom du compte comptable est mis à jour</li>
<li>Un compte comptable est déjà existant si les 6 premiers chiffres du code comptable sont identique (par ex: le compte 120000 et 12000000 sont les mêmes comptes)</li>
<li>Si le compte comptable n'existe pas dans bdd, il est créé. Puis un compte similaire est recherché dans la bdd,
<br/>le compte comptable nouvellement créé aura le même type et la même autorisation de lettrage.</li>
</ul>
</p>
<br/>
<p><strong>Exemple :</strong>
<ul>
<li>J'importe le compte comptable <strong>607730 Epicerie divers</strong></li>
<li>Ce compte comptable n'existe pas déjà dans Odoo, il est créé.</li>
<li>Pour le configurer automatiquement, on se fonde sur le compte le plus proche dans Odoo</li>
<li>Ici il s'agit de <strong>607000 Achats de marchandise</strong>:<br/>
Il a pour <strong>Type</strong> Charges car c'est une compte de charges et <strong>Autoriser le lettrage</strong> est à False.<br/>
Le compte 607730 Epicerie divers sera donc enregistré dans Odoo avec le même paramétrage,<br/>
c'est-à-dire avec un type Charge et une non autorisation du lettrage</li>
</ul>
</p>
</div>
</group>
<group name="import">
<field name="coa_file" filename="filename" />
<field name="filename" invisible="1"/>
</group>
<footer>
<button name="import_plan_comptable" type="object"
class="btn-primary" string="Import"/>
<button special="cancel" string="Cancel" class="btn-default"/>
</footer>
</form>
</field>
</record>
<record id="action_import_coa_wizard" model="ir.actions.act_window">
<field name="name">Upload Chart Of Accounts</field>
<field name="res_model">import.coa.wizard</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<menuitem
id="import_coa_menu"
action="action_import_coa_wizard"
sequence="1"
parent="account.account_account_menu"
/>
</odoo>