Commit 57044e23 by François C.

Merge branch 'maj_code_prod' into 'master'

Added missing directories and modified files to reflect actual prod. code

See merge request !1
parents eb41ec18 562b349f
...@@ -45,7 +45,7 @@ coverage.xml ...@@ -45,7 +45,7 @@ coverage.xml
# Translations # Translations
*.mo *.mo
*.pot # *.pot
# Django stuff: # Django stuff:
*.log *.log
......
# -*- 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
<?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>
# -*- coding: utf-8 -*-
from openerp import models, api, exceptions
from openerp import SUPERUSER_ID
@api.multi
def check_access_buttons(self):
"""
Check group current user to hide buttons
"""
presence_group = self.env.user.has_group(
'coop_membership.group_membership_bdm_presence')
lecture_group = self.env.user.has_group(
'coop_membership.group_membership_bdm_lecture')
saisie_group = self.env.user.has_group(
'coop_membership.group_membership_bdm_saisie')
deceased_group = self.env.user.has_group(
'coop_membership.group_membership_view_partner_deceased')
manager_group = self.env.user.has_group(
'coop_membership.group_membership_access_manager')
writer_group = self.env.user.has_group(
'coop_membership.group_membership_access_edit')
if self.env.user.id == SUPERUSER_ID:
return False
elif self._name == 'res.partner':
if presence_group and not (manager_group and writer_group):
return 'presence_group_partner'
if lecture_group and not deceased_group:
return 'lecture_group_partner'
if saisie_group:
return 'saisie_group_partner'
elif self._name == 'shift.shift':
if presence_group and not (manager_group and writer_group):
return 'presence_group_shift'
if lecture_group and not deceased_group:
return 'lecture_group_shift'
if saisie_group:
return 'saisie_group_shift'
elif self._name == "shift.leave":
if saisie_group:
return 'saisie_group_leave'
elif self._name == "shift.registration":
if saisie_group:
return 'saisie_group_registration'
elif self._name == "shift.template.registration.line":
if saisie_group:
return 'saisie_group_template_registration_line'
elif self._name == "shift.extension":
if saisie_group:
return 'saisie_group_extension'
else:
return False
models.BaseModel.check_access_buttons = check_access_buttons
# -*- coding: utf-8 -*-
from openerp import models, api, exceptions
from openerp import SUPERUSER_ID
@api.multi
def check_access_buttons(self):
"""
Check group current user to hide buttons
"""
presence_group = self.env.user.has_group(
'coop_membership.group_membership_bdm_presence')
lecture_group = self.env.user.has_group(
'coop_membership.group_membership_bdm_lecture')
saisie_group = self.env.user.has_group(
'coop_membership.group_membership_bdm_saisie')
deceased_group = self.env.user.has_group(
'coop_membership.group_membership_view_partner_deceased')
if self.env.user.id == SUPERUSER_ID:
return False
elif self._name == 'res.partner':
if saisie_group:
return 'saisie_group_partner'
if presence_group:
return 'presence_group_partner'
if lecture_group and not deceased_group:
return 'lecture_group_partner'
elif self._name == 'shift.shift':
if presence_group:
return 'presence_group_shift'
if lecture_group and not deceased_group:
return 'lecture_group_shift'
if saisie_group:
return 'saisie_group_shift'
elif self._name == "shift.leave":
if saisie_group:
return 'saisie_group_leave'
elif self._name == "shift.registration":
if saisie_group:
return 'saisie_group_registration'
elif self._name == "shift.template.registration.line":
if saisie_group:
return 'saisie_group_template_registration_line'
elif self._name == "shift.extension":
if saisie_group:
return 'saisie_group_extension'
else:
return False
models.BaseModel.check_access_buttons = check_access_buttons
...@@ -6,7 +6,13 @@ ...@@ -6,7 +6,13 @@
Adaptation pour corriger des fonctions""", Adaptation pour corriger des fonctions""",
'description': """ 'description': """
Recherche par num. de coop Recherche par num. de coop\n
Après une recherche, le champ perd le focus\n
Utilisation du pavé numérique du clavier sur le panier\n
Personnalisation de la popup d'erreur "codebarre non reconnu" :\n
- Faire clignoter la popup d'erreur quand le codebarre n'est pas reconnu
- Jouer le son d'erreur plusieurs fois
- Afficher dans la popup le dernier produit scanné
""", """,
'author': "fracolo", 'author': "fracolo",
...@@ -20,6 +26,7 @@ ...@@ -20,6 +26,7 @@
# any module necessary for this one to work correctly # any module necessary for this one to work correctly
'depends': ['base', 'point_of_sale'], 'depends': ['base', 'point_of_sale'],
'qweb': ['static/src/xml/qweb.xml'],
# 'qweb': ['static/src/xml/qweb.xml'], # 'qweb': ['static/src/xml/qweb.xml'],
# always loaded # always loaded
'data': [ 'data': [
......
.pos .clientlist-screen .client-picture {width: 192px !important; height: 192px !important;} .pos .clientlist-screen .client-picture {width: 192px !important; height: 192px !important;}
.pos .clientlist-screen .client-picture > img {width: 128px !important; height: 128px !important;} .pos .clientlist-screen .client-picture > img {width: 128px !important; height: 128px !important;}
.blink-popup-barcode {
background: #FF6961 !important;
}
.popup-barcode{
-webkit-transition: background 0.5s ease-in-out;
-ms-transition: background 0.5s ease-in-out;
transition: background 0.5s ease-in-out;
}
odoo.define('lacagette_custom_pos.DB', function(require) { odoo.define('lacagette_custom_pos.DB', function(require) {
"use strict"; "use strict";
var PosDB = require('point_of_sale.DB'); var PosDB = require('point_of_sale.DB');
PosDB.include({ PosDB.include({
_partner_search_string: function(partner){ _partner_search_string: function(partner){
var str = partner.name; var str = partner.name;
//Diacritric search //Diacritric search
try { try {
str += '|' + Diacritics.replace(partner.name) str += '|' + Diacritics.replace(partner.name)
} catch(e) { } catch(e) {
console.log(e) console.log(e)
} }
if(partner.barcode){ if(partner.barcode){
str += '|' + partner.barcode; str += '|' + partner.barcode;
} }
if(partner.barcode_base){ if(partner.barcode_base){
str += '|' + partner.barcode_base; str += '|' + partner.barcode_base;
} }
str = '' + partner.id + ':' + str.replace(':','') + '\n'; str = '' + partner.id + ':' + str.replace(':','') + '\n';
return str; return str;
}, }
});
/* Custom behavior on barcode error */
var popups = require('point_of_sale.popups');
var gui = require('point_of_sale.gui');
// Custom popup definition
var CustomErrorBarcodePopupWidget = popups.extend({
template:'CustomErrorBarcodePopupWidget',
show: function(options) {
this._super(options);
// Play the error sound every second
this.gui.play_sound('error');
var playSoundInterval = setInterval(() => {
this.gui.play_sound('error');
}, 1300)
// stop after 4s
setTimeout(function() {
clearInterval(playSoundInterval)
}, 3000)
}
}); });
gui.define_popup({name:'custom-error-barcode', widget: CustomErrorBarcodePopupWidget});
var screens = require('point_of_sale.screens');
screens.ScreenWidget.include({
// Redefine action on barcode error
barcode_error_action: function(code) {
var show_code;
if (code.code.length > 32) {
show_code = code.code.substring(0,29)+'...';
} else {
show_code = code.code;
}
// Only on products screen
if (this.gui.get_current_screen() == 'products') {
// Get last product scanned
var orderlines = this.pos.get_order().orderlines.models
var last_product_name = orderlines.length > 0
? orderlines[orderlines.length-1].product.display_name
: 'Panier vide'
// Display custom popum with options
this.gui.show_popup('custom-error-barcode', {
barcode: show_code,
last_product_name: last_product_name
});
var popup_barcode = $('.popup-barcode')
// Make popup blink
if (popup_barcode.length != 0) {
var backgroundInterval = setInterval(function(){
popup_barcode.toggleClass("blink-popup-barcode");
}, 750)
setTimeout(function() {
clearInterval(backgroundInterval)
popup_barcode.removeClass("blink-popup-barcode")
}, 5000)
}
} else {
this.gui.show_popup('error-barcode',show_code);
}
}
})
/* Make search input loose focus after 5s without a key press */
screens.ProductCategoriesWidget.include({
// Redefine init function of the widget handling research
init: function(parent, options){
var self = this;
this._super(parent,options);
this.product_type = options.product_type || 'all'; // 'all' | 'weightable'
this.onlyWeightable = options.onlyWeightable || false;
this.category = this.pos.root_category;
this.breadcrumb = [];
this.subcategories = [];
this.product_list_widget = options.product_list_widget || null;
this.category_cache = new screens.DomCache();
this.start_categ_id = this.pos.config.iface_start_categ_id ? this.pos.config.iface_start_categ_id[0] : 0;
this.set_category(this.pos.db.get_category_by_id(this.start_categ_id));
this.switch_category_handler = function(event){
self.set_category(self.pos.db.get_category_by_id(Number(this.dataset.categoryId)));
self.renderElement();
};
this.clear_search_handler = function(event){
self.clear_search();
};
var search_timeout = null;
var blur_timeout = null;
this.search_handler = function(event){
if(event.type == "keypress" || event.keyCode === 46 || event.keyCode === 8){
clearTimeout(search_timeout);
var searchbox = this;
search_timeout = setTimeout(function(){
self.perform_search(self.category, searchbox.value, event.which === 13);
},70);
// Add timeout: loose focus after 5s without a keypress
clearTimeout(blur_timeout)
blur_timeout = setTimeout(function() {
$('.searchbox input').blur()
}, 5000)
}
};
}
})
/* Enable keyboard numpad on products screen */
screens.ProductScreenWidget.include({
// Redefine init function to add en event listener on this screen
start: function(){
var self = this;
this.actionpad = new screens.ActionpadWidget(this,{});
this.actionpad.replace(this.$('.placeholder-ActionpadWidget'));
this.numpad = new screens.NumpadWidget(this,{});
this.numpad.replace(this.$('.placeholder-NumpadWidget'));
this.order_widget = new screens.OrderWidget(this,{
numpad_state: this.numpad.state,
});
this.order_widget.replace(this.$('.placeholder-OrderWidget'));
this.product_list_widget = new screens.ProductListWidget(this,{
click_product_action: function(product){ self.click_product(product); },
product_list: this.pos.db.get_product_by_category(0)
});
this.product_list_widget.replace(this.$('.placeholder-ProductListWidget'));
this.product_categories_widget = new screens.ProductCategoriesWidget(this,{
product_list_widget: this.product_list_widget,
});
this.product_categories_widget.replace(this.$('.placeholder-ProductCategoriesWidget'));
this.action_buttons = {};
var classes = [];
for (var i = 0; i < classes.length; i++) {
var classe = classes[i];
if ( !classe.condition || classe.condition.call(this) ) {
var widget = new classe.widget(this,{});
widget.appendTo(this.$('.control-buttons'));
this.action_buttons[classe.name] = widget;
}
}
if (_.size(this.action_buttons)) {
this.$('.control-buttons').removeClass('oe_hidden');
}
// Add listener on keypress
$(document).on("keypress", (e) => {
// Only on products screen & when not focused on searchbox
if (this.gui.get_current_screen() == 'products'
&& !$('.searchbox input').is(":focus")) {
if (e.which >= 48 && e.which <= 57 || e.which == 46) {
this.numpad.state.appendNewChar(e.key);
} else if (e.which == 45) {
try {
// setMinusSign is a custom method
this.numpad.state.setMinusSign();
} catch (e) {
console.log(e)
}
} else if (e.which == 43) {
try {
// setPlusSign is a custom method
this.numpad.state.setPlusSign();
} catch (e) {
console.log(e)
}
}
}
});
}
})
}); });
<?xml version="1.0" encoding="UTF-8"?>
<template>
<div t-name="CustomErrorBarcodePopupWidget">
<div class="modal-dialog">
<div class="popup popup-barcode">
<p class="title">Unknown Barcode
<br />
<span class='barcode'><t t-esc="widget.options.barcode" /></span>
</p>
<p class="body">
Le Point de Vente n'a pas pu trouver de produit associé
au code-barre scanné.
</p>
<p class="body last-product-scanned">
Dernier produit scanné :
<br />
<b><t t-esc="widget.options.last_product_name" /></b>
</p>
<div class="footer">
<div class="button cancel">
Ok
</div>
</div>
</div>
</div>
</div>
</template>
...@@ -6,8 +6,9 @@ ...@@ -6,8 +6,9 @@
Retrieve and display products information to help with future sales - via API or Odoo Menu""", Retrieve and display products information to help with future sales - via API or Odoo Menu""",
'description': """ 'description': """
Display on the product page buttons with Total Losses, Autoconsommation, Employees meals... Display on the product page buttons with total losses, autoconsommation,
Odoo system parameters need to be set: losses, autoconso and meals locations id employees meals & and nb of discounts in sales.\n
These Odoo system parameters need to be set: losses, autoconso and meals locations id.
""", """,
'author': "damien.moulard", 'author': "damien.moulard",
......
...@@ -29,6 +29,7 @@ class ProductTemplate(models.Model): ...@@ -29,6 +29,7 @@ class ProductTemplate(models.Model):
total_losses_qty = fields.Float(string="Total Pertes", compute='_compute_total_losses_qty') total_losses_qty = fields.Float(string="Total Pertes", compute='_compute_total_losses_qty')
total_autoconso_qty = fields.Float(string="Total Autoconsommation", compute='_compute_total_autoconso_qty') total_autoconso_qty = fields.Float(string="Total Autoconsommation", compute='_compute_total_autoconso_qty')
total_meals_qty = fields.Float(string="Total Repas Salariés", compute='_compute_total_meals_qty') total_meals_qty = fields.Float(string="Total Repas Salariés", compute='_compute_total_meals_qty')
total_discounts_qty = fields.Float(string="Total Remises", compute='_compute_total_discounts_qty')
sql_stock_move = """ sql_stock_move = """
SELECT sum(product_uom_qty) as qty SELECT sum(product_uom_qty) as qty
...@@ -41,7 +42,7 @@ class ProductTemplate(models.Model): ...@@ -41,7 +42,7 @@ class ProductTemplate(models.Model):
@api.multi @api.multi
def _compute_total_losses_qty(self): def _compute_total_losses_qty(self):
for product_t in self: for product_t in self:
qty = -1 qty = 0
try: try:
conf = self.env['ir.config_parameter'] conf = self.env['ir.config_parameter']
losses_loc_id = conf.get_param("lacagette_sales_helper.losses_location_id") losses_loc_id = conf.get_param("lacagette_sales_helper.losses_location_id")
...@@ -57,7 +58,7 @@ class ProductTemplate(models.Model): ...@@ -57,7 +58,7 @@ class ProductTemplate(models.Model):
@api.multi @api.multi
def _compute_total_autoconso_qty(self): def _compute_total_autoconso_qty(self):
for product_t in self: for product_t in self:
qty = -1 qty = 0
try: try:
conf = self.env['ir.config_parameter'] conf = self.env['ir.config_parameter']
autoconso_loc_id = conf.get_param("lacagette_sales_helper.autoconso_location_id") autoconso_loc_id = conf.get_param("lacagette_sales_helper.autoconso_location_id")
...@@ -73,7 +74,7 @@ class ProductTemplate(models.Model): ...@@ -73,7 +74,7 @@ class ProductTemplate(models.Model):
@api.multi @api.multi
def _compute_total_meals_qty(self): def _compute_total_meals_qty(self):
for product_t in self: for product_t in self:
qty = -1 qty = 0
try: try:
conf = self.env['ir.config_parameter'] conf = self.env['ir.config_parameter']
meals_loc_id = conf.get_param("lacagette_sales_helper.meals_location_id") meals_loc_id = conf.get_param("lacagette_sales_helper.meals_location_id")
...@@ -87,6 +88,29 @@ class ProductTemplate(models.Model): ...@@ -87,6 +88,29 @@ class ProductTemplate(models.Model):
product_t.total_meals_qty = qty product_t.total_meals_qty = qty
@api.multi @api.multi
def _compute_total_discounts_qty(self):
for product_t in self:
qty = 0
try:
sql = """
SELECT qty
FROM pos_order_line
WHERE product_id = (SELECT id FROM product_product WHERE product_tmpl_id = %s)
AND discount > 0
"""
self.env.cr.execute(sql , [product_t.id])
req_res = self.env.cr.dictfetchall()
if len(req_res) > 0:
for i in req_res:
qty += req_res[0]['qty']
qty = round(qty, 3)
except Exception as e:
print(str(e))
product_t.total_discounts_qty = qty
@api.multi
def view_losses_client_action(self): def view_losses_client_action(self):
return { return {
'res_model': 'lacagette.sales_helper', 'res_model': 'lacagette.sales_helper',
...@@ -112,3 +136,7 @@ class ProductTemplate(models.Model): ...@@ -112,3 +136,7 @@ class ProductTemplate(models.Model):
'tag': 'custom_product_meals', 'tag': 'custom_product_meals',
'target': 'new', 'target': 'new',
} }
@api.multi
def view_discounts_client_action(self):
return 0;
...@@ -42,4 +42,18 @@ ...@@ -42,4 +42,18 @@
</div> </div>
</field> </field>
</record> </record>
<record id="view_template_discount_history_form" model="ir.ui.view">
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_form_view"/>
<field name="arch" type="xml">
<div name="button_box" position="inside">
<button name="view_discounts_client_action" type="object"
icon="fa-dollar" class="oe_stat_button display_discounts_stats"
groups="stock.group_stock_manager"
string="">
<field name="total_discounts_qty" widget="statinfo"/>
</button>
</div>
</field>
</record>
</odoo> </odoo>
# -*- coding: utf-8 -*-
from . import models
# -*- coding: utf-8 -*-
{
'name': "La Cagette - Shifts",
'summary': """
Specific actions related to Shifts""",
'description': """
Actions currently implemented:
- Retrieve all shifts, counting for each of them only active registrations
""",
'author': "damien.moulard",
'website': "https://lacagette-coop.fr",
# Categories can be used to filter modules in modules listing
# Check https://github.com/odoo/odoo/blob/master/openerp/addons/base/module/module_data.xml
# for the full list
'category': 'Uncategorized',
'version': '0.0.1',
# any module necessary for this one to work correctly
'depends': ['base'],
# always loaded
'data': [
],
'installable': True,
}
# -*- coding: utf-8 -*-
from . import lacagette_shifts
# -*- coding: utf-8 -*-
from openerp import _, api, models, fields
class LaCagetteShifts(models.Model):
_name = "lacagette_shifts"
@api.model
def get_active_shifts(self):
""" Get shifts, counting active registrations to each of them"""
# Get registrations which:
# - belong to an active shift
# - are in an accepted state
# - begin before now
# - don't have an end date OR end after now
# Group by shift and count
sql = """SELECT str.shift_template_id, COUNT(str.shift_template_id) AS seats_active_registration
FROM shift_template st
LEFT JOIN shift_template_registration str ON str.shift_template_id = st.id
LEFT JOIN shift_template_registration_line strl ON strl.registration_id = str.id
WHERE active IS TRUE
AND str.state IN ('draft', 'open', 'done', 'replacing')
AND strl.date_begin < NOW()
AND (strl.date_end IS NULL OR strl.date_end >= NOW())
GROUP BY str.shift_template_id"""
self.env.cr.execute(sql)
res = self.env.cr.dictfetchall()
return (res)
# Translation of Odoo Server.
# This file contains the translation of the following modules:
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-09-07 14:40+0000\n"
"PO-Revision-Date: 2015-09-07 14:40+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"
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * account_tax_adjustments
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0c\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-04-05 16:21+0000\n"
"PO-Revision-Date: 2016-04-05 16:21+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_tax_adjustments
#: model:ir.ui.view,arch_db:account_tax_adjustments.tax_adjustments_wizard
msgid "Accounts"
msgstr ""
#. module: account_tax_adjustments
#: model:ir.model.fields,field_description:account_tax_adjustments.field_tax_adjustments_wizard_tax_id
msgid "Adjustment Tax"
msgstr ""
#. module: account_tax_adjustments
#: model:ir.model.fields,field_description:account_tax_adjustments.field_tax_adjustments_wizard_amount
msgid "Amount"
msgstr ""
#. module: account_tax_adjustments
#: model:ir.ui.view,arch_db:account_tax_adjustments.tax_adjustments_wizard
msgid "Cancel"
msgstr ""
#. module: account_tax_adjustments
#: model:ir.model.fields,field_description:account_tax_adjustments.field_tax_adjustments_wizard_company_currency_id
msgid "Company currency id"
msgstr ""
#. module: account_tax_adjustments
#: model:ir.ui.view,arch_db:account_tax_adjustments.tax_adjustments_wizard
msgid "Create and post move"
msgstr ""
#. module: account_tax_adjustments
#: model:ir.model.fields,field_description:account_tax_adjustments.field_tax_adjustments_wizard_create_uid
msgid "Created by"
msgstr ""
#. module: account_tax_adjustments
#: model:ir.model.fields,field_description:account_tax_adjustments.field_tax_adjustments_wizard_create_date
msgid "Created on"
msgstr ""
#. module: account_tax_adjustments
#: model:ir.model.fields,field_description:account_tax_adjustments.field_tax_adjustments_wizard_credit_account_id
msgid "Credit account"
msgstr ""
#. module: account_tax_adjustments
#: model:ir.model.fields,field_description:account_tax_adjustments.field_tax_adjustments_wizard_date
msgid "Date"
msgstr ""
#. module: account_tax_adjustments
#: model:ir.model.fields,field_description:account_tax_adjustments.field_tax_adjustments_wizard_debit_account_id
msgid "Debit account"
msgstr ""
#. module: account_tax_adjustments
#: model:ir.model.fields,field_description:account_tax_adjustments.field_tax_adjustments_wizard_display_name
msgid "Display Name"
msgstr ""
#. module: account_tax_adjustments
#: model:ir.model.fields,field_description:account_tax_adjustments.field_tax_adjustments_wizard_id
msgid "ID"
msgstr ""
#. module: account_tax_adjustments
#: model:ir.model.fields,field_description:account_tax_adjustments.field_tax_adjustments_wizard_journal_id
msgid "Journal"
msgstr ""
#. module: account_tax_adjustments
#: model:ir.model.fields,field_description:account_tax_adjustments.field_tax_adjustments_wizard_reason
msgid "Justification"
msgstr ""
#. module: account_tax_adjustments
#: model:ir.model.fields,field_description:account_tax_adjustments.field_tax_adjustments_wizard___last_update
msgid "Last Modified on"
msgstr ""
#. module: account_tax_adjustments
#: model:ir.model.fields,field_description:account_tax_adjustments.field_tax_adjustments_wizard_write_uid
msgid "Last Updated by"
msgstr ""
#. module: account_tax_adjustments
#: model:ir.model.fields,field_description:account_tax_adjustments.field_tax_adjustments_wizard_write_date
msgid "Last Updated on"
msgstr ""
#. module: account_tax_adjustments
#: model:ir.ui.view,arch_db:account_tax_adjustments.tax_adjustments_wizard
msgid "Options"
msgstr ""
#. module: account_tax_adjustments
#: model:ir.model,name:account_tax_adjustments.model_account_tax
msgid "Tax"
msgstr ""
#. module: account_tax_adjustments
#: model:ir.actions.act_window,name:account_tax_adjustments.tax_adjustments_form
#: model:ir.ui.menu,name:account_tax_adjustments.menu_action_account_form
msgid "Tax Adjustments"
msgstr ""
#. module: account_tax_adjustments
#: model:ir.model,name:account_tax_adjustments.model_tax_adjustments_wizard
msgid "Wizard for Tax Adjustments"
msgstr ""
#. module: account_tax_adjustments
#: model:ir.ui.view,arch_db:account_tax_adjustments.tax_adjustments_wizard
msgid "or"
msgstr ""
# Translation of Odoo Server.
# This file contains the translation of the following modules:
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-09-07 14:40+0000\n"
"PO-Revision-Date: 2015-09-07 14:40+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"
# Translation of Odoo Server.
# This file contains the translation of the following modules:
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-09-07 14:39+0000\n"
"PO-Revision-Date: 2015-09-07 14:39+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"
# Translation of Odoo Server.
# This file contains the translation of the following modules:
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-09-07 14:39+0000\n"
"PO-Revision-Date: 2015-09-07 14:39+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"
# Translation of Odoo Server.
# This file contains the translation of the following modules:
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-09-07 14:39+0000\n"
"PO-Revision-Date: 2015-09-07 14:39+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"
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * l10n_au
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-10-06 08:19+0000\n"
"PO-Revision-Date: 2015-10-06 08: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: l10n_au
#: model:ir.actions.client,name:l10n_au.action_client_l10n_au_menu
msgid "Open Account Dashboard Menu"
msgstr ""
# Translation of Odoo Server.
# This file contains the translation of the following modules:
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-09-07 14:55+0000\n"
"PO-Revision-Date: 2015-09-07 14:55+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"
# Translation of OpenERP Server.
# This file contains the translation of the following modules:
# * l10n_ca
#
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 6.0dev\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2010-08-02 21:08:34+0000\n"
"PO-Revision-Date: 2010-08-02 21:08:34+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: l10n_ca
#: model:account.account.type,name:l10n_ca.account_type_receivable
msgid "Receivable"
msgstr "Receivable"
#. module: l10n_ca
#: model:account.account.type,name:l10n_ca.acct_type_asset_view
msgid "Asset View"
msgstr "Asset View"
#. module: l10n_ca
#: model:ir.module.module,description:l10n_ca.module_meta_information
msgid "This is the module to manage the canadian accounting chart in OpenERP."
msgstr "This is the module to manage the canadian accounting chart in OpenERP."
#. module: l10n_ca
#: model:account.account.type,name:l10n_ca.acct_type_expense_view
msgid "Expense View"
msgstr "Expense View"
#. module: l10n_ca
#: constraint:account.account.template:0
msgid "Error ! You can not create recursive account templates."
msgstr "Error ! You can not create recursive account templates."
#. module: l10n_ca
#: model:account.account.type,name:l10n_ca.acct_type_income_view
msgid "Income View"
msgstr "Income View"
#. module: l10n_ca
#: model:ir.module.module,shortdesc:l10n_ca.module_meta_information
msgid "Canada - Chart of Accounts"
msgstr "Canada - Chart of Accounts"
#. module: l10n_ca
#: constraint:account.account.type:0
msgid "Error ! You can not create recursive types."
msgstr "Error ! You can not create recursive types."
#. module: l10n_ca
#: model:account.account.type,name:l10n_ca.account_type_tax
msgid "Tax"
msgstr "Tax"
#. module: l10n_ca
#: model:account.account.type,name:l10n_ca.account_type_cash
msgid "Cash"
msgstr "Cash"
#. module: l10n_ca
#: model:ir.actions.todo,note:l10n_ca.config_call_account_template_ca
msgid "Generate Chart of Accounts from a Chart Template. You will be asked to pass the name of the company, the chart template to follow, the no. of digits to generate the code for your accounts and Bank account, currency to create Journals. Thus,the pure copy of chart Template is generated.\n" " This is the same wizard that runs from Financial Management/Configuration/Financial Accounting/Financial Accounts/Generate Chart of Accounts from a Chart Template."
msgstr "Generate Chart of Accounts from a Chart Template. You will be asked to pass the name of the company, the chart template to follow, the no. of digits to generate the code for your accounts and Bank account, currency to create Journals. Thus,the pure copy of chart Template is generated.\n" " This is the same wizard that runs from Financial Management/Configuration/Financial Accounting/Financial Accounts/Generate Chart of Accounts from a Chart Template."
#. module: l10n_ca
#: model:account.account.type,name:l10n_ca.account_type_payable
msgid "Payable"
msgstr "Payable"
#. module: l10n_ca
#: model:account.account.type,name:l10n_ca.account_type_asset
msgid "Asset"
msgstr "Asset"
#. module: l10n_ca
#: model:account.account.type,name:l10n_ca.account_type_equity
msgid "Equity"
msgstr "Equity"
#. module: l10n_ca
#: constraint:account.tax.code.template:0
msgid "Error ! You can not create recursive Tax Codes."
msgstr "Error ! You can not create recursive Tax Codes."
#. module: l10n_ca
#: model:account.account.type,name:l10n_ca.acct_type_liability_view
msgid "Liability View"
msgstr "Liability View"
#. module: l10n_ca
#: model:account.account.type,name:l10n_ca.account_type_expense
msgid "Expense"
msgstr "Expense"
#. module: l10n_ca
#: model:account.account.type,name:l10n_ca.account_type_income
msgid "Income"
msgstr "Income"
#. module: l10n_ca
#: model:account.account.type,name:l10n_ca.account_type_view
msgid "View"
msgstr "View"
# Translation of Odoo Server.
# This file contains the translation of the following modules:
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-09-07 14:55+0000\n"
"PO-Revision-Date: 2015-09-07 14:55+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"
# Translation of Odoo Server.
# This file contains the translation of the following modules:
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-09-07 14:55+0000\n"
"PO-Revision-Date: 2015-09-07 14:55+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"
# Translation of Odoo Server.
# This file contains the translation of the following modules:
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-09-07 14:55+0000\n"
"PO-Revision-Date: 2015-09-07 14:55+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"
# Translation of Odoo Server.
# This file contains the translation of the following modules:
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-09-07 14:55+0000\n"
"PO-Revision-Date: 2015-09-07 14:55+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"
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * l10n_et
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-09-18 08:19+0000\n"
"PO-Revision-Date: 2015-09-18 08: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: l10n_et
#: model:ir.ui.menu,name:l10n_et.account_reports_et_statements_menu
msgid "Ethiopian Statements"
msgstr ""
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * l10n_fr_hr_payroll
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-09-21 09:27+0000\n"
"PO-Revision-Date: 2015-09-21 09: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: l10n_fr_hr_payroll
#: model:ir.ui.view,arch_db:l10n_fr_hr_payroll.report_l10nfrfichepaye
msgid "<span>Matricule :</span><br/>\n"
" <span>N° s.s :</span><br/>\n"
" <span>Emploi :</span><br/>\n"
" <span>Qualif :</span><br/>\n"
" <span>Niveau :</span><br/>\n"
" <span>Coef :</span><br/>\n"
" <span>Entrée :</span><br/>\n"
" <span>Sortie :</span><br/>\n"
" <span>ORG. S.S :</span>"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.ui.view,arch_db:l10n_fr_hr_payroll.report_l10nfrfichepaye
msgid "<strong>Mode de réglement</strong> :"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.ui.view,arch_db:l10n_fr_hr_payroll.report_l10nfrfichepaye
msgid "<strong>Net à payer </strong>:"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.ui.view,arch_db:l10n_fr_hr_payroll.report_l10nfrfichepaye
msgid "<strong>Payé</strong>"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.ui.view,arch_db:l10n_fr_hr_payroll.report_l10nfrfichepaye
msgid "<strong>Total Charges Patronales</strong> :"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.ui.view,arch_db:l10n_fr_hr_payroll.report_l10nfrfichepaye
msgid "APE:"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.ui.view,arch_db:l10n_fr_hr_payroll.report_l10nfrfichepaye
msgid "Bulletin de paie"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.ui.view,arch_db:l10n_fr_hr_payroll.report_l10nfrfichepaye
msgid "Code"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.model.fields,field_description:l10n_fr_hr_payroll.field_hr_contract_coef
msgid "Coefficient"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.model,name:l10n_fr_hr_payroll.model_res_company
msgid "Companies"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.model,name:l10n_fr_hr_payroll.model_hr_contract
msgid "Contract"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.model.fields,field_description:l10n_fr_hr_payroll.field_res_company_conv_coll
msgid "Convention collective"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.model.fields,field_description:l10n_fr_hr_payroll.field_res_company_cotisation_prevoyance
msgid "Cotisation Patronale Prevoyance"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.ui.view,arch_db:l10n_fr_hr_payroll.report_l10nfrfichepaye
msgid "Coût Global Salarié"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.ui.view,arch_db:l10n_fr_hr_payroll.report_l10nfrfichepaye
msgid "DANS VOTRE INTERET ET POUR VOUS AIDER A FAIRE VALOIR VOS DROITS, CONSERVEZ CE \n"
"BULLETIN DE PAIE SANS LIMITATION DE DUREE"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.model.fields,field_description:l10n_fr_hr_payroll.field_report_l10n_fr_hr_payroll_report_l10nfrfichepaye_display_name
msgid "Display Name"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.ui.view,arch_db:l10n_fr_hr_payroll.report_l10nfrfichepaye
msgid "Désignation"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.actions.report.xml,name:l10n_fr_hr_payroll.action_report_report_l10nfrfichepaye
msgid "Fiche de paye"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:hr.holidays.status,name:l10n_fr_hr_payroll.holiday_status_heures_sup
msgid "Heures Supplementaires"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.model.fields,field_description:l10n_fr_hr_payroll.field_report_l10n_fr_hr_payroll_report_l10nfrfichepaye_id
msgid "ID"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.model.fields,field_description:l10n_fr_hr_payroll.field_report_l10n_fr_hr_payroll_report_l10nfrfichepaye___last_update
msgid "Last Modified on"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.model.fields,field_description:l10n_fr_hr_payroll.field_hr_payslip_payment_mode
msgid "Mode de paiement"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.ui.view,arch_db:l10n_fr_hr_payroll.report_l10nfrfichepaye
msgid "Montant"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.ui.view,arch_db:l10n_fr_hr_payroll.report_l10nfrfichepaye
msgid "Montant Charges Patronales"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.ui.view,arch_db:l10n_fr_hr_payroll.report_l10nfrfichepaye
msgid "Net Imposable"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.model.fields,field_description:l10n_fr_hr_payroll.field_hr_contract_niveau
msgid "Niveau"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.model.fields,field_description:l10n_fr_hr_payroll.field_res_company_nombre_employes
msgid "Nombre d'employes"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.model.fields,field_description:l10n_fr_hr_payroll.field_res_company_org_ss
msgid "Organisme de securite sociale"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.ui.view,arch_db:l10n_fr_hr_payroll.res_company_form_l10n_fr_payroll
msgid "Paie"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.ui.view,arch_db:l10n_fr_hr_payroll.report_l10nfrfichepaye
msgid "Paie du"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.model,name:l10n_fr_hr_payroll.model_hr_payslip
msgid "Pay Slip"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.model.fields,field_description:l10n_fr_hr_payroll.field_res_company_plafond_secu
msgid "Plafond de la Securite Sociale"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.ui.view,arch_db:l10n_fr_hr_payroll.report_l10nfrfichepaye
msgid "Plafond s.s."
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.model.fields,field_description:l10n_fr_hr_payroll.field_hr_contract_qualif
msgid "Qualification"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.ui.view,arch_db:l10n_fr_hr_payroll.report_l10nfrfichepaye
msgid "Quantité / Base"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.ui.view,arch_db:l10n_fr_hr_payroll.report_l10nfrfichepaye
msgid "SIRET:"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.ui.view,arch_db:l10n_fr_hr_payroll.report_l10nfrfichepaye
msgid "Salaire Brut"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.ui.view,arch_db:l10n_fr_hr_payroll.report_l10nfrfichepaye
msgid "Taux"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.ui.view,arch_db:l10n_fr_hr_payroll.report_l10nfrfichepaye
msgid "Taux Charges Patronales"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.ui.view,arch_db:l10n_fr_hr_payroll.report_l10nfrfichepaye
msgid "Total Charges Salariales"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.ui.view,arch_db:l10n_fr_hr_payroll.report_l10nfrfichepaye
msgid "au"
msgstr ""
#. module: l10n_fr_hr_payroll
#: model:ir.model,name:l10n_fr_hr_payroll.model_report_l10n_fr_hr_payroll_report_l10nfrfichepaye
msgid "report.l10n_fr_hr_payroll.report_l10nfrfichepaye"
msgstr ""
# Translation of Odoo Server.
# This file contains the translation of the following modules:
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-09-07 14:55+0000\n"
"PO-Revision-Date: 2015-09-07 14:55+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"
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * l10n_hu
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-09-18 08:19+0000\n"
"PO-Revision-Date: 2015-09-18 08: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: l10n_hu
#: model:ir.ui.menu,name:l10n_hu.account_reports_hu_statements_menu
msgid "Hungarian Statements"
msgstr ""
# Translation of Odoo Server.
# This file contains the translation of the following modules:
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-09-07 14:55+0000\n"
"PO-Revision-Date: 2015-09-07 14:55+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"
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * l10n_nz
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-10-09 08:19+0000\n"
"PO-Revision-Date: 2015-10-09 08: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: l10n_nz
#: model:ir.actions.client,name:l10n_nz.action_client_l10n_nz_menu
msgid "Open Account Dashboard Menu"
msgstr ""
# Translation of Odoo Server.
# This file contains the translation of the following modules:
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-09-07 14:56+0000\n"
"PO-Revision-Date: 2015-09-07 14:56+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"
# Translation of Odoo Server.
# This file contains the translation of the following modules:
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-09-07 14:40+0000\n"
"PO-Revision-Date: 2015-09-07 14:40+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"
#
set meta-flag on
set convert-meta off
set input-meta on
set output-meta on
set show-all-if-ambiguous on
set visible-stats on
set bell-style none
# set bell-style visible
#"\M-k": kill-whole-line
#----------------------------------------------------------
# arrows left/right/up/down
"\e[C": forward-char
"\e[D": backward-char
"\e[A": previous-history
"\e[B": next-history
# ---------------------------------------------------------
# pgup/pgdn
"\e[6~": history-search-forward
"\e[5~": history-search-backward
#----------------------------------------------------------
# insert,delete
#"\e[2~": quoted-insert
"\e[3~": delete-char
# esc+delete, esc+backspace
"\e\e[3~": kill-word
"\e\C-h": backward-kill-word
#----------------------------------------------------------
# ctrl left/right (rxvt)
"\eOc": forward-word
"\eOd": backward-word
# ctrl left/right (xterm)
"\e[1;5C": forward-word
"\e[1;5D": backward-word
# ctrl left/right (unknown)
#"\e[5C": forward-word
#"\e[5D": backward-word
#"\e\e[C": forward-word
#"\e\e[D": backward-word
# ---------------------------------------------------------
# home/end (linux console)
"\e[1~": beginning-of-line
"\e[4~": end-of-line
# home/end (rxvt)
"\e[7~": beginning-of-line
"\e[8~": end-of-line
# home/end (xterm, freebsd console)
"\e[H": beginning-of-line
"\e[F": end-of-line
# home/end (non RH/Debian xterm, unknown)
"\eOH": beginning-of-line
"\eOF": end-of-line
"\eOw": end-of-line
set all&
set autoindent
set backspace=2
set nobackup
set nocompatible
set noerrorbells
set noexpandtab
set expandtab
set number
set hidden
set history=500
set hlsearch
set ignorecase
set modeline
set ruler
set shiftwidth=4
set scrolloff=5
set showcmd
set showmode
set tabstop=4
set textwidth=0
set visualbell
set t_vb=
set wrap
set list
set listchars=tab:~.,trail:.,extends:>,precedes:<
set viminfo="NONE"
# Translation of Odoo Server.
# This file contains the translation of the following modules:
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-09-07 14:41+0000\n"
"PO-Revision-Date: 2015-09-07 14:41+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"
# Translation of Odoo Server.
# This file contains the translation of the following modules:
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-09-07 14:41+0000\n"
"PO-Revision-Date: 2015-09-07 14:41+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"
{
"directory": "static/lib/"
}
repo: 076b192d0d8ab2b92d1dbcfa3da055382f30eaea
node: 7ee0bc7b4e9138f485cdc9ec791961d8ef452f17
branch: default
latesttag: 0.7
latesttagdistance: 11
# Translation of Odoo Server.
# This file contains the translation of the following modules:
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-09-07 14:41+0000\n"
"PO-Revision-Date: 2015-09-07 14:41+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"
# Translation of Odoo Server.
# This file contains the translation of the following modules:
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 9.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2015-09-07 14:41+0000\n"
"PO-Revision-Date: 2015-09-07 14:41+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"
# -*- encoding: utf-8 -*-
##############################################################################
#
# Sale - Food Module for Odoo
# Copyright (C) 2012-Today GRAP (http://www.grap.coop)
# @author Julien WESTE
# @author Sylvain LE GAL (https://twitter.com/legalsylvain)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from . import model
from . import report
# -*- coding: utf-8 -*-
##############################################################################
#
# Sale - Food Module for Odoo
# Copyright (C) 2012-Today GRAP (http://www.grap.coop)
# @author Julien WESTE
# @author Sylvain LE GAL (https://twitter.com/legalsylvain)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': 'Supercafoutch Price Tag',
'version': '9.0.1.0.1',
'category': 'Custom',
'description': """
Functionnalities
- Showing a new tab `Food Informations` on product form view.
- Default price tag for products with its management by user's right.
""",
'author': 'GRAP,'
'Akretion - Julien WESTE - original',
'website': 'http://www.grap.coop',
'license': 'AGPL-3',
'depends': [
'product',
'product_to_print',
'report',
'l10n_fr_department',
'purchase_package_qty',
],
'data': [
'security/res_groups.yml',
'security/ir.model.access.csv',
'data/ir_actions_report_xml.yml',
'data/report_paperformat.xml',
'data/pricetag_model.xml',
'data/product_category_print.xml',
'report/coop_custom_product_report.xml',
'report/report_pricetag.xml',
'views/view_product_label.xml',
'views/view_product_product.xml',
'views/view_product_template.xml',
'views/view_product_uom_categ.xml',
'views/action.xml',
'views/menu.xml',
],
'demo': [
'demo/res_groups.yml',
],
'css': [
'static/src/css/pricetag.css',
],
}
-
I remove report_product_label on button "Print"
-
!python {model: ir.actions.report.xml}: |
report_product_label_id = self.search(cr, uid, [('report_name', '=', 'product.report_productlabel')])
report_product_label = self.browse(cr, uid, report_product_label_id[0])
if report_product_label and report_product_label.ir_values_id:
report_product_label.unlink_action()
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="product_to_print.pricetag_model_default" model="pricetag.model">
<field name="pricetag_paperformat_id" ref="bulk_product_pricetag.paperformat_pricetag"/>
<field name="report_model">bulk_product_pricetag.report_pricetag</field>
</record>
</odoo>
<?xml version="1.0"?>
<!--
Copyright (C) 2016-Today: La Louve (<http://www.lalouve.net/>)
@author: Julien Weste
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-->
<odoo>
<record model="product.category.print" id="demo_category">
<field name="name">Default Category</field>
<field name="field_ids" eval="[(4, ref('product.field_product_product_name')),(4, ref('product.field_product_product_list_price'))]" />
<field name="pricetag_model_id" ref="product_to_print.pricetag_model_default"/>
</record>
</odoo>
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="paperformat_pricetag" model="report.paperformat">
<field name="name">Default pricetag paper</field>
<field name="default" eval="True" />
<field name="format">A4</field>
<field name="page_height">0</field>
<field name="page_width">0</field>
<field name="orientation">Portrait</field>
<field name="margin_top">8</field>
<field name="margin_bottom">1</field>
<field name="margin_left">3</field>
<field name="margin_right">2</field>
<field name="header_line" eval="False" />
<field name="header_spacing">0</field>
<field name="dpi">2400</field>
</record>
</odoo>
\ No newline at end of file
# -*- encoding: utf-8 -*-
##############################################################################
#
# Sale - Food Module for Odoo
# Copyright (C) 2012-Today GRAP (http://www.grap.coop)
# @author Julien WESTE
# @author Sylvain LE GAL (https://twitter.com/legalsylvain)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
- !record {model: res.groups, id: group_food_manager}:
users:
- base.user_root
- !record {model: res.groups, id: base.group_sale_manager}:
users:
- base.user_root
# -*- coding: utf-8 -*-
##############################################################################
#
# Sale - Food Module for Odoo
# Copyright (C) 2012-Today GRAP (http://www.grap.coop)
# @author Julien WESTE
# @author Sylvain LE GAL (https://twitter.com/legalsylvain)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from . import product_label
from . import product_template
from . import product_uom_categ
# -*- encoding: utf-8 -*-
##############################################################################
#
# Sale - Food Module for Odoo
# Copyright (C) 2012-Today GRAP (http://www.grap.coop)
# Copyright (C) 2016-Today La Louve (http://www.lalouve.net)
# @author Julien WESTE
# @author Sylvain LE GAL (https://twitter.com/legalsylvain)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import tools, fields, models, api
class ProductLabel(models.Model):
_name = 'product.label'
# Columns Section
code = fields.Char(string='Code', required=True)
name = fields.Char(string='Name', required=True)
active = fields.Boolean(string='Active', default=True)
company_id = fields.Many2one(string='Company', comodel_name='res.company')
website = fields.Char(string='Website')
note = fields.Text(string='Note')
# image: all image fields are base64 encoded and PIL-supported
image = fields.Binary(
string='Image', attachment=True, help="This field holds the image"
" used as image for the label, limited to 1024x1024px.")
image_medium = fields.Binary(
string='Medium-sized image', attachment=True, help="Medium-sized"
" image of the product. It is automatically resized as a 128x128px"
" image, with aspect ratio preserved, only when the image exceeds one"
" of those sizes. Use this field in form views or some kanban views.")
image_small = fields.Binary(
string='Small-sized image', attachment=True, help="Small-sized image"
" of the product. It is automatically resized as a 64x64px image,"
" with aspect ratio preserved. Use this field anywhere a small image"
" is required.")
# Overload Section
@api.model
def create(self, vals):
tools.image_resize_images(vals)
return super(ProductLabel, self).create(vals)
@api.multi
def write(self, vals):
tools.image_resize_images(vals)
return super(ProductLabel, self).write(vals)
# -*- coding: utf-8 -*-
##############################################################################
#
# Sale - Food Module for Odoo
# Copyright (C) 2012-Today GRAP (http://www.grap.coop)
# @author Julien WESTE
# @author Sylvain LE GAL (https://twitter.com/legalsylvain)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import api, fields, models, _
from openerp.exceptions import UserError
class ProductTemplate(models.Model):
_inherit = 'product.template'
# Constant Section
_FRESH_CATEGORY_KEYS = [
('extra', 'Extra'),
('1', 'Category I'),
('2', 'Category II'),
('3', 'Category III'),
]
_FRESH_RANGE_KEYS = [
('1', '1 - Fresh'),
('2', '2 - Canned'),
('3', '3 - Frozen'),
('4', '4 - Uncooked and Ready to Use'),
('5', '5 - Cooked and Ready to Use'),
('6', '6 - Dehydrated and Shelf'),
]
@api.depends('farming_method', 'other_information')
@api.multi
def _compute_pricetag_coopinfos(self):
for pt in self:
tmp = ''
if pt.other_information:
tmp = pt.other_information
if pt.farming_method:
tmp = pt.farming_method + \
(' - ' + tmp if tmp else '')
pt.pricetag_coopinfos = tmp
@api.depends(
'rack_instruction', 'rack_location', 'rack_number_of_packages',
'default_seller_id')
@api.multi
def _compute_pricetag_rackinfos(self):
for pt in self:
tmp = ''
if pt.rack_instruction:
tmp = pt.rack_instruction
if pt.rack_location:
tmp = pt.rack_location + \
(' - ' + tmp if tmp else '')
if pt.rack_number_of_packages:
tmp = pt.rack_number_of_packages + \
(' - ' + tmp if tmp else '')
if pt.default_seller_id.package_qty:
tmp = str(pt.default_seller_id.package_qty) + \
(' - ' + tmp if tmp else '')
pt.pricetag_rackinfos = tmp
# Columns section
label_ids = fields.Many2many(
string='Labels', comodel_name='product.label',
relation='product_label_product_rel',
column_1='product_id', column_2='label_id')
expiration_date_days = fields.Integer(
string='Expiration Date (Days)', help="Field used to compute the"
" expiration date. (Number of days after packaging the product)")
expiration_comsumption_days = fields.Integer(
string='Expiration Consumption (Days)')
ingredients = fields.Text(string='Ingredients')
extra_note_bizerba_pricetag_1 = fields.Char(
string='Extra Note printed on Bizerba Pricetags #1')
extra_note_bizerba_pricetag_2 = fields.Char(
string='Extra Note printed on Bizerba Pricetags #2')
is_mercuriale = fields.Boolean(
'Mercuriale Product', help="A product in mercuriale has price"
" that changes very regularly.")
weight_net = fields.Float('Net Weight', default=0)
price_volume = fields.Char(
compute='_compute_price_volume', string='Price by liter')
price_weight_net = fields.Char(
compute='_compute_price_weight_net', string='Price by kg')
country_id = fields.Many2one(
string='Origin Country', comodel_name='res.country',
help="Country of production of the product")
department_id = fields.Many2one(
string='Origin Department', comodel_name='res.country.department',
help="Department of production of the product")
origin_description = fields.Char(
string='Origin Complement',
help="Production location complementary information",)
maker_description = fields.Char(string='Maker')
pricetag_origin = fields.Char(
compute='_compute_pricetag_origin', string='Text about origin')
fresh_category = fields.Selection(
_FRESH_CATEGORY_KEYS, string='Category for Fresh Product',
help="Extra - Hight Quality : product without default ;\n"
"Quality I - Good Quality : Product with little defaults ;\n"
"Quality II - Normal Quality : Product with default ;\n"
"Quality III - Bad Quality : Use this option only in"
" specific situation.")
fresh_range = fields.Selection(
_FRESH_RANGE_KEYS, 'Range for Fresh Product')
extra_food_info = fields.Char(
compute='_compute_extra_food_info',
string='Extra information for invoices')
rack_instruction = fields.Char(
"Rack Instruction", help="""For example, the number of packages that
should be stored on the rack""")
rack_location = fields.Char(
"Rack Location", help="""The name or place of the rack""")
rack_number_of_packages = fields.Char(
"Number of packages on the rack")
farming_method = fields.Char(
"Farming Method", help="""Organic Label""")
other_information = fields.Char("Other Information")
pricetag_rackinfos = fields.Char(
compute=_compute_pricetag_rackinfos, string='Coop rack fields')
pricetag_coopinfos = fields.Char(
compute=_compute_pricetag_coopinfos, string='Coop custom fields')
category_print_id = fields.Many2one(
comodel_name='product.category.print', string='Print Category')
# Compute Section
@api.depends('list_price', 'volume')
@api.multi
def _compute_price_volume(self):
"""Return the price by liter"""
for pt in self:
if pt.list_price and pt.volume:
pt.price_volume = "%.2f" % round(pt.list_price / pt.volume, 2)
else:
pt.price_volume = ""
@api.depends('list_price', 'weight_net')
@api.multi
def _compute_price_weight_net(self):
"""Return the price by kg"""
for pt in self:
if pt.list_price and pt.weight_net:
pt.price_weight_net = "%.2f" % round(
pt.list_price / pt.weight_net, 2)
else:
pt.price_weight_net = ""
@api.depends('origin_description', 'department_id', 'country_id')
@api.multi
def _compute_pricetag_origin(self):
for pt in self:
tmp = ''
if pt.origin_description:
tmp = pt.origin_description
if pt.department_id:
tmp = pt.department_id.name + \
(' - ' + tmp if tmp else '')
if pt.country_id:
tmp = pt.country_id.name.upper() + \
(' - ' + tmp if tmp else '')
if pt.maker_description:
tmp = (tmp and (tmp + ' - ') or '') + pt.maker_description
pt.pricetag_origin = tmp
@api.depends('fresh_category', 'fresh_range')
@api.multi
def _compute_extra_food_info(self):
"""Return extra information about food for legal documents"""
for pt in self:
tmp = ''
if pt.fresh_range:
tmp += _(' - Range: ') + pt.fresh_range
if pt.fresh_category:
tmp += _(" - Category: ") + pt.fresh_category
pt.extra_food_info = tmp
# Constraints section
@api.multi
@api.constrains('department_id', 'country_id')
def _check_origin_department_country(self):
for pt in self:
if pt.department_id.country_id and \
pt.department_id.country_id.id != \
pt.country_id.id:
raise UserError(
_("Error ! Department %s doesn't belong to %s.")
% (pt.department_id.name, pt.country_id.name))
# Views section
@api.multi
@api.onchange('department_id')
def onchange_department_id(self):
for pt in self:
if pt.department_id:
pt.country_id = pt.department_id.country_id
else:
pt.country_id = False
@api.multi
@api.onchange('country_id')
def onchange_country_id(self):
for pt in self:
if pt.country_id:
pt.department_id = False
# -*- coding: utf-8 -*-
##############################################################################
#
# Sale - Food Module for Odoo
# Copyright (C) 2012-Today GRAP (http://www.grap.coop)
# @author Julien WESTE
# @author Sylvain LE GAL (https://twitter.com/legalsylvain)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import fields, models
class ProductUomCateg(models.Model):
_inherit = 'product.uom.categ'
pricetag_printable = fields.Boolean('Print on Price Tag')
# -*- coding: utf-8 -*-
##############################################################################
#
# Sale - Food Module for Odoo
# Copyright (C) 2012-Today GRAP (http://www.grap.coop)
# @author Julien WESTE
# @author Sylvain LE GAL (https://twitter.com/legalsylvain)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from . import report_pricetag
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- QWeb Reports -->
<report
id="pricetag"
model="report.pricetag"
string="Pricetags"
report_type="qweb-pdf"
name="bulk_product_pricetag.report_pricetag"
file="bulk_product_pricetag.report_pricetag"
attachment_use="False"
/>
<record id="bulk_product_pricetag.pricetag" model="ir.actions.report.xml">
<field name="paperformat_id" ref="bulk_product_pricetag.paperformat_pricetag"/>
<field name="attachment_use" eval="0"/>
</record>
</odoo>
# -*- coding: utf-8 -*-
from openerp import api, models
class ReportPricetag(models.AbstractModel):
_name = 'report.bulk_product_pricetag.report_pricetag'
@api.model
def _get_products(self, lines, fields):
result = []
line_ids = self.env['product.pricetag.wizard.line'].browse(lines)
for line in line_ids:
val = {}
val['line'] = line
val['product'] = line.product_id
result.append(val)
return result
@api.multi
def render_html(self, data):
self.model = self.env.context.get('active_model')
docs = self.env[self.model].browse(self.env.context.get('active_id'))
line_ids = data['form'].get('line_ids', [])
fields = data['form'].get('fields', [])
report_context = self._context.copy()
report_context.update(data['form'].get('used_context', {}))
product_res = self.with_context(report_context)._get_products(
line_ids, fields)
pricetag_model = self.env['product.category.print'].browse(
data['form']['category_print_id']).pricetag_model_id
report_model = pricetag_model.report_model
docargs = {
'doc_ids': self.ids,
'partner_id': self.env.user.partner_id,
'doc_model': self.model,
'data': data['form'],
'docs': docs,
'Products': product_res,
}
return self.env['report'].render(
report_model, docargs)
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="minimal_layout_inherit" inherit_id="report.minimal_layout">
<xpath expr="//head" position="inside">
<link rel='stylesheet' href="/bulk_product_pricetag/static/src/css/pricetag.css"/>
</xpath>
</template>
<template id="report_pricetag">
<t t-call="report.html_container">
<div class="page">
<t t-foreach="Products" t-as="product">
<t t-foreach="product['line'].quantity" t-as="q">
<div class="label_container">
<div class="pricetag">
<div class="label_top">
<div class="product_name">
<t t-esc="product['product'].name"/>
</div>
</div>
<div class="label_left">
<div class="product_informations">
<t t-if="product['product'].code">Code: <t t-esc="product['product'].code"/><br/></t>
<t t-if="product['product'].weight_net"><t t-esc="product['product'].weight_net"/> kg --- <t t-esc="product['product'].price_weight_net"/> €/kg<br/></t>
<t t-if="not(product['product'].weight_net) and product['product'].volume"><t t-esc="product['product'].volume"/>L --- <t t-esc="product['product'].price_volume"/> €/L<br/></t>
</div>
</div>
<div class="label_right">
<div class="product_price">
<t t-esc="'%0.2f' % (product['product'].list_price)"/>
</div>
</div>
<div class="label_bottom">
<div class="product_shelf_origin">
<t name="pricetag_origine" t-if="product['product'].pricetag_origin">Origine: <t t-esc="product['product'].pricetag_origin"/><br/></t>
</div>
<div class="product_shelf_rackinfo_barcode">
<t t-if="product['product'].pricetag_rackinfos"><t t-esc="product['product'].pricetag_rackinfos"/></t>&#160;&#160;
<t t-if="product['product'].barcode"><t t-esc="product['product'].barcode"/></t>
</div>
<div class="pricetag_shelf_coopinfos">
<t t-if="product['product'].pricetag_coopinfos"><t t-esc="product['product'].pricetag_coopinfos"/> </t>
</div>
</div>
</div>
</div>
</t>
</t>
</div>
</t>
</template>
</odoo>
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
,,,,,,,
,,,,,,,
access_model_product_label,access_model_product_label,bulk_product_pricetag.model_product_label,,1,0,0,0
access_model_product_label,access_model_product_label,bulk_product_pricetag.model_product_label,bulk_product_pricetag.group_food_manager_sc,1,1,1,0
# -*- coding: utf-8 -*-
##############################################################################
#
# Sale - Food Module for Odoo
# Copyright (C) 2012-Today GRAP (http://www.grap.coop)
# @author Julien WESTE
# @author Sylvain LE GAL (https://twitter.com/legalsylvain)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
- !record {model: res.groups, id: group_food_manager_sc}:
category_id: product_to_print.module_product_to_print
name: Manage Food fields SC
.page_pricetag{
padding:0px;margin:58mm;border:0px;overflow:hidden;
}
.body_pricetag{
padding:0px;margin:50mm;border:0px;overflow:hidden;
}
.label_container{
page-break-inside: avoid;
width:6.4cm; height:3.45cm; float:left;
margin-left:0cm;
margin-right:0cm;
margin-top:0cm;
margin-bottom:0cm;
padding:0cm;
}
.label_border{
border:1px solid;
}
.pricetag{
height: 100%;
width:100%;
padding:0.1cm;
}
.label_top{
width:100%; height:22%; float:left;
margin-bottom:0.2cm;
}
.label_left{
width:60%; height:33%; float:left;
}
.label_right{
width:40%; height:33%; float:right;
}
.label_bottom{
width:100%; height:45%; float:left;
font-size: 11px;
}
.product_name{
height: 100%;
width:100%;
font-size: 12px;
font-weight:bold;
line-height:13px;
overflow: hidden;
}
.product_informations{
background-color: rgba(255, 255, 255, 1);
width:100%;height:100%;
font-size: 11px;
}
.product_price{
width:100%;height:100%;
line-height: 1.2cm;
text-align:center; font-size:22px; font-weight:bold;
}
.product_shelf_origin{
width: 100%;
height: 20%;
}
.product_shelf_rackinfo_barcode{
width: 100%;
height: 20%;
}
.pricetag_shelf_coopinfos{
width: 100%;
height: 60%;
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!-- ********************************************************************** -->
<!--Sale - Food Module for Odoo -->
<!--Copyright (C) 2012-Today GRAP (http://www.grap.coop) -->
<!--@author Julien Weste -->
<!--@author Sylvain LE GAL (https://twitter.com/legalsylvain) -->
<!--This program is free software: you can redistribute it and/or modify -->
<!--it under the terms of the GNU Affero General Public License as -->
<!--published by the Free Software Foundation, either version 3 of the -->
<!--License, or (at your option) any later version. -->
<!--This program is distributed in the hope that it will be useful, -->
<!--but WITHOUT ANY WARRANTY; without even the implied warranty of -->
<!--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
<!--GNU Affero General Public License for more details. -->
<!--You should have received a copy of the GNU Affero General Public License-->
<!--along with this program. If not, see <http://www.gnu.org/licenses/>. -->
<!-- ********************************************************************** -->
<odoo>
<record id="action_product_product_food" model="ir.actions.act_window">
<field name="name">Products (Food)</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">product.product</field>
<field name="view_type">form</field>
<field name="view_mode">tree</field>
<field name="view_id" ref="view_product_product_food_tree"/>
</record>
<record id="action_product_product_origin" model="ir.actions.act_window">
<field name="name">Products (Origin)</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">product.product</field>
<field name="view_type">form</field>
<field name="view_mode">tree</field>
<field name="view_id" ref="view_product_product_origin_tree"/>
</record>
<record id="action_product_product_pricetag" model="ir.actions.act_window">
<field name="name">Products (Price Tags)</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">product.product</field>
<field name="view_type">form</field>
<field name="view_mode">tree</field>
<field name="context">{'search_default_print_todo':1}</field>
<field name="search_view_id" ref="view_product_product_search"/>
<!-- <field name="view_id" ref="view_product_product_pricetag_tree"/> -->
</record>
<record id="action_product_label" model="ir.actions.act_window">
<field name="name">Labels</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">product.label</field>
<field name="view_type">form</field>
<field name="view_mode">kanban,tree,form</field>
</record>
</odoo>
<?xml version="1.0" encoding="UTF-8"?>
<!-- ********************************************************************** -->
<!--Sale - Food Module for Odoo -->
<!--Copyright (C) 2012-Today GRAP (http://www.grap.coop) -->
<!--@author Julien Weste -->
<!--@author Sylvain LE GAL (https://twitter.com/legalsylvain) -->
<!--This program is free software: you can redistribute it and/or modify -->
<!--it under the terms of the GNU Affero General Public License as -->
<!--published by the Free Software Foundation, either version 3 of the -->
<!--License, or (at your option) any later version. -->
<!--This program is distributed in the hope that it will be useful, -->
<!--but WITHOUT ANY WARRANTY; without even the implied warranty of -->
<!--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
<!--GNU Affero General Public License for more details. -->
<!--You should have received a copy of the GNU Affero General Public License-->
<!--along with this program. If not, see <http://www.gnu.org/licenses/>. -->
<!-- ********************************************************************** -->
<odoo>
<!-- Model: product.label -->
<menuitem id="menu_product_label"
parent="base.menu_sale_config"
action="action_product_label"/>
<!-- Model: product.product -->
<menuitem id="menu_product_product_food"
parent="base.menu_product"
action="action_product_product_food"/>
<menuitem id="menu_product_product_origin_3"
parent="base.menu_product"
action="action_product_product_origin"/>
<menuitem id="menu_product_product_pricetag_3"
parent="base.menu_product"
action="action_product_product_pricetag"/>
</odoo>
<?xml version="1.0" encoding="UTF-8"?>
<!-- ********************************************************************** -->
<!--Sale - Food Module for Odoo -->
<!--Copyright (C) 2012-Today GRAP (http://www.grap.coop) -->
<!--@author Julien Weste -->
<!--@author Sylvain LE GAL (https://twitter.com/legalsylvain) -->
<!--This program is free software: you can redistribute it and/or modify -->
<!--it under the terms of the GNU Affero General Public License as -->
<!--published by the Free Software Foundation, either version 3 of the -->
<!--License, or (at your option) any later version. -->
<!--This program is distributed in the hope that it will be useful, -->
<!--but WITHOUT ANY WARRANTY; without even the implied warranty of -->
<!--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
<!--GNU Affero General Public License for more details. -->
<!--You should have received a copy of the GNU Affero General Public License-->
<!--along with this program. If not, see <http://www.gnu.org/licenses/>. -->
<!-- ********************************************************************** -->
<odoo>
<record id="view_product_label_tree" model="ir.ui.view">
<field name="model">product.label</field>
<field name="arch" type="xml">
<tree string="Label">
<field name="code"/>
<field name="name"/>
<field name="website"/>
<field name="company_id" groups="base.group_multi_company"/>
</tree>
</field>
</record>
<record id="view_product_label_form" model="ir.ui.view">
<field name="model">product.label</field>
<field name="arch" type="xml">
<form string="Label" version="7.0">
<sheet>
<field name="image" widget="image" class="oe_avatar oe_left"/>
<div class="oe_title">
<div class="oe_edit_only"><label for="name"/></div>
<h1><field name="name"/></h1>
<label for="code" class="oe_edit_only"/>
<h2><field name="code"/></h2>
</div>
<notebook>
<page string="Information">
<group col="4">
<field name="active"/>
<field name="company_id" groups="base.group_multi_company"/>
<newline />
<field name="website" colspan="4"/>
<field name="note" widget="html" colspan="4"/>
</group>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<record id="view_product_label_kanban" model="ir.ui.view">
<field name="model">product.label</field>
<field name="arch" type="xml">
<kanban>
<field name="image"/>
<templates>
<t t-name="kanban-box">
<div class="oe_kanban_box oe_kanban_color_border">
<div class="product_label_kanban">
<div class="product_label_kanban_name">
<a type="edit">
<field name="name"/>
</a>
</div>
<div class="product_label_kanban_image">
<img t-att-src="kanban_image('product.label', 'image', record.id.value)" width="48"/>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
</odoo>
<?xml version="1.0" encoding="UTF-8"?>
<!-- ********************************************************************** -->
<!--Sale - Food Module for Odoo -->
<!--Copyright (C) 2012-Today GRAP (http://www.grap.coop) -->
<!--@author Julien Weste -->
<!--@author Sylvain LE GAL (https://twitter.com/legalsylvain) -->
<!--This program is free software: you can redistribute it and/or modify -->
<!--it under the terms of the GNU Affero General Public License as -->
<!--published by the Free Software Foundation, either version 3 of the -->
<!--License, or (at your option) any later version. -->
<!--This program is distributed in the hope that it will be useful, -->
<!--but WITHOUT ANY WARRANTY; without even the implied warranty of -->
<!--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
<!--GNU Affero General Public License for more details. -->
<!--You should have received a copy of the GNU Affero General Public License-->
<!--along with this program. If not, see <http://www.gnu.org/licenses/>. -->
<!-- ********************************************************************** -->
<odoo>
<!-- Model: product.product -->
<record id="view_product_product_search" model="ir.ui.view">
<field name="model">product.product</field>
<field name="inherit_id" ref="product.product_search_form_view"/>
<field name="arch" type="xml">
<filter name="filter_to_sell" position="after">
<separator/>
<filter string="Mercuriale Product" name="is_mercuriale" domain="[('is_mercuriale', '=', True)]"/>
</filter>
</field>
</record>
<record id="view_product_product_food_tree" model="ir.ui.view">
<field name="model">product.product</field>
<field name="arch" type="xml">
<tree string="Products (Food)" editable="bottom">
<field name="name" readonly="1"/>
<field name="is_mercuriale"/>
<field name="fresh_category"/>
<field name="fresh_range"/>
</tree>
</field>
</record>
<record id="view_product_product_origin_tree" model="ir.ui.view">
<field name="model">product.product</field>
<field name="arch" type="xml">
<tree string="Products (Origin)" editable="bottom">
<field name="name" readonly="1"/>
<field name="country_id" options="{'quick_create':false}"/>
<field name="department_id" options="{'quick_create':false}"
domain="[('country_id', '=', country_id)]"/>
<field name="maker_description"/>
<field name="origin_description"/>
</tree>
</field>
</record>
</odoo>
<?xml version="1.0" encoding="UTF-8"?>
<!-- ********************************************************************** -->
<!--Sale - Food Module for Odoo -->
<!--Copyright (C) 2012-Today GRAP (http://www.grap.coop) -->
<!--@author Julien Weste -->
<!--@author Sylvain LE GAL (https://twitter.com/legalsylvain) -->
<!--This program is free software: you can redistribute it and/or modify -->
<!--it under the terms of the GNU Affero General Public License as -->
<!--published by the Free Software Foundation, either version 3 of the -->
<!--License, or (at your option) any later version. -->
<!--This program is distributed in the hope that it will be useful, -->
<!--but WITHOUT ANY WARRANTY; without even the implied warranty of -->
<!--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
<!--GNU Affero General Public License for more details. -->
<!--You should have received a copy of the GNU Affero General Public License-->
<!--along with this program. If not, see <http://www.gnu.org/licenses/>. -->
<!-- ********************************************************************** -->
<odoo>
<record id="product_template_form_view_food" model="ir.ui.view">
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_form_view" />
<field name="arch" type="xml">
<notebook position="inside">
<page string="Food Informations" groups="bulk_product_pricetag.group_food_manager">
<group colspan="4">
<group>
<separator string="Origin" colspan="2"/>
<field name="country_id" options="{'quick_create':false}"/>
<field name="department_id" options="{'quick_create':false}"/>
<field name="origin_description"/>
<field name="maker_description"/>
</group>
<group>
<separator string="Food" colspan="2"/>
<field name="fresh_category"/>
<field name="fresh_range"/>
<field name="is_mercuriale"/>
<field name="label_ids" widget="many2many_tags"/>
</group>
<group>
<separator string="Price Tag" colspan="4"/>
<field name="expiration_date_days"/>
<field name="expiration_comsumption_days"/>
<field name="extra_note_bizerba_pricetag_1"/>
<field name="extra_note_bizerba_pricetag_2"/>
<field name="ingredients" widget="hmtl"/>
</group>
</group>
</page>
</notebook>
<xpath expr="//field[@name='weight']/.." position="after">
<field name="weight_net"/>
<field name="price_weight_net"/>
</xpath>
<xpath expr="//field[@name='volume']/.." position="after">
<field name="price_volume"/>
</xpath>
<xpath expr="//group[@name='group_standard_price']" position="after">
<group string="Pricetag Information" name="sticker_info">
<field name="rack_instruction"/>
<field name="rack_location"/>
<field name="rack_number_of_packages"/>
<field name="farming_method"/>
<field name="other_information"/>
</group>
</xpath>
</field>
</record>
</odoo>
<?xml version="1.0" encoding="UTF-8"?>
<!-- ********************************************************************** -->
<!--Sale - Food Module for Odoo -->
<!--Copyright (C) 2012-Today GRAP (http://www.grap.coop) -->
<!--@author Julien Weste -->
<!--@author Sylvain LE GAL (https://twitter.com/legalsylvain) -->
<!--This program is free software: you can redistribute it and/or modify -->
<!--it under the terms of the GNU Affero General Public License as -->
<!--published by the Free Software Foundation, either version 3 of the -->
<!--License, or (at your option) any later version. -->
<!--This program is distributed in the hope that it will be useful, -->
<!--but WITHOUT ANY WARRANTY; without even the implied warranty of -->
<!--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
<!--GNU Affero General Public License for more details. -->
<!--You should have received a copy of the GNU Affero General Public License-->
<!--along with this program. If not, see <http://www.gnu.org/licenses/>. -->
<!-- ********************************************************************** -->
<odoo>
<!-- Model: product.uom.categ -->
<record id="view_product_uom_categ_form" model="ir.ui.view">
<field name="model">product.uom.categ</field>
<field name="inherit_id" ref="product.product_uom_categ_form_view" />
<field name="arch" type="xml">
<field name="name" position="after">
<field name="pricetag_printable"/>
</field>
</field>
</record>
</odoo>
\ No newline at end of file
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