diff --git a/__init__.py b/__init__.py index 957992f377d7ce8942a87238397684babc5eb305..5b2ef480c07b807b141e836f50066c048468afb0 100644 --- a/__init__.py +++ b/__init__.py @@ -1,4 +1,5 @@ # Copyright 2021 Le Filament (<http://www.le-filament.com>) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from . import controllers from . import models diff --git a/__manifest__.py b/__manifest__.py index cb8cfbf5eca51f841d6d26e6d12726a8d86ab581..93b08e06da8442a7ea7f7069febbe6a589fc6bb4 100644 --- a/__manifest__.py +++ b/__manifest__.py @@ -6,9 +6,9 @@ "summary": "Ajout données spécifiques AFAC", "author": "Le Filament", "website": "https://www.le-filament.com", - "version": "14.0.0.0.0", + "version": "14.0.0.0.1", "license": "AGPL-3", - "depends": ["base", "contacts", "partner_firstname"], + "depends": ["base", "contacts", "partner_firstname", "web"], "data": [ # security "security/security_rules.xml", @@ -23,8 +23,11 @@ "views/afac_project_partner.xml", "views/res_company.xml", "views/res_partner.xml", + + ], + "qweb": [ + "static/src/xml/base.xml", ], - "qweb": [], "installable": True, "auto_install": False, "sequence": 101, diff --git a/controllers/__init__.py b/controllers/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..12a7e529b674164f0ad189b131c5d5c8fb9ae0bc --- /dev/null +++ b/controllers/__init__.py @@ -0,0 +1 @@ +from . import main diff --git a/controllers/main.py b/controllers/main.py new file mode 100644 index 0000000000000000000000000000000000000000..8834915753fc3e0f7d03f943f36ce6fb7f64f72b --- /dev/null +++ b/controllers/main.py @@ -0,0 +1,93 @@ +import json +import logging +import operator + +from odoo.http import content_disposition, request, route + +from odoo.addons.web.controllers.main import ( + ExportFormat, + GroupsTreeNode, + ExcelExport, + CSVExport, + serialize_exception, +) + + +_logger = logging.getLogger(__name__) + + +class ExcelExport(ExcelExport): + @route("/web/export/xlsx", type="http", auth="user") + @serialize_exception + def index(self, data, token): + return afac_base(self, data, token) + + +class CSVExport(CSVExport): + + @route("/web/export/csv", type="http", auth="user") + @serialize_exception + def index(self, data, token): + return afac_base(self, data, token) + + +def afac_base(object, data, token): + + params = json.loads(data) + model, fields, ids, domain, import_compat = operator.itemgetter( + "model", "fields", "ids", "domain", "import_compat" + )(params) + + model_object = request.env[model].with_context( + import_compat=import_compat, **params.get("context", {}) + ) + if not model_object._is_an_ordinary_table(): + fields = [field for field in fields if field["name"] != "id"] + + field_names = [f["name"] for f in fields] + if import_compat: + columns_headers = field_names + else: + columns_headers = [val["label"].strip() for val in fields] + + groupby = params.get("groupby") + if not import_compat and groupby: + groupby_type = [model_object._fields[x.split(":")[0]].type for x in groupby] + domain = [("id", "in", ids)] if ids else domain + groups_data = model_object.read_group( + domain, + [x if x != ".id" else "id" for x in field_names], + groupby, + lazy=False, + ) + + tree = GroupsTreeNode(model_object, field_names, groupby, groupby_type) + for leaf in groups_data: + tree.insert_leaf(leaf) + + response_data = object.from_group_data(fields, tree) + else: + records = ( + model_object.browse(ids) + if ids + else model_object.search(domain, offset=0, limit=False, order=False) + ) + + datas = records.export_data( + fields_to_export=field_names, afac=params.get("afac", False) + ) + response_data = object.from_data( + (columns_headers + datas.get("column", [])), datas.get("datas", []) + ) + + return request.make_response( + response_data, + headers=[ + ( + "Content-Disposition", + content_disposition(object.filename(model)), + ), + ("Content-Type", object.content_type), + ], + cookies={"fileToken": token}, + ) diff --git a/models/afac_project.py b/models/afac_project.py index 3e70ce69f7ba30df9a2d02f6630a0bb00219e58d..2546c5ec992212ab6eca462c13b4f449b348bad8 100644 --- a/models/afac_project.py +++ b/models/afac_project.py @@ -69,3 +69,4 @@ class AfacProject(models.Model): "default_company_id": self.company_id.id, }, } + diff --git a/models/res_partner.py b/models/res_partner.py index 9bf4c5ab7b00500357c2f320a8a848f422f22ce4..5506cc3fd2b672d6d484267d6331bab736623ad0 100644 --- a/models/res_partner.py +++ b/models/res_partner.py @@ -122,6 +122,52 @@ class ResPartner(models.Model): # Default methods # ------------------------------------------------------ + def export_data(self, fields_to_export, afac=False): + + out = super().export_data(fields_to_export) + if afac: + column = [] + datas = out.get("datas", []) + all_projects = ( + self.env["afac.project.partner"] + .search([("partner_id", "in", self.ids)]) + .mapped("project_id") + ) + + if datas: + for afac_project in all_projects: + data_index = 0 + column.append(afac_project.name) + afac_project_category = self.env["afac.project.category"].search( + [("project_id", "=", afac_project.id)] + ) + for project_category in afac_project_category: + column.append(project_category.name) + + for partner in self: + project_partner = self.env["afac.project.partner"].search( + [ + "&", + ("partner_id", "=", partner.id), + ("project_id", "=", afac_project.id), + ] + ) + if project_partner: + datas[data_index].append(1) + else: + datas[data_index].append(0) + + for project_category in afac_project_category: + if project_category in project_partner.project_cat_ids: + datas[data_index].append(1) + else: + datas[data_index].append(0) + data_index += 1 + out["datas"] = datas + out["column"] = column + return out + return out + # ------------------------------------------------------ # Computed fields / Search Fields # ------------------------------------------------------ diff --git a/static/src/js/data_export.js b/static/src/js/data_export.js new file mode 100644 index 0000000000000000000000000000000000000000..100248b60227c2151d436ab4bb098da2f50355f1 --- /dev/null +++ b/static/src/js/data_export.js @@ -0,0 +1,58 @@ +odoo.define("base_export_async.DataExport", function (require) { + "use strict"; + + var core = require("web.core"); + var DataExport = require("web.DataExport"); + var framework = require("web.framework"); + var pyUtils = require("web.py_utils"); + var Dialog = require("web.Dialog"); + var _t = core._t; + + DataExport.include({ + /* + Overwritten Object responsible for the standard export. + A flag (checkbox) afac is checked + */ + _exportData(exportedFields, exportFormat, idsToExport) { + const afac = this.$("#o-export-afac-project"); + if (afac && afac.is(":checked")) { + console.log("CHECKED"); + console.log(exportedFields); + console.log(exportFormat); + console.log(idsToExport); + if (_.isEmpty(exportedFields)) { + Dialog.alert(this, _t("Please select fields to export...")); + return; + } + if (this.isCompatibleMode) { + exportedFields.unshift({ name: 'id', label: _t('External ID') }); + } + + framework.blockUI(); + this.getSession().get_file({ + url: '/web/export/' + exportFormat, + data: { + data: JSON.stringify({ + model: this.record.model, + fields: exportedFields, + ids: idsToExport, + domain: this.domain, + groupby: this.groupby, + context: pyUtils.eval('contexts', [this.record.getContext()]), + import_compat: this.isCompatibleMode, + afac: true + }) + }, + complete: framework.unblockUI, + error: (error) => this.call('crash_manager', 'rpc_error', error), + }); + + } else { + /* + Call the standard method if afac is not checked + */ + this._super.apply(this, arguments); + } + }, + }); +}); diff --git a/static/src/xml/base.xml b/static/src/xml/base.xml new file mode 100644 index 0000000000000000000000000000000000000000..6163e5d0554d27ab96f66b6a2d6debd6078e527c --- /dev/null +++ b/static/src/xml/base.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<templates id="template" xml:space="preserve"> + <t + t-name="ExportDialog" + t-inherit="web.ExportDialog" + t-inherit-mode="extension" +> + <xpath expr="//div[hasclass('o_import_compat')]" position="after"> + <p> + <div class="form-check"> + <input class="form-check-input" id="o-export-afac-project" type="checkbox"/> + <label class="form-check-label" for="o-export-afac-project"> + Export AFAC project + </label> + </div> + </p> + </xpath> + </t> +</templates> diff --git a/views/assets.xml b/views/assets.xml index 6e7c7760a17152ac21c00039e18c9453395e95f5..5bbe70edb1175816b7c7c4b8a11db69a86a731dc 100644 --- a/views/assets.xml +++ b/views/assets.xml @@ -10,6 +10,10 @@ rel="stylesheet" href="/afac_partner/static/src/css/afac_partner.css" /> + <script + type="text/javascript" + src="/afac_partner/static/src/js/data_export.js" + /> </xpath> </template> </odoo>