Commit 58222c66 by François C.

Add modules to export in inventory product values in XLSX format

parent d8a0fc7a
# -*- coding: utf-8 -*-
# Copyright (C) 2016-Today: La Louve (<http://www.lalouve.net/>)
from . import report
from . import wizard
# -*- coding: utf-8 -*-
# Copyright (C) 2018-Today: La Louve (<https://cooplalouve.fr>)
# @author: Simon Mas (linkedin.com/in/simon-mas)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
'name': 'Account Asset Management xlsx',
'version': '9.0.1.0.0',
'category': 'Accounting',
'summary': 'account_asset_management_xlsx',
'author': 'Simon Mas, Ân Lê Hoàng',
'website': 'https://cooplalouve.fr',
'depends': [
'account',
'account_asset',
'report_xlsx',
],
'data': [
"report/report_account_asset_xlsx.xml",
"security/ir.model.access.csv",
"wizard/account_asset_xlsx_wizard.xml",
],
'installable': True,
}
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * account_asset_management_xlsx
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0c\n"
"Report-Msgid-Bugs-To: \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: account_asset_management_xlsx
#: model:ir.actions.report.xml,name:account_asset_management_xlsx.report_account_asset_xlsx
msgid "Account Asset Report"
msgstr ""
#. module: account_asset_management_xlsx
#: model:ir.ui.view,arch_db:account_asset_management_xlsx.view_account_asset_xlsx_wizard
msgid "Account Asset Xlsx Wizard"
msgstr ""
#. module: account_asset_management_xlsx
#: selection:account.asset.xlsx.wizard,asset_state:0
msgid "All assets"
msgstr ""
#. module: account_asset_management_xlsx
#: selection:account.asset.xlsx.wizard,target_move:0
msgid "All moves"
msgstr ""
#. module: account_asset_management_xlsx
#: model:ir.model.fields,field_description:account_asset_management_xlsx.field_account_asset_xlsx_wizard_asset_category_ids
msgid "Asset Categories"
msgstr ""
#. module: account_asset_management_xlsx
#: model:ir.ui.menu,name:account_asset_management_xlsx.open_account_asset_xlsx_wizard
msgid "Asset Report Xlsx"
msgstr ""
#. module: account_asset_management_xlsx
#: model:ir.ui.view,arch_db:account_asset_management_xlsx.view_account_asset_xlsx_wizard
msgid "Cancel"
msgstr ""
#. module: account_asset_management_xlsx
#: model:ir.model.fields,field_description:account_asset_management_xlsx.field_account_asset_xlsx_wizard_create_uid
msgid "Created by"
msgstr ""
#. module: account_asset_management_xlsx
#: model:ir.model.fields,field_description:account_asset_management_xlsx.field_account_asset_xlsx_wizard_create_date
msgid "Created on"
msgstr ""
#. module: account_asset_management_xlsx
#: model:ir.model.fields,field_description:account_asset_management_xlsx.field_account_asset_xlsx_wizard_display_name
msgid "Display Name"
msgstr ""
#. module: account_asset_management_xlsx
#: model:ir.ui.view,arch_db:account_asset_management_xlsx.view_account_asset_xlsx_wizard
msgid "Export"
msgstr ""
#. module: account_asset_management_xlsx
#: model:ir.actions.act_window,name:account_asset_management_xlsx.action_account_asset_xlsx_wizard
msgid "Export Account Asset Report"
msgstr ""
#. module: account_asset_management_xlsx
#: model:ir.model.fields,field_description:account_asset_management_xlsx.field_account_asset_xlsx_wizard_from_date
msgid "From date"
msgstr ""
#. module: account_asset_management_xlsx
#: model:ir.model.fields,field_description:account_asset_management_xlsx.field_account_asset_xlsx_wizard_id
msgid "ID"
msgstr ""
#. module: account_asset_management_xlsx
#: model:ir.model.fields,field_description:account_asset_management_xlsx.field_account_asset_xlsx_wizard___last_update
msgid "Last Modified on"
msgstr ""
#. module: account_asset_management_xlsx
#: model:ir.model.fields,field_description:account_asset_management_xlsx.field_account_asset_xlsx_wizard_write_uid
msgid "Last Updated by"
msgstr ""
#. module: account_asset_management_xlsx
#: model:ir.model.fields,field_description:account_asset_management_xlsx.field_account_asset_xlsx_wizard_write_date
msgid "Last Updated on"
msgstr ""
#. module: account_asset_management_xlsx
#: selection:account.asset.xlsx.wizard,asset_state:0
msgid "Open only"
msgstr ""
#. module: account_asset_management_xlsx
#: selection:account.asset.xlsx.wizard,target_move:0
msgid "Posted moves"
msgstr ""
#. module: account_asset_management_xlsx
#: model:ir.model.fields,field_description:account_asset_management_xlsx.field_account_asset_xlsx_wizard_asset_state
msgid "Status"
msgstr ""
#. module: account_asset_management_xlsx
#: model:ir.model.fields,field_description:account_asset_management_xlsx.field_account_asset_xlsx_wizard_target_move
msgid "Target move"
msgstr ""
#. module: account_asset_management_xlsx
#: model:ir.model.fields,field_description:account_asset_management_xlsx.field_account_asset_xlsx_wizard_to_date
msgid "To date"
msgstr ""
#. module: account_asset_management_xlsx
#: model:ir.model,name:account_asset_management_xlsx.model_account_asset_xlsx_wizard
msgid "account.asset.xlsx.wizard"
msgstr ""
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * account_asset_management_xlsx
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0c\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-12-10 04:19+0000\n"
"PO-Revision-Date: 2018-12-10 04:19+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: account_asset_management_xlsx
#: model:ir.actions.report.xml,name:account_asset_management_xlsx.report_account_asset_xlsx
msgid "Account Asset Report"
msgstr "Account Asset Report"
#. module: account_asset_management_xlsx
#: model:ir.ui.view,arch_db:account_asset_management_xlsx.view_account_asset_xlsx_wizard
msgid "Account Asset Xlsx Wizard"
msgstr "Account Asset Xlsx Wizard"
#. module: account_asset_management_xlsx
#: selection:account.asset.xlsx.wizard,asset_state:0
msgid "All assets"
msgstr "Toutes les immobilisations"
#. module: account_asset_management_xlsx
#: selection:account.asset.xlsx.wizard,target_move:0
msgid "All moves"
msgstr "Toutes les écritures"
#. module: account_asset_management_xlsx
#: model:ir.model.fields,field_description:account_asset_management_xlsx.field_account_asset_xlsx_wizard_asset_category_ids
msgid "Asset Categories"
msgstr "Catégories"
#. module: account_asset_management_xlsx
#: model:ir.ui.menu,name:account_asset_management_xlsx.open_account_asset_xlsx_wizard
msgid "Asset Report Xlsx"
msgstr "État immobilisations"
#. module: account_asset_management_xlsx
#: model:ir.ui.view,arch_db:account_asset_management_xlsx.view_account_asset_xlsx_wizard
msgid "Cancel"
msgstr "Annuler"
#. module: account_asset_management_xlsx
#: model:ir.model.fields,field_description:account_asset_management_xlsx.field_account_asset_xlsx_wizard_create_uid
msgid "Created by"
msgstr "Créé par"
#. module: account_asset_management_xlsx
#: model:ir.model.fields,field_description:account_asset_management_xlsx.field_account_asset_xlsx_wizard_create_date
msgid "Created on"
msgstr "Créé le"
#. module: account_asset_management_xlsx
#: model:ir.model.fields,field_description:account_asset_management_xlsx.field_account_asset_xlsx_wizard_display_name
msgid "Display Name"
msgstr "Nom affiché"
#. module: account_asset_management_xlsx
#: model:ir.ui.view,arch_db:account_asset_management_xlsx.view_account_asset_xlsx_wizard
msgid "Export"
msgstr "Exporter"
#. module: account_asset_management_xlsx
#: model:ir.actions.act_window,name:account_asset_management_xlsx.action_account_asset_xlsx_wizard
msgid "Export Account Asset Report"
msgstr "Export Account Asset Report"
#. module: account_asset_management_xlsx
#: model:ir.model.fields,field_description:account_asset_management_xlsx.field_account_asset_xlsx_wizard_from_date
msgid "From date"
msgstr "Début"
#. module: account_asset_management_xlsx
#: model:ir.model.fields,field_description:account_asset_management_xlsx.field_account_asset_xlsx_wizard_id
msgid "ID"
msgstr "ID"
#. module: account_asset_management_xlsx
#: model:ir.model.fields,field_description:account_asset_management_xlsx.field_account_asset_xlsx_wizard___last_update
msgid "Last Modified on"
msgstr "Dernière modification le"
#. module: account_asset_management_xlsx
#: model:ir.model.fields,field_description:account_asset_management_xlsx.field_account_asset_xlsx_wizard_write_uid
msgid "Last Updated by"
msgstr "Mis à jour par"
#. module: account_asset_management_xlsx
#: model:ir.model.fields,field_description:account_asset_management_xlsx.field_account_asset_xlsx_wizard_write_date
msgid "Last Updated on"
msgstr "Mis à jour le"
#. module: account_asset_management_xlsx
#: selection:account.asset.xlsx.wizard,asset_state:0
msgid "Open only"
msgstr "Uniquement les immobilisations en cours"
#. module: account_asset_management_xlsx
#: selection:account.asset.xlsx.wizard,target_move:0
msgid "Posted moves"
msgstr "Toutes les écritures comptabilisées"
#. module: account_asset_management_xlsx
#: model:ir.model.fields,field_description:account_asset_management_xlsx.field_account_asset_xlsx_wizard_asset_state
msgid "Status"
msgstr "Statut"
#. module: account_asset_management_xlsx
#: model:ir.model.fields,field_description:account_asset_management_xlsx.field_account_asset_xlsx_wizard_target_move
msgid "Target move"
msgstr "Target move"
#. module: account_asset_management_xlsx
#: model:ir.model.fields,field_description:account_asset_management_xlsx.field_account_asset_xlsx_wizard_to_date
msgid "To date"
msgstr "Fin"
#. module: account_asset_management_xlsx
#: model:ir.model,name:account_asset_management_xlsx.model_account_asset_xlsx_wizard
msgid "account.asset.xlsx.wizard"
msgstr "account.asset.xlsx.wizard"
# -*- coding: utf-8 -*-
# Copyright (C) 2016-Today: La Louve (<http://www.lalouve.net/>)
from . import report_account_asset_xlsx
# -*- coding: utf-8 -*-
# Copyright (C) 2016-Today: La Louve (<http://www.lalouve.net/>)
from openerp.tools import image as IMG
import base64
import os
import logging
import tempfile
_logger = logging.getLogger(__name__)
def get_record_image_path(record, image, size=(128, 128)):
"""
:param record: instance of model
:param image: example: product_id.image
:param size: example: (128, 128)
:return: path to image or None if no image
"""
if not image:
return None
temp_folder = tempfile.mkdtemp()
record_image_path = os.path.join(
temp_folder, str(record.id) + ".jpg")
try:
record_image = IMG.image_resize_image(
image, size)
record_image = base64.b64decode(record_image)
with open(record_image_path, 'wb') as f:
f.write(record_image)
return record_image_path
except Exception as e:
logging.error('Error when processing the image for'
'record: %s: %s', record, str(e))
raise e
return False
# -*- coding: utf-8 -*-
# Copyright (C) 2016-Today: La Louve (<http://www.lalouve.fr/>)
# @author: La Louve
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html
from xlsxwriter.utility import xl_rowcol_to_cell
from .image_util import get_record_image_path
from openerp.addons.report_xlsx.report.report_xlsx import ReportXlsx
from openerp.api import Environment
from openerp import SUPERUSER_ID
from openerp import fields
class ReportAccountAssetXlsx(ReportXlsx):
def create_xlsx_report(self, ids, data, report):
self.env = Environment(self.env.cr, SUPERUSER_ID, self.env.context)
return super(ReportAccountAssetXlsx,
self).create_xlsx_report(ids, data, report)
def generate_xlsx_report(self, workbook, data, objects):
self.object = objects[0]
self._define_formats(workbook)
self.sheet = workbook.add_worksheet()
self.setup_config()
self.generate_report_title()
self.generate_report_general()
self.row_pos += 2
self.table_columns = [
'name',
'state',
'date',
'value',
'salvage_value',
'method',
'method_number',
'prorata',
'amo_ant',
'amo_de_lan',
'cum_amo',
'value_residual'
]
self.info_labels = {
'name': {'str': u"Nom de l'immobilisation"},
'state': {'str': 'Statut'},
'date': {'str': 'Date', 'format': self.format_table_date},
'value': {
'str': 'Valeur brute',
'type': 'formula',
'format': self.format_table_number
},
'salvage_value': {
'str': 'N/amortissable',
'type': 'formula',
'format': self.format_table_number
},
'method': {'str': u'Méthode'},
'method_number': {'str': 'Nb. amort.'},
'prorata': {'str': 'Prorata'},
'amo_ant': {
'str': 'Amo. ant.',
'type': 'formula',
'format': self.format_table_number
},
'amo_de_lan': {
'str': u"Amortissement de l'année",
'type': 'formula',
'format': self.format_table_number
},
'cum_amo': {
'str': 'Cum. amo.',
'type': 'formula',
'format': self.format_table_number
},
'value_residual': {
'str': u'Val. résiduelle',
'type': 'formula',
'format': self.format_table_number
},
}
category_datas_lst = data.get('category_datas_lst', [])
self.summary_column_info = {
'value': [],
'value_residual': [],
'salvage_value': [],
'amo_ant': [],
'amo_de_lan': [],
'cum_amo': [],
'val_nette': [],
}
for category_datas in category_datas_lst:
self.generate_report_category(category_datas)
self.row_pos += 1
self.generate_report_summary()
def setup_config(self):
self.row_pos = 5
self._set_default_format()
def _set_default_format(self):
self.sheet.set_default_row(20)
self.sheet.set_column('A:Z', None, self.format_default)
self.sheet.set_column('A:A', 40)
self.sheet.set_column('B:L', 20)
def generate_report_title(self):
company = self.env.user.company_id
company_logo = company.logo
company_logo_path = get_record_image_path(
record=company,
image=company_logo,
)
if company_logo_path:
self.sheet.insert_image(0, 0, company_logo_path)
self.sheet.merge_range(
'B2:K5',
u'Immobilisations et amortissements',
self.format_report_title)
def generate_report_general(self):
row_pos = self.row_pos
col_pos = 0
today = fields.Date.from_string(fields.Date.today())
formated_today_str = today.strftime("%d/%m/%Y")
created_by_header = u'Créé le : '
created_uid = self.object._context.get('uid', self.env.uid)
created_user = self.env['res.users'].browse(created_uid)
created_by_info = '{} par {}'.format(
formated_today_str, created_user.name)
self.sheet.write_rich_string(
row_pos, col_pos,
self.format_bold, created_by_header,
self.format_default, created_by_info
)
row_pos += 2
from_date_header = u'Début : '
from_date_dt = fields.Date.from_string(self.object.from_date)
from_date_str = from_date_dt.strftime("%d/%m/%Y")
self.sheet.write_rich_string(
row_pos, col_pos,
self.format_bold, from_date_header,
self.format_default, from_date_str
)
row_pos += 1
to_date_header = 'Fin : '
to_date_dt = fields.Date.from_string(self.object.to_date)
to_date_str = to_date_dt.strftime("%d/%m/%Y")
self.sheet.write_rich_string(
row_pos, col_pos,
self.format_bold, to_date_header,
self.format_default, to_date_str
)
self.row_pos = row_pos
def generate_report_category(self, category_datas):
row_pos = self.row_pos
col_pos = 0
category_name = category_datas.get('category_name', '')
self.sheet.write(row_pos, col_pos, category_name, self.format_table)
for i in range(1, 12):
col_pos = i
self.sheet.write(row_pos, col_pos, '', self.format_table)
row_pos += 1
column_labels = self.info_labels
for col_index, column in enumerate(self.table_columns, 0):
col_pos = col_index
label_dict = column_labels.get(column)
label_str = label_dict.get('str')
cell_format = self.format_table_header
self.sheet.write(row_pos, col_pos, label_str, cell_format)
row_pos += 1
category_data_lines = category_datas.get('lines', [])
category_data_lines_length = len(category_data_lines)
start_row_pos = row_pos
for index in range(category_data_lines_length + 1):
is_sub_summary_section = False
if index < category_data_lines_length:
line_data = category_data_lines[index]
else:
is_sub_summary_section = True
stop_row_pos = row_pos - 1
line_data = {
'name': 'Sous-total',
'value': '=SUM({}:{})',
'value_residual': '=SUM({}:{})',
'salvage_value': '=SUM({}:{})',
'amo_ant': '=SUM({}:{})',
'amo_de_lan': '=SUM({}:{})',
'cum_amo': '=SUM({}:{})',
'val_nette': '=SUM({}:{})',
}
for col_index, column in enumerate(self.table_columns, 0):
col_pos = col_index
cell_value = line_data.get(column, '')
if isinstance(cell_value, bool):
cell_value = cell_value and 'Oui' or 'Non'
cell_type = column_labels.get(column).get('type', '')
cell_format = column_labels.get(column).get(
'format', self.format_default)
need_to_write_summary_formula = \
is_sub_summary_section and cell_type == 'formula'
if is_sub_summary_section:
cell_format = self.format_table_bold
# Write formula
if need_to_write_summary_formula:
cell_format = self.format_table_number_bold
start_cell = xl_rowcol_to_cell(start_row_pos, col_pos)
stop_cell = xl_rowcol_to_cell(stop_row_pos, col_pos)
cell_formula_value = \
cell_value.format(start_cell, stop_cell)
self.sheet.write_formula(
row_pos, col_pos, cell_formula_value, cell_format)
# append cell to summary section info
self.summary_column_info[column].append(
xl_rowcol_to_cell(row_pos, col_pos)
)
else:
if column == 'date' and not is_sub_summary_section:
cell_format = self.format_table_date
cell_value = fields.Date.from_string(cell_value)
self.sheet.write(row_pos, col_pos, cell_value, cell_format)
row_pos += 1
self.row_pos = row_pos
def generate_report_summary(self):
row_pos = self.row_pos
summary_data = {
'name': u'Total général',
'value': '=SUM({})',
'value_residual': '=SUM({})',
'salvage_value': '=SUM({})',
'amo_ant': '=SUM({})',
'amo_de_lan': '=SUM({})',
'cum_amo': '=SUM({})',
'val_nette': '=SUM({})',
}
cell_format = self.format_table_header_dark_grey
for col_index, column in enumerate(self.table_columns, 0):
col_pos = col_index
cell_value = summary_data.get(column, '')
if '=SUM' in cell_value:
cell_format = self.format_table_number_bold_dark_grey
cell_formula_value = cell_value.format(
', '.join(self.summary_column_info[column])
)
self.sheet.write_formula(
row_pos, col_pos, cell_formula_value, cell_format)
else:
self.sheet.write(row_pos, col_pos, cell_value, cell_format)
row_pos += 1
self.row_pos = row_pos
def _define_formats(self, workbook):
# ---------------------------------------------------------------------
# Common
# ---------------------------------------------------------------------
format_config = {
'font_size': 10,
'valign': 'vcenter',
'text_wrap': True,
}
self.format_default = workbook.add_format(format_config)
format_bold = format_config.copy()
format_bold.update({
'bold': True,
})
self.format_bold = workbook.add_format(format_bold)
format_center = format_config.copy()
format_center.update({
'align': 'center',
})
self.format_center = workbook.add_format(format_center)
# ---------------------------------------------------------------------
# Report Title
# ---------------------------------------------------------------------
format_report_title = format_config.copy()
format_report_title.update({
'bold': True,
'align': 'center',
'font_size': 36,
})
self.format_report_title = workbook.add_format(format_report_title)
format_title_table = format_config.copy()
format_title_table.update({
'bold': True,
'align': 'center',
})
self.format_title_table = workbook.add_format(format_title_table)
# ---------------------------------------------------------------------
# Table format
# ---------------------------------------------------------------------
format_table = format_config.copy()
format_table.update({
'font_size': 11,
'bold': True,
'align': 'vcenter',
})
self.format_table = workbook.add_format(format_table)
self.format_table.set_bg_color('#0070c0')
self.format_table.set_font_color('#ffffff')
format_table_header = format_table.copy()
format_table_header.update({
'font_size': 10,
})
self.format_table_header = workbook.add_format(format_table_header)
self.format_table_header.set_bg_color('#d9d9d9')
self.format_table_header.set_font_color('#000000')
format_table_bold = format_table.copy()
format_table_bold.update({
'font_size': 10,
})
self.format_table_bold = workbook.add_format(format_table_bold)
self.format_table_bold.set_bg_color('#d9d9d9')
self.format_table_bold.set_font_color('#000000')
format_table_bold_total = format_table.copy()
format_table_bold_total.update({
'font_size': 11,
'align': 'right',
})
format_table_number = format_table.copy()
format_table_number.update({
'font_size': 10,
'bold': False,
})
self.format_table_number = workbook.add_format(
format_table_number)
self.format_table_number.set_num_format('#,##0.00')
format_table_number_bold = format_table.copy()
format_table_number_bold.update({
'font_size': 10,
})
self.format_table_number_bold = workbook.add_format(
format_table_number_bold)
self.format_table_number_bold.set_num_format('#,##0.00')
self.format_table_number_bold.set_bg_color('#d9d9d9')
self.format_table_number_bold.set_font_color('#000000')
format_table_date = format_config.copy()
format_table_date.update({
'num_format': 'dd/mm/yyyy',
'font_size': 10
})
self.format_table_date = workbook.add_format(format_table_date)
self.format_table_header_dark_grey = workbook.add_format(
format_table_header)
self.format_table_header_dark_grey.set_bg_color('#808080')
self.format_table_header_dark_grey.set_font_color('#000000')
self.format_table_number_bold_dark_grey = workbook.add_format(
format_table_number_bold)
self.format_table_number_bold_dark_grey.set_num_format('#,##0.00')
self.format_table_number_bold_dark_grey.set_bg_color('#808080')
self.format_table_number_bold_dark_grey.set_font_color('#000000')
ReportAccountAssetXlsx(
'report.report_account_asset_xlsx',
'account.asset.xlsx.wizard',
)
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<report
id="report_account_asset_xlsx"
model="account.asset.xlsx.wizard"
name="report_account_asset_xlsx"
file="report_account_asset_xlsx"
report_type="xlsx"
string="Account Asset Report"
/>
</odoo>
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_model_account_asset_xlsx_wizard,access_model_account_asset_xlsx_wizard,model_account_asset_xlsx_wizard,account.group_account_manager,1,1,1,1
# -*- coding: utf-8 -*-
# Copyright (C) 2016-Today: La Louve (<http://www.lalouve.net/>)
from . import account_asset_xlsx_wizard
# -*- coding: utf-8 -*-
# Copyright (C) 2016-Today: La Louve (<http://www.lalouve.net/>)
from openerp import api, fields, models
class AccountAssetXlsxWizard(models.TransientModel):
_name = 'account.asset.xlsx.wizard'
from_date = fields.Date(required=True)
to_date = fields.Date(required=True)
asset_category_ids = fields.Many2many(
comodel_name='account.asset.category',
string='Asset Categories'
)
asset_state = fields.Selection(
selection=[
('all', 'All assets'),
('open', 'Open only'),
],
string='Status',
default='all',
required=True
)
target_move = fields.Selection(
selection=[
('all', 'All moves'),
('posted', 'Posted moves'),
],
default='all'
)
@api.onchange('to_date')
def onchange_to_date(self):
if self.to_date:
self.from_date = self.to_date[:5] + '01-01'
else:
self.from_date = False
@api.multi
def export_report(self):
self.ensure_one()
datas = dict()
res = self.env['report'].get_action(self, "report_account_asset_xlsx")
datas['context'] = self._context
datas['category_datas_lst'] = self.get_category_datas()
res.update({
'datas': datas,
})
return res
@api.multi
def get_category_datas(self):
self.ensure_one()
process_datas = []
domain = []
if self.asset_category_ids:
domain.append(
('category_id', 'in', self.asset_category_ids.ids)
)
if self.asset_state and self.asset_state != 'all':
domain.append(
('state', '=', self.asset_state)
)
read_line_fields = [
'name',
'state',
'date',
'value',
'salvage_value',
'method',
'method_number',
'prorata'
]
categories = self.asset_category_ids and self.asset_category_ids or \
self.env['account.asset.category'].search([])
if categories:
category_datas = {
category: {
'account_asset_code': category.account_asset_id.code,
'category_name': category.name,
'lines': []
}
for category in categories
}
# Mapping selection values
fr_context = self._context.copy()
fr_context.update({'lang': 'fr_FR'})
selection_field_values = self.with_context(fr_context).env[
'account.asset.asset'].fields_get(
['state', 'method'], context=fr_context
)
account_assets = self.env['account.asset.asset'].search(
domain, order="category_id,id")
asset_state_dict = dict(
selection_field_values['state']['selection'])
asset_method_dict = dict(
selection_field_values['method']['selection'])
for asset in account_assets:
asset_category = asset.category_id
asset_data = asset.sudo().read(read_line_fields)
line_data = asset_data and asset_data[0] or {}
for column, value in line_data.items():
new_value = False
if column == 'state':
new_value = asset_state_dict.get(value, value)
elif column == 'method':
new_value = asset_method_dict.get(value, value)
if new_value:
line_data[column] = new_value
if line_data and asset_category:
account_amount_values = \
self.get_account_amount_values(asset)
having_account_amount = any(
value != 0 for value in account_amount_values.values()
)
if not having_account_amount:
continue
line_data.update(account_amount_values)
category_datas[asset_category]['lines'].append(line_data)
for category_data in category_datas.values():
if category_data.get('lines', []):
process_datas.append(category_data)
return process_datas
@api.multi
def get_account_amount_values(self, asset=False):
self.ensure_one()
account_amount_values = {}
# Significant for account move line value
sign = -1
if asset:
asset_category = asset.category_id
category_asset_depreciation_account = \
asset_category.account_depreciation_id
fixed_asset_account_type = self.env.ref(
'account.data_account_type_fixed_assets')
# Calculate history and the selected range account values
aml_period_domain = [
('move_id.asset_id', '=', asset.id),
('account_id', '=', category_asset_depreciation_account.id),
]
state_domain = []
if self.target_move == 'posted':
state_domain.append(
('move_id.state', '=', 'posted')
)
aml_period_domain += state_domain
read_fields = ['credit', 'debit']
aml_before_date_start = self.env['account.move.line'].search_read([
('date', '<', self.from_date),
] + aml_period_domain, fields=read_fields)
aml_in_range = self.env['account.move.line'].search_read([
('date', '>=', self.from_date),
('date', "<=", self.to_date),
] + aml_period_domain, fields=read_fields)
amount_before_date_start = sum(
[(l['credit'] - l['debit']) for l in aml_before_date_start]
)
amount_in_range = sum(
[(l['credit'] - l['debit']) for l in aml_in_range]
)
cum_amo = amount_in_range + amount_before_date_start
account_amount_values.update({
'amo_ant': amount_before_date_start * sign,
'amo_de_lan': amount_in_range * sign,
'cum_amo': cum_amo * sign,
'value_residual': asset.value - cum_amo,
})
return account_amount_values
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="view_account_asset_xlsx_wizard" model="ir.ui.view">
<field name="name">view.account.asset.xlsx.wizard</field>
<field name="model">account.asset.xlsx.wizard</field>
<field name="arch" type="xml">
<form string="Account Asset Xlsx Wizard">
<group col="4">
<field name="from_date" invisible="1"/>
<field name="to_date" />
<field name="asset_state" />
<field name="target_move" widget="radio"/>
</group>
<group>
<field name="asset_category_ids" options="{'no_create_edit': True, 'no_quick_create': True}"/>
</group>
<footer>
<button name="export_report" string="Export" type="object" class="btn btn-primary"/>
<button special="cancel" string="Cancel" class="btn btn-danger"/>
</footer>
</form>
</field>
</record>
<record id="action_account_asset_xlsx_wizard" model="ir.actions.act_window">
<field name="name">Export Account Asset Report</field>
<field name="res_model">account.asset.xlsx.wizard</field>
<field name="view_type">form</field>
<field name="target">new</field>
<field name="view_id" ref="view_account_asset_xlsx_wizard"/>
</record>
<menuitem
id="open_account_asset_xlsx_wizard"
action="action_account_asset_xlsx_wizard"
name="Asset Report Xlsx"
parent="account.account_reports_management_menu"
sequence="100"
/>
</odoo>
# -*- coding: utf-8 -*-
from . import report
from . import wizard
# -*- coding: utf-8 -*-
{
'name': 'Stock Inventory Xlsx',
'version': '9.0.1.0.0',
'category': 'Custom',
'summary': 'Stock Inventory Xlsx',
'author': 'La Louve',
'website': 'http://www.lalouve.net',
'depends': [
'report_xlsx',
'stock_account',
],
'data': [
'report/report_inventory.xml',
'wizard/stock_valuation_history_view.xml',
],
'installable': True,
}
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * stock_inventory_xlsx
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0c\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-01-15 03:33+0000\n"
"PO-Revision-Date: 2019-01-15 03:33+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: stock_inventory_xlsx
#: code:addons/stock_inventory_xlsx/report/report_inventory_xlsx.py:139
#, python-format
msgid "Total"
msgstr "Total"
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * stock_inventory_xlsx
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0c\n"
"Report-Msgid-Bugs-To: \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: stock_inventory_xlsx
#: model:ir.ui.view,arch_db:stock_inventory_xlsx.view_wizard_valuation_history_inherit
msgid "Excel"
msgstr ""
#. module: stock_inventory_xlsx
#: model:ir.actions.report.xml,name:stock_inventory_xlsx.report_stock_inventory_xlsx
msgid "Stock Inventory At Date"
msgstr ""
#. module: stock_inventory_xlsx
#: code:addons/stock_inventory_xlsx/report/report_inventory_xlsx.py:139
#, python-format
msgid "Total"
msgstr ""
#. module: stock_inventory_xlsx
#: model:ir.model,name:stock_inventory_xlsx.model_wizard_valuation_history
msgid "Wizard that opens the stock valuation history table"
msgstr ""
# -*- coding: utf-8 -*-
from . import report_inventory_xlsx
<?xml version="1.0" encoding="UTF-8" ?>
<openerp>
<data>
<report
id="report_stock_inventory_xlsx"
model="wizard.valuation.history"
name="stock_inventory_xlsx"
file="stock_inventory_xlsx"
report_type="xlsx"
string="Stock Inventory At Date"
/>
</data>
</openerp>
# -*- coding: utf-8 -*-
from collections import OrderedDict
from xlsxwriter.utility import xl_rowcol_to_cell
from openerp.addons.report_xlsx.report.report_xlsx import ReportXlsx
from openerp.api import Environment
from openerp import SUPERUSER_ID
from openerp import fields, _
class ReportStockInventoryXlsx(ReportXlsx):
def create_xlsx_report(self, ids, data, report):
self.env = Environment(self.env.cr, SUPERUSER_ID, self.env.context)
return super(ReportStockInventoryXlsx,
self).create_xlsx_report(ids, data, report)
def generate_xlsx_report(self, workbook, data, objects):
self.object = objects[0]
self._define_formats(workbook)
self.sheet = workbook.add_worksheet()
self.setup_config()
self.generate_report_title()
self.generate_report_general(data)
self.row_pos += 2
history_values_lst = data.get('history_values_lst', [])
self.generate_table_header()
self.write_history_data(history_values_lst)
def setup_config(self):
self.row_pos = 5
self._set_default_format()
self.info_labels = {
'internal_ref': {
'str': u"Référence",
'index': 1
},
'barcode': {
'str': 'Code barre',
'index': 2
},
'name': {
'str': 'Article',
'index': 3
},
'quantity': {
'str': u'Quantité',
'format': self.format_table_number,
'index': 4
},
'standard_price': {
'str': u"Coût",
'format': self.format_table_number,
'index': 5
},
'value': {
'str': u'Valeur',
'type': 'formula',
'format': self.format_table_number,
'index': 6,
}
}
# Get list of column key ordered by index
self.columns = OrderedDict(
sorted(self.info_labels.items(), key=lambda (k, v): v['index'])
).keys()
def _set_default_format(self):
self.sheet.set_default_row(20)
self.sheet.set_column('A:Z', None, self.format_default)
self.sheet.set_column('A:A', 30)
self.sheet.set_column('B:B', 20)
self.sheet.set_column('C:C', 50)
self.sheet.set_column('D:F', 20)
def generate_report_general(self, data):
row_pos = self.row_pos
col_pos = 0
print_date_str = data.get('print_date', '')
created_at_header = u'Créé le : '
self.sheet.write_rich_string(
row_pos, col_pos,
self.format_bold, created_at_header,
self.format_default, print_date_str
)
row_pos += 1
created_uid = self.object._context.get('uid', self.env.uid)
created_user = self.env['res.users'].browse(created_uid)
created_by_header = u'Créé par : '
self.sheet.write_rich_string(
row_pos, col_pos,
self.format_bold, created_by_header,
self.format_default, created_user.name
)
row_pos += 1
inventory_date_str = data.get('inventory_date', '')
inventory_at_header = u'Inventaire au : '
self.sheet.write_rich_string(
row_pos, col_pos,
self.format_bold, inventory_at_header,
self.format_default, inventory_date_str
)
row_pos += 1
self.row_pos = row_pos
def generate_report_title(self):
self.sheet.merge_range(
'B2:F5',
u'Inventaire à date',
self.format_report_title)
def generate_table_header(self):
row_pos = self.row_pos
cell_format = self.format_table_header
for col_pos, column in enumerate(self.columns):
label_str = self.info_labels.get(column, {}).get('str', '')
self.sheet.write(row_pos, col_pos, label_str, cell_format)
row_pos += 1
self.row_pos = row_pos
def write_history_data(self, history_values_lst):
row_pos = self.row_pos
start_row_pos = row_pos
stop_row_pos = row_pos
length = len(history_values_lst)
is_summary_section = False
for index in range(length + 1):
if index < length:
history_values = history_values_lst[index]
else:
is_summary_section = True
history_values = {
'internal_ref': _('Total'),
'barcode': '',
'name': '',
'quantity': '',
'standard_price': '',
'value': 'SUM({}:{})',
}
for col_pos, column in enumerate(self.columns):
cell_type = self.info_labels.get(column).get('type', '')
cell_format = self.info_labels.get(column).get(
'format', self.format_default)
cell_value = history_values.get(column, '')
if is_summary_section:
cell_format = self.format_table_header
if cell_type == 'formula':
cell_value = cell_value or '{}*{}'
start_cell = xl_rowcol_to_cell(row_pos, col_pos - 2)
stop_cell = xl_rowcol_to_cell(row_pos, col_pos - 1)
if is_summary_section:
cell_format = self.format_table_number_bold
start_cell = xl_rowcol_to_cell(start_row_pos, col_pos)
stop_cell = xl_rowcol_to_cell(stop_row_pos, col_pos)
cell_formula_value = cell_value.format(
start_cell, stop_cell)
self.sheet.write_formula(
row_pos, col_pos, cell_formula_value, cell_format)
else:
self.sheet.write(
row_pos, col_pos, cell_value, cell_format)
stop_row_pos = row_pos
row_pos += 1
self.row_pos = row_pos
def _define_formats(self, workbook):
# ---------------------------------------------------------------------
# Common
# ---------------------------------------------------------------------
format_config = {
'font_size': 10,
'valign': 'vcenter',
'text_wrap': True,
}
self.format_default = workbook.add_format(format_config)
format_bold = format_config.copy()
format_bold.update({
'bold': True,
})
self.format_bold = workbook.add_format(format_bold)
# ---------------------------------------------------------------------
# Report Title
# ---------------------------------------------------------------------
format_report_title = format_config.copy()
format_report_title.update({
'bold': True,
'align': 'center',
'font_size': 36,
})
self.format_report_title = workbook.add_format(format_report_title)
# ---------------------------------------------------------------------
# Table format
# ---------------------------------------------------------------------
format_table = format_config.copy()
format_table.update({
'font_size': 11,
'bold': True,
'align': 'vcenter',
})
self.format_table = workbook.add_format(format_table)
self.format_table.set_bg_color('#0070c0')
self.format_table.set_font_color('#ffffff')
format_table_header = format_table.copy()
format_table_header.update({
'font_size': 10,
})
self.format_table_header = workbook.add_format(format_table_header)
self.format_table_header.set_bg_color('#d9d9d9')
self.format_table_header.set_font_color('#000000')
format_table_number = format_table.copy()
format_table_number.update({
'font_size': 10,
'bold': False,
})
self.format_table_number = workbook.add_format(
format_table_number)
self.format_table_number.set_num_format('#,##0.0000')
format_table_number_bold = format_table.copy()
format_table_number_bold.update({
'font_size': 10,
})
self.format_table_number_bold = workbook.add_format(
format_table_number_bold)
self.format_table_number_bold.set_num_format('#,##0.0000')
self.format_table_number_bold.set_bg_color('#d9d9d9')
self.format_table_number_bold.set_font_color('#000000')
ReportStockInventoryXlsx(
'report.stock_inventory_xlsx',
'account.asset.xlsx.wizard',
)
# -*- coding: utf-8 -*-
from . import stock_valuation_history
# -*- coding: utf-8 -*-
from openerp import api, fields, models
class WizardValuationHistory(models.TransientModel):
_inherit = 'wizard.valuation.history'
@api.multi
def export_xlsx(self):
self.ensure_one()
fmt_datetime = "%d/%m/%Y %H:%M:%S"
user_tz = self._context.get('tz', self.env.user.tz) or 'UTC'
self_with_ctx = self.with_context(tz=user_tz)
inventory_dt = fields.Datetime.context_timestamp(
self_with_ctx, fields.Datetime.from_string(self.date)
)
today_dt = fields.Datetime.context_timestamp(
self_with_ctx, fields.Datetime.from_string(fields.Datetime.now())
)
inventory_dt_str = inventory_dt.strftime(fmt_datetime)
today_dt_str = today_dt.strftime(fmt_datetime)
datas = dict()
res = self.env['report'].get_action(self, "stock_inventory_xlsx")
datas['context'] = self._context
datas['history_values_lst'] = self.get_history_datas()
datas['inventory_date'] = inventory_dt_str
datas['print_date'] = today_dt_str
res.update({
'datas': datas,
})
return res
@api.multi
def get_history_datas(self):
self.ensure_one()
history_values_lst = []
date_str = self.date or fields.Datetime.now()
query = """
SELECT product_id, sum(quantity) AS quantity
FROM
(
(
SELECT sum(quant.qty) AS quantity,
stock_move.product_id AS product_id
FROM stock_quant AS quant
JOIN stock_quant_move_rel
ON stock_quant_move_rel.quant_id = quant.id
JOIN stock_move
ON stock_move.id = stock_quant_move_rel.move_id
JOIN stock_location dest_location
ON stock_move.location_dest_id = dest_location.id
JOIN stock_location source_location
ON stock_move.location_id = source_location.id
JOIN product_product product
ON stock_move.product_id = product.id
WHERE quant.qty > 0
AND product.active IS TRUE
AND stock_move.state = 'done'
AND dest_location.usage IN ( 'internal', 'transit' )
AND ( NOT ( source_location.company_id IS NULL
AND dest_location.company_id IS NULL )
OR source_location.company_id != dest_location.company_id
OR source_location.usage NOT IN ( 'internal', 'transit' )
)
AND stock_move.date <= %s
GROUP BY stock_move.product_id
)
UNION ALL
(
SELECT sum(-quant.qty) AS quantity,
stock_move.product_id AS product_id
FROM stock_quant AS quant
JOIN stock_quant_move_rel
ON stock_quant_move_rel.quant_id = quant.id
JOIN stock_move
ON stock_move.id = stock_quant_move_rel.move_id
JOIN stock_location source_location
ON stock_move.location_id = source_location.id
JOIN stock_location dest_location
ON stock_move.location_dest_id = dest_location.id
JOIN product_product product
ON stock_move.product_id = product.id
WHERE quant.qty > 0
AND product.active IS TRUE
AND stock_move.state = 'done'
AND source_location.usage IN ( 'internal', 'transit' )
AND ( NOT ( dest_location.company_id IS NULL
AND source_location.company_id IS NULL )
OR dest_location.company_id != source_location.company_id
OR dest_location.usage NOT IN ( 'internal', 'transit' )
)
AND stock_move.date <= %s
GROUP BY stock_move.product_id
)
) AS foo
GROUP BY product_id
"""
self.env.cr.execute(query, (date_str, date_str))
history_datas = self.env.cr.fetchall()
for history in history_datas:
product_id = int(history[0])
product_obj = self.env['product.product'].browse(product_id)
history_values_lst.append({
'internal_ref': product_obj.default_code or '',
'barcode': product_obj.barcode or '',
'name': product_obj.name,
'quantity': history[1],
'standard_price': product_obj.standard_price,
})
return history_values_lst
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_wizard_valuation_history_inherit" model="ir.ui.view">
<field name="name">Inventory at Date</field>
<field name="model">wizard.valuation.history</field>
<field name="inherit_id" ref="stock_account.view_wizard_valuation_history"/>
<field name="arch" type="xml">
<xpath expr="//footer/button[@name='open_table']" position="after">
<button name="export_xlsx" string="Excel" type="object" class="btn-success"/>
</xpath>
</field>
</record>
</data>
</openerp>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment