Compare commits
116 Commits
10-account
...
8.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
79e51a1b2c | ||
|
|
ab3c17f687 | ||
|
|
6d50a1d6a5 | ||
|
|
549328b846 | ||
|
|
361176a280 | ||
|
|
1df8d0a461 | ||
|
|
f09e459e82 | ||
|
|
47d659a320 | ||
|
|
4a77ff9e8f | ||
|
|
e4ff071565 | ||
|
|
210c6e2583 | ||
|
|
b21159940b | ||
|
|
9b0d3c1311 | ||
|
|
199496380d | ||
|
|
34439b72ad | ||
|
|
2a454294c3 | ||
|
|
4c097fdb96 | ||
|
|
d88211408b | ||
|
|
8b069d314e | ||
|
|
3a71748b8d | ||
|
|
0b4a1add6b | ||
|
|
2abbe14109 | ||
|
|
0d3c98d99e | ||
|
|
8463de054b | ||
|
|
8c0717db2f | ||
|
|
3888495071 | ||
|
|
93acac8e19 | ||
|
|
44b32672e2 | ||
|
|
1160cce1d8 | ||
|
|
16664bcb7f | ||
|
|
cfb92ec23a | ||
|
|
a3844004fb | ||
|
|
9319b120bf | ||
|
|
7fd5ab9cf1 | ||
|
|
8f463db179 | ||
|
|
f8720c7a36 | ||
|
|
e74e53c804 | ||
|
|
5388638941 | ||
|
|
d943ef262f | ||
|
|
a787e092ed | ||
|
|
8e5f0b0afa | ||
|
|
cb21028a48 | ||
|
|
ffa6e74a19 | ||
|
|
1e062af883 | ||
|
|
31f191aecb | ||
|
|
51c982bf2f | ||
|
|
3d7241407e | ||
|
|
817fadd167 | ||
|
|
25ea1991cf | ||
|
|
c8c1f78e66 | ||
|
|
0bc6cb32d9 | ||
|
|
db736d95a3 | ||
|
|
f83c948889 | ||
|
|
d736663f3f | ||
|
|
f051537a92 | ||
|
|
193e5e6ecc | ||
|
|
00592100f7 | ||
|
|
0d524f27d8 | ||
|
|
4509b2631a | ||
|
|
2ff7943c62 | ||
|
|
d85e7270b3 | ||
|
|
7b6916ce16 | ||
|
|
a9c6f9ed69 | ||
|
|
7a11966992 | ||
|
|
d4fcaa7d14 | ||
|
|
77fb97f273 | ||
|
|
9670eb7c10 | ||
|
|
f8e955d5b7 | ||
|
|
a803d1dcb9 | ||
|
|
a141f0506b | ||
|
|
7c554aee33 | ||
|
|
07c81e441d | ||
|
|
4c3c8e50db | ||
|
|
60beb99580 | ||
|
|
709bde8fb7 | ||
|
|
281c0b7052 | ||
|
|
8d55f9aaa5 | ||
|
|
964b1fca67 | ||
|
|
e20f88baf0 | ||
|
|
15d9c31f6f | ||
|
|
e74864e54f | ||
|
|
146c0e6b7d | ||
|
|
869c7176f7 | ||
|
|
4b26ab78be | ||
|
|
662494db35 | ||
|
|
aafc36dfdb | ||
|
|
e94168ad27 | ||
|
|
9b62198115 | ||
|
|
309027198a | ||
|
|
c8f1517881 | ||
|
|
6cb195a3eb | ||
|
|
b85f5184c2 | ||
|
|
2d392ce465 | ||
|
|
e71ad5f952 | ||
|
|
3905a826fa | ||
|
|
18ea374d8c | ||
|
|
f8d3340e48 | ||
|
|
9761c7527b | ||
|
|
baf7359cc7 | ||
|
|
33561ed930 | ||
|
|
aad2121f20 | ||
|
|
880cf7c7a9 | ||
|
|
d3eef1e5a5 | ||
|
|
b41f188eb4 | ||
|
|
891c64bb1f | ||
|
|
b9e07ea986 | ||
|
|
12fbd5dc2c | ||
|
|
7948193fe0 | ||
|
|
64cb3d44ad | ||
|
|
08f434b6a0 | ||
|
|
6176b37fa6 | ||
|
|
4015f5b1c9 | ||
|
|
ef920f58f4 | ||
|
|
c108f617c2 | ||
|
|
4acce9509f | ||
|
|
e9ab3187e7 |
3
account_analytic_analysis_usability/__init__.py
Normal file
3
account_analytic_analysis_usability/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import account_analytic_analysis
|
||||
29
account_analytic_analysis_usability/__openerp__.py
Normal file
29
account_analytic_analysis_usability/__openerp__.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
'name': 'Account Analytic Analysis Usability',
|
||||
'version': '8.0.1.0.0',
|
||||
'category': 'Accounting & Finance',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Usability improvements on Account Analytic Analysis',
|
||||
'description': """
|
||||
Account Analytic Analysis Usability
|
||||
===================================
|
||||
|
||||
Usability improvements include:
|
||||
|
||||
* add next invoice date in tree view of contrats (and add a group by)
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion
|
||||
<alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['account_analytic_analysis'],
|
||||
'data': [
|
||||
'analytic_view.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from openerp import models, fields
|
||||
|
||||
|
||||
class AccountAnalyticAccount(models.Model):
|
||||
_inherit = "account.analytic.account"
|
||||
|
||||
recurring_next_date = fields.Date(track_visibility='onchange')
|
||||
recurring_rule_type = fields.Selection(track_visibility='onchange')
|
||||
recurring_interval = fields.Integer(track_visibility='onchange')
|
||||
recurring_invoices = fields.Boolean(track_visibility='onchange')
|
||||
40
account_analytic_analysis_usability/analytic_view.xml
Normal file
40
account_analytic_analysis_usability/analytic_view.xml
Normal file
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="view_account_analytic_account_tree_c2c_3" model="ir.ui.view">
|
||||
<field name="name">usability.analytic_analysis.account.analytic.account.tree.contract</field>
|
||||
<field name="model">account.analytic.account</field>
|
||||
<field name="inherit_id" ref="account_analytic_analysis.view_account_analytic_account_tree_c2c_3"/>
|
||||
<field name="groups_id" eval="[(4, ref('account.group_account_invoice'))]"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="date" position="after">
|
||||
<field name="recurring_rule_type"/>
|
||||
<field name="recurring_next_date"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_account_analytic_account_overdue_search" model="ir.ui.view">
|
||||
<field name="name">usability.analytic_analysis.account.analytic.account.search</field>
|
||||
<field name="model">account.analytic.account</field>
|
||||
<field name="inherit_id" ref="account_analytic_analysis.view_account_analytic_account_overdue_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<filter context="{'group_by' : 'pricelist_id'}" position="after">
|
||||
<filter name="recurring_rule_type_groupby" string="Invoicing Frequency" context="{'group_by': 'recurring_rule_type'}"/>
|
||||
<filter name="recurring_next_date_groupby" string="Next Invoice Date" context="{'group_by': 'recurring_next_date'}"/>
|
||||
</filter>
|
||||
<filter name="cancelled" position="after">
|
||||
<separator/>
|
||||
<filter name="recurring_invoices" string="Recurring Invoicing" domain="[('recurring_invoices', '=', True)]"/>
|
||||
</filter>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -0,0 +1,32 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * account_bank_statement_import_usability
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 8.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-11-06 10:15+0000\n"
|
||||
"PO-Revision-Date: 2017-11-06 10:15+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_bank_statement_import_usability
|
||||
#: model:ir.model,name:account_bank_statement_import_usability.model_account_bank_statement
|
||||
msgid "Bank Statement"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_bank_statement_import_usability
|
||||
#: model:ir.model,name:account_bank_statement_import_usability.model_account_bank_statement_import
|
||||
msgid "Import Bank Statement"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_bank_statement_import_usability
|
||||
#: view:account.bank.statement:account_bank_statement_import_usability.view_bank_statement_tree
|
||||
msgid "blue:state=='draft';black:state=='confirm'"
|
||||
msgstr ""
|
||||
|
||||
32
account_bank_statement_import_usability/i18n/fr.po
Normal file
32
account_bank_statement_import_usability/i18n/fr.po
Normal file
@@ -0,0 +1,32 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * account_bank_statement_import_usability
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 8.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-11-06 10:15+0000\n"
|
||||
"PO-Revision-Date: 2017-11-06 10:15+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_bank_statement_import_usability
|
||||
#: model:ir.model,name:account_bank_statement_import_usability.model_account_bank_statement
|
||||
msgid "Bank Statement"
|
||||
msgstr "Relevé Bancaire"
|
||||
|
||||
#. module: account_bank_statement_import_usability
|
||||
#: model:ir.model,name:account_bank_statement_import_usability.model_account_bank_statement_import
|
||||
msgid "Import Bank Statement"
|
||||
msgstr "Importer Relevé Bancaire"
|
||||
|
||||
#. module: account_bank_statement_import_usability
|
||||
#: view:account.bank.statement:account_bank_statement_import_usability.view_bank_statement_tree
|
||||
msgid "blue:state=='draft';black:state=='confirm'"
|
||||
msgstr "blue:state=='draft';black:state=='confirm'"
|
||||
|
||||
3
account_fiscal_position_payable_receivable/__init__.py
Normal file
3
account_fiscal_position_payable_receivable/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import account_fiscal_position
|
||||
26
account_fiscal_position_payable_receivable/__openerp__.py
Normal file
26
account_fiscal_position_payable_receivable/__openerp__.py
Normal file
@@ -0,0 +1,26 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
'name': 'Account Fiscal Position Payable Receivable',
|
||||
'version': '8.0.1.0.0',
|
||||
'category': 'Accounting & Finance',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Configure payable/receivable accounts on fiscal positions',
|
||||
'description': """
|
||||
Account Fiscal Position Payable Receivable
|
||||
==========================================
|
||||
|
||||
This module allows to configure a special *Partner Receivable Account* and a special *Partner Payable Account* on fiscal positions. This is used in the onchange of the fiscal position of partners.
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': "Akretion",
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['account'],
|
||||
'data': [
|
||||
'account_fiscal_position_view.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from openerp import models, fields, api
|
||||
|
||||
|
||||
class AccountFiscalPosition(models.Model):
|
||||
_inherit = 'account.fiscal.position'
|
||||
|
||||
receivable_account_id = fields.Many2one(
|
||||
'account.account', string='Partner Receivable Account',
|
||||
company_dependent=True, domain=[('type', '=', 'receivable')])
|
||||
payable_account_id = fields.Many2one(
|
||||
'account.account', string='Partner Payable Account',
|
||||
company_dependent=True, domain=[('type', '=', 'payable')])
|
||||
|
||||
|
||||
class ResPartner(models.Model):
|
||||
_inherit = 'res.partner'
|
||||
|
||||
@api.onchange('property_account_position')
|
||||
def fiscal_position_receivable_payable_change(self):
|
||||
fp = self.property_account_position
|
||||
ipo = self.env['ir.property']
|
||||
if fp.receivable_account_id:
|
||||
self.property_account_receivable = fp.receivable_account_id
|
||||
else:
|
||||
self.property_account_receivable = ipo.get(
|
||||
'property_account_receivable', 'res.partner')
|
||||
if fp.payable_account_id:
|
||||
self.property_account_payable = fp.payable_account_id
|
||||
else:
|
||||
self.property_account_payable = ipo.get(
|
||||
'property_account_payable', 'res.partner')
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
|
||||
<record id="view_account_position_form" model="ir.ui.view">
|
||||
<field name="name">receivable_payable.fiscal_position_form</field>
|
||||
<field name="model">account.fiscal.position</field>
|
||||
<field name="inherit_id" ref="account.view_account_position_form" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='country_group_id']/.." position="after">
|
||||
<group string="Payable and Receivable Accounts"
|
||||
name="payable_receivable_account" col="4">
|
||||
<field name="receivable_account_id"/>
|
||||
<field name="payable_account_id"/>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -28,6 +28,10 @@ class AccountInvoice(models.Model):
|
||||
|
||||
@api.multi
|
||||
def invoice_filename_to_match(self):
|
||||
# I cannot use
|
||||
# safe_eval(report.attachment, {'object': obj, 'time': time})
|
||||
# Because, when this code is executed, the obj.state is not 'open'
|
||||
# nor 'paid', so we can't get the filename that way
|
||||
return 'INV%.pdf'
|
||||
|
||||
@api.multi
|
||||
|
||||
@@ -34,9 +34,6 @@ Account Invoice Picking Label
|
||||
Adds a function field named *picking_ids_label* on invoices. This field contains the list of pickings related to the invoice as a string. This field is designed to be displayed in the invoice report.""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com/',
|
||||
'depends': ['stock_account'],
|
||||
'data': [],
|
||||
'depends': ['stock_picking_invoice_link'],
|
||||
'installable': True,
|
||||
'active': False,
|
||||
}
|
||||
|
||||
|
||||
@@ -36,13 +36,10 @@ class account_invoice(orm.Model):
|
||||
pickings = self.pool['stock.picking'].read(
|
||||
cr, uid, invoice['picking_ids'], ['name'],
|
||||
context=context)
|
||||
first = True
|
||||
pick_names = []
|
||||
for picking in pickings:
|
||||
if first:
|
||||
label += picking['name']
|
||||
first = False
|
||||
else:
|
||||
label += ', %s' % picking['name']
|
||||
pick_names.append(picking['name'])
|
||||
label = ','.join(pick_names)
|
||||
res[invoice['id']] = label
|
||||
return res
|
||||
|
||||
|
||||
3
account_invoice_update_wizard/__init__.py
Normal file
3
account_invoice_update_wizard/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import wizard
|
||||
34
account_invoice_update_wizard/__openerp__.py
Normal file
34
account_invoice_update_wizard/__openerp__.py
Normal file
@@ -0,0 +1,34 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
'name': 'Account Invoice Update Wizard',
|
||||
'version': '8.0.1.0.0',
|
||||
'category': 'Accounting & Finance',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Wizard to update non-legal fields of an open/paid invoice',
|
||||
'description': """
|
||||
Account Invoice Update Wizard
|
||||
=============================
|
||||
|
||||
This module adds a button *Update Invoice* on Customer and Supplier invoices in Open or Paid state. This button starts a wizard which allows the user to update non-legal fields of the invoice:
|
||||
|
||||
* Source Document
|
||||
* Reference/Description
|
||||
* Payment terms (update allowed only to a payment term with same number of terms of the same amount and on invoices without any payment)
|
||||
* Bank Account
|
||||
* Salesman
|
||||
* Notes
|
||||
* Description of invoice lines
|
||||
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['account'],
|
||||
'data': [
|
||||
'wizard/account_invoice_update_view.xml',
|
||||
'views/account_invoice.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
31
account_invoice_update_wizard/views/account_invoice.xml
Normal file
31
account_invoice_update_wizard/views/account_invoice.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="invoice_supplier_form" model="ir.ui.view">
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="account.invoice_supplier_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<button name="invoice_cancel" position="before">
|
||||
<button name="%(account_invoice_update_action)d" type="action" string="Update Invoice" states="open,paid" groups="account.group_account_invoice"/>
|
||||
</button>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="invoice_form" model="ir.ui.view">
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="account.invoice_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<button name="invoice_cancel" position="before">
|
||||
<button name="%(account_invoice_update_action)d" type="action" string="Update Invoice" states="open,paid" groups="account.group_account_invoice"/>
|
||||
</button>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
3
account_invoice_update_wizard/wizard/__init__.py
Normal file
3
account_invoice_update_wizard/wizard/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import account_invoice_update
|
||||
206
account_invoice_update_wizard/wizard/account_invoice_update.py
Normal file
206
account_invoice_update_wizard/wizard/account_invoice_update.py
Normal file
@@ -0,0 +1,206 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from openerp import models, fields, api, _
|
||||
from openerp.exceptions import Warning as UserError
|
||||
import openerp.addons.decimal_precision as dp
|
||||
|
||||
|
||||
class AccountInvoiceUpdate(models.TransientModel):
|
||||
_name = 'account.invoice.update'
|
||||
_description = 'Wizard to update non-legal fields of invoice'
|
||||
|
||||
invoice_id = fields.Many2one(
|
||||
'account.invoice', string='Invoice', required=True,
|
||||
readonly=True)
|
||||
type = fields.Selection(related='invoice_id.type', readonly=True)
|
||||
company_id = fields.Many2one(
|
||||
related='invoice_id.company_id', readonly=True)
|
||||
commercial_partner_id = fields.Many2one(
|
||||
related='invoice_id.commercial_partner_id', readonly=True)
|
||||
user_id = fields.Many2one('res.users', string='Salesperson')
|
||||
# I use the same field name as the original invoice field name
|
||||
# even if it the name is "bad"
|
||||
# Updating payment_term will not work if you use
|
||||
# the OCA module account_constraints (you will just get an error)
|
||||
payment_term = fields.Many2one(
|
||||
'account.payment.term', string='Payment Terms')
|
||||
reference = fields.Char(string='Invoice Reference')
|
||||
name = fields.Char(string='Reference/Description')
|
||||
origin = fields.Char(string='Source Document')
|
||||
comment = fields.Text('Additional Information')
|
||||
partner_bank_id = fields.Many2one(
|
||||
'res.partner.bank', string='Bank Account')
|
||||
line_ids = fields.One2many(
|
||||
'account.invoice.line.update', 'parent_id', string='Invoice Lines')
|
||||
|
||||
@api.model
|
||||
def _simple_fields2update(self):
|
||||
'''List boolean, date, datetime, char, text fields'''
|
||||
return ['reference', 'name', 'origin', 'comment']
|
||||
|
||||
@api.model
|
||||
def _m2o_fields2update(self):
|
||||
return ['payment_term', 'user_id', 'partner_bank_id']
|
||||
|
||||
@api.model
|
||||
def _prepare_default_get(self, invoice):
|
||||
res = {'invoice_id': invoice.id, 'line_ids': []}
|
||||
for sfield in self._simple_fields2update():
|
||||
res[sfield] = invoice[sfield]
|
||||
for m2ofield in self._m2o_fields2update():
|
||||
res[m2ofield] = invoice[m2ofield].id or False
|
||||
for line in invoice.invoice_line:
|
||||
res['line_ids'].append({
|
||||
'invoice_line_id': line.id,
|
||||
'name': line.name,
|
||||
'quantity': line.quantity,
|
||||
'price_subtotal': line.price_subtotal,
|
||||
})
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields_list):
|
||||
res = super(AccountInvoiceUpdate, self).default_get(fields_list)
|
||||
assert self._context.get('active_model') == 'account.invoice',\
|
||||
'active_model should be account.invoice'
|
||||
inv = self.env['account.invoice'].browse(self._context['active_id'])
|
||||
res = self._prepare_default_get(inv)
|
||||
return res
|
||||
|
||||
@api.onchange('type')
|
||||
def type_on_change(self):
|
||||
res = {'domain': {}}
|
||||
if self.type in ('out_invoice', 'out_refund'):
|
||||
res['domain']['partner_bank_id'] =\
|
||||
"[('partner_id.ref_companies', 'in', [company_id])]"
|
||||
else:
|
||||
res['domain']['partner_bank_id'] =\
|
||||
"[('partner_id', '=', commercial_partner_id)]"
|
||||
return res
|
||||
|
||||
@api.multi
|
||||
def _prepare_invoice(self):
|
||||
vals = {}
|
||||
inv = self.invoice_id
|
||||
for sfield in self._simple_fields2update():
|
||||
if self[sfield] != inv[sfield]:
|
||||
vals[sfield] = self[sfield]
|
||||
for m2ofield in self._m2o_fields2update():
|
||||
if self[m2ofield] != inv[m2ofield]:
|
||||
vals[m2ofield] = self[m2ofield].id or False
|
||||
if 'payment_term' in vals:
|
||||
pterm_list = self.payment_term.compute(
|
||||
value=1, date_ref=inv.date_invoice)[0]
|
||||
if pterm_list:
|
||||
vals['date_due'] = max(line[0] for line in pterm_list)
|
||||
return vals
|
||||
|
||||
@api.model
|
||||
def _prepare_invoice_line(self, line):
|
||||
vals = {}
|
||||
if line.name != line.invoice_line_id.name:
|
||||
vals['name'] = line.name
|
||||
return vals
|
||||
|
||||
@api.multi
|
||||
def _prepare_move(self):
|
||||
mvals = {}
|
||||
inv = self.invoice_id
|
||||
ini_ref = inv.move_id.ref
|
||||
ref = inv.reference or inv.name
|
||||
if ini_ref != ref:
|
||||
mvals['ref'] = ref
|
||||
return mvals
|
||||
|
||||
@api.multi
|
||||
def _update_payment_term_move(self):
|
||||
self.ensure_one()
|
||||
inv = self.invoice_id
|
||||
if (
|
||||
self.payment_term and
|
||||
self.payment_term != inv.payment_term and
|
||||
inv.move_id and
|
||||
inv.move_id.period_id.state == 'draft'):
|
||||
# I don't update pay term when the invoice is partially (or fully)
|
||||
# paid because if you have a payment term with several lines
|
||||
# of the same amount, you would also have to take into account
|
||||
# the reconcile marks to put the new maturity date on the right
|
||||
# lines
|
||||
if inv.payment_ids:
|
||||
raise UserError(_(
|
||||
"This wizard doesn't support the update of payment "
|
||||
"terms on an invoice which is partially or fully "
|
||||
"paid."))
|
||||
prec = self.env['decimal.precision'].precision_get('Account')
|
||||
term_res = self.payment_term.compute(
|
||||
inv.amount_total, inv.date_invoice)[0]
|
||||
new_pterm = {} # key = int(amount * 100), value = [date1, date2]
|
||||
for entry in term_res:
|
||||
amount = int(entry[1] * 10 * prec)
|
||||
if amount in new_pterm:
|
||||
new_pterm[amount].append(entry[0])
|
||||
else:
|
||||
new_pterm[amount] = [entry[0]]
|
||||
mlines = {} # key = int(amount * 100), value : [line1, line2]
|
||||
for line in inv.move_id.line_id:
|
||||
if line.account_id == inv.account_id:
|
||||
amount = int(abs(line.credit - line.debit) * 10 * prec)
|
||||
if amount in mlines:
|
||||
mlines[amount].append(line)
|
||||
else:
|
||||
mlines[amount] = [line]
|
||||
for iamount, lines in mlines.iteritems():
|
||||
if len(lines) != len(new_pterm.get(iamount, [])):
|
||||
raise UserError(_(
|
||||
"The original payment term '%s' doesn't have the "
|
||||
"same terms (number of terms and/or amount) as the "
|
||||
"new payment term '%s'. You can only switch to a "
|
||||
"payment term that has the same number of terms "
|
||||
"with the same amount.") % (
|
||||
inv.payment_term.name, self.payment_term.name))
|
||||
for line in lines:
|
||||
line.date_maturity = new_pterm[iamount].pop()
|
||||
|
||||
@api.multi
|
||||
def run(self):
|
||||
self.ensure_one()
|
||||
inv = self.invoice_id
|
||||
updated = False
|
||||
# re-write date_maturity on move line
|
||||
self._update_payment_term_move()
|
||||
ivals = self._prepare_invoice()
|
||||
if ivals:
|
||||
updated = True
|
||||
inv.write(ivals)
|
||||
for line in self.line_ids:
|
||||
ilvals = self._prepare_invoice_line(line)
|
||||
if ilvals:
|
||||
updated = True
|
||||
line.invoice_line_id.write(ilvals)
|
||||
if inv.move_id and inv.move_id.period_id.state == 'draft':
|
||||
mvals = self._prepare_move()
|
||||
if mvals:
|
||||
inv.move_id.write(mvals)
|
||||
if updated:
|
||||
inv.message_post(_(
|
||||
'Non-legal fields of invoice updated via the Invoice Update '
|
||||
'wizard.'))
|
||||
return True
|
||||
|
||||
|
||||
class AccountInvoiceLineUpdate(models.TransientModel):
|
||||
_name = 'account.invoice.line.update'
|
||||
_description = 'Update non-legal fields of invoice lines'
|
||||
|
||||
parent_id = fields.Many2one(
|
||||
'account.invoice.update', string='Wizard', ondelete='cascade')
|
||||
invoice_line_id = fields.Many2one(
|
||||
'account.invoice.line', string='Invoice Line', readonly=True)
|
||||
name = fields.Text(string='Description', required=True)
|
||||
quantity = fields.Float(
|
||||
string='Quantity', digits=dp.get_precision('Product Unit of Measure'),
|
||||
readonly=True)
|
||||
price_subtotal = fields.Float(
|
||||
string='Amount', readonly=True, digits=dp.get_precision('Account'))
|
||||
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="account_invoice_update_form" model="ir.ui.view">
|
||||
<field name="model">account.invoice.update</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Update Invoice Wizard">
|
||||
<group name="main">
|
||||
<field name="invoice_id" invisible="1"/>
|
||||
<field name="type" invisible="1"/>
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="commercial_partner_id" invisible="1"/>
|
||||
<field name="reference" attrs="{'invisible': [('type', 'not in', ('in_invoice', 'in_refund'))]}"/>
|
||||
<field name="origin"/>
|
||||
<field name="name"/>
|
||||
<field name="payment_term" widget="selection"/>
|
||||
<field name="partner_bank_id"/>
|
||||
<field name="user_id"/>
|
||||
<field name="comment"/>
|
||||
</group>
|
||||
<group name="lines">
|
||||
<field name="line_ids" nolabel="1">
|
||||
<tree editable="bottom">
|
||||
<field name="invoice_line_id" invisible="1"/>
|
||||
<field name="name"/>
|
||||
<field name="quantity"/>
|
||||
<field name="price_subtotal"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="run" type="object" class="oe_highlight" string="Update"/>
|
||||
or
|
||||
<button special="cancel" string="Cancel" class="oe_link"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="account_invoice_update_action" model="ir.actions.act_window">
|
||||
<field name="name">Invoice Update Wizard</field>
|
||||
<field name="res_model">account.invoice.update</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
{
|
||||
'name': 'Account Move Line Filter Wizard',
|
||||
'version': '0.1',
|
||||
'version': '8.0.1.0.1',
|
||||
'category': 'Accounting & Finance',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Easy and fast access to the details of an account',
|
||||
@@ -31,7 +31,7 @@
|
||||
Account Move Line Filter Wizard
|
||||
===============================
|
||||
|
||||
This module adds a wizard in Accounting > ... >
|
||||
This module adds a wizard in *Accounting > Adviser > Journal Items of Account*.
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>.
|
||||
""",
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * account_move_line_filter_wizard
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 8.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-12-13 22:53+0000\n"
|
||||
"PO-Revision-Date: 2017-12-13 22:53+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_move_line_filter_wizard
|
||||
#: field:account.move.line.filter.wizard,account_id:0
|
||||
msgid "Account"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: view:account.move.line.filter.wizard:account_move_line_filter_wizard.account_move_line_filter_wizard_form
|
||||
msgid "Account Move Lines"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: view:account.move.line.filter.wizard:account_move_line_filter_wizard.account_move_line_filter_wizard_form
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: field:account.move.line.filter.wizard,create_uid:0
|
||||
msgid "Created by"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: field:account.move.line.filter.wizard,create_date:0
|
||||
msgid "Created on"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: view:account.move.line.filter.wizard:account_move_line_filter_wizard.account_move_line_filter_wizard_form
|
||||
msgid "Filters"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: selection:account.move.line.filter.wizard,reconcile:0
|
||||
msgid "Fully Reconciled"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: field:account.move.line.filter.wizard,id:0
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: model:ir.actions.act_window,name:account_move_line_filter_wizard.account_move_line_filter_wizard_action
|
||||
#: model:ir.ui.menu,name:account_move_line_filter_wizard.account_move_line_filter_wizard_menu
|
||||
msgid "Journal Items of Account"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: field:account.move.line.filter.wizard,write_uid:0
|
||||
msgid "Last Updated by"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: field:account.move.line.filter.wizard,write_date:0
|
||||
msgid "Last Updated on"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: selection:account.move.line.filter.wizard,reconcile:0
|
||||
msgid "Partially Reconciled"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: field:account.move.line.filter.wizard,partner_id:0
|
||||
msgid "Partner"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: field:account.move.line.filter.wizard,reconcile:0
|
||||
msgid "Reconciliation Filter"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: view:account.move.line.filter.wizard:account_move_line_filter_wizard.account_move_line_filter_wizard_form
|
||||
msgid "Show"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: selection:account.move.line.filter.wizard,reconcile:0
|
||||
msgid "Unreconciled"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: model:ir.model,name:account_move_line_filter_wizard.model_account_move_line_filter_wizard
|
||||
msgid "Wizard for easy and fast access to account move lines"
|
||||
msgstr ""
|
||||
|
||||
103
account_move_line_filter_wizard/i18n/fr.po
Normal file
103
account_move_line_filter_wizard/i18n/fr.po
Normal file
@@ -0,0 +1,103 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * account_move_line_filter_wizard
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 8.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-12-13 22:53+0000\n"
|
||||
"PO-Revision-Date: 2017-12-13 22:53+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_move_line_filter_wizard
|
||||
#: field:account.move.line.filter.wizard,account_id:0
|
||||
msgid "Account"
|
||||
msgstr "Compte"
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: view:account.move.line.filter.wizard:account_move_line_filter_wizard.account_move_line_filter_wizard_form
|
||||
msgid "Account Move Lines"
|
||||
msgstr "Lignes comptables"
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: view:account.move.line.filter.wizard:account_move_line_filter_wizard.account_move_line_filter_wizard_form
|
||||
msgid "Cancel"
|
||||
msgstr "Annuler"
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: field:account.move.line.filter.wizard,create_uid:0
|
||||
msgid "Created by"
|
||||
msgstr "Created by"
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: field:account.move.line.filter.wizard,create_date:0
|
||||
msgid "Created on"
|
||||
msgstr "Created on"
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: view:account.move.line.filter.wizard:account_move_line_filter_wizard.account_move_line_filter_wizard_form
|
||||
msgid "Filters"
|
||||
msgstr "Filtres"
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: selection:account.move.line.filter.wizard,reconcile:0
|
||||
msgid "Fully Reconciled"
|
||||
msgstr "Totalement lettré"
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: field:account.move.line.filter.wizard,id:0
|
||||
msgid "ID"
|
||||
msgstr "ID"
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: model:ir.actions.act_window,name:account_move_line_filter_wizard.account_move_line_filter_wizard_action
|
||||
#: model:ir.ui.menu,name:account_move_line_filter_wizard.account_move_line_filter_wizard_menu
|
||||
msgid "Journal Items of Account"
|
||||
msgstr "Consulter compte"
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: field:account.move.line.filter.wizard,write_uid:0
|
||||
msgid "Last Updated by"
|
||||
msgstr "Last Updated by"
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: field:account.move.line.filter.wizard,write_date:0
|
||||
msgid "Last Updated on"
|
||||
msgstr "Last Updated on"
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: selection:account.move.line.filter.wizard,reconcile:0
|
||||
msgid "Partially Reconciled"
|
||||
msgstr "Partiellement lettré"
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: field:account.move.line.filter.wizard,partner_id:0
|
||||
msgid "Partner"
|
||||
msgstr "Partenaire"
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: field:account.move.line.filter.wizard,reconcile:0
|
||||
msgid "Reconciliation Filter"
|
||||
msgstr "Filtre lettrage"
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: view:account.move.line.filter.wizard:account_move_line_filter_wizard.account_move_line_filter_wizard_form
|
||||
msgid "Show"
|
||||
msgstr "Consulter"
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: selection:account.move.line.filter.wizard,reconcile:0
|
||||
msgid "Unreconciled"
|
||||
msgstr "Non lettré"
|
||||
|
||||
#. module: account_move_line_filter_wizard
|
||||
#: model:ir.model,name:account_move_line_filter_wizard.model_account_move_line_filter_wizard
|
||||
msgid "Wizard for easy and fast access to account move lines"
|
||||
msgstr "Wizard for easy and fast access to account move lines"
|
||||
|
||||
@@ -53,7 +53,10 @@ class AccountMoveLineFilterWizard(models.TransientModel):
|
||||
self.ensure_one()
|
||||
action = self.env['ir.actions.act_window'].for_xml_id(
|
||||
'account', 'action_account_moves_all_a')
|
||||
action['context'] = {'search_default_account_id': [self.account_id.id]}
|
||||
action['context'] = {
|
||||
'search_default_account_id': [self.account_id.id],
|
||||
'journal_show_code_only': True,
|
||||
}
|
||||
if self.partner_id:
|
||||
action['context']['search_default_partner_id'] =\
|
||||
[self.partner_id.id]
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
attrs="{'invisible': [('account_reconcile', '!=', True)]}"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button type="object" name="go" string="Go" class="oe_highlight"/>
|
||||
<button type="object" name="go" string="Show" class="oe_highlight"/>
|
||||
<button special="cancel" string="Cancel" class="oe_link"/>
|
||||
</footer>
|
||||
</form>
|
||||
|
||||
@@ -21,9 +21,16 @@
|
||||
##############################################################################
|
||||
|
||||
import xlwt
|
||||
import logging
|
||||
from openerp import models, api
|
||||
from openerp.addons.report_xls.utils import _render
|
||||
from openerp.addons.report_xls.report_xls import report_xls
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
try:
|
||||
from openerp.addons.report_xls.utils import _render
|
||||
from openerp.addons.report_xls.report_xls import report_xls
|
||||
except (ImportError, IOError) as err:
|
||||
_logger.debug(err)
|
||||
|
||||
|
||||
class AccountMoveLine(models.Model):
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
from . import account
|
||||
from . import wizard
|
||||
|
||||
@@ -49,6 +49,9 @@ This module has been written by Alexis de Lattre from Akretion <alexis.delattre@
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['account'],
|
||||
'conflicts': ['account_invoice_overdue_filter'],
|
||||
'data': ['account_view.xml'],
|
||||
'data': [
|
||||
'account_view.xml',
|
||||
'wizard/account_invoice_mark_sent_view.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
|
||||
@@ -23,10 +23,13 @@
|
||||
from openerp import models, fields, api, _
|
||||
from openerp.tools import float_compare
|
||||
from openerp.exceptions import Warning as UserError
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AccountInvoice(models.Model):
|
||||
_inherit = 'account.invoice'
|
||||
_order = "date_invoice desc, number desc, id desc"
|
||||
|
||||
origin = fields.Char(track_visibility='onchange')
|
||||
supplier_invoice_number = fields.Char(track_visibility='onchange')
|
||||
@@ -41,9 +44,41 @@ class AccountInvoice(models.Model):
|
||||
journal_id = fields.Many2one(track_visibility='onchange')
|
||||
partner_bank_id = fields.Many2one(track_visibility='onchange')
|
||||
fiscal_position = fields.Many2one(track_visibility='onchange')
|
||||
# has_attachment is useful for those who use attachment to archive
|
||||
# supplier invoices. It allows them to find supplier invoices
|
||||
# that don't have any attachment
|
||||
has_attachment = fields.Boolean(
|
||||
compute='_compute_has_attachment',
|
||||
search='_search_has_attachment', readonly=True)
|
||||
|
||||
@api.multi
|
||||
def onchange_payment_term_date_invoice(self, payment_term_id, date_invoice):
|
||||
def _compute_has_attachment(self):
|
||||
iao = self.env['ir.attachment']
|
||||
for inv in self:
|
||||
if iao.search([
|
||||
('res_model', '=', 'account.invoice'),
|
||||
('res_id', '=', inv.id),
|
||||
('type', '=', 'binary'),
|
||||
('company_id', '=', inv.company_id.id)], limit=1):
|
||||
inv.has_attachment = True
|
||||
else:
|
||||
inv.has_attachment = False
|
||||
|
||||
def _search_has_attachment(self, operator, value):
|
||||
att_inv_ids = {}
|
||||
if operator == '=':
|
||||
search_res = self.env['ir.attachment'].search_read([
|
||||
('res_model', '=', 'account.invoice'),
|
||||
('type', '=', 'binary'),
|
||||
('res_id', '!=', False)], ['res_id'])
|
||||
for att in search_res:
|
||||
att_inv_ids[att['res_id']] = True
|
||||
res = [('id', value and 'in' or 'not in', att_inv_ids.keys())]
|
||||
return res
|
||||
|
||||
@api.multi
|
||||
def onchange_payment_term_date_invoice(
|
||||
self, payment_term_id, date_invoice):
|
||||
res = super(AccountInvoice, self).onchange_payment_term_date_invoice(
|
||||
payment_term_id, date_invoice)
|
||||
if res and isinstance(res, dict) and 'value' in res:
|
||||
@@ -54,8 +89,8 @@ class AccountInvoice(models.Model):
|
||||
# generated from customer invoices linked to the partners' account because:
|
||||
# 1) the label of an account move line is an important field, we can't
|
||||
# write a rubbish '/' in it !
|
||||
# 2) the 'name' field of the account.move.line is used in the overdue letter,
|
||||
# and '/' is not meaningful for our customer !
|
||||
# 2) the 'name' field of the account.move.line is used in the overdue
|
||||
# letter and '/' is not meaningful for our customer !
|
||||
@api.multi
|
||||
def action_number(self):
|
||||
res = super(AccountInvoice, self).action_number()
|
||||
@@ -69,6 +104,28 @@ class AccountInvoice(models.Model):
|
||||
return res
|
||||
|
||||
|
||||
class AccountInvoiceLine(models.Model):
|
||||
_inherit = 'account.invoice.line'
|
||||
|
||||
# In the 'account' module, we have related stored field for:
|
||||
# company_id, partner_id
|
||||
currency_id = fields.Many2one(
|
||||
related='invoice_id.currency_id', readonly=True, store=True)
|
||||
invoice_type = fields.Selection(
|
||||
related='invoice_id.type', store=True, readonly=True)
|
||||
date_invoice = fields.Date(
|
||||
related='invoice_id.date_invoice', store=True, readonly=True)
|
||||
commercial_partner_id = fields.Many2one(
|
||||
related='invoice_id.partner_id.commercial_partner_id',
|
||||
store=True, readonly=True)
|
||||
state = fields.Selection(
|
||||
related='invoice_id.state', store=True, readonly=True,
|
||||
string='Invoice State')
|
||||
invoice_number = fields.Char(
|
||||
related='invoice_id.move_id.name', store=True, readonly=True,
|
||||
string='Invoice Number')
|
||||
|
||||
|
||||
class AccountFiscalYear(models.Model):
|
||||
_inherit = 'account.fiscalyear'
|
||||
|
||||
@@ -105,10 +162,51 @@ class AccountAccount(models.Model):
|
||||
else:
|
||||
return super(AccountAccount, self).name_get()
|
||||
|
||||
def _check_account_type(self, cr, uid, ids, context=None):
|
||||
'''Disable this native python constraint, because we want to be able
|
||||
to configure payable/receivable accounts with an account type
|
||||
with close_method == 'balance' in order to have opening entries with
|
||||
fewer lines. It is not a problem because we always use
|
||||
account_financial_report_webkit which doesn't take the detailed
|
||||
opening entries into account.'''
|
||||
return True
|
||||
|
||||
_constraints = [
|
||||
# The method name must be exactly the same as the native
|
||||
# method, in order to override it
|
||||
(_check_account_type, 'No error message', ['user_type', 'type']),
|
||||
]
|
||||
|
||||
@api.model
|
||||
def check_account_hierarchy(self):
|
||||
'''designed to be called by a script'''
|
||||
accounts = self.env['account.account'].search([])
|
||||
parent_accounts = self
|
||||
for account in accounts:
|
||||
if account.parent_id and account.parent_id not in parent_accounts:
|
||||
parent_accounts += account.parent_id
|
||||
err_msg = []
|
||||
view_user_type = self.env.ref('account.data_account_type_view')
|
||||
for pacc in parent_accounts:
|
||||
if pacc.type != 'view':
|
||||
err_msg.append(_(
|
||||
'Parent account %s should have type=view '
|
||||
'(current type=%s)') % (pacc.code, pacc.type))
|
||||
if pacc.user_type != view_user_type:
|
||||
err_msg.append(_(
|
||||
'Parent account %s should have user_type=view (current '
|
||||
'(user_type=%s)') % (pacc.code, pacc.user_type.name))
|
||||
if err_msg:
|
||||
raise UserError('\n'.join(err_msg))
|
||||
|
||||
|
||||
class AccountAnalyticAccount(models.Model):
|
||||
_inherit = 'account.analytic.account'
|
||||
|
||||
invoice_line_ids = fields.One2many(
|
||||
'account.invoice.line', 'account_analytic_id', 'Invoice Lines',
|
||||
readonly=True)
|
||||
|
||||
@api.multi
|
||||
def name_get(self):
|
||||
if self._context.get('analytic_account_show_code_only'):
|
||||
@@ -125,11 +223,55 @@ class AccountAnalyticAccount(models.Model):
|
||||
class AccountMove(models.Model):
|
||||
_inherit = 'account.move'
|
||||
|
||||
# When ref is too long, the PDF general ledger report becomes
|
||||
# unreadable
|
||||
ref = fields.Char(size=32)
|
||||
# If you want to migrate existing data :
|
||||
# update account_move set ref=left(ref,32) where ref is not null;
|
||||
# update account_move_line set ref=left(ref,32) where ref is not null;
|
||||
|
||||
# Allow to duplicate an account.move that belongs to a closed period
|
||||
period_id = fields.Many2one(copy=False)
|
||||
date = fields.Date(copy=False)
|
||||
|
||||
@api.onchange('date')
|
||||
def date_onchange(self):
|
||||
if self.date:
|
||||
self.period_id = self.env['account.period'].find(self.date)
|
||||
|
||||
@api.model
|
||||
def delete_move_no_lines(self):
|
||||
'''designed to be called by a script'''
|
||||
moves_no_lines = self.search([('line_id', '=', False)])
|
||||
inv_moves_sr = self.env['account.invoice'].search_read(
|
||||
[('move_id', '!=', False)], ['move_id'])
|
||||
move2inv = {} # key=move_id, value=invoice_id
|
||||
invoice_move_no_line = {} # key=ID, value=number
|
||||
deleted_move_ids = []
|
||||
for inv_move_sr in inv_moves_sr:
|
||||
move2inv[inv_move_sr['move_id'][0]] = inv_move_sr['id']
|
||||
for move in moves_no_lines:
|
||||
for l in move.line_id:
|
||||
raise UserError(_('Move %d has a line !') % move.id)
|
||||
if move.id not in move2inv:
|
||||
if move.state == 'posted':
|
||||
move.state = 'draft'
|
||||
deleted_move_ids.append(move.id)
|
||||
move.unlink()
|
||||
else:
|
||||
invoice_move_no_line[move2inv[move.id]] = move.name
|
||||
if deleted_move_ids:
|
||||
logger.info(
|
||||
'Account move IDs %s have been deleted because they '
|
||||
'had 0 lines', deleted_move_ids)
|
||||
else:
|
||||
logger.info('0 moves without lines found')
|
||||
if invoice_move_no_line:
|
||||
for inv_id, inv_number in invoice_move_no_line.iteritems():
|
||||
logger.info(
|
||||
'Invoice ID %d number %s has a move with 0 lines',
|
||||
inv_id, inv_number)
|
||||
|
||||
|
||||
class AccountMoveLine(models.Model):
|
||||
_inherit = 'account.move.line'
|
||||
@@ -163,6 +305,28 @@ class AccountMoveLine(models.Model):
|
||||
else:
|
||||
self.credit = amount_company_currency
|
||||
|
||||
analytic_account_id = fields.Many2one(
|
||||
domain=[('type', 'not in', ('view', 'template'))])
|
||||
|
||||
|
||||
class AccountBankStatement(models.Model):
|
||||
_inherit = 'account.bank.statement'
|
||||
|
||||
start_date = fields.Date(
|
||||
compute='_compute_dates', string='Start Date', readonly=True,
|
||||
store=True)
|
||||
end_date = fields.Date(
|
||||
compute='_compute_dates', string='End Date', readonly=True,
|
||||
store=True)
|
||||
|
||||
@api.multi
|
||||
@api.depends('line_ids.date')
|
||||
def _compute_dates(self):
|
||||
for st in self:
|
||||
dates = [line.date for line in st.line_ids]
|
||||
st.start_date = dates and min(dates) or False
|
||||
st.end_date = dates and max(dates) or False
|
||||
|
||||
|
||||
class AccountBankStatementLine(models.Model):
|
||||
_inherit = 'account.bank.statement.line'
|
||||
@@ -210,6 +374,7 @@ class AccountBankStatementLine(models.Model):
|
||||
raise UserError(_(
|
||||
'No journal entry linked to this bank statement line.'))
|
||||
|
||||
|
||||
class ResPartner(models.Model):
|
||||
_inherit = 'res.partner'
|
||||
|
||||
@@ -252,6 +417,8 @@ class ResPartner(models.Model):
|
||||
payable_journal_item_count = fields.Integer(
|
||||
compute='_compute_journal_item_count',
|
||||
string="Payable Journal Items", readonly=True)
|
||||
property_account_position = fields.Many2one(
|
||||
track_visibility='onchange')
|
||||
|
||||
|
||||
class AccountFiscalPosition(models.Model):
|
||||
|
||||
@@ -38,6 +38,11 @@
|
||||
<field name="period_id" position="attributes">
|
||||
<attribute name="groups"></attribute>
|
||||
</field>
|
||||
<!-- move sent field and make it visible -->
|
||||
<field name="sent" position="replace"/>
|
||||
<field name="move_id" position="after">
|
||||
<field name="sent"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -61,6 +66,123 @@
|
||||
<filter name="unpaid" position="after">
|
||||
<filter name="overdue" string="Overdue"
|
||||
domain="[('state', '=', 'open'), ('date_due', '<', current_date)]"/>
|
||||
<separator/>
|
||||
<filter name="to_send" string="To Send" domain="[('sent', '=', False), ('state', 'in', ('open', 'paid'))]"/>
|
||||
<filter name="sent" string="Sent" domain="[('sent', '=', True)]"/>
|
||||
<separator/>
|
||||
<filter name="no_attachment" string="Missing Attachment" domain="[('has_attachment', '=', False)]"/>
|
||||
</filter>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Having a menu entry on invoice lines is often very usefull for odoo user:
|
||||
they can search in their lines, etc...
|
||||
So I enhance the generic views and add actions, but I don't add menu entries here ;
|
||||
the creation of the corresponding menu entry should be done in the customer-specific
|
||||
module -->
|
||||
<record id="view_invoice_line_tree" model="ir.ui.view">
|
||||
<field name="name">account_usability.invoice_line_tree</field>
|
||||
<field name="model">account.invoice.line</field>
|
||||
<field name="inherit_id" ref="account.view_invoice_line_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="name" position="before">
|
||||
<field name="partner_id" invisible="not context.get('show_invoice_fields')"/>
|
||||
<field name="date_invoice" invisible="not context.get('show_invoice_fields')"/>
|
||||
<field name="invoice_number" invisible="not context.get('show_invoice_fields')"/>
|
||||
</field>
|
||||
<field name="price_subtotal" position="after">
|
||||
<field name="currency_id"/>
|
||||
<field name="state" invisible="not context.get('show_invoice_fields')"/>
|
||||
<field name="invoice_type" invisible="1"/>
|
||||
</field>
|
||||
<xpath expr="/tree" position="attributes">
|
||||
<attribute name="edit">0</attribute>
|
||||
<attribute name="create">0</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="account_invoice_line_search" model="ir.ui.view">
|
||||
<field name="name">account_usability.invoice_line_search</field>
|
||||
<field name="model">account.invoice.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Invoice Lines">
|
||||
<field name="partner_id"/>
|
||||
<field name="product_id"/>
|
||||
<field name="account_id"/>
|
||||
<field name="invoice_number"/>
|
||||
<field name="name"/>
|
||||
<filter name="out_invoice" string="Customer Invoices"
|
||||
domain="[('invoice_type', '=', 'out_invoice')]"/>
|
||||
<filter name="out_refund" string="Customer Refunds"
|
||||
domain="[('invoice_type', '=', 'out_refund')]"/>
|
||||
<filter name="in_invoice" string="Supplier Invoices"
|
||||
domain="[('invoice_type', '=', 'in_invoice')]"/>
|
||||
<filter name="in_refund" string="Supplier Refunds"
|
||||
domain="[('invoice_type', '=', 'in_refund')]"/>
|
||||
<separator/>
|
||||
<filter name="draft" string="Draft" domain="[('state', '=', 'draft')]"/>
|
||||
<filter name="unpaid" string="Not Paid" domain="[('state', '=', 'open')]"/>
|
||||
<filter name="paid" string="Paid" domain="[('state', '=', 'paid')]"/>
|
||||
|
||||
<group string="Group By" name="groupby">
|
||||
<filter name="partner_groupby" string="Partner"
|
||||
context="{'group_by': 'partner_id'}"/>
|
||||
<filter name="commercial_partner_group_by" string="Commercial Partner"
|
||||
context="{'group_by': 'commercial_partner_id'}"/>
|
||||
<filter name="date_groupby" string="Invoice Date"
|
||||
context="{'group_by': 'date_invoice'}"/>
|
||||
<filter name="product_groupby" string="Product"
|
||||
context="{'group_by': 'product_id'}"/>
|
||||
<filter name="account_groupby" string="Account"
|
||||
context="{'group_by': 'account_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="out_invoice_line_action" model="ir.actions.act_window">
|
||||
<field name="name">Customer Invoice Lines</field>
|
||||
<field name="res_model">account.invoice.line</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('invoice_type', '=', 'out_invoice')]</field>
|
||||
<field name="context">{'show_invoice_fields': True}</field>
|
||||
</record>
|
||||
|
||||
<record id="out_refund_line_action" model="ir.actions.act_window">
|
||||
<field name="name">Customer Refund Lines</field>
|
||||
<field name="res_model">account.invoice.line</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('invoice_type', '=', 'out_refund')]</field>
|
||||
<field name="context">{'show_invoice_fields': True}</field>
|
||||
</record>
|
||||
|
||||
<record id="in_invoice_line_action" model="ir.actions.act_window">
|
||||
<field name="name">Supplier Invoice Lines</field>
|
||||
<field name="res_model">account.invoice.line</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('invoice_type', '=', 'in_invoice')]</field>
|
||||
<field name="context">{'show_invoice_fields': True}</field>
|
||||
</record>
|
||||
|
||||
<record id="in_refund_line_action" model="ir.actions.act_window">
|
||||
<field name="name">Supplier Refund Lines</field>
|
||||
<field name="res_model">account.invoice.line</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('invoice_type', '=', 'in_refund')]</field>
|
||||
<field name="context">{'show_invoice_fields': True}</field>
|
||||
</record>
|
||||
|
||||
<record id="view_account_invoice_report_search" model="ir.ui.view">
|
||||
<field name="name">usability.account.invoice.report.search</field>
|
||||
<field name="model">account.invoice.report</field>
|
||||
<field name="inherit_id" ref="account.view_account_invoice_report_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="categ_id" position="after">
|
||||
<field name="product_id"/>
|
||||
</field>
|
||||
<filter name="category_product" position="after">
|
||||
<filter string="Product" name="product_group_by" context="{'group_by': 'product_id'}"/>
|
||||
</filter>
|
||||
</field>
|
||||
</record>
|
||||
@@ -68,10 +190,24 @@
|
||||
<!-- model account.move.line / Journal Items -->
|
||||
<record id="account.action_account_moves_all_a" model="ir.actions.act_window">
|
||||
<field name="limit">200</field>
|
||||
<!-- add graph -->
|
||||
<field name="view_mode">tree_account_move_line_quickadd,form,graph</field>
|
||||
<!-- Win space, because there are already many columns -->
|
||||
<field name="context">{'journal_show_code_only': True}</field>
|
||||
</record>
|
||||
|
||||
<record id="account_move_line_graph" model="ir.ui.view">
|
||||
<field name="name">usability.account.move.line.graph</field>
|
||||
<field name="model">account.move.line</field>
|
||||
<field name="inherit_id" ref="account.account_move_line_graph"/>
|
||||
<field name="arch" type="xml">
|
||||
<graph position="attributes">
|
||||
<!-- pivot by default instead of bar -->
|
||||
<attribute name="type">pivot</attribute>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- model account.move / Journal Entries -->
|
||||
<record id="account.action_move_journal_line" model="ir.actions.act_window">
|
||||
<field name="limit">200</field>
|
||||
@@ -101,6 +237,7 @@
|
||||
<field name="arch" type="xml">
|
||||
<field name="partner_id" position="after">
|
||||
<field name="reconcile_ref" />
|
||||
<field name="debit" filter_domain="['|', ('debit', '=', self), ('credit', '=', self)]" string="Debit or Credit"/>
|
||||
</field>
|
||||
<filter name="unreconciled" position="before">
|
||||
<filter name="reconciled" string="Fully Reconciled" domain="[('reconcile_id', '!=', False)]"/>
|
||||
@@ -109,6 +246,9 @@
|
||||
<field name="name" position="attributes">
|
||||
<attribute name="string">Name or Reference</attribute>
|
||||
</field>
|
||||
<field name="account_id" position="after">
|
||||
<field name="analytic_account_id"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -128,6 +268,7 @@
|
||||
<field name="name">account_usability.account_move_line_tree</field>
|
||||
<field name="model">account.move.line</field>
|
||||
<field name="inherit_id" ref="account.view_move_line_tree"/>
|
||||
<field name="priority">1</field> <!-- to be compatible with account_analytic_plans which removes the field analytic_account_id and has a priority of 2 -->
|
||||
<field name="arch" type="xml">
|
||||
<field name="analytic_account_id" position="attributes">
|
||||
<attribute name="invisible"></attribute>
|
||||
@@ -179,9 +320,10 @@
|
||||
</button>
|
||||
</button>
|
||||
<button name="%(account.action_account_moves_all_tree)d" position="attributes">
|
||||
<attribute name="type">object</attribute>
|
||||
<attribute name="name">show_receivable_account</attribute>
|
||||
<attribute name="attrs">{'invisible': [('customer', '=', False)]}</attribute>
|
||||
<attribute name="invisible">True</attribute>
|
||||
</button>
|
||||
<button name="%(account.action_account_moves_all_tree)d" position="after">
|
||||
<button type="object" class="oe_stat_button" name="show_receivable_account" icon="fa-list" attrs="{'invisible': [('customer', '=', False)]}"/>
|
||||
</button>
|
||||
<field name="journal_item_count" position="attributes">
|
||||
<attribute name="string">Receivable Account</attribute>
|
||||
@@ -189,6 +331,12 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- When you click on the "Contract" button of partner form view,
|
||||
the newly created analytic accounts should be of type contract ! -->
|
||||
<record id="account.action_open_partner_analytic_accounts" model="ir.actions.act_window">
|
||||
<field name="context">{'search_default_partner_id': [active_id], 'default_partner_id': active_id, 'default_type': 'contract'}</field>
|
||||
</record>
|
||||
|
||||
<record id="view_bank_statement_form" model="ir.ui.view">
|
||||
<field name="name">usability.account.bank.statement.form</field>
|
||||
<field name="model">account.bank.statement</field>
|
||||
@@ -200,6 +348,65 @@
|
||||
string="View Account Move" icon="gtk-redo"
|
||||
attrs="{'invisible': [('journal_entry_id', '=', False)]}"/>
|
||||
</xpath>
|
||||
<field name="company_id" position="before">
|
||||
<field name="start_date"/>
|
||||
<field name="end_date"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_bank_statement_tree" model="ir.ui.view">
|
||||
<field name="name">usability.account.bank.statement.tree</field>
|
||||
<field name="model">account.bank.statement</field>
|
||||
<field name="inherit_id" ref="account.view_bank_statement_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="period_id" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</field>
|
||||
<field name="date" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</field>
|
||||
<field name="journal_id" position="after">
|
||||
<field name="start_date"/>
|
||||
<field name="end_date"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_bank_statement_search" model="ir.ui.view">
|
||||
<field name="name">usability.account.bank.statement.search</field>
|
||||
<field name="model">account.bank.statement</field>
|
||||
<field name="inherit_id" ref="account.view_bank_statement_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="date" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</field>
|
||||
<filter context="{'group_by': 'period_id'}" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</filter>
|
||||
<filter context="{'group_by': 'period_id'}" position="after">
|
||||
<filter name="start_date_groupby" string="Start Date"
|
||||
context="{'group_by': 'start_date'}"/>
|
||||
<filter name="end_date_groupby" string="End Date"
|
||||
context="{'group_by': 'end_date'}"/>
|
||||
</filter>
|
||||
<field name="date" position="after">
|
||||
<field name="start_date"/>
|
||||
<field name="end_date"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_account_analytic_account_form" model="ir.ui.view">
|
||||
<field name="name">analytic.analytic.account.form</field>
|
||||
<field name="model">account.analytic.account</field>
|
||||
<field name="inherit_id" ref="analytic.view_account_analytic_account_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<notebook position="inside">
|
||||
<page name="invoice_lines" string="Related Invoice Lines" attrs="{'invisible': [('type', 'not in', ('contract', 'normal'))]}">
|
||||
<field name="invoice_line_ids" nolabel="1" context="{'show_invoice_fields': 1}"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
379
account_usability/i18n/account_usability.pot
Normal file
379
account_usability/i18n/account_usability.pot
Normal file
@@ -0,0 +1,379 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * account_usability
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 8.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-11-06 10:16+0000\n"
|
||||
"PO-Revision-Date: 2017-11-06 10:16+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_usability
|
||||
#: help:account.invoice.line,state:0
|
||||
msgid " * The 'Draft' status is used when a user is encoding a new and unconfirmed Invoice.\n"
|
||||
" * The 'Pro-forma' when invoice is in Pro-forma status,invoice does not have an invoice number.\n"
|
||||
" * The 'Open' status is used when user create invoice,a invoice number is generated.Its in open status till user does not pay invoice.\n"
|
||||
" * The 'Paid' status is set automatically when the invoice is paid. Its related journal entries may or may not be reconciled.\n"
|
||||
" * The 'Cancelled' status is used when user cancel invoice."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
#: model:ir.model,name:account_usability.model_account_account
|
||||
msgid "Account"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.model,name:account_usability.model_account_move
|
||||
msgid "Account Entry"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.model,name:account_usability.model_account_analytic_account
|
||||
msgid "Analytic Account"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.model,name:account_usability.model_account_bank_statement
|
||||
msgid "Bank Statement"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.model,name:account_usability.model_account_bank_statement_line
|
||||
msgid "Bank Statement Line"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.mark.sent:account_usability.account_invoice_mark_sent_form
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.invoice.line,commercial_partner_id:0
|
||||
msgid "Commercial Entity"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
msgid "Commercial Partner"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.invoice.mark.sent,create_uid:0
|
||||
msgid "Created by"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.invoice.mark.sent,create_date:0
|
||||
msgid "Created on"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.invoice.line,currency_id:0
|
||||
msgid "Currency"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.actions.act_window,name:account_usability.out_invoice_line_action
|
||||
msgid "Customer Invoice Lines"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
msgid "Customer Invoices"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.actions.act_window,name:account_usability.out_refund_line_action
|
||||
msgid "Customer Refund Lines"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
msgid "Customer Refunds"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.move.line:account_usability.view_account_move_line_filter
|
||||
msgid "Debit or Credit"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.invoice.mark.sent,display_name:0
|
||||
msgid "Display Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
msgid "Draft"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.bank.statement:account_usability.view_bank_statement_search
|
||||
#: field:account.bank.statement,end_date:0
|
||||
msgid "End Date"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.model,name:account_usability.model_account_fiscal_position
|
||||
msgid "Fiscal Position"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.model,name:account_usability.model_account_fiscalyear
|
||||
msgid "Fiscal Year"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.move.line:account_usability.view_account_move_line_filter
|
||||
msgid "Fully Reconciled"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
msgid "Group By"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.invoice.mark.sent,id:0
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.model,name:account_usability.model_account_invoice
|
||||
msgid "Invoice"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
#: field:account.invoice.line,date_invoice:0
|
||||
msgid "Invoice Date"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.model,name:account_usability.model_account_invoice_line
|
||||
msgid "Invoice Line"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.analytic.account,invoice_line_ids:0
|
||||
msgid "Invoice Lines"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.invoice.line,invoice_number:0
|
||||
msgid "Invoice Number"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.invoice.line,state:0
|
||||
msgid "Invoice State"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.model,name:account_usability.model_account_journal
|
||||
msgid "Journal"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.model,name:account_usability.model_account_move_line
|
||||
msgid "Journal Items"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: help:account.invoice.line,date_invoice:0
|
||||
msgid "Keep empty to use the current date"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.invoice.mark.sent,__last_update:0
|
||||
msgid "Last Modified on"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.invoice.mark.sent,write_uid:0
|
||||
msgid "Last Updated by"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.invoice.mark.sent,write_date:0
|
||||
msgid "Last Updated on"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.mark.sent:account_usability.account_invoice_mark_sent_form
|
||||
#: model:ir.actions.act_window,name:account_usability.account_invoice_mark_sent_action
|
||||
msgid "Mark as Sent"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.mark.sent:account_usability.account_invoice_mark_sent_form
|
||||
#: model:ir.model,name:account_usability.model_account_invoice_mark_sent
|
||||
msgid "Mark invoices as sent"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice:account_usability.view_account_invoice_filter
|
||||
msgid "Missing Attachment"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: code:addons/account_usability/account.py:255
|
||||
#, python-format
|
||||
msgid "Move %d has a line !"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.move.line:account_usability.view_account_move_line_filter
|
||||
msgid "Name or Reference"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: constraint:account.account:0
|
||||
msgid "No error message"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: code:addons/account_usability/account.py:374
|
||||
#, python-format
|
||||
msgid "No journal entry linked to this bank statement line."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
msgid "Not Paid"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice:account_usability.view_account_invoice_filter
|
||||
msgid "Overdue"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
msgid "Paid"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: code:addons/account_usability/account.py:192
|
||||
#, python-format
|
||||
msgid "Parent account %s should have type=view (current type=%s)"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: code:addons/account_usability/account.py:196
|
||||
#, python-format
|
||||
msgid "Parent account %s should have user_type=view (current (user_type=%s)"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.move.line:account_usability.view_account_move_line_filter
|
||||
msgid "Partially Reconciled"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
#: model:ir.model,name:account_usability.model_res_partner
|
||||
msgid "Partner"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:res.partner:account_usability.partner_view_button_journal_item_count
|
||||
msgid "Payable Account"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
#: view:account.invoice.report:account_usability.view_account_invoice_report_search
|
||||
msgid "Product"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:res.partner:account_usability.partner_view_button_journal_item_count
|
||||
msgid "Receivable Account"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.analytic.account:account_usability.view_account_analytic_account_form
|
||||
msgid "Related Invoice Lines"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
msgid "Search Invoice Lines"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice:account_usability.view_account_invoice_filter
|
||||
msgid "Sent"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.bank.statement:account_usability.view_bank_statement_search
|
||||
#: field:account.bank.statement,start_date:0
|
||||
msgid "Start Date"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.actions.act_window,name:account_usability.in_invoice_line_action
|
||||
msgid "Supplier Invoice Lines"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
msgid "Supplier Invoices"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.actions.act_window,name:account_usability.in_refund_line_action
|
||||
msgid "Supplier Refund Lines"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
msgid "Supplier Refunds"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.mark.sent:account_usability.account_invoice_mark_sent_form
|
||||
msgid "This wizard will mark as sent all the selected invoices."
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice:account_usability.view_account_invoice_filter
|
||||
msgid "To Send"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:res.partner:account_usability.partner_view_button_journal_item_count
|
||||
msgid "True"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.invoice.line,invoice_type:0
|
||||
msgid "Type"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.bank.statement:account_usability.view_bank_statement_form
|
||||
msgid "View Account Move"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.move.line:account_usability.account_move_line_graph
|
||||
msgid "pivot"
|
||||
msgstr ""
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice:account_usability.invoice_form
|
||||
#: view:account.invoice:account_usability.invoice_supplier_form
|
||||
msgid "selection"
|
||||
msgstr ""
|
||||
|
||||
383
account_usability/i18n/fr.po
Normal file
383
account_usability/i18n/fr.po
Normal file
@@ -0,0 +1,383 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * account_usability
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 8.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2017-11-06 10:16+0000\n"
|
||||
"PO-Revision-Date: 2017-11-06 10:16+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_usability
|
||||
#: help:account.invoice.line,state:0
|
||||
msgid " * The 'Draft' status is used when a user is encoding a new and unconfirmed Invoice.\n"
|
||||
" * The 'Pro-forma' when invoice is in Pro-forma status,invoice does not have an invoice number.\n"
|
||||
" * The 'Open' status is used when user create invoice,a invoice number is generated.Its in open status till user does not pay invoice.\n"
|
||||
" * The 'Paid' status is set automatically when the invoice is paid. Its related journal entries may or may not be reconciled.\n"
|
||||
" * The 'Cancelled' status is used when user cancel invoice."
|
||||
msgstr " * The 'Draft' status is used when a user is encoding a new and unconfirmed Invoice.\n"
|
||||
" * The 'Pro-forma' when invoice is in Pro-forma status,invoice does not have an invoice number.\n"
|
||||
" * The 'Open' status is used when user create invoice,a invoice number is generated.Its in open status till user does not pay invoice.\n"
|
||||
" * The 'Paid' status is set automatically when the invoice is paid. Its related journal entries may or may not be reconciled.\n"
|
||||
" * The 'Cancelled' status is used when user cancel invoice."
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
#: model:ir.model,name:account_usability.model_account_account
|
||||
msgid "Account"
|
||||
msgstr "Compte"
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.model,name:account_usability.model_account_move
|
||||
msgid "Account Entry"
|
||||
msgstr "Pièce comptable"
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.model,name:account_usability.model_account_analytic_account
|
||||
msgid "Analytic Account"
|
||||
msgstr "Compte analytique"
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.model,name:account_usability.model_account_bank_statement
|
||||
msgid "Bank Statement"
|
||||
msgstr "Relevé Bancaire"
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.model,name:account_usability.model_account_bank_statement_line
|
||||
msgid "Bank Statement Line"
|
||||
msgstr "Ligne de Relevé Bancaire"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.mark.sent:account_usability.account_invoice_mark_sent_form
|
||||
msgid "Cancel"
|
||||
msgstr "Annuler"
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.invoice.line,commercial_partner_id:0
|
||||
msgid "Commercial Entity"
|
||||
msgstr "Entité Commercial"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
msgid "Commercial Partner"
|
||||
msgstr "Partenaire Commercial"
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.invoice.mark.sent,create_uid:0
|
||||
msgid "Created by"
|
||||
msgstr "Créé par"
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.invoice.mark.sent,create_date:0
|
||||
msgid "Created on"
|
||||
msgstr "Créé le"
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.invoice.line,currency_id:0
|
||||
msgid "Currency"
|
||||
msgstr "Monnaie"
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.actions.act_window,name:account_usability.out_invoice_line_action
|
||||
msgid "Customer Invoice Lines"
|
||||
msgstr "Lignes de facture client"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
msgid "Customer Invoices"
|
||||
msgstr "Factures Client"
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.actions.act_window,name:account_usability.out_refund_line_action
|
||||
msgid "Customer Refund Lines"
|
||||
msgstr "Lignes d'avoir client"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
msgid "Customer Refunds"
|
||||
msgstr "Avoir CLient"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.move.line:account_usability.view_account_move_line_filter
|
||||
msgid "Debit or Credit"
|
||||
msgstr "Debit ou Credit"
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.invoice.mark.sent,display_name:0
|
||||
msgid "Display Name"
|
||||
msgstr "Display Name"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
msgid "Draft"
|
||||
msgstr "Brouillon"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.bank.statement:account_usability.view_bank_statement_search
|
||||
#: field:account.bank.statement,end_date:0
|
||||
msgid "End Date"
|
||||
msgstr "Date de Fin"
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.model,name:account_usability.model_account_fiscal_position
|
||||
msgid "Fiscal Position"
|
||||
msgstr "Position fiscale"
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.model,name:account_usability.model_account_fiscalyear
|
||||
msgid "Fiscal Year"
|
||||
msgstr "Exercice"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.move.line:account_usability.view_account_move_line_filter
|
||||
msgid "Fully Reconciled"
|
||||
msgstr "Complétement Réconcillié"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
msgid "Group By"
|
||||
msgstr "Groupé par"
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.invoice.mark.sent,id:0
|
||||
msgid "ID"
|
||||
msgstr "ID"
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.model,name:account_usability.model_account_invoice
|
||||
msgid "Invoice"
|
||||
msgstr "Facture"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
#: field:account.invoice.line,date_invoice:0
|
||||
msgid "Invoice Date"
|
||||
msgstr "Date de Facture"
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.model,name:account_usability.model_account_invoice_line
|
||||
msgid "Invoice Line"
|
||||
msgstr "Lignes de facture"
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.analytic.account,invoice_line_ids:0
|
||||
msgid "Invoice Lines"
|
||||
msgstr "Lignes de Facture"
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.invoice.line,invoice_number:0
|
||||
msgid "Invoice Number"
|
||||
msgstr "N° de Facture"
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.invoice.line,state:0
|
||||
msgid "Invoice State"
|
||||
msgstr "Etat de la facture"
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.model,name:account_usability.model_account_journal
|
||||
msgid "Journal"
|
||||
msgstr "Journal"
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.model,name:account_usability.model_account_move_line
|
||||
msgid "Journal Items"
|
||||
msgstr "Écritures comptables"
|
||||
|
||||
#. module: account_usability
|
||||
#: help:account.invoice.line,date_invoice:0
|
||||
msgid "Keep empty to use the current date"
|
||||
msgstr "Laisser vide pour utiliser la date courante"
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.invoice.mark.sent,__last_update:0
|
||||
msgid "Last Modified on"
|
||||
msgstr "Modifié le"
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.invoice.mark.sent,write_uid:0
|
||||
msgid "Last Updated by"
|
||||
msgstr "Modifié par"
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.invoice.mark.sent,write_date:0
|
||||
msgid "Last Updated on"
|
||||
msgstr "Modifié le"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.mark.sent:account_usability.account_invoice_mark_sent_form
|
||||
#: model:ir.actions.act_window,name:account_usability.account_invoice_mark_sent_action
|
||||
msgid "Mark as Sent"
|
||||
msgstr "Marquer comme envoyé"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.mark.sent:account_usability.account_invoice_mark_sent_form
|
||||
#: model:ir.model,name:account_usability.model_account_invoice_mark_sent
|
||||
msgid "Mark invoices as sent"
|
||||
msgstr "Marquer les factures comme envoyé"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice:account_usability.view_account_invoice_filter
|
||||
msgid "Missing Attachment"
|
||||
msgstr "Pièce jointe manquante"
|
||||
|
||||
#. module: account_usability
|
||||
#: code:addons/account_usability/account.py:255
|
||||
#, python-format
|
||||
msgid "Move %d has a line !"
|
||||
msgstr "Le mouvement %d a une ligne !"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.move.line:account_usability.view_account_move_line_filter
|
||||
msgid "Name or Reference"
|
||||
msgstr "Nom ou Réference"
|
||||
|
||||
#. module: account_usability
|
||||
#: constraint:account.account:0
|
||||
msgid "No error message"
|
||||
msgstr "No error message"
|
||||
|
||||
#. module: account_usability
|
||||
#: code:addons/account_usability/account.py:374
|
||||
#, python-format
|
||||
msgid "No journal entry linked to this bank statement line."
|
||||
msgstr "Aucune entrée de journal n'est liée à ce relevé bancaire."
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
msgid "Not Paid"
|
||||
msgstr "Non Payé"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice:account_usability.view_account_invoice_filter
|
||||
msgid "Overdue"
|
||||
msgstr "En retard"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
msgid "Paid"
|
||||
msgstr "Payé"
|
||||
|
||||
#. module: account_usability
|
||||
#: code:addons/account_usability/account.py:192
|
||||
#, python-format
|
||||
msgid "Parent account %s should have type=view (current type=%s)"
|
||||
msgstr "Parent account %s should have type=view (current type=%s)"
|
||||
|
||||
#. module: account_usability
|
||||
#: code:addons/account_usability/account.py:196
|
||||
#, python-format
|
||||
msgid "Parent account %s should have user_type=view (current (user_type=%s)"
|
||||
msgstr "Parent account %s should have user_type=view (current (user_type=%s)"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.move.line:account_usability.view_account_move_line_filter
|
||||
msgid "Partially Reconciled"
|
||||
msgstr "Partiellement Réconcillié"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
#: model:ir.model,name:account_usability.model_res_partner
|
||||
msgid "Partner"
|
||||
msgstr "Partenaire"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:res.partner:account_usability.partner_view_button_journal_item_count
|
||||
msgid "Payable Account"
|
||||
msgstr "Compte Créditeur"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
#: view:account.invoice.report:account_usability.view_account_invoice_report_search
|
||||
msgid "Product"
|
||||
msgstr "Produit"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:res.partner:account_usability.partner_view_button_journal_item_count
|
||||
msgid "Receivable Account"
|
||||
msgstr "Compte Débiteur"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.analytic.account:account_usability.view_account_analytic_account_form
|
||||
msgid "Related Invoice Lines"
|
||||
msgstr "Lignes de facture associées"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
msgid "Search Invoice Lines"
|
||||
msgstr "Rechercher les lignes de facture"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice:account_usability.view_account_invoice_filter
|
||||
msgid "Sent"
|
||||
msgstr "Envoyé"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.bank.statement:account_usability.view_bank_statement_search
|
||||
#: field:account.bank.statement,start_date:0
|
||||
msgid "Start Date"
|
||||
msgstr "Date de Début"
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.actions.act_window,name:account_usability.in_invoice_line_action
|
||||
msgid "Supplier Invoice Lines"
|
||||
msgstr "Lignes de Facture Fournisseur"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
msgid "Supplier Invoices"
|
||||
msgstr "Facture Fournisseur"
|
||||
|
||||
#. module: account_usability
|
||||
#: model:ir.actions.act_window,name:account_usability.in_refund_line_action
|
||||
msgid "Supplier Refund Lines"
|
||||
msgstr "Lignes d'avoir fournisseur"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.line:account_usability.account_invoice_line_search
|
||||
msgid "Supplier Refunds"
|
||||
msgstr "Avoirs Fournisseur"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice.mark.sent:account_usability.account_invoice_mark_sent_form
|
||||
msgid "This wizard will mark as sent all the selected invoices."
|
||||
msgstr "Cet assistant marquera comme envoyé toutes les factures sélectionnées."
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice:account_usability.view_account_invoice_filter
|
||||
msgid "To Send"
|
||||
msgstr "A Envoyer"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:res.partner:account_usability.partner_view_button_journal_item_count
|
||||
msgid "True"
|
||||
msgstr "Vrai"
|
||||
|
||||
#. module: account_usability
|
||||
#: field:account.invoice.line,invoice_type:0
|
||||
msgid "Type"
|
||||
msgstr "Type"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.bank.statement:account_usability.view_bank_statement_form
|
||||
msgid "View Account Move"
|
||||
msgstr "Voir les mouvements comptables"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.move.line:account_usability.account_move_line_graph
|
||||
msgid "pivot"
|
||||
msgstr "pivot"
|
||||
|
||||
#. module: account_usability
|
||||
#: view:account.invoice:account_usability.invoice_form
|
||||
#: view:account.invoice:account_usability.invoice_supplier_form
|
||||
msgid "selection"
|
||||
msgstr "selection"
|
||||
|
||||
BIN
account_usability/static/description/icon.png
Normal file
BIN
account_usability/static/description/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 84 KiB |
3
account_usability/wizard/__init__.py
Normal file
3
account_usability/wizard/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
from . import account_invoice_mark_sent
|
||||
23
account_usability/wizard/account_invoice_mark_sent.py
Normal file
23
account_usability/wizard/account_invoice_mark_sent.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from openerp import models, api
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AccountInvoiceMarkSent(models.TransientModel):
|
||||
_name = 'account.invoice.mark.sent'
|
||||
_description = 'Mark invoices as sent'
|
||||
|
||||
@api.multi
|
||||
def run(self):
|
||||
assert self.env.context.get('active_model') == 'account.invoice',\
|
||||
'Source model must be invoices'
|
||||
assert self.env.context.get('active_ids'), 'No invoices selected'
|
||||
invoices = self.env['account.invoice'].browse(
|
||||
self.env.context.get('active_ids'))
|
||||
invoices.write({'sent': True})
|
||||
logger.info('Marking invoices with ID %s as sent', invoices.ids)
|
||||
return
|
||||
36
account_usability/wizard/account_invoice_mark_sent_view.xml
Normal file
36
account_usability/wizard/account_invoice_mark_sent_view.xml
Normal file
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
The licence is in the file __openerp__.py
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="account_invoice_mark_sent_form" model="ir.ui.view">
|
||||
<field name="name">account.invoice.mark.sent.form</field>
|
||||
<field name="model">account.invoice.mark.sent</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Mark invoices as sent">
|
||||
<p>
|
||||
This wizard will mark as sent all the selected invoices.
|
||||
</p>
|
||||
<footer>
|
||||
<button type="object" name="run" string="Mark as Sent" class="oe_highlight"/>
|
||||
<button special="cancel" string="Cancel" class="oe_link"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<act_window id="account_invoice_mark_sent_action"
|
||||
multi="True"
|
||||
key2="client_action_multi"
|
||||
name="Mark as Sent"
|
||||
res_model="account.invoice.mark.sent"
|
||||
src_model="account.invoice"
|
||||
view_mode="form"
|
||||
target="new" />
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
3
base_mail_sender_bcc/__init__.py
Normal file
3
base_mail_sender_bcc/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import ir_mail_server
|
||||
22
base_mail_sender_bcc/__openerp__.py
Normal file
22
base_mail_sender_bcc/__openerp__.py
Normal file
@@ -0,0 +1,22 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
'name': 'Mail Sender Bcc',
|
||||
'version': '8.0.1.0.0',
|
||||
'category': 'Mail',
|
||||
'license': 'AGPL-3',
|
||||
'summary': "Always send a copy of the mail to the sender",
|
||||
'description': """
|
||||
Mail Sender Bcc
|
||||
===============
|
||||
|
||||
With this module, when Odoo sends an outgoing email, it adds the sender as Bcc (blind copy) of the email.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['base'],
|
||||
'installable': True,
|
||||
}
|
||||
28
base_mail_sender_bcc/ir_mail_server.py
Normal file
28
base_mail_sender_bcc/ir_mail_server.py
Normal file
@@ -0,0 +1,28 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from openerp import models
|
||||
|
||||
|
||||
class IrMailServer(models.Model):
|
||||
_inherit = 'ir.mail_server'
|
||||
|
||||
def build_email(
|
||||
self, email_from, email_to, subject, body, email_cc=None,
|
||||
email_bcc=None, reply_to=False, attachments=None,
|
||||
message_id=None, references=None, object_id=False,
|
||||
subtype='plain', headers=None,
|
||||
body_alternative=None, subtype_alternative='plain'):
|
||||
if email_from:
|
||||
if email_bcc is None:
|
||||
email_bcc = [email_from]
|
||||
elif isinstance(email_bcc, list) and email_from not in email_bcc:
|
||||
email_bcc.append(email_from)
|
||||
return super(IrMailServer, self).build_email(
|
||||
email_from, email_to, subject, body, email_cc=email_cc,
|
||||
email_bcc=email_bcc, reply_to=reply_to, attachments=attachments,
|
||||
message_id=message_id, references=references, object_id=object_id,
|
||||
subtype=subtype, headers=headers,
|
||||
body_alternative=body_alternative,
|
||||
subtype_alternative=subtype_alternative)
|
||||
3
base_partner_ref/__init__.py
Normal file
3
base_partner_ref/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import models
|
||||
27
base_partner_ref/__openerp__.py
Normal file
27
base_partner_ref/__openerp__.py
Normal file
@@ -0,0 +1,27 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2017-2024 Akretion France (https://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
'name': 'Base Partner Reference',
|
||||
'version': '8.0.1.0.0',
|
||||
'category': 'Partner',
|
||||
'license': 'AGPL-3',
|
||||
'summary': "Improve usage of partner's Internal Reference",
|
||||
'description': """
|
||||
Base Partner Reference
|
||||
======================
|
||||
|
||||
* Adds Internal Reference in partner tree view
|
||||
|
||||
* Adds Internal Reference in name_get()
|
||||
|
||||
* Adds unicity constraint on Internal Reference
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'https://github.com/akretion/odoo-usability',
|
||||
'depends': ['base'],
|
||||
'data': ['views/res_partner.xml'],
|
||||
'installable': True,
|
||||
}
|
||||
3
base_partner_ref/models/__init__.py
Normal file
3
base_partner_ref/models/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import res_partner
|
||||
62
base_partner_ref/models/res_partner.py
Normal file
62
base_partner_ref/models/res_partner.py
Normal file
@@ -0,0 +1,62 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2017-2024 Akretion France
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from openerp import models, fields, api
|
||||
|
||||
|
||||
class ResPartner(models.Model):
|
||||
_inherit = 'res.partner'
|
||||
|
||||
display_name = fields.Char(compute="_compute_display_name", store=True, string="Name")
|
||||
# copy=False on 'ref' is already in base_usability
|
||||
|
||||
_sql_constraints = [(
|
||||
'ref_unique',
|
||||
'unique(ref)',
|
||||
'A partner already exists with this internal reference!'
|
||||
)]
|
||||
|
||||
# inspired by _display_name_compute from base module
|
||||
@api.multi
|
||||
@api.depends('parent_id', 'is_company', 'name', 'ref')
|
||||
def _compute_display_name(self):
|
||||
for partner in self:
|
||||
partner.display_name = partner.with_context(show_address=False, show_address_only=False, show_email=False).name_get()[0][1]
|
||||
|
||||
def name_get(self, cr, uid, ids, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
res = []
|
||||
for record in self.browse(cr, uid, ids, context=context):
|
||||
name = record.name
|
||||
# START modif of native name_get() method
|
||||
if record.ref:
|
||||
name = u"[%s] %s" % (record.ref, name)
|
||||
# END modif of native name_get() method
|
||||
if record.parent_id and not record.is_company:
|
||||
name = "%s, %s" % (record.parent_name, name)
|
||||
if context.get('show_address_only'):
|
||||
name = self._display_address(cr, uid, record, without_company=True, context=context)
|
||||
if context.get('show_address'):
|
||||
name = name + "\n" + self._display_address(cr, uid, record, without_company=True, context=context)
|
||||
name = name.replace('\n\n', '\n')
|
||||
name = name.replace('\n\n', '\n')
|
||||
if context.get('show_email') and record.email:
|
||||
name = "%s <%s>" % (name, record.email)
|
||||
res.append((record.id, name))
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def name_search(self, name='', args=None, operator='ilike', limit=100):
|
||||
if args is None:
|
||||
args = []
|
||||
if name and operator == 'ilike':
|
||||
recs = self.search([('ref', '=', name)] + args, limit=limit)
|
||||
if recs:
|
||||
rec_childs = self.search([('id', 'child_of', recs.ids)])
|
||||
return rec_childs.name_get()
|
||||
return super(ResPartner, self).name_search(name=name, args=args, operator=operator, limit=limit)
|
||||
54
base_partner_ref/views/res_partner.xml
Normal file
54
base_partner_ref/views/res_partner.xml
Normal file
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2017-2024 Akretion France (https://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="view_partner_form" model="ir.ui.view">
|
||||
<field name="name">Move ref in partner form to make it more visible</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.view_partner_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="website" position="before">
|
||||
<field name="ref"/>
|
||||
</field>
|
||||
<xpath expr="//page[@name='sales_purchases']//field[@name='ref']" position="replace"/>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_partner_tree" model="ir.ui.view">
|
||||
<field name="name">Add ref in partner tree view</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.view_partner_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<!-- show name and ref in separate columns -->
|
||||
<field name="display_name" position="after">
|
||||
<field name="ref"/>
|
||||
<field name="name"/>
|
||||
</field>
|
||||
<field name="display_name" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="res_partner_kanban_view" model="ir.ui.view">
|
||||
<field name="name">Add ref in partner kanban view</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.res_partner_kanban_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="display_name" position="after">
|
||||
<field name="ref"/>
|
||||
</field>
|
||||
<li t-if="record.email.raw_value" position="after">
|
||||
<li t-if="record.ref.raw_value">Ref: <field name="ref"/></li>
|
||||
</li>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -12,6 +12,9 @@
|
||||
<field name="model">ir.module.module</field>
|
||||
<field name="inherit_id" ref="base.view_module_filter"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//filter[@name='extra']" position="after">
|
||||
<filter name="installable" string="Installable" domain="[('state', '!=', 'uninstallable')]"/>
|
||||
</xpath>
|
||||
<xpath expr="//filter[@string='Category']" position="after">
|
||||
<filter string="State" domain="[]" context="{'group_by':'state'}"/>
|
||||
</xpath>
|
||||
@@ -20,7 +23,7 @@
|
||||
|
||||
<record id="base.open_module_tree" model="ir.actions.act_window">
|
||||
<field name="res_model">ir.module.module</field>
|
||||
<field name="context">{}</field>
|
||||
<field name="context">{'search_default_installable': 1}</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
|
||||
@@ -28,7 +28,7 @@ class Partner(models.Model):
|
||||
|
||||
name = fields.Char(track_visibility='onchange')
|
||||
parent_id = fields.Many2one(track_visibility='onchange')
|
||||
ref = fields.Char(track_visibility='onchange')
|
||||
ref = fields.Char(track_visibility='onchange', copy=False)
|
||||
lang = fields.Selection(track_visibility='onchange')
|
||||
user_id = fields.Many2one(track_visibility='onchange')
|
||||
vat = fields.Char(track_visibility='onchange')
|
||||
@@ -45,6 +45,7 @@ class Partner(models.Model):
|
||||
is_company = fields.Boolean(track_visibility='onchange')
|
||||
use_parent_address = fields.Boolean(track_visibility='onchange')
|
||||
active = fields.Boolean(track_visibility='onchange')
|
||||
company_id = fields.Many2one(track_visibility='onchange')
|
||||
# For reports
|
||||
name_title = fields.Char(
|
||||
compute='_compute_name_title', string='Name with Title')
|
||||
@@ -54,9 +55,15 @@ class Partner(models.Model):
|
||||
def _compute_name_title(self):
|
||||
name_title = self.name
|
||||
if self.title:
|
||||
title = self.title.shortcut or self.title
|
||||
title = self.title.shortcut or self.title.name
|
||||
if self.is_company:
|
||||
name_title = ' '.join([name_title, title])
|
||||
else:
|
||||
name_title = ' '.join([title, name_title])
|
||||
self.name_title = name_title
|
||||
|
||||
|
||||
class ResPartnerCategory(models.Model):
|
||||
_inherit = 'res.partner.category'
|
||||
|
||||
name = fields.Char(translate=False)
|
||||
|
||||
BIN
base_usability/static/description/icon.png
Normal file
BIN
base_usability/static/description/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 84 KiB |
37
base_user_auth_log/README.rst
Normal file
37
base_user_auth_log/README.rst
Normal file
@@ -0,0 +1,37 @@
|
||||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
|
||||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||
:alt: License: AGPL-3
|
||||
|
||||
========================
|
||||
User Authentication Logs
|
||||
========================
|
||||
|
||||
This module adds user authentication logs in Odoo. It logs both authentication success and failures.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
The authentication logs can be seen:
|
||||
|
||||
* on the users's form view in the *Auth Logs* tab,
|
||||
* in the menu *Settings > Technical > Security > Authentication Logs*.
|
||||
|
||||
Authentication failure logs are displayed in red. Authentication success logs are displayed in black.
|
||||
|
||||
To have read access to the logs, you need to be part of the *Access Rights* group.
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues
|
||||
<https://github.com/akretion/odoo-usability/issues>`_. In case of trouble, please
|
||||
check there if your issue has already been reported. If you spotted it first,
|
||||
help us smashing it by providing a detailed and welcomed feedback.
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
* Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
3
base_user_auth_log/__init__.py
Normal file
3
base_user_auth_log/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import models
|
||||
21
base_user_auth_log/__openerp__.py
Normal file
21
base_user_auth_log/__openerp__.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
'name': 'Users authentification logs',
|
||||
'version': '8.0.1.0.0',
|
||||
'category': 'Tools',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Adds users authentication logs',
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['base'],
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'views/res_users_auth_log.xml',
|
||||
'views/res_users.xml',
|
||||
'data/ir_cron.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
24
base_user_auth_log/data/ir_cron.xml
Normal file
24
base_user_auth_log/data/ir_cron.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data noupdate="1"> <!-- noupdate = 1 for the 'active' field -->
|
||||
|
||||
<record id="purge_auth_log_cron" model="ir.cron">
|
||||
<field name="name">Purge old authentication logs</field>
|
||||
<field name="active" eval="True"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="interval_number">1</field>
|
||||
<field name="interval_type">months</field>
|
||||
<field name="numbercall">-1</field> <!-- don't limit the number of calls -->
|
||||
<field name="doall" eval="False"/>
|
||||
<field name="model" eval="'res.users.auth.log'"/>
|
||||
<field name="function" eval="'_purge_old_auth_logs'" />
|
||||
<field name="args" eval="'()'"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
4
base_user_auth_log/models/__init__.py
Normal file
4
base_user_auth_log/models/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import res_users_auth_log
|
||||
from . import res_users
|
||||
42
base_user_auth_log/models/res_users.py
Normal file
42
base_user_auth_log/models/res_users.py
Normal file
@@ -0,0 +1,42 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from openerp import models, fields, registry, SUPERUSER_ID
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ResUsers(models.Model):
|
||||
_inherit = 'res.users'
|
||||
|
||||
auth_log_ids = fields.One2many(
|
||||
'res.users.auth.log', 'user_id', string='Authentication Logs')
|
||||
|
||||
def _login(self, db, login, password):
|
||||
user_id = super(ResUsers, self)._login(db, login, password)
|
||||
with registry(db).cursor() as cr:
|
||||
if user_id:
|
||||
result = 'success'
|
||||
else:
|
||||
user_id = None # To write a null value, psycopg2 wants None
|
||||
result = 'failure'
|
||||
cr.execute(
|
||||
"SELECT id FROM res_users WHERE login=%s", (login, ))
|
||||
user_select = cr.fetchall()
|
||||
if user_select:
|
||||
user_id = user_select[0][0]
|
||||
|
||||
cr.execute("""
|
||||
INSERT INTO res_users_auth_log (
|
||||
create_uid,
|
||||
create_date,
|
||||
date,
|
||||
login,
|
||||
result,
|
||||
user_id
|
||||
) VALUES (
|
||||
%s, NOW() AT TIME ZONE 'UTC', NOW() AT TIME ZONE 'UTC',
|
||||
%s, %s, %s)""", (SUPERUSER_ID, login, result, user_id))
|
||||
logger.info('Auth log created for login %s type %s', login, result)
|
||||
return user_id
|
||||
44
base_user_auth_log/models/res_users_auth_log.py
Normal file
44
base_user_auth_log/models/res_users_auth_log.py
Normal file
@@ -0,0 +1,44 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from openerp import models, fields, api, _
|
||||
from openerp.exceptions import Warning as UserError
|
||||
from datetime import datetime, timedelta
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ResUsersAuthLog(models.Model):
|
||||
_name = 'res.users.auth.log'
|
||||
_description = 'Users Authentication Logs'
|
||||
_order = 'date desc'
|
||||
_rec_name = 'date'
|
||||
|
||||
user_id = fields.Many2one(
|
||||
'res.users', string='User', ondelete='cascade', readonly=True)
|
||||
login = fields.Char(string='Login', readonly=True)
|
||||
date = fields.Datetime(
|
||||
string='Authentication Date', required=True, readonly=True)
|
||||
result = fields.Selection([
|
||||
('success', 'Success'),
|
||||
('failure', 'Failure'),
|
||||
], string='Result', required=True, readonly=True)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if not self._context.get('authenticate_create'):
|
||||
raise UserError(_(
|
||||
"You cannot manually create an authentication log."))
|
||||
return super(ResUsersAuthLog, self).create(vals)
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
raise UserError(_("You cannot modify an authentication log."))
|
||||
|
||||
@api.model
|
||||
def _purge_old_auth_logs(self):
|
||||
expiry_date = datetime.today() - timedelta(days=365)
|
||||
self._cr.execute(
|
||||
"DELETE FROM res_users_auth_log WHERE date <= %s", (expiry_date, ))
|
||||
logger.info('Auth logs older than %s have been purged', expiry_date)
|
||||
2
base_user_auth_log/security/ir.model.access.csv
Normal file
2
base_user_auth_log/security/ir.model.access.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_res_users_auth_log,Read access to Access rights group,model_res_users_auth_log,base.group_erp_manager,1,0,0,0
|
||||
|
26
base_user_auth_log/views/res_users.xml
Normal file
26
base_user_auth_log/views/res_users.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
|
||||
<record id="view_users_form" model="ir.ui.view">
|
||||
<field name="name">auth_logs.res.users.form</field>
|
||||
<field name="model">res.users</field>
|
||||
<field name="inherit_id" ref="base.view_users_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<notebook position="inside">
|
||||
<page string="Auth Logs" name="auth_logs">
|
||||
<field name="auth_log_ids" nolabel="1"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
81
base_user_auth_log/views/res_users_auth_log.xml
Normal file
81
base_user_auth_log/views/res_users_auth_log.xml
Normal file
@@ -0,0 +1,81 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
|
||||
<record id="res_users_auth_log_form" model="ir.ui.view">
|
||||
<field name="name">res.users.auth.logs.form</field>
|
||||
<field name="model">res.users.auth.log</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Authentication Log">
|
||||
<group name="main">
|
||||
<field name="date"/>
|
||||
<field name="user_id"/>
|
||||
<field name="login"/>
|
||||
<field name="result"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="res_users_auth_log_tree" model="ir.ui.view">
|
||||
<field name="name">res.users.auth.logs.tree</field>
|
||||
<field name="model">res.users.auth.log</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Authentication Logs" colors="red:result=='failure'">
|
||||
<field name="date"/>
|
||||
<field name="user_id" invisible="not context.get('auth_logs_main_view')"/>
|
||||
<field name="login" invisible="not context.get('auth_logs_main_view')"/>
|
||||
<field name="result"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="res_users_auth_log_search" model="ir.ui.view">
|
||||
<field name="name">res.users.auth.logs.search</field>
|
||||
<field name="model">res.users.auth.log</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Authentication Logs">
|
||||
<field name="user_id"/>
|
||||
<filter name="success" string="Success" domain="[('result', '=', 'success')]"/>
|
||||
<filter name="failure" string="Failure" domain="[('result', '=', 'failure')]"/>
|
||||
<group string="Group By" name="groupby">
|
||||
<filter name="day_groupby" string="Day" context="{'group_by': 'date:day'}"/>
|
||||
<filter name="week_groupby" string="Week" context="{'group_by': 'date:week'}"/>
|
||||
<filter name="month_groupby" string="Month" context="{'group_by': 'date:month'}"/>
|
||||
<filter name="user_groupby" string="User" context="{'group_by': 'user_id'}"/>
|
||||
<filter name="result_groupby" string="Result" context="{'group_by': 'result'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="res_users_auth_log_graph" model="ir.ui.view">
|
||||
<field name="name">res.users.auth.logs.graph</field>
|
||||
<field name="model">res.users.auth.log</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Analyze Authentication Logs" type="pivot">
|
||||
<field name="date" type="row" interval="week"/>
|
||||
<field name="user_id" type="col"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="res_users_auth_log_action" model="ir.actions.act_window">
|
||||
<field name="name">Authentication Logs</field>
|
||||
<field name="res_model">res.users.auth.log</field>
|
||||
<field name="view_mode">tree,form,graph</field>
|
||||
<field name="context">{'auth_logs_main_view': True}</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="res_users_auth_log_menu" action="res_users_auth_log_action"
|
||||
parent="base.menu_security" sequence="100"/>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
4
crm_usability/__init__.py
Normal file
4
crm_usability/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import wizard
|
||||
from . import crm
|
||||
35
crm_usability/__openerp__.py
Normal file
35
crm_usability/__openerp__.py
Normal file
@@ -0,0 +1,35 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2016 Akretion (http://www.akretion.com)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
|
||||
{
|
||||
'name': 'CRM Usability',
|
||||
'version': '8.0.1.0.1',
|
||||
'category': 'Customer Relationship Management',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'CRM usability enhancements',
|
||||
'description': """
|
||||
CRM Usability
|
||||
=============
|
||||
|
||||
The usability improvements include :
|
||||
|
||||
* Adds multi-company record rules on crm.lead.
|
||||
* Some enhancements in the *Merge Partners* wizard:
|
||||
* take into account the unaccent option of the server config file
|
||||
* add optional group by on 'customer' and 'supplier' (active by default)
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion
|
||||
<alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['crm'],
|
||||
'data': [
|
||||
'crm_view.xml',
|
||||
'wizard/base_partner_merge_view.xml',
|
||||
'security/rule.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
12
crm_usability/crm.py
Normal file
12
crm_usability/crm.py
Normal file
@@ -0,0 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (http://www.akretion.com)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
|
||||
from openerp import models, fields
|
||||
|
||||
|
||||
class CrmCaseCateg(models.Model):
|
||||
_inherit = 'crm.case.categ'
|
||||
|
||||
name = fields.Char(translate=False)
|
||||
37
crm_usability/crm_view.xml
Normal file
37
crm_usability/crm_view.xml
Normal file
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2017 Akretion (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
|
||||
<record id="crm_case_form_view_oppor" model="ir.ui.view">
|
||||
<field name="name">usability.crm.opportunity.form</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="inherit_id" ref="crm.crm_case_form_view_oppor"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="active" position="before">
|
||||
<field name="company_id" groups="base.group_multi_company"
|
||||
widget="selection"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="crm_case_inbound_phone_tree_view" model="ir.ui.view">
|
||||
<field name="name">crm_usability.crm.phonecall.tree.inbound</field>
|
||||
<field name="model">crm.phonecall</field>
|
||||
<field name="inherit_id" ref="crm.crm_case_inbound_phone_tree_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="state" position="attributes">
|
||||
<attribute name="invisible">0</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
14
crm_usability/security/rule.xml
Normal file
14
crm_usability/security/rule.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
|
||||
<record id="crm_lead_company_rule" model="ir.rule">
|
||||
<field name="name">Lead/opportunity multi-company rule</field>
|
||||
<field name="model_id" ref="crm.model_crm_lead"/>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
BIN
crm_usability/static/description/icon.png
Normal file
BIN
crm_usability/static/description/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.5 KiB |
3
crm_usability/wizard/__init__.py
Normal file
3
crm_usability/wizard/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import base_partner_merge
|
||||
29
crm_usability/wizard/base_partner_merge.py
Normal file
29
crm_usability/wizard/base_partner_merge.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2016 Akretion (http://www.akretion.com)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
|
||||
from openerp import models, fields, tools
|
||||
|
||||
|
||||
class MergePartnerAutomatic(models.TransientModel):
|
||||
_inherit = 'base.partner.merge.automatic.wizard'
|
||||
|
||||
group_by_customer = fields.Boolean('Customer', default=True)
|
||||
group_by_supplier = fields.Boolean('Supplier', default=True)
|
||||
|
||||
def _generate_query(self, fields, maximum_group=100):
|
||||
sql = super(MergePartnerAutomatic, self)._generate_query(
|
||||
fields, maximum_group=maximum_group)
|
||||
name_sql_original = 'lower(name)'
|
||||
if name_sql_original in sql:
|
||||
if tools.config.get('unaccent', False):
|
||||
sql = sql.replace(
|
||||
name_sql_original,
|
||||
"unaccent(lower(replace(name, ' ', '')))")
|
||||
else:
|
||||
sql = sql.replace(
|
||||
name_sql_original,
|
||||
"lower(replace(name, ' ', ''))")
|
||||
|
||||
return sql
|
||||
23
crm_usability/wizard/base_partner_merge_view.xml
Normal file
23
crm_usability/wizard/base_partner_merge_view.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="base_partner_merge_automatic_wizard_form" model="ir.ui.view">
|
||||
<field name="name">rvip.base.partner.merge.automatic.wizard.form</field>
|
||||
<field name="model">base.partner.merge.automatic.wizard</field>
|
||||
<field name="inherit_id" ref="crm.base_partner_merge_automatic_wizard_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="group_by_is_company" position="after">
|
||||
<field name="group_by_customer"/>
|
||||
<field name="group_by_supplier"/>
|
||||
</field>
|
||||
<xpath expr="//field[@name='partner_ids']/tree/field[@name='is_company']" position="after">
|
||||
<field name="customer"/>
|
||||
<field name="supplier"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
1
delivery_usability/__init__.py
Normal file
1
delivery_usability/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
30
delivery_usability/__openerp__.py
Normal file
30
delivery_usability/__openerp__.py
Normal file
@@ -0,0 +1,30 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2017 Akretion (http://www.akretion.com).
|
||||
# @author Sébastien BEAU <sebastien.beau@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
"name": "Delivery usability",
|
||||
"summary": "Delivery Usability",
|
||||
"version": "8.0.1.0.0",
|
||||
"category": "Warehouse",
|
||||
"website": "www.akretion.com",
|
||||
"author": " Akretion",
|
||||
"license": "AGPL-3",
|
||||
"application": False,
|
||||
"installable": True,
|
||||
"external_dependencies": {
|
||||
"python": [],
|
||||
"bin": [],
|
||||
},
|
||||
"depends": [
|
||||
"delivery",
|
||||
],
|
||||
"data": [
|
||||
"views/stock_picking_view.xml",
|
||||
],
|
||||
"demo": [
|
||||
],
|
||||
"qweb": [
|
||||
]
|
||||
}
|
||||
20
delivery_usability/views/stock_picking_view.xml
Normal file
20
delivery_usability/views/stock_picking_view.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="view_picking_withcarrier_out_form" model="ir.ui.view">
|
||||
<field name="model">stock.picking</field>
|
||||
<field name="inherit_id" ref="delivery.view_picking_withcarrier_out_form"/>
|
||||
<field name="priority" eval="100"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='carrier_id']/.." position="replace">
|
||||
</xpath>
|
||||
<field name="backorder_id" position="after">
|
||||
<field name="carrier_id"/>
|
||||
<field name="carrier_tracking_ref"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 4.6 KiB |
BIN
hr_expense_usability/static/description/icon.png
Normal file
BIN
hr_expense_usability/static/description/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 84 KiB |
7
hr_holidays_lunch_voucher/__init__.py
Normal file
7
hr_holidays_lunch_voucher/__init__.py
Normal file
@@ -0,0 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import company
|
||||
from . import hr_holidays
|
||||
from . import hr_employee
|
||||
from . import lunch_voucher_attribution
|
||||
from . import wizard
|
||||
28
hr_holidays_lunch_voucher/__openerp__.py
Normal file
28
hr_holidays_lunch_voucher/__openerp__.py
Normal file
@@ -0,0 +1,28 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
'name': 'HR Holidays Lunch Voucher',
|
||||
'version': '8.0.1.0.0',
|
||||
'category': 'Human Resources',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Manage lunch vouchers in holidays requests',
|
||||
'description': '',
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['hr_holidays_usability', 'purchase'],
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'security/lunch_voucher_security.xml',
|
||||
'product_data.xml',
|
||||
'company_view.xml',
|
||||
'wizard/lunch_voucher_purchase_view.xml',
|
||||
'lunch_voucher_attribution_view.xml',
|
||||
'hr_employee_view.xml',
|
||||
'hr_holidays_view.xml',
|
||||
'wizard/hr_holidays_post_view.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
20
hr_holidays_lunch_voucher/company.py
Normal file
20
hr_holidays_lunch_voucher/company.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from openerp import models, fields
|
||||
import openerp.addons.decimal_precision as dp
|
||||
|
||||
|
||||
class ResCompany(models.Model):
|
||||
_inherit = 'res.company'
|
||||
|
||||
lunch_voucher_product_id = fields.Many2one(
|
||||
'product.product', string='Lunch Voucher Product',
|
||||
ondelete='restrict')
|
||||
lunch_voucher_employer_price = fields.Float(
|
||||
'Lunch Voucher Employer Price', digits=dp.get_precision('Account'))
|
||||
|
||||
# Add constrain to check that lunch_voucher_employer_price is between
|
||||
# 50% and 60% of the price of lunch_voucher_product_id for France
|
||||
29
hr_holidays_lunch_voucher/company_view.xml
Normal file
29
hr_holidays_lunch_voucher/company_view.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2017 Akretion France (www.akretion.com)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
|
||||
<record id="view_company_form" model="ir.ui.view">
|
||||
<field name="name">lunch_voucher.company.form</field>
|
||||
<field name="model">res.company</field>
|
||||
<field name="inherit_id" ref="base.view_company_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<group name="account_grp" position="after">
|
||||
<group name="lunch_voucher" string="Lunch Vouchers">
|
||||
<field name="lunch_voucher_product_id"/>
|
||||
<!-- <field name="lunch_voucher_po_type"/> -->
|
||||
<field name="lunch_voucher_employer_price"/>
|
||||
</group>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
12
hr_holidays_lunch_voucher/hr_employee.py
Normal file
12
hr_holidays_lunch_voucher/hr_employee.py
Normal file
@@ -0,0 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from openerp import models, fields
|
||||
|
||||
|
||||
class HrEmployee(models.Model):
|
||||
_inherit = 'hr.employee'
|
||||
|
||||
lunch_voucher = fields.Boolean(string="Has Lunch Vouchers", default=True)
|
||||
25
hr_holidays_lunch_voucher/hr_employee_view.xml
Normal file
25
hr_holidays_lunch_voucher/hr_employee_view.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2017 Akretion France (www.akretion.com)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
|
||||
<record id="view_employee_form_leave_inherit" model="ir.ui.view">
|
||||
<field name="name">lunch_voucher.hr.employee.form</field>
|
||||
<field name="model">hr.employee</field>
|
||||
<field name="inherit_id" ref="hr_holidays_usability.view_employee_form_leave_inherit"/>
|
||||
<field name="arch" type="xml">
|
||||
<group name="holidays" position="inside">
|
||||
<field name="lunch_voucher"/>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
45
hr_holidays_lunch_voucher/hr_holidays.py
Normal file
45
hr_holidays_lunch_voucher/hr_holidays.py
Normal file
@@ -0,0 +1,45 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from openerp import models, fields, api
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
|
||||
class HrHolidays(models.Model):
|
||||
_inherit = 'hr.holidays'
|
||||
|
||||
lunch_voucher_id = fields.Many2one(
|
||||
'lunch.voucher.attribution',
|
||||
string="Related Lunch Voucher Attribution")
|
||||
lunch_voucher_remove_qty = fields.Integer(
|
||||
compute='_compute_lunch_voucher_remove_qty', readonly=True,
|
||||
store=True, string='Lunch Vouchers to Deduct')
|
||||
|
||||
@api.depends('employee_id', 'vacation_date_from', 'vacation_date_to')
|
||||
@api.multi
|
||||
def _compute_lunch_voucher_remove_qty(self):
|
||||
hhpo = self.env['hr.holidays.public']
|
||||
for hol in self:
|
||||
qty = 0
|
||||
if (
|
||||
hol.type == 'remove' and
|
||||
hol.vacation_date_from and
|
||||
hol.vacation_date_to):
|
||||
start_date_dt = fields.Date.from_string(hol.vacation_date_from)
|
||||
end_date_str = hol.vacation_date_to
|
||||
date_dt = start_date_dt
|
||||
# Remove 1 full LV when vacation_time_from == noon
|
||||
# and also when vacation_time_to == noon
|
||||
while True:
|
||||
if (
|
||||
date_dt.weekday() not in (5, 6) and
|
||||
not hhpo.is_public_holiday(
|
||||
date_dt, hol.employee_id.id)):
|
||||
qty += 1
|
||||
date_dt += relativedelta(days=1)
|
||||
date_str = fields.Date.to_string(date_dt)
|
||||
if date_str > end_date_str:
|
||||
break
|
||||
hol.lunch_voucher_remove_qty = qty
|
||||
39
hr_holidays_lunch_voucher/hr_holidays_view.xml
Normal file
39
hr_holidays_lunch_voucher/hr_holidays_view.xml
Normal file
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2017 Akretion (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
|
||||
<record id="edit_holiday_new" model="ir.ui.view">
|
||||
<field name="name">hr_holidays_lunch_voucher.leave_request_form</field>
|
||||
<field name="model">hr.holidays</field>
|
||||
<field name="inherit_id" ref="hr_holidays_usability.edit_holiday_new"/>
|
||||
<field name="arch" type="xml">
|
||||
<group name="counters" position="after">
|
||||
<group name="lunch_vouchers" string="Lunch Vouchers" attrs="{'invisible': [('type', '!=', 'remove')]}">
|
||||
<field name="lunch_voucher_remove_qty"/>
|
||||
<field name="lunch_voucher_id"/>
|
||||
</group>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_holiday" model="ir.ui.view">
|
||||
<field name="name">hr_holidays_lunch_voucher.leave_request_tree</field>
|
||||
<field name="model">hr.holidays</field>
|
||||
<field name="inherit_id" ref="hr_holidays_usability.view_holiday"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="number_of_days" position="after">
|
||||
<field name="lunch_voucher_remove_qty" string="Lunch Vouchers -=" sum="Total"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
45
hr_holidays_lunch_voucher/lunch_voucher_attribution.py
Normal file
45
hr_holidays_lunch_voucher/lunch_voucher_attribution.py
Normal file
@@ -0,0 +1,45 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from openerp import models, fields, api
|
||||
|
||||
|
||||
class LunchVoucherAttribution(models.Model):
|
||||
_name = 'lunch.voucher.attribution'
|
||||
_description = 'Lunch Voucher Attribution'
|
||||
_order = 'date desc'
|
||||
|
||||
employee_id = fields.Many2one(
|
||||
'hr.employee', string='Employee', ondelete='restrict',
|
||||
required=True, readonly=True)
|
||||
company_id = fields.Many2one(
|
||||
related='employee_id.resource_id.company_id', readonly=True,
|
||||
store=True)
|
||||
date = fields.Date('Attribution Date', readonly=True)
|
||||
purchase_id = fields.Many2one(
|
||||
'purchase.order', 'Purchase Order',
|
||||
readonly=True)
|
||||
month_work_days = fields.Integer(
|
||||
'Month Work Days',
|
||||
help="Number of work days of the month (without taking into "
|
||||
"account the holidays)")
|
||||
no_lunch_days = fields.Integer(
|
||||
compute='_compute_qty', string='No Lunch Days',
|
||||
readonly=True, store=True)
|
||||
qty = fields.Integer(
|
||||
compute='_compute_qty', readonly=True, store=True,
|
||||
string='Lunch Voucher Quantity')
|
||||
holiday_ids = fields.One2many(
|
||||
'hr.holidays', 'lunch_voucher_id', readonly=True)
|
||||
|
||||
@api.depends('month_work_days', 'holiday_ids.lunch_voucher_remove_qty')
|
||||
@api.multi
|
||||
def _compute_qty(self):
|
||||
for rec in self:
|
||||
no_lunch_days = 0
|
||||
for hol in rec.holiday_ids:
|
||||
no_lunch_days += hol.lunch_voucher_remove_qty
|
||||
rec.no_lunch_days = no_lunch_days
|
||||
rec.qty = rec.month_work_days - no_lunch_days
|
||||
97
hr_holidays_lunch_voucher/lunch_voucher_attribution_view.xml
Normal file
97
hr_holidays_lunch_voucher/lunch_voucher_attribution_view.xml
Normal file
@@ -0,0 +1,97 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2017 Akretion France (www.akretion.com)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
|
||||
<record id="lunch_voucher_attribution_form" model="ir.ui.view">
|
||||
<field name="name">lunch.voucher.attribution.form</field>
|
||||
<field name="model">lunch.voucher.attribution</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Lunch Vouchers Attribution">
|
||||
<group name="main">
|
||||
<field name="employee_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="date"/>
|
||||
<field name="month_work_days"/>
|
||||
<field name="no_lunch_days"/>
|
||||
<field name="qty"/>
|
||||
<field name="purchase_id"/>
|
||||
</group>
|
||||
<group name="holidays" string="Related Holidays">
|
||||
<field name="holiday_ids" nolabel="1" context="{'tree_view_ref': 'hr_holidays_lunch_voucher.view_holiday', 'form_view_ref': 'hr_holidays_lunch_voucher.edit_holiday_new'}"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="lunch_voucher_attribution_tree" model="ir.ui.view">
|
||||
<field name="name">lunch.voucher.attribution.tree</field>
|
||||
<field name="model">lunch.voucher.attribution</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Lunch Vouchers Attribution">
|
||||
<field name="date"/>
|
||||
<field name="employee_id"/>
|
||||
<field name="month_work_days"/>
|
||||
<field name="no_lunch_days" sum="Total"/>
|
||||
<field name="qty" sum="Total"/>
|
||||
<field name="purchase_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="lunch_voucher_attribution_search" model="ir.ui.view">
|
||||
<field name="name">lunch.voucher.attribution.search</field>
|
||||
<field name="model">lunch.voucher.attribution</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Lunch Vouchers Attribution">
|
||||
<field name="date"/>
|
||||
<field name="employee_id"/>
|
||||
<filter name="purchased" string="Purchased" domain="[('purchase_id', '!=', False)]"/>
|
||||
<filter name="to_purchase" string="To Purchase" domain="[('purchase_id', '=', False)]"/>
|
||||
<group string="Group By" name="groupby">
|
||||
<filter name="employee_groupby" string="Employee" context="{'group_by': 'employee_id'}"/>
|
||||
<filter name="purchase_order_groupby" string="Purchase Order" context="{'group_by': 'purchase_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="lunch_voucher_attribution_graph" model="ir.ui.view">
|
||||
<field name="name">lunch.voucher.attribution.graph</field>
|
||||
<field name="model">lunch.voucher.attribution</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Lunch Vouchers Attribution" type="pivot">
|
||||
<field name="date" type="row" interval="month"/>
|
||||
<field name="qty" type="measure"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="lunch_voucher_attribution_action" model="ir.actions.act_window">
|
||||
<field name="name">Lunch Voucher Attribution</field>
|
||||
<field name="res_model">lunch.voucher.attribution</field>
|
||||
<field name="view_mode">tree,form,graph</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="lunch_voucher_attribution_menu"
|
||||
action="lunch_voucher_attribution_action"
|
||||
parent="hr_holidays.menu_open_ask_holidays" sequence="200"/>
|
||||
|
||||
<act_window id="lunch_voucher_attribution_action_create_po"
|
||||
multi="True"
|
||||
key2="client_action_multi"
|
||||
name="Create Purchase Order"
|
||||
res_model="lunch.voucher.purchase"
|
||||
src_model="lunch.voucher.attribution"
|
||||
view_mode="form"
|
||||
target="new" />
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
27
hr_holidays_lunch_voucher/product_data.xml
Normal file
27
hr_holidays_lunch_voucher/product_data.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
|
||||
<record id="lunch_voucher_product" model="product.product">
|
||||
<field name="name">Lunch Vouchers</field>
|
||||
<field name="categ_id" ref="product.product_category_all"/>
|
||||
<field name="sale_ok" eval="False"/>
|
||||
<field name="purchase_ok" eval="True"/>
|
||||
<field name="list_price">0</field>
|
||||
<field name="standard_price">8</field>
|
||||
<field name="type">service</field> <!-- For those who want to manage stock of lunch vouchers, they can switch type to product manually -->
|
||||
<field name="uom_id" ref="product.product_uom_unit"/>
|
||||
<field name="uom_po_id" ref="product.product_uom_unit"/>
|
||||
<field name="supplier_taxes_id" eval="False"/>
|
||||
<field name="taxes_id" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record id="base.main_company" model="res.company">
|
||||
<field name="lunch_voucher_product_id" ref="lunch_voucher_product"/>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
3
hr_holidays_lunch_voucher/security/ir.model.access.csv
Normal file
3
hr_holidays_lunch_voucher/security/ir.model.access.csv
Normal file
@@ -0,0 +1,3 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_lunch_voucher_attribution_full,Full access on lunch_voucher_attribution,model_lunch_voucher_attribution,base.group_hr_manager,1,1,1,1
|
||||
access_lunch_voucher_attribution_read,Read access on lunch_voucher_attribution,model_lunch_voucher_attribution,base.group_user,1,0,0,0
|
||||
|
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
|
||||
<record id="lunch_voucher_attribution_employee" model="ir.rule">
|
||||
<field name="name">Personal Lunch Voucher Attributions</field>
|
||||
<field name="model_id" ref="hr_holidays_lunch_voucher.model_lunch_voucher_attribution"/>
|
||||
<field name="domain_force">[('employee_id.user_id', '=', user.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="lunch_voucher_attribution_officer" model="ir.rule">
|
||||
<field name="name">HR Officer sees all Lunch Voucher Attributions</field>
|
||||
<field name="model_id" ref="hr_holidays_lunch_voucher.model_lunch_voucher_attribution"/>
|
||||
<field name="domain_force">[(1, '=', 1)]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_hr_manager'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="lunch_voucher_attribution_multicompany_rule" model="ir.rule">
|
||||
<field name="name">Lunch Voucher Attribution multi-company</field>
|
||||
<field name="model_id" ref="hr_holidays_lunch_voucher.model_lunch_voucher_attribution"/>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
4
hr_holidays_lunch_voucher/wizard/__init__.py
Normal file
4
hr_holidays_lunch_voucher/wizard/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
from . import hr_holidays_post
|
||||
from . import lunch_voucher_purchase
|
||||
74
hr_holidays_lunch_voucher/wizard/hr_holidays_post.py
Normal file
74
hr_holidays_lunch_voucher/wizard/hr_holidays_post.py
Normal file
@@ -0,0 +1,74 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from openerp import models, fields, api
|
||||
from dateutil.relativedelta import relativedelta
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HrHolidaysPost(models.TransientModel):
|
||||
_inherit = 'hr.holidays.post'
|
||||
|
||||
lunch_voucher_po = fields.Boolean(
|
||||
string='Generate Lunch Voucher Purchase Order')
|
||||
work_days = fields.Integer(string='Work Days')
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields_list):
|
||||
res = super(HrHolidaysPost, self).default_get(fields_list)
|
||||
hhpo = self.env['hr.holidays.public']
|
||||
company = self.env.user.company_id
|
||||
if company.lunch_voucher_product_id:
|
||||
res['lunch_voucher_po'] = True
|
||||
today = fields.Date.context_today(self)
|
||||
today_dt = fields.Date.from_string(today)
|
||||
cur_month = today_dt.month
|
||||
# last day of month
|
||||
date_dt = today_dt + relativedelta(day=31)
|
||||
work_days = date_dt.day
|
||||
logger.info('Number of days in the month: %d', work_days)
|
||||
# from last day of month to the first
|
||||
while date_dt.month == cur_month:
|
||||
if hhpo.is_public_holiday(date_dt):
|
||||
work_days -= 1
|
||||
logger.info(
|
||||
"%s is a bank holiday, don't count", date_dt)
|
||||
# if it's a saturday/sunday
|
||||
elif date_dt.weekday() in (5, 6):
|
||||
work_days -= 1
|
||||
logger.info(
|
||||
"%s is a saturday/sunday, don't count", date_dt)
|
||||
date_dt += relativedelta(days=-1)
|
||||
logger.info('Number of work days in the month: %d', work_days)
|
||||
res['work_days'] = work_days
|
||||
return res
|
||||
|
||||
@api.multi
|
||||
def run(self):
|
||||
self.ensure_one()
|
||||
lvao = self.env['lunch.voucher.attribution']
|
||||
today = fields.Date.context_today(self)
|
||||
employees = self.env['hr.employee'].search([
|
||||
('lunch_voucher', '=', True),
|
||||
('company_id', '=', self.env.user.company_id.id),
|
||||
])
|
||||
lv_dict = {}
|
||||
for employee in employees:
|
||||
lv_dict[employee.id] = []
|
||||
for hol in self.holidays_to_post_ids:
|
||||
if not hol.lunch_voucher_id and hol.employee_id.id in lv_dict:
|
||||
lv_dict[hol.employee_id.id].append(hol.id)
|
||||
for employee_id, hol_ids in lv_dict.iteritems():
|
||||
vals = {
|
||||
'employee_id': employee_id,
|
||||
'date': today,
|
||||
'month_work_days': self.work_days,
|
||||
}
|
||||
if hol_ids:
|
||||
vals['holiday_ids'] = [(6, 0, hol_ids)]
|
||||
lvao.create(vals)
|
||||
return super(HrHolidaysPost, self).run()
|
||||
27
hr_holidays_lunch_voucher/wizard/hr_holidays_post_view.xml
Normal file
27
hr_holidays_lunch_voucher/wizard/hr_holidays_post_view.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2017 Akretion (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
|
||||
<record id="hr_holidays_post_form" model="ir.ui.view">
|
||||
<field name="name">hr_holidays_post_form</field>
|
||||
<field name="model">hr.holidays.post</field>
|
||||
<field name="inherit_id" ref="hr_holidays_usability.hr_holidays_post_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="holidays_to_post_ids" position="before">
|
||||
<field name="lunch_voucher_po" states="done"/>
|
||||
<field name="work_days"
|
||||
attrs="{'invisible': ['|', ('state', '!=', 'done'), ('lunch_voucher_po', '=', False)]}"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
77
hr_holidays_lunch_voucher/wizard/lunch_voucher_purchase.py
Normal file
77
hr_holidays_lunch_voucher/wizard/lunch_voucher_purchase.py
Normal file
@@ -0,0 +1,77 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from openerp import models, api, _
|
||||
from openerp.exceptions import Warning as UserError
|
||||
|
||||
|
||||
class LunchVoucherPurchase(models.TransientModel):
|
||||
_name = 'lunch.voucher.purchase'
|
||||
_description = 'Purchase Lunch Vouchers Wizard'
|
||||
|
||||
@api.multi
|
||||
def run(self):
|
||||
self.ensure_one()
|
||||
company = self.env.user.company_id
|
||||
if not company.lunch_voucher_product_id:
|
||||
raise UserError(_(
|
||||
"Lunch Voucher Product not configured on company %s")
|
||||
% company.name)
|
||||
if not company.lunch_voucher_product_id.seller_id:
|
||||
raise UserError(_(
|
||||
"Missing supplier on Product '%s'.")
|
||||
% company.lunch_voucher_product_id.name)
|
||||
|
||||
poo = self.env['purchase.order']
|
||||
polo = self.env['purchase.order.line']
|
||||
lvao = self.env['lunch.voucher.attribution']
|
||||
assert self._context.get('active_model') ==\
|
||||
'lunch.voucher.attribution', 'wrong source model'
|
||||
assert self._context.get('active_ids'), 'missing active_ids in ctx'
|
||||
lvouchers = lvao.browse(self._context['active_ids'])
|
||||
total_qty = 0
|
||||
for lvoucher in lvouchers:
|
||||
if lvoucher.purchase_id:
|
||||
raise UserError(_(
|
||||
"One of the Lunch Voucher Attributions you selected "
|
||||
"related to employee '%s' is already linked to a "
|
||||
"purchase order.") % lvoucher.employee_id.name)
|
||||
if lvoucher.qty < 0:
|
||||
raise UserError(_(
|
||||
"One of the Lunch Voucher Attributions you selected "
|
||||
"related to employee '%s' has a negative quantity.")
|
||||
% lvoucher.employee_id.name)
|
||||
total_qty += lvoucher.qty
|
||||
|
||||
supplier = company.lunch_voucher_product_id.seller_id
|
||||
pick_type_id = poo.default_get(['picking_type_id'])['picking_type_id']
|
||||
onchange_ptype_vals = poo.browse(False).onchange_picking_type_id(
|
||||
pick_type_id)
|
||||
vals = onchange_ptype_vals['value']
|
||||
onchange_vals = poo.browse(False).onchange_partner_id(supplier.id)
|
||||
vals.update(onchange_vals['value'])
|
||||
vals['partner_id'] = supplier.id
|
||||
|
||||
product = company.lunch_voucher_product_id
|
||||
onchange_product_vals = polo.browse(False).onchange_product_id(
|
||||
vals.get('pricelist_id'), product.id, total_qty, False,
|
||||
supplier.id, fiscal_position_id=vals.get('fiscal_position_id'))
|
||||
lvals = onchange_product_vals['value']
|
||||
lvals['product_id'] = product.id
|
||||
lvals['product_qty'] = total_qty
|
||||
if lvals['taxes_id']:
|
||||
lvals['taxes_id'] = [(6, 0, lvals['taxes_id'])]
|
||||
vals['order_line'] = [(0, 0, lvals)]
|
||||
po = poo.create(vals)
|
||||
lvouchers.write({'purchase_id': po.id})
|
||||
|
||||
action = self.env['ir.actions.act_window'].for_xml_id(
|
||||
'purchase', 'purchase_rfq')
|
||||
action.update({
|
||||
'res_id': po.id,
|
||||
'view_mode': 'form,tree',
|
||||
'views': False,
|
||||
})
|
||||
return action
|
||||
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2017 Akretion (http://www.akretion.com/)
|
||||
@author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="lunch_voucher_purchase_form" model="ir.ui.view">
|
||||
<field name="name">lunch_voucher_purchase_form</field>
|
||||
<field name="model">lunch.voucher.purchase</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Create Purchase Order of Lunch Vouchers">
|
||||
<group name="main">
|
||||
<label string="Click on the button below to create the purchase order for the selected lunch vouchers attributions." colspan="2"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="run" type="object" string="Create"
|
||||
class="oe_highlight"/>
|
||||
<button special="cancel" string="Cancel" class="oe_link"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="lunch_voucher_purchase_action" model="ir.actions.act_window">
|
||||
<field name="name">Create PO for Lunch Vouchers</field>
|
||||
<field name="res_model">lunch.voucher.purchase</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
4
hr_holidays_lunch_voucher_natixis/__init__.py
Normal file
4
hr_holidays_lunch_voucher_natixis/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import company
|
||||
from . import wizard
|
||||
20
hr_holidays_lunch_voucher_natixis/__openerp__.py
Normal file
20
hr_holidays_lunch_voucher_natixis/__openerp__.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
'name': 'HR Holidays Lunch Voucher Natixis',
|
||||
'version': '8.0.1.0.0',
|
||||
'category': 'Human Resources',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Generate order file for Natixis lunch vouchers',
|
||||
'description': '',
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['hr_holidays_lunch_voucher'],
|
||||
'data': [
|
||||
'company_view.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
15
hr_holidays_lunch_voucher_natixis/company.py
Normal file
15
hr_holidays_lunch_voucher_natixis/company.py
Normal file
@@ -0,0 +1,15 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from openerp import models, fields
|
||||
|
||||
|
||||
class ResCompany(models.Model):
|
||||
_inherit = 'res.company'
|
||||
|
||||
lunch_voucher_natixis_customer_code = fields.Char(
|
||||
string='Natixis Customer Ref', size=7)
|
||||
lunch_voucher_natixis_delivery_code = fields.Char(
|
||||
string='Natixis Delivery Code', size=7)
|
||||
26
hr_holidays_lunch_voucher_natixis/company_view.xml
Normal file
26
hr_holidays_lunch_voucher_natixis/company_view.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2017 Akretion France (www.akretion.com)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
|
||||
<record id="view_company_form" model="ir.ui.view">
|
||||
<field name="name">natixis.lunch_voucher.company.form</field>
|
||||
<field name="model">res.company</field>
|
||||
<field name="inherit_id" ref="hr_holidays_lunch_voucher.view_company_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<group name="lunch_voucher" position="inside">
|
||||
<field name="lunch_voucher_natixis_customer_code"/>
|
||||
<field name="lunch_voucher_natixis_delivery_code"/>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
3
hr_holidays_lunch_voucher_natixis/wizard/__init__.py
Normal file
3
hr_holidays_lunch_voucher_natixis/wizard/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
from . import lunch_voucher_purchase
|
||||
@@ -0,0 +1,92 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# © 2017 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from openerp import models, fields, api, _
|
||||
from openerp.exceptions import Warning as UserError
|
||||
from openerp.tools import float_is_zero
|
||||
|
||||
|
||||
class LunchVoucherPurchase(models.TransientModel):
|
||||
_inherit = 'lunch.voucher.purchase'
|
||||
|
||||
@api.multi
|
||||
def run(self):
|
||||
self.ensure_one()
|
||||
action = super(LunchVoucherPurchase, self).run()
|
||||
company = self.env.user.company_id
|
||||
# force_company to read standard_price properly
|
||||
company = company.with_context(force_company=company.id)
|
||||
lvao = self.env['lunch.voucher.attribution']
|
||||
assert self._context.get('active_model')\
|
||||
== 'lunch.voucher.attribution', 'wrong source model'
|
||||
assert self._context.get('active_ids'), 'missing active_ids in ctx'
|
||||
if not company.lunch_voucher_natixis_customer_code:
|
||||
raise UserError(_(
|
||||
"Missing Natixis Customer Ref on company '%s'.")
|
||||
% company.name)
|
||||
if not company.lunch_voucher_natixis_delivery_code:
|
||||
raise UserError(_(
|
||||
"Missing Natixis Delivery Code on company '%s'.")
|
||||
% company.name)
|
||||
if len(company.lunch_voucher_natixis_customer_code) != 7:
|
||||
raise UserError(_(
|
||||
"Natixis Customer Ref '%s' on company '%s' should "
|
||||
"have 7 characters/digits.")
|
||||
% (company.lunch_voucher_natixis_customer_code, company.name))
|
||||
if len(company.lunch_voucher_natixis_delivery_code) != 7:
|
||||
raise UserError(_(
|
||||
"Natixis Delivery Code on company '%s' should "
|
||||
"have 7 characters/digits.")
|
||||
% (company.lunch_voucher_natixis_delivery_code, company.name))
|
||||
if float_is_zero(
|
||||
company.lunch_voucher_employer_price,
|
||||
precision_digits=2):
|
||||
raise UserError(_(
|
||||
"Lunch Voucher Employer Price not set on company '%s'.")
|
||||
% company.name)
|
||||
if float_is_zero(
|
||||
company.lunch_voucher_product_id.standard_price,
|
||||
precision_digits=2):
|
||||
raise UserError(_(
|
||||
"Lunch Voucher Standard Price is not set on product '%s'.")
|
||||
% company.lunch_voucher_product_id.display_name)
|
||||
lvouchers = lvao.browse(self._context['active_ids'])
|
||||
of = u''
|
||||
tmp = {}
|
||||
for lvoucher in lvouchers:
|
||||
if lvoucher.qty > 0:
|
||||
if lvoucher.qty not in tmp:
|
||||
tmp[lvoucher.qty] = 1
|
||||
else:
|
||||
tmp[lvoucher.qty] += 1
|
||||
for vouchers_per_pack, pack_qty in tmp.iteritems():
|
||||
if vouchers_per_pack > 99:
|
||||
raise UserError(_(
|
||||
"Cannot order more than 99 vouchers per pack"))
|
||||
line = u'%s%s%s%s%s%s%s%s\n' % (
|
||||
company.lunch_voucher_natixis_delivery_code,
|
||||
company.lunch_voucher_natixis_customer_code,
|
||||
unicode(pack_qty).zfill(3),
|
||||
unicode(vouchers_per_pack).zfill(2),
|
||||
unicode(pack_qty * vouchers_per_pack).zfill(5),
|
||||
'{:05.2f}'.format(
|
||||
company.lunch_voucher_product_id.standard_price),
|
||||
'{:05.2f}'.format(company.lunch_voucher_employer_price),
|
||||
' ' * 64)
|
||||
of += line
|
||||
today_dt = fields.Date.from_string(
|
||||
fields.Date.context_today(self))
|
||||
filename = 'E%s_%s.txt' % (
|
||||
company.lunch_voucher_natixis_customer_code,
|
||||
today_dt.strftime('%d%m%Y'))
|
||||
self.env['ir.attachment'].create({
|
||||
'name': filename,
|
||||
'res_id': action['res_id'],
|
||||
'res_model': 'purchase.order',
|
||||
'datas': of.encode('base64'),
|
||||
'datas_fname': filename,
|
||||
'type': 'binary',
|
||||
})
|
||||
return action
|
||||
@@ -241,6 +241,10 @@ class HrHolidays(models.Model):
|
||||
string='Public Title',
|
||||
help="Warning: this title is shown publicly in the "
|
||||
"calendar. Don't write private/personnal information in this field.")
|
||||
# by default, there is no company_id field on hr.holidays !
|
||||
company_id = fields.Many2one(
|
||||
related='employee_id.resource_id.company_id', store=True,
|
||||
readonly=True)
|
||||
|
||||
@api.one
|
||||
@api.constrains(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<data noupdate="0">
|
||||
|
||||
<record id="ir_actions_server_hr_holidays_confirm_mail" model="ir.actions.server">
|
||||
<field name="name">Auto-email confirmed leave</field>
|
||||
@@ -59,6 +59,9 @@ if not object.no_email_notification:
|
||||
<field name="action_id" ref="ir_actions_server_hr_holidays_refuse_mail"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
<data noupdate="1">
|
||||
|
||||
<record id="email_template_hr_holidays" model="email.template">
|
||||
<field name="name">Holidays email template</field>
|
||||
<field name="model_id" ref="hr_holidays.model_hr_holidays"/>
|
||||
|
||||
@@ -61,6 +61,7 @@ hr_holidays.edit_holiday_new is used for both leaves and allocation -->
|
||||
</group>
|
||||
</field>
|
||||
<field name="department_id" position="after">
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="posted_date" groups="base.group_hr_manager"/>
|
||||
</field>
|
||||
</field>
|
||||
@@ -90,6 +91,7 @@ hr_holidays.edit_holiday_new is used for both leaves and allocation -->
|
||||
</field>
|
||||
<field name="holiday_status_id" position="after">
|
||||
<field name="posted_date" groups="base.group_hr_manager"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="0">
|
||||
<data noupdate="1">
|
||||
|
||||
<!--
|
||||
Employee : only see his holidays
|
||||
@@ -41,5 +41,12 @@ Manager = person that administrates the holidays process : can see everything, d
|
||||
<field name="groups" eval="[(4, ref('base.group_hr_manager'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="hr_holidays_multicompany_rule" model="ir.rule">
|
||||
<field name="name">Holidays multi-company</field>
|
||||
<field name="model_id" ref="hr_holidays.model_hr_holidays"/>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -31,7 +31,9 @@ class HrHolidaysMassAllocation(models.TransientModel):
|
||||
@api.model
|
||||
def _default_employees(self):
|
||||
return self.env['hr.employee'].search([
|
||||
('holiday_exclude_mass_allocation', '=', False)])
|
||||
('holiday_exclude_mass_allocation', '=', False),
|
||||
('company_id', '=', self.env.user.company_id.id),
|
||||
])
|
||||
|
||||
@api.model
|
||||
def _get_default_holiday_status(self):
|
||||
|
||||
@@ -56,6 +56,7 @@ class HrHolidaysPost(models.TransientModel):
|
||||
('state', '=', 'validate'),
|
||||
('posted_date', '=', False),
|
||||
('vacation_date_to', '<=', self.before_date),
|
||||
('company_id', '=', self.env.user.company_id.id),
|
||||
])
|
||||
self.write({
|
||||
'state': 'done',
|
||||
@@ -73,9 +74,11 @@ class HrHolidaysPost(models.TransientModel):
|
||||
# because, after the write, it doesn't have a value any more !!!
|
||||
holidays_to_post = self.holidays_to_post_ids
|
||||
today = fields.Date.context_today(self)
|
||||
if not self.holidays_to_post_ids:
|
||||
raise Warning(
|
||||
_('No leave request to post.'))
|
||||
# Disable the raise below to make the module "hr_holidays_lunch_voucher"
|
||||
# work even when nobody took holidays on the current month
|
||||
# if not self.holidays_to_post_ids:
|
||||
# raise Warning(
|
||||
# _('No leave request to post.'))
|
||||
self.holidays_to_post_ids.write({'posted_date': today})
|
||||
view_id = self.env.ref('hr_holidays_usability.hr_holiday_graph').id
|
||||
action = {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user