Compare commits
89 Commits
18-mig-com
...
7.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1d0fd885d | ||
|
|
4ee0d18712 | ||
|
|
6f8ffc403a | ||
|
|
c492904e2b | ||
|
|
64e08b93de | ||
|
|
e3793989c0 | ||
|
|
158648e604 | ||
|
|
38dd25f471 | ||
|
|
81d97b2981 | ||
|
|
87ec05e5ef | ||
|
|
237c0e484a | ||
|
|
cc1efeafdb | ||
|
|
753333521f | ||
|
|
e22b56c7a9 | ||
|
|
a93a203f2d | ||
|
|
698327c5a1 | ||
|
|
4f566a8ff8 | ||
|
|
f80e8117fe | ||
|
|
0331fb1290 | ||
|
|
941366ee47 | ||
|
|
cb3942f501 | ||
|
|
c030d20c68 | ||
|
|
84c6b03e09 | ||
|
|
07a90ce45f | ||
|
|
7d5efb1c49 | ||
|
|
fea48b5738 | ||
|
|
fe28781b9f | ||
|
|
ca6bfa9227 | ||
|
|
55589c52c2 | ||
|
|
b2a259308d | ||
|
|
b2a0e44121 | ||
|
|
1108f79664 | ||
|
|
085aeb62c5 | ||
|
|
94c693a06f | ||
|
|
7a07d438e4 | ||
|
|
7831277c14 | ||
|
|
2dbf95cb97 | ||
|
|
edcd3c7637 | ||
|
|
7d0f3976dd | ||
|
|
10c8a2e681 | ||
|
|
6702381665 | ||
|
|
753d4b5d5d | ||
|
|
810a7d795b | ||
|
|
1230dbb711 | ||
|
|
8756bc4b24 | ||
|
|
8973d4bf98 | ||
|
|
7130581012 | ||
|
|
898b1e6d2e | ||
|
|
a330ae1711 | ||
|
|
c6e8c79d45 | ||
|
|
bdf4a7e15d | ||
|
|
560beb826b | ||
|
|
80145000d8 | ||
|
|
2ef4a5946c | ||
|
|
b7d902aa2d | ||
|
|
48a720f8dd | ||
|
|
64ab60d350 | ||
|
|
14bacaeba5 | ||
|
|
fe08942e39 | ||
|
|
bc4dd21316 | ||
|
|
0c5a496ba2 | ||
|
|
0a626f39ae | ||
|
|
e9806b73c6 | ||
|
|
2b522f5702 | ||
|
|
082c133128 | ||
|
|
c33ef19086 | ||
|
|
6f07d50d90 | ||
|
|
037e4d4214 | ||
|
|
53b1ff6ed4 | ||
|
|
2847f14dc7 | ||
|
|
4fb4ed9ca4 | ||
|
|
98bc291b54 | ||
|
|
532b9cb53c | ||
|
|
5075221428 | ||
|
|
3ee3edb8ce | ||
|
|
f3085a163f | ||
|
|
7b04e578af | ||
|
|
9daeeca997 | ||
|
|
0c5366420f | ||
|
|
f388d0d10f | ||
|
|
e588686d5f | ||
|
|
2e6e1c07bf | ||
|
|
a98dbc0b1c | ||
|
|
529b585d07 | ||
|
|
46d177fb9f | ||
|
|
24abaec406 | ||
|
|
673afbac0f | ||
|
|
5dc05f3c81 | ||
|
|
dce0604e7d |
56
.gitignore
vendored
Normal file
56
.gitignore
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
env/
|
||||
bin/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
|
||||
# Pycharm
|
||||
.idea
|
||||
|
||||
# Mr Developer
|
||||
.mr.developer.cfg
|
||||
.project
|
||||
.pydevproject
|
||||
|
||||
# Rope
|
||||
.ropeproject
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# Backup files
|
||||
*~
|
||||
*.swp
|
||||
1
account_banking_payment_transfer_simple/__init__.py
Normal file
1
account_banking_payment_transfer_simple/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import model
|
||||
47
account_banking_payment_transfer_simple/__openerp__.py
Normal file
47
account_banking_payment_transfer_simple/__openerp__.py
Normal file
@@ -0,0 +1,47 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
|
||||
# (C) 2011 - 2013 Therp BV (<http://therp.nl>).
|
||||
# (C) 2014 ACSONE SA/NV (<http://acsone.eu>).
|
||||
#
|
||||
# All other contributions are (C) by their respective contributors
|
||||
#
|
||||
# All Rights Reserved
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
{
|
||||
'name': 'Account Banking - Payments Transfer Account (simple)',
|
||||
'version': '0.2',
|
||||
'license': 'AGPL-3',
|
||||
'author': "Akretion,Odoo Community Association (OCA)",
|
||||
'website': 'http://www.akretion.com',
|
||||
'category': 'Banking addons',
|
||||
'depends': [
|
||||
'account_banking_payment_export',
|
||||
],
|
||||
'data': [
|
||||
'view/payment_mode.xml',
|
||||
'workflow/account_payment_workflow.xml',
|
||||
],
|
||||
'description': '''
|
||||
This is a simple equivalent for Odoo v7 of the module *account_banking_payment_transfer* for v8.0.
|
||||
|
||||
I developped this module to be able to make some SEPA direct debits / credit transfer with transfer move on Odoo v7, without installing the module account_banking (I can't install account_banking because I used the OCA modules from https://github.com/OCA/bank-statement-reconcile)
|
||||
''',
|
||||
'installable': True,
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
from . import account_payment
|
||||
from . import payment_line
|
||||
from . import payment_mode
|
||||
from . import account_move_line
|
||||
@@ -0,0 +1,45 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
|
||||
# (C) 2011 - 2013 Therp BV (<http://therp.nl>).
|
||||
#
|
||||
# All other contributions are (C) by their respective contributors
|
||||
#
|
||||
# All Rights Reserved
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import orm
|
||||
|
||||
|
||||
class account_move_line(orm.Model):
|
||||
_inherit = "account.move.line"
|
||||
|
||||
def get_balance(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
Return the balance of any set of move lines.
|
||||
|
||||
Not to be confused with the 'balance' field on this model, which
|
||||
returns the account balance that the move line applies to.
|
||||
"""
|
||||
total = 0.0
|
||||
if not ids:
|
||||
return total
|
||||
for line in self.read(
|
||||
cr, uid, ids, ['debit', 'credit'], context=context):
|
||||
total += (line['debit'] or 0.0) - (line['credit'] or 0.0)
|
||||
return total
|
||||
246
account_banking_payment_transfer_simple/model/account_payment.py
Normal file
246
account_banking_payment_transfer_simple/model/account_payment.py
Normal file
@@ -0,0 +1,246 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
|
||||
# (C) 2011 - 2013 Therp BV (<http://therp.nl>).
|
||||
# (C) 2014 ACSONE SA (<http://acsone.eu>).
|
||||
# (C) 2014 Akretion (www.akretion.com)
|
||||
#
|
||||
# All other contributions are (C) by their respective contributors
|
||||
#
|
||||
# All Rights Reserved
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import orm, fields
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
class PaymentOrder(orm.Model):
|
||||
_inherit = 'payment.order'
|
||||
|
||||
# @api.multi
|
||||
# def get_partial_reconcile_ids(self):
|
||||
# self.ensure_one()
|
||||
# reconcile_partial_ids = [line.move_line_id.reconcile_partial_id.id
|
||||
# for line in self.line_ids if
|
||||
# line.move_line_id.reconcile_partial_id.id]
|
||||
# return reconcile_partial_ids
|
||||
|
||||
# @api.one
|
||||
# def get_partial_reconcile_count(self):
|
||||
# self.partial_reconcile_count = len(self.get_partial_reconcile_ids())
|
||||
|
||||
def action_rejected(self, cr, uid, ids, context=None):
|
||||
return True
|
||||
|
||||
# @api.multi
|
||||
# def action_done(self):
|
||||
# for line in self.line_ids:
|
||||
# line.date_done = fields.Date.context_today(self)
|
||||
# self.date_done = fields.Date.context_today(self)
|
||||
# state is written in workflow definition
|
||||
# return True
|
||||
|
||||
# @api.multi
|
||||
# def _get_transfer_move_lines(self):
|
||||
# """
|
||||
# Get the transfer move lines (on the transfer account).
|
||||
# """
|
||||
# res = []
|
||||
# for order in self:
|
||||
# for order_line in order.line_ids:
|
||||
# move_line = order_line.transfer_move_line_id
|
||||
# if move_line:
|
||||
# res.append(move_line)
|
||||
# return res
|
||||
|
||||
# @api.multi
|
||||
# def get_transfer_move_line_ids(self, *args):
|
||||
# '''Used in the workflow for trigger_expr_id'''
|
||||
# return [move_line.id for move_line in self._get_transfer_move_lines()]
|
||||
|
||||
# @api.multi
|
||||
# def test_done(self):
|
||||
# """
|
||||
# Test if all moves on the transfer account are reconciled.
|
||||
#
|
||||
# Called from the workflow to move to the done state when
|
||||
# all transfer move have been reconciled through bank statements.
|
||||
# """
|
||||
# return all([move_line.reconcile_id for move_line in
|
||||
# self._get_transfer_move_lines()])
|
||||
|
||||
# @api.multi
|
||||
# def test_undo_done(self):
|
||||
# return not self.test_done()
|
||||
|
||||
def _prepare_transfer_move(self, cr, uid, order, context=None):
|
||||
# TODO question : can I use self.mode.xxx in an @api.model ??
|
||||
# It works, but I'm not sure we are supposed to do that !
|
||||
# I didn't want to use api.one to avoid having to
|
||||
# do self._prepare_transfer_move()[0] in action_sent
|
||||
# I prefer to just have to do self._prepare_transfer_move()
|
||||
vals = {
|
||||
'journal_id': order.mode.transfer_journal_id.id,
|
||||
'ref': '%s %s' % (
|
||||
order.payment_order_type[:3].upper(), order.reference)
|
||||
}
|
||||
return vals
|
||||
|
||||
def _prepare_move_line_transfer_account(
|
||||
self, cr, uid, order, amount, move_id, payment_lines, labels,
|
||||
context=None):
|
||||
payment_order_type = order.payment_order_type
|
||||
if len(payment_lines) == 1:
|
||||
partner_id = payment_lines[0].partner_id.id
|
||||
name = _('%s line %s') % (
|
||||
labels[payment_order_type], payment_lines[0].name)
|
||||
else:
|
||||
partner_id = False
|
||||
name = '%s %s' % (
|
||||
labels[payment_order_type], order.reference)
|
||||
vals = {
|
||||
'name': name,
|
||||
'move_id': move_id,
|
||||
'partner_id': partner_id,
|
||||
'account_id': order.mode.transfer_account_id.id,
|
||||
'credit': (payment_order_type == 'payment' and
|
||||
amount or 0.0),
|
||||
'debit': (payment_order_type == 'debit' and
|
||||
amount or 0.0),
|
||||
}
|
||||
return vals
|
||||
|
||||
def _prepare_move_line_partner_account(
|
||||
self, cr, uid, line, move_id, labels, context=None):
|
||||
payment_order_type = line.order_id.payment_order_type
|
||||
if line.move_line_id:
|
||||
account_id = line.move_line_id.account_id.id
|
||||
else:
|
||||
if payment_order_type == 'debit':
|
||||
account_id = line.partner_id.property_account_receivable.id
|
||||
else:
|
||||
account_id = line.partner_id.property_account_payable.id
|
||||
vals = {
|
||||
'name': _('%s line %s') % (
|
||||
labels[payment_order_type], line.name),
|
||||
'move_id': move_id,
|
||||
'partner_id': line.partner_id.id,
|
||||
'account_id': account_id,
|
||||
'credit': (payment_order_type == 'debit' and
|
||||
line.amount or 0.0),
|
||||
'debit': (payment_order_type == 'payment' and
|
||||
line.amount or 0.0),
|
||||
}
|
||||
return vals
|
||||
|
||||
# @api.model
|
||||
# def action_sent_no_move_line_hook(self, pay_line):
|
||||
# """This function is designed to be inherited"""
|
||||
# return
|
||||
|
||||
def action_done(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
Create the moves that pay off the move lines from
|
||||
the debit order. This happens when the debit order file is
|
||||
generated.
|
||||
"""
|
||||
am_obj = self.pool['account.move']
|
||||
aml_obj = self.pool['account.move.line']
|
||||
pl_obj = self.pool['payment.line']
|
||||
labels = {
|
||||
'payment': _('Payment order'),
|
||||
'debit': _('Direct debit order'),
|
||||
}
|
||||
for order in self.browse(cr, uid, ids, context=context):
|
||||
if order.mode.transfer_journal_id and order.mode.transfer_account_id:
|
||||
# prepare a dict "trfmoves" that can be used when
|
||||
# self.mode.transfer_move_option = date or line
|
||||
# key = unique identifier (date or True or line.id)
|
||||
# value = [pay_line1, pay_line2, ...]
|
||||
trfmoves = {}
|
||||
if order.mode.transfer_move_option == 'line':
|
||||
for line in order.line_ids:
|
||||
trfmoves[line.id] = [line]
|
||||
else:
|
||||
if order.date_prefered in ('now', 'fixed'):
|
||||
trfmoves[True] = []
|
||||
for line in order.line_ids:
|
||||
trfmoves[True].append(line)
|
||||
else: # date_prefered == due
|
||||
for line in order.line_ids:
|
||||
if line.date in trfmoves:
|
||||
trfmoves[line.date].append(line)
|
||||
else:
|
||||
trfmoves[line.date] = [line]
|
||||
|
||||
for identifier, lines in trfmoves.iteritems():
|
||||
mvals = self._prepare_transfer_move(
|
||||
cr, uid, order, context=context)
|
||||
move_id = am_obj.create(cr, uid, mvals, context=context)
|
||||
total_amount = 0
|
||||
for line in lines:
|
||||
# TODO: take multicurrency into account
|
||||
|
||||
# create the payment/debit counterpart move line
|
||||
# on the partner account
|
||||
partner_ml_vals = self._prepare_move_line_partner_account(
|
||||
cr, uid, line, move_id, labels, context=context)
|
||||
partner_move_line_id = aml_obj.create(
|
||||
cr, uid, partner_ml_vals, context=context)
|
||||
total_amount += line.amount
|
||||
|
||||
# register the payment/debit move line
|
||||
# on the payment line and call reconciliation on it
|
||||
line.write({'transit_move_line_id': partner_move_line_id})
|
||||
|
||||
if line.move_line_id:
|
||||
pl_obj.debit_reconcile(cr, uid, line.id, context=context)
|
||||
#else:
|
||||
# self.action_sent_no_move_line_hook(line)
|
||||
|
||||
# create the payment/debit move line on the transfer account
|
||||
trf_ml_vals = self._prepare_move_line_transfer_account(
|
||||
cr, uid, order, total_amount, move_id, lines, labels,
|
||||
context=context)
|
||||
aml_obj.create(cr, uid, trf_ml_vals, context=context)
|
||||
|
||||
# post account move
|
||||
am_obj.post(cr, uid, [move_id], context=context)
|
||||
|
||||
# State field is written by act_sent_wait
|
||||
order.write({'state': 'done'})
|
||||
return True
|
||||
|
||||
# @api.multi
|
||||
# def partial(self):
|
||||
# self.ensure_one()
|
||||
# view_id = self.env.ref('account.view_move_line_tree').id
|
||||
# reconcile_partial_ids = self.get_partial_reconcile_ids()
|
||||
# reconcile_partial_domain = [('reconcile_partial_id', 'in',
|
||||
# reconcile_partial_ids)]
|
||||
# return {
|
||||
# 'name': _('Partial Reconcile Moves Line'),
|
||||
# 'context': self.env.context,
|
||||
# 'domain': reconcile_partial_domain,
|
||||
# 'view_type': 'form',
|
||||
# 'view_mode': 'tree,form',
|
||||
# 'res_model': 'account.move.line',
|
||||
# 'views': [(view_id, 'tree')],
|
||||
# 'type': 'ir.actions.act_window',
|
||||
# 'target': 'current',
|
||||
# }
|
||||
195
account_banking_payment_transfer_simple/model/payment_line.py
Normal file
195
account_banking_payment_transfer_simple/model/payment_line.py
Normal file
@@ -0,0 +1,195 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
|
||||
# (C) 2011 - 2013 Therp BV (<http://therp.nl>).
|
||||
#
|
||||
# All other contributions are (C) by their respective contributors
|
||||
#
|
||||
# All Rights Reserved
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import orm, fields
|
||||
from openerp import netsvc
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
class PaymentLine(orm.Model):
|
||||
'''
|
||||
Add some fields; make destination bank account
|
||||
mandatory, as it makes no sense to send payments into thin air.
|
||||
Edit: Payments can be by cash too, which is prohibited by mandatory bank
|
||||
accounts.
|
||||
'''
|
||||
_inherit = 'payment.line'
|
||||
|
||||
def _get_transfer_move_line(self, cr, uid, ids, name, arg, context=None):
|
||||
res = {}
|
||||
for order_line in self.browse(cr, uid, ids, context=context):
|
||||
if order_line.transit_move_line_id:
|
||||
order_type = order_line.order_id.payment_order_type
|
||||
trf_lines = order_line.transit_move_line_id.move_id.line_id
|
||||
for move_line in trf_lines:
|
||||
if order_type == 'debit' and move_line.debit > 0:
|
||||
res[order_line.id] = move_line.id
|
||||
elif order_type == 'payment' and move_line.credit > 0:
|
||||
res[order_line.id] = move_line.id
|
||||
else:
|
||||
res[order_line.id] = False
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'msg': fields.char('Message', size=255, required=False, readonly=True),
|
||||
'date_done': fields.date(
|
||||
'Date Confirmed', select=True, readonly=True),
|
||||
'transit_move_line_id': fields.many2one(
|
||||
'account.move.line', 'Transfer move line',
|
||||
readonly=True,
|
||||
help="Move line through which the payment/debit order "
|
||||
"pays the invoice",
|
||||
),
|
||||
'transfer_move_line_id': fields.function(
|
||||
_get_transfer_move_line,
|
||||
type='many2one',
|
||||
relation='account.move.line',
|
||||
string='Transfer move line counterpart',
|
||||
readonly=True,
|
||||
help="Counterpart move line on the transfer account",
|
||||
),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'msg': '',
|
||||
}
|
||||
|
||||
"""
|
||||
Hooks for processing direct debit orders, such as implemented in
|
||||
account_direct_debit module.
|
||||
"""
|
||||
def get_storno_account_id(self, cr, uid, payment_line_id, amount,
|
||||
currency_id, context=None):
|
||||
"""
|
||||
Hook for verifying a match of the payment line with the amount.
|
||||
Return the account associated with the storno.
|
||||
Used in account_banking interactive mode
|
||||
:param payment_line_id: the single payment line id
|
||||
:param amount: the (signed) amount debited from the bank account
|
||||
:param currency: the bank account's currency *browse object*
|
||||
:return: an account if there is a full match, False otherwise
|
||||
:rtype: database id of an account.account resource.
|
||||
"""
|
||||
|
||||
return False
|
||||
|
||||
def debit_storno(self, cr, uid, payment_line_id, amount,
|
||||
currency_id, storno_retry=True, context=None):
|
||||
"""
|
||||
Hook for handling a canceled item of a direct debit order.
|
||||
Presumably called from a bank statement import routine.
|
||||
|
||||
Decide on the direction that the invoice's workflow needs to take.
|
||||
You may optionally return an incomplete reconcile for the caller
|
||||
to reconcile the now void payment.
|
||||
|
||||
:param payment_line_id: the single payment line id
|
||||
:param amount: the (negative) amount debited from the bank account
|
||||
:param currency: the bank account's currency *browse object*
|
||||
:param boolean storno_retry: whether the storno is considered fatal \
|
||||
or not.
|
||||
:return: an incomplete reconcile for the caller to fill
|
||||
:rtype: database id of an account.move.reconcile resource.
|
||||
"""
|
||||
|
||||
return False
|
||||
|
||||
def debit_reconcile(self, cr, uid, payment_line_id, context=None):
|
||||
"""
|
||||
Reconcile a debit order's payment line with the the move line
|
||||
that it is based on. Called from payment_order.action_sent().
|
||||
As the amount is derived directly from the counterpart move line,
|
||||
we do not expect a write off. Take partial reconciliations into
|
||||
account though.
|
||||
|
||||
:param payment_line_id: the single id of the canceled payment line
|
||||
"""
|
||||
|
||||
if isinstance(payment_line_id, (list, tuple)):
|
||||
payment_line_id = payment_line_id[0]
|
||||
reconcile_obj = self.pool.get('account.move.reconcile')
|
||||
move_line_obj = self.pool.get('account.move.line')
|
||||
payment_line = self.browse(cr, uid, payment_line_id, context=context)
|
||||
|
||||
transit_move_line = payment_line.transit_move_line_id
|
||||
torec_move_line = payment_line.move_line_id
|
||||
|
||||
if (not transit_move_line or not torec_move_line):
|
||||
raise orm.except_orm(
|
||||
_('Can not reconcile'),
|
||||
_('No move line for line %s') % payment_line.name
|
||||
)
|
||||
if torec_move_line.reconcile_id:
|
||||
raise orm.except_orm(
|
||||
_('Error'),
|
||||
_('Move line %s has already been reconciled') %
|
||||
torec_move_line.name
|
||||
)
|
||||
if (transit_move_line.reconcile_id or
|
||||
transit_move_line.reconcile_partial_id):
|
||||
raise orm.except_orm(
|
||||
_('Error'),
|
||||
_('Move line %s has already been reconciled') %
|
||||
transit_move_line.name
|
||||
)
|
||||
|
||||
def is_zero(total):
|
||||
return self.pool.get('res.currency').is_zero(
|
||||
cr, uid, transit_move_line.company_id.currency_id, total)
|
||||
|
||||
line_ids = [transit_move_line.id, torec_move_line.id]
|
||||
if torec_move_line.reconcile_partial_id:
|
||||
line_ids = [
|
||||
x.id for x in
|
||||
torec_move_line.reconcile_partial_id.line_partial_ids
|
||||
] + [transit_move_line.id]
|
||||
|
||||
total = move_line_obj.get_balance(cr, uid, line_ids)
|
||||
vals = {
|
||||
'type': 'auto',
|
||||
'line_id': is_zero(total) and [(6, 0, line_ids)] or [(6, 0, [])],
|
||||
'line_partial_ids': (is_zero(total) and
|
||||
[(6, 0, [])] or
|
||||
[(6, 0, line_ids)]),
|
||||
}
|
||||
|
||||
if torec_move_line.reconcile_partial_id:
|
||||
reconcile_obj.write(
|
||||
cr, uid, [torec_move_line.reconcile_partial_id.id],
|
||||
vals, context=context)
|
||||
else:
|
||||
reconcile_obj.create(
|
||||
cr, uid, vals, context=context)
|
||||
workflow = netsvc.LocalService("workflow")
|
||||
for line_id in line_ids:
|
||||
workflow.trg_trigger(
|
||||
uid, 'account.move.line', line_id, cr)
|
||||
|
||||
# If a bank transaction of a storno was first confirmed
|
||||
# and now canceled (the invoice is now in state 'debit_denied'
|
||||
if torec_move_line.invoice:
|
||||
workflow.trg_validate(
|
||||
uid, 'account.invoice', torec_move_line.invoice.id,
|
||||
'undo_debit_denied', cr)
|
||||
@@ -0,0 +1,52 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>).
|
||||
# (C) 2011 - 2013 Therp BV (<http://therp.nl>).
|
||||
# (C) 2014 Akretion (www.akretion.com)
|
||||
#
|
||||
# All other contributions are (C) by their respective contributors
|
||||
#
|
||||
# All Rights Reserved
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import orm, fields
|
||||
|
||||
|
||||
class PaymentMode(orm.Model):
|
||||
_inherit = "payment.mode"
|
||||
|
||||
_columns = {
|
||||
'transfer_account_id': fields.many2one(
|
||||
'account.account', 'Transfer account',
|
||||
domain=[('type', '=', 'other'), ('reconcile', '=', True)],
|
||||
help='Pay off lines in sent orders with a move on this '
|
||||
'account. You can only select accounts of type regular '
|
||||
'that are marked for reconciliation'),
|
||||
'transfer_journal_id': fields.many2one(
|
||||
'account.journal', 'Transfer journal',
|
||||
help='Journal to write payment entries when confirming '
|
||||
'a debit order of this mode'),
|
||||
'transfer_move_option': fields.selection([
|
||||
('date', 'One move per payment date'),
|
||||
('line', 'One move per payment line'),
|
||||
], 'Transfer move option')
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'transfer_move_option': 'date',
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!--
|
||||
Add the payment mode transfer account settings
|
||||
-->
|
||||
<record id="view_payment_mode_form_inherit" model="ir.ui.view">
|
||||
<field name="name">payment.mode.form.inherit</field>
|
||||
<field name="model">payment.mode</field>
|
||||
<field name="inherit_id" ref="account_banking_payment_export.view_payment_mode_form_inherit"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="/form/group[@col='4']" position="inside">
|
||||
<group name="trf-move-config" string="Transfer move settings" colspan="2">
|
||||
<field name="transfer_account_id"
|
||||
domain="[('type', '=', 'other'),
|
||||
('reconcile', '=', True),
|
||||
('company_id', '=', company_id)]"
|
||||
context="{
|
||||
'default_type': 'other',
|
||||
'default_reconcile': True,
|
||||
'default_company_id': company_id}"
|
||||
/>
|
||||
<field name="transfer_journal_id"
|
||||
domain="[('company_id', '=', company_id)]"
|
||||
/>
|
||||
<field name="transfer_move_option"/>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="account_payment.act_done" model="workflow.activity">
|
||||
<field name="action">action_done()</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
23
account_invoice_del_attachment_cancel/__init__.py
Normal file
23
account_invoice_del_attachment_cancel/__init__.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Account Invoice Del Attachment Cancel module for OpenERP
|
||||
# Copyright (C) 2015 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from . import account_invoice
|
||||
45
account_invoice_del_attachment_cancel/__openerp__.py
Normal file
45
account_invoice_del_attachment_cancel/__openerp__.py
Normal file
@@ -0,0 +1,45 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Account Invoice Del Attachment Cancel module for OpenERP
|
||||
# Copyright (C) 2015 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
{
|
||||
'name': 'Account Invoice Delete Attachment on Cancel',
|
||||
'version': '0.1',
|
||||
'category': 'Accounting & Finance',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Delete the attachment on the invoice when it is cancelled',
|
||||
'description': """
|
||||
Account Invoice Delete Attachment on Cancel
|
||||
===========================================
|
||||
|
||||
When an invoice is validated, on the first generation of the invoice report, a copy of the report is stored as attachment on the invoice. After that, every time you a user asks for the Invoice report, it will be taken from the attachment.
|
||||
|
||||
With this module, when an invoice is cancelled, the attachment is deleted.
|
||||
|
||||
Please contact Alexis de Lattre from Akretion <alexis.delattre@akretion.com> for any help or question about this module.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['account'],
|
||||
'data': [],
|
||||
'installable': True,
|
||||
}
|
||||
53
account_invoice_del_attachment_cancel/account_invoice.py
Normal file
53
account_invoice_del_attachment_cancel/account_invoice.py
Normal file
@@ -0,0 +1,53 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Account Invoice Del Attachment Cancel module for OpenERP
|
||||
# Copyright (C) 2015 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import orm
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
class AccountInvoice(orm.Model):
|
||||
_inherit = 'account.invoice'
|
||||
|
||||
def action_cancel(self, cr, uid, ids, context=None):
|
||||
res = super(AccountInvoice, self).action_cancel(
|
||||
cr, uid, ids, context=context)
|
||||
iao = self.pool['ir.attachment']
|
||||
for invoice in self.browse(cr, uid, ids, context=context):
|
||||
# search for attachments
|
||||
if 'out' in invoice.type:
|
||||
attach_ids = iao.search(
|
||||
cr, uid, [
|
||||
('res_id', '=', invoice.id),
|
||||
('res_model', '=', self._name),
|
||||
('type', '=', 'binary'),
|
||||
('datas_fname', '=like', 'INV%.pdf'),
|
||||
], context=context)
|
||||
if len(attach_ids) == 1:
|
||||
# delete attachment
|
||||
attach = iao.browse(
|
||||
cr, uid, attach_ids[0], context=context)
|
||||
attach_name = attach.name
|
||||
iao.unlink(cr, uid, attach_ids, context=context)
|
||||
self.message_post(
|
||||
cr, uid, invoice.id,
|
||||
_('Attachement %s has been deleted') % attach_name)
|
||||
return res
|
||||
3
account_invoice_margin/__init__.py
Normal file
3
account_invoice_margin/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import account_invoice
|
||||
43
account_invoice_margin/__openerp__.py
Normal file
43
account_invoice_margin/__openerp__.py
Normal file
@@ -0,0 +1,43 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Account Invoice Margin module for Odoo
|
||||
# Copyright (C) 2015 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
{
|
||||
'name': 'Account Invoice Margin',
|
||||
'version': '0.1',
|
||||
'category': 'Accounting & Finance',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Copy standard price on invoice line and compute margins',
|
||||
'description': """
|
||||
This module copies the field *standard_price* of the product on the invoice line when the invoice line is created. The allows the computation of the margin of the invoice.
|
||||
|
||||
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_invoice_view.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
286
account_invoice_margin/account_invoice.py
Normal file
286
account_invoice_margin/account_invoice.py
Normal file
@@ -0,0 +1,286 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Account Invoice Margin module for Odoo
|
||||
# Copyright (C) 2015-2016 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import orm, fields
|
||||
import openerp.addons.decimal_precision as dp
|
||||
|
||||
|
||||
class AccountInvoiceLine(orm.Model):
|
||||
_inherit = 'account.invoice.line'
|
||||
|
||||
def _compute_margin(self, cr, uid, ids, name, arg, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
res = {}
|
||||
# we need an up-to-date price_subtotal
|
||||
# We cannot read il.price_subtotal, because it may be out-of-date
|
||||
# (I saw that with invoices in foreign currency)
|
||||
price_subtotal = self._amount_line(cr, uid, ids, name, arg, context)
|
||||
for il in self.browse(cr, uid, ids, context=context):
|
||||
standard_price_inv_cur = 0.0
|
||||
margin_inv_cur = 0.0
|
||||
margin_comp_cur = 0.0
|
||||
margin_rate = 0.0
|
||||
if (
|
||||
il.invoice_id and
|
||||
il.invoice_id.type in ('out_invoice', 'out_refund')):
|
||||
# it works in _get_current_rate
|
||||
# even if we set date = False in context
|
||||
# standard_price_inv_cur is in the UoM of the invoice line
|
||||
|
||||
rco = self.pool['res.currency']
|
||||
ctx_currency = context.copy()
|
||||
if il.invoice_id.date_invoice:
|
||||
ctx_currency['date'] = il.invoice_id.date_invoice
|
||||
standard_price_inv_cur =\
|
||||
rco.compute(
|
||||
cr, uid, il.invoice_id.company_id.currency_id.id,
|
||||
il.invoice_id.currency_id.id,
|
||||
il.standard_price_company_currency,
|
||||
context=ctx_currency)
|
||||
margin_inv_cur =\
|
||||
price_subtotal[il.id] - il.quantity * standard_price_inv_cur
|
||||
margin_comp_cur = rco.compute(
|
||||
cr, uid, il.invoice_id.currency_id.id,
|
||||
il.invoice_id.company_id.currency_id.id,
|
||||
margin_inv_cur, context=ctx_currency)
|
||||
if price_subtotal[il.id]:
|
||||
margin_rate = 100 * margin_inv_cur / price_subtotal[il.id]
|
||||
# for a refund, margin should be negative
|
||||
# but margin rate should stay positive
|
||||
if il.invoice_id.type == 'out_refund':
|
||||
margin_inv_cur *= -1
|
||||
margin_comp_cur *= -1
|
||||
res[il.id] = {
|
||||
'standard_price_invoice_currency': standard_price_inv_cur,
|
||||
'margin_invoice_currency': margin_inv_cur,
|
||||
'margin_company_currency': margin_comp_cur,
|
||||
'margin_rate': margin_rate,
|
||||
}
|
||||
return res
|
||||
|
||||
def _get_lines_from_invoices(self, cr, uid, ids, context=None):
|
||||
return self.pool['account.invoice.line'].search(
|
||||
cr, uid, [('invoice_id', 'in', ids)], context=context)
|
||||
|
||||
_columns = {
|
||||
'standard_price_company_currency': fields.float(
|
||||
'Cost Price per Unit in Company Currency', readonly=True,
|
||||
digits_compute=dp.get_precision('Product Price'),
|
||||
help="Cost price in company currency in the unit of measure "
|
||||
"of the invoice line (which may be different from the unit "
|
||||
"of measure of the product)."),
|
||||
'standard_price_invoice_currency': fields.function(
|
||||
_compute_margin, string='Cost Price per Unit in Invoice Currency',
|
||||
type='float', readonly=True, multi='il-margin', store={
|
||||
'account.invoice.line': (
|
||||
lambda self, cr, uid, ids, c={}: ids, [
|
||||
'standard_price_company_currency',
|
||||
'quantity',
|
||||
'price_unit',
|
||||
'discount',
|
||||
'invoice_line_tax_id'], 10),
|
||||
'account.invoice': (
|
||||
_get_lines_from_invoices, [
|
||||
'type',
|
||||
'currency_id',
|
||||
'date_invoice',
|
||||
'company_id'], 20),
|
||||
},
|
||||
digits_compute=dp.get_precision('Product Price'),
|
||||
help="Cost price in invoice currency in the unit of measure "
|
||||
"of the invoice line"),
|
||||
'margin_invoice_currency': fields.function(
|
||||
_compute_margin, string='Margin in Invoice Currency',
|
||||
type='float', readonly=True, multi='il-margin', store={
|
||||
'account.invoice.line': (
|
||||
lambda self, cr, uid, ids, c={}: ids, [
|
||||
'standard_price_company_currency',
|
||||
'quantity',
|
||||
'price_unit',
|
||||
'discount',
|
||||
'invoice_line_tax_id'], 10),
|
||||
'account.invoice': (
|
||||
_get_lines_from_invoices, [
|
||||
'type',
|
||||
'currency_id',
|
||||
'date_invoice',
|
||||
'company_id'], 20),
|
||||
},
|
||||
digits_compute=dp.get_precision('Account')),
|
||||
'margin_company_currency': fields.function(
|
||||
_compute_margin, type='float',
|
||||
string='Margin in Company Currency', readonly=True,
|
||||
multi='il-margin', store={
|
||||
'account.invoice.line': (
|
||||
lambda self, cr, uid, ids, c={}: ids, [
|
||||
'standard_price_company_currency',
|
||||
'quantity',
|
||||
'price_unit',
|
||||
'discount',
|
||||
'invoice_line_tax_id'], 10),
|
||||
'account.invoice': (
|
||||
_get_lines_from_invoices, [
|
||||
'type',
|
||||
'currency_id',
|
||||
'date_invoice',
|
||||
'company_id'], 20),
|
||||
},
|
||||
digits_compute=dp.get_precision('Account')),
|
||||
'margin_rate': fields.function(
|
||||
_compute_margin, type='float',
|
||||
string="Margin Rate", readonly=True, multi='il-margin', store={
|
||||
'account.invoice.line': (
|
||||
lambda self, cr, uid, ids, c={}: ids, [
|
||||
'standard_price_company_currency',
|
||||
'quantity',
|
||||
'price_unit',
|
||||
'discount',
|
||||
'invoice_line_tax_id'], 10),
|
||||
'account.invoice': (
|
||||
_get_lines_from_invoices, [
|
||||
'type',
|
||||
'currency_id',
|
||||
'date_invoice',
|
||||
'company_id'], 20),
|
||||
},
|
||||
digits=(16, 2),
|
||||
help="Margin rate in percentage of the sale price"),
|
||||
}
|
||||
|
||||
# We want to copy standard_price on invoice line for customer
|
||||
# invoice/refunds. We can't do that via on_change of product_id,
|
||||
# because it is not always played when invoice is created from code
|
||||
# => we inherit write/create
|
||||
# We write standard_price_company_currency even on supplier invoice/refunds
|
||||
# because we don't have access to the 'type' of the invoice
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
if (
|
||||
vals.get('product_id') and
|
||||
'standard_price_company_currency' not in vals):
|
||||
pp = self.pool['product.product'].browse(
|
||||
cr, uid, vals['product_id'], context=context)
|
||||
std_price = pp.standard_price
|
||||
inv_uom_id = vals.get('uos_id')
|
||||
if inv_uom_id and inv_uom_id != pp.uom_id.id:
|
||||
std_price = self.pool['product.uom']._compute_price(
|
||||
cr, uid, pp.uom_id.id, std_price, inv_uom_id)
|
||||
vals['standard_price_company_currency'] = std_price
|
||||
return super(AccountInvoiceLine, self).create(
|
||||
cr, uid, vals, context=context)
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
"""This code can seem a bit strange with the super() inside
|
||||
the loop, but it is required if we want to support all scenarios,
|
||||
including very strange scenarios where you write a uos_id on
|
||||
several lines with different products, etc...
|
||||
OK, these scenarios will probably never happen, but I prefer
|
||||
to make sure that the code is right and works in all
|
||||
scenarios
|
||||
"""
|
||||
if not vals:
|
||||
vals = {}
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
if 'product_id' in vals or 'uos_id' in vals:
|
||||
for il in self.browse(cr, uid, ids, context=context):
|
||||
if 'product_id' in vals:
|
||||
if vals.get('product_id'):
|
||||
pp = self.pool['product.product'].browse(
|
||||
cr, uid, vals['product_id'], context=context)
|
||||
else:
|
||||
pp = False
|
||||
else:
|
||||
pp = il.product_id or False
|
||||
# uos_id is NOT a required field
|
||||
if 'uos_id' in vals:
|
||||
if vals.get('uos_id'):
|
||||
inv_uom = self.pool['product.uom'].browse(
|
||||
cr, uid, vals['uos_id'], context=context)
|
||||
else:
|
||||
inv_uom = False
|
||||
else:
|
||||
inv_uom = il.uos_id or False
|
||||
std_price = 0.0
|
||||
if pp:
|
||||
std_price = pp.standard_price
|
||||
if inv_uom and inv_uom != pp.uom_id:
|
||||
std_price = self.pool['product.uom']._compute_price(
|
||||
cr, uid, pp.uom_id.id, std_price, inv_uom.id)
|
||||
vals_line = vals.copy()
|
||||
vals_line['standard_price_company_currency'] = std_price
|
||||
super(AccountInvoiceLine, self).write(
|
||||
cr, uid, [il.id], vals_line, context=context)
|
||||
return True
|
||||
else:
|
||||
return super(AccountInvoiceLine, self).write(
|
||||
cr, uid, ids, vals, context=context)
|
||||
|
||||
|
||||
class AccountInvoice(orm.Model):
|
||||
_inherit = 'account.invoice'
|
||||
|
||||
def _compute_margin(self, cr, uid, ids, name, arg, context=None):
|
||||
res = {}
|
||||
for inv in self.browse(cr, uid, ids, context=context):
|
||||
margin_inv_cur = 0.0
|
||||
margin_comp_cur = 0.0
|
||||
if inv.type in ('out_invoice', 'out_refund'):
|
||||
for il in inv.invoice_line:
|
||||
margin_inv_cur += il.margin_invoice_currency
|
||||
margin_comp_cur += il.margin_company_currency
|
||||
res[inv.id] = {
|
||||
'margin_invoice_currency': margin_inv_cur,
|
||||
'margin_company_currency': margin_comp_cur,
|
||||
}
|
||||
return res
|
||||
|
||||
def _get_invoices_from_inv_lines(self, cr, uid, ids, context=None):
|
||||
return self.pool['account.invoice'].search(
|
||||
cr, uid, [('invoice_line', 'in', ids)], context=context)
|
||||
|
||||
_columns = {
|
||||
'margin_invoice_currency': fields.function(
|
||||
_compute_margin, type='float',
|
||||
string='Margin in Invoice Currency',
|
||||
readonly=True, multi='inv-margin',
|
||||
digits_compute=dp.get_precision('Account'), store={
|
||||
'account.invoice': (
|
||||
lambda self, cr, uid, ids, c={}: ids, [
|
||||
'type', 'currency_id'], 10),
|
||||
'account.invoice.line': (
|
||||
_get_invoices_from_inv_lines, [
|
||||
'margin_company_currency'], 20),
|
||||
}),
|
||||
'margin_company_currency': fields.function(
|
||||
_compute_margin, type='float',
|
||||
string='Margin in Company Currency',
|
||||
readonly=True, multi='inv-margin',
|
||||
digits_compute=dp.get_precision('Account'), store={
|
||||
'account.invoice': (
|
||||
lambda self, cr, uid, ids, c={}: ids, [
|
||||
'type', 'currency_id'], 10),
|
||||
'account.invoice.line': (
|
||||
_get_invoices_from_inv_lines, [
|
||||
'margin_company_currency'], 20),
|
||||
}),
|
||||
}
|
||||
59
account_invoice_margin/account_invoice_view.xml
Normal file
59
account_invoice_margin/account_invoice_view.xml
Normal file
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 Akretion (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
The licence is in the file __openerp__.py
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="view_invoice_line_form" model="ir.ui.view">
|
||||
<field name="name">margin.account.invoice.line.form</field>
|
||||
<field name="model">account.invoice.line</field>
|
||||
<field name="inherit_id" ref="account.view_invoice_line_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="discount" position="after">
|
||||
<field name="standard_price_company_currency"
|
||||
groups="account.group_account_user"/>
|
||||
<field name="standard_price_invoice_currency"
|
||||
widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}"
|
||||
groups="account.group_account_user"/>
|
||||
<field name="margin_invoice_currency"
|
||||
widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}"
|
||||
groups="account.group_account_user"/>
|
||||
<field name="margin_company_currency"
|
||||
groups="account.group_account_user"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="invoice_form" model="ir.ui.view">
|
||||
<field name="name">margin.account.invoice.form</field>
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="account.invoice_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="move_id" position="after">
|
||||
<field name="margin_invoice_currency"
|
||||
string="Margin"
|
||||
widget="monetary"
|
||||
options="{'currency_field': 'currency_id'}"
|
||||
groups="account.group_account_user"/>
|
||||
<field name="margin_company_currency"
|
||||
groups="account.group_account_user"/>
|
||||
</field>
|
||||
<xpath expr="//field[@name='invoice_line']/tree/field[@name='price_subtotal']" position="after">
|
||||
<field name="standard_price_invoice_currency" groups="account.group_account_user"/>
|
||||
<field name="standard_price_company_currency" groups="base.group_no_one"/>
|
||||
<field name="margin_invoice_currency" groups="account.group_account_user"/>
|
||||
<field name="margin_company_currency" groups="base.group_no_one"/>
|
||||
<field name="margin_rate" groups="base.group_no_one"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
21
account_invoice_overdue_filter/__init__.py
Normal file
21
account_invoice_overdue_filter/__init__.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Account Invoice Overdue Filter module for OpenERP
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
43
account_invoice_overdue_filter/__openerp__.py
Normal file
43
account_invoice_overdue_filter/__openerp__.py
Normal file
@@ -0,0 +1,43 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Account Invoice Overdue Filter module for OpenERP
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
{
|
||||
'name': 'Account Invoice Overdue Filter',
|
||||
'version': '0.1',
|
||||
'category': 'Accounting & Finance',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Add an Overdue filter in the invoice search view',
|
||||
'description': """
|
||||
Account Invoice Overdue Filter
|
||||
==============================
|
||||
|
||||
This module adds a filter *Overdue* in the invoice search view.
|
||||
|
||||
Please contact Alexis de Lattre from Akretion <alexis.delattre@akretion.com> for any help or question about this module.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['account'],
|
||||
'data': ['account_invoice_view.xml'],
|
||||
'installable': True,
|
||||
}
|
||||
24
account_invoice_overdue_filter/account_invoice_view.xml
Normal file
24
account_invoice_overdue_filter/account_invoice_view.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2014 Akretion (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
The licence is in the file __openerp__.py
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="view_account_invoice_filter" model="ir.ui.view">
|
||||
<field name="name">filter.overdue.account.invoice.search</field>
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="account.view_account_invoice_filter"/>
|
||||
<field name="arch" type="xml">
|
||||
<filter name="unpaid" position="after">
|
||||
<filter name="overdue" string="Overdue"
|
||||
domain="[('state', '=', 'open'), ('date_due', '<', current_date)]"/>
|
||||
</filter>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -31,7 +31,7 @@
|
||||
Account Invoice Partner Bank Usability
|
||||
======================================
|
||||
|
||||
If the company has a single bank account, we get set this bank account by default on the customer invoice.
|
||||
If the company has a single bank account, we set this single bank account by default on the customer invoice.
|
||||
|
||||
Please contact Alexis de Lattre from Akretion <alexis.delattre@akretion.com> for any help or question about this module.
|
||||
""",
|
||||
|
||||
23
account_invoice_sale_link/__init__.py
Normal file
23
account_invoice_sale_link/__init__.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Account Invoice Sale Link module for OpenERP
|
||||
# Copyright (C) 2013 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from . import account_invoice
|
||||
44
account_invoice_sale_link/__openerp__.py
Normal file
44
account_invoice_sale_link/__openerp__.py
Normal file
@@ -0,0 +1,44 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Account Invoice Sale Link module for OpenERP
|
||||
# Copyright (C) 2013 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
{
|
||||
'name': 'Account Invoice Sale Link',
|
||||
'version': '0.1',
|
||||
'category': 'Accounting & Finance',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Add the reverse link from invoices to sale orders',
|
||||
'description': """
|
||||
Account Invoice Sale Link
|
||||
=========================
|
||||
|
||||
On the customer invoice report, you usually need to display the customer order number. For that, you need to have the link from invoices to sale orders, and this link is not available in the official addons.
|
||||
|
||||
Please contact Alexis de Lattre from Akretion <alexis.delattre@akretion.com> for any help or question about this module.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['sale'],
|
||||
'data': [],
|
||||
'installable': True,
|
||||
'active': False,
|
||||
}
|
||||
36
account_invoice_sale_link/account_invoice.py
Normal file
36
account_invoice_sale_link/account_invoice.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Account Invoice Sale Link module for OpenERP
|
||||
# Copyright (C) 2013 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import orm, fields
|
||||
|
||||
|
||||
class account_invoice(orm.Model):
|
||||
_inherit = 'account.invoice'
|
||||
|
||||
_columns = {
|
||||
# This is the reverse link of the field 'invoice_ids' of sale.order
|
||||
# defined in addons/sale/sale.py
|
||||
'sale_ids': fields.many2many(
|
||||
'sale.order', 'sale_order_invoice_rel', 'invoice_id',
|
||||
'order_id', 'Sale Orders', readonly=True,
|
||||
help="This is the list of sale orders related to this invoice."),
|
||||
}
|
||||
23
account_move_line_start_end_dates_xls/__init__.py
Normal file
23
account_move_line_start_end_dates_xls/__init__.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Account Move Line Start End Dates XLS module for OpenERP
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from . import account_move_line
|
||||
43
account_move_line_start_end_dates_xls/__openerp__.py
Normal file
43
account_move_line_start_end_dates_xls/__openerp__.py
Normal file
@@ -0,0 +1,43 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Account Move Line Start End Dates XLS module for OpenERP
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
{
|
||||
'name': 'Account Move Line Start End Dates XLS',
|
||||
'version': '0.1',
|
||||
'category': 'Accounting & Finance',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Adds start and end dates in the XLS export of the move lines',
|
||||
'description': """
|
||||
Account Move Line Start End Dates XLS
|
||||
=====================================
|
||||
|
||||
This module adds *Start Date* and *End Date* in the XLS export of the account move lines.
|
||||
|
||||
Please contact Alexis de Lattre from Akretion <alexis.delattre@akretion.com> for any help or question about this module.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com/',
|
||||
'depends': ['account_cutoff_prepaid', 'account_move_line_report_xls'],
|
||||
'data': [],
|
||||
'active': False,
|
||||
}
|
||||
61
account_move_line_start_end_dates_xls/account_move_line.py
Normal file
61
account_move_line_start_end_dates_xls/account_move_line.py
Normal file
@@ -0,0 +1,61 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Account Move Line Start End Dates XLS module for OpenERP
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import xlwt
|
||||
from openerp.osv import orm
|
||||
from openerp.addons.report_xls.utils import _render
|
||||
from openerp.addons.report_xls.report_xls import report_xls
|
||||
|
||||
|
||||
class account_move_line(orm.Model):
|
||||
_inherit = 'account.move.line'
|
||||
|
||||
def _report_xls_template(self, cr, uid, context=None):
|
||||
res = super(account_move_line, self)._report_xls_template(
|
||||
cr, uid, context=context)
|
||||
bc = '22'
|
||||
aml_cell_style_date = xlwt.easyxf(
|
||||
'borders: left thin, right thin, top thin, bottom thin, '
|
||||
'left_colour %s, right_colour %s, top_colour %s, '
|
||||
'bottom_colour %s; align: horz left;'
|
||||
% (bc, bc, bc, bc), num_format_str=report_xls.date_format)
|
||||
res.update({
|
||||
'start_date': {
|
||||
'header': [1, 13, 'text', _render("_('Start Date')")],
|
||||
'lines': [1, 0, _render(
|
||||
"line.start_date and line.start_date != 'False' and "
|
||||
"'date' or 'text'"), _render(
|
||||
"line.start_date and line.start_date != 'False' and "
|
||||
"datetime.strptime(line.start_date, '%Y-%m-%d') or None"),
|
||||
None, aml_cell_style_date],
|
||||
'totals': [1, 0, 'text', None]},
|
||||
'end_date': {
|
||||
'header': [1, 13, 'text', _render("_('End Date')")],
|
||||
'lines': [1, 0, _render(
|
||||
"line.end_date and line.end_date != 'False' and "
|
||||
"'date' or 'text'"), _render(
|
||||
"line.end_date and line.end_date != 'False' and "
|
||||
"datetime.strptime(line.end_date, '%Y-%m-%d') or None"),
|
||||
None, aml_cell_style_date],
|
||||
'totals': [1, 0, 'text', None]},
|
||||
})
|
||||
return res
|
||||
21
account_payment_hide_communication2/__init__.py
Normal file
21
account_payment_hide_communication2/__init__.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Account Payment Hide Communication2 module for OpenERP
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
43
account_payment_hide_communication2/__openerp__.py
Normal file
43
account_payment_hide_communication2/__openerp__.py
Normal file
@@ -0,0 +1,43 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Account Payment Hide Communication2 module for OpenERP
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
{
|
||||
'name': 'Account Payment Hide Communication2',
|
||||
'version': '1.0',
|
||||
'category': 'Accounting & Finance',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Hide the field Communication2 on Payment Lines',
|
||||
'description': """
|
||||
Account Payment Hide Communication2
|
||||
===================================
|
||||
|
||||
This module hides the field 'Communication2' on the form view of Payment Lines. I consider that is field is useless and tend to confuse users.
|
||||
|
||||
Please contact Alexis de Lattre from Akretion <alexis.delattre@akretion.com> for any help or question about this module.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'depends': ['account_payment'],
|
||||
'data': [
|
||||
'payment_view.xml',
|
||||
],
|
||||
'active': False,
|
||||
}
|
||||
21
account_payment_hide_communication2/payment_view.xml
Normal file
21
account_payment_hide_communication2/payment_view.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2014 Akretion (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
The licence is in the file __openerp__.py
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="view_payment_order_form" model="ir.ui.view">
|
||||
<field name="name">hide.communication2.on.payment.line.form</field>
|
||||
<field name="model">payment.order</field>
|
||||
<field name="inherit_id" ref="account_payment.view_payment_order_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='line_ids']/form//field[@name='communication2']" position="replace" />
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
21
account_payment_security/__init__.py
Normal file
21
account_payment_security/__init__.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Account Payment Security module for OpenERP
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
46
account_payment_security/__openerp__.py
Normal file
46
account_payment_security/__openerp__.py
Normal file
@@ -0,0 +1,46 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Account Payment Security module for OpenERP
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
{
|
||||
'name': 'Account Payment Security',
|
||||
'version': '1.0',
|
||||
'category': 'Accounting & Finance',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Only members of Account Payment can create/write on bank accounts',
|
||||
'description': """
|
||||
Account Payment Security
|
||||
========================
|
||||
|
||||
By default in OpenERP, members of the group *Contact Creation* can create and modify bank accounts ; this can be a risk, as explained in this mail : https://lists.launchpad.net/openerp-community/msg01035.html
|
||||
|
||||
With this module, only the members of the group *Accounting / Payments* can create and modify bank accounts. Also, some rights on the configuration of bank accounts (res.partner.bank.type and res.partner.bank.type.field) are moved from the group *Contact Creation* to *Financial Manager*.
|
||||
|
||||
Please contact Alexis de Lattre from Akretion <alexis.delattre@akretion.com> for any help or question about this module.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'depends': ['account_payment'],
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'security/payment_security.xml',
|
||||
],
|
||||
'active': False,
|
||||
}
|
||||
5
account_payment_security/security/ir.model.access.csv
Normal file
5
account_payment_security/security/ir.model.access.csv
Normal file
@@ -0,0 +1,5 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_res_partner_bank_account_payment,Full access on res.partner.bank to Account Payment,base.model_res_partner_bank,account_payment.group_account_payment,1,1,1,1
|
||||
access_res_bank_account_payment,Full access on res.bank to Account Payment,base.model_res_bank,account_payment.group_account_payment,1,1,1,1
|
||||
access_res_partner_bank_type_account_manager,Full access on res.partner.bank.type to Financial Manager,base.model_res_partner_bank_type,account.group_account_manager,1,1,1,1
|
||||
access_res_partner_bank_type_field_account_manager,Full access on res.partner.bank.type.field to Financial Manager,base.model_res_partner_bank_type_field,account.group_account_manager,1,1,1,1
|
||||
|
22
account_payment_security/security/payment_security.xml
Normal file
22
account_payment_security/security/payment_security.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Copyright (C) 2014 Akretion (http://www.akretion.com/)
|
||||
@author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
The licence is in the file __openerp__.py
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<delete model="ir.model.access"
|
||||
id="base.access_res_bank_group_partner_manager"/>
|
||||
<delete model="ir.model.access"
|
||||
id="base.access_res_partner_bank_group_partner_manager"/>
|
||||
<delete model="ir.model.access"
|
||||
id="base.access_res_partner_bank_type_group_partner_manager"/>
|
||||
<delete model="ir.model.access"
|
||||
id="base.access_res_partner_bank_type_field_group_partner_manager"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
23
base_fix_display_address/__init__.py
Normal file
23
base_fix_display_address/__init__.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Base Fix Display Address module for OpenERP
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from . import partner
|
||||
44
base_fix_display_address/__openerp__.py
Normal file
44
base_fix_display_address/__openerp__.py
Normal file
@@ -0,0 +1,44 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Base Fix Display Address module for OpenERP
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
{
|
||||
'name': 'Base Fix Display Address',
|
||||
'version': '0.1',
|
||||
'category': 'Hidden',
|
||||
'license': 'AGPL-3',
|
||||
'summary': "Avoid the empty line in address when street2 is not set",
|
||||
'description': """
|
||||
Base Fix Display Address
|
||||
========================
|
||||
|
||||
This module fixes the "empty line in address when street2 is not set" issue when using the method display_address in reports.
|
||||
|
||||
Please contact Alexis de Lattre from Akretion <alexis.delattre@akretion.com> for any help or question about this module.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['base'],
|
||||
'data': [],
|
||||
'installable': True,
|
||||
'active': False,
|
||||
}
|
||||
36
base_fix_display_address/partner.py
Normal file
36
base_fix_display_address/partner.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Base Fix Display Address module for OpenERP
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import orm
|
||||
|
||||
|
||||
class res_partner(orm.Model):
|
||||
_inherit = 'res.partner'
|
||||
|
||||
def _display_address(
|
||||
self, cr, uid, address, without_company=False, context=None):
|
||||
'''Remove empty street2 line'''
|
||||
res = super(res_partner, self)._display_address(
|
||||
cr, uid, address, without_company=without_company, context=context)
|
||||
if res and "\n\n" in res:
|
||||
res = res.replace('\n\n', '\n')
|
||||
return res
|
||||
42
base_partner_always_multi_contacts/__openerp__.py
Normal file
42
base_partner_always_multi_contacts/__openerp__.py
Normal file
@@ -0,0 +1,42 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Base Partner Always Multi Contacts module for OpenERP
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
{
|
||||
'name': 'Base Partner Always Multi Contacts',
|
||||
'version': '0.1',
|
||||
'category': 'Partner',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Both individuals and companies can have multiple contacts',
|
||||
'description': """
|
||||
Base Partner Always Multi Contacts
|
||||
==================================
|
||||
|
||||
By default, you can't enter several addresses for an individual in OpenERP because thee "Contacts" tab is hidden when the field *is Company* is not active. This module solves this.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['base'],
|
||||
'data': ['partner_view.xml'],
|
||||
'installable': True,
|
||||
'active': False,
|
||||
}
|
||||
23
base_partner_always_multi_contacts/partner_view.xml
Normal file
23
base_partner_always_multi_contacts/partner_view.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2014 Akretion (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
The licence is in the file __openerp__.py
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="view_partner_form" model="ir.ui.view">
|
||||
<field name="name">always.show.contacts.tab.on.partner.form</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.view_partner_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<page string="Contacts" position="attributes">
|
||||
<attribute name="attrs">{'invisible': [('parent_id', '!=', False)]}</attribute>
|
||||
</page>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
23
base_partner_link_on_users/__init__.py
Normal file
23
base_partner_link_on_users/__init__.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Base Title on Partner module for OpenERP
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
42
base_partner_link_on_users/__openerp__.py
Normal file
42
base_partner_link_on_users/__openerp__.py
Normal file
@@ -0,0 +1,42 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Base Partner Link on User module for OpenERP
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
{
|
||||
'name': 'Partner Link on User',
|
||||
'version': '0.1',
|
||||
'category': 'Partner',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Display partner_id on user form view',
|
||||
'description': """
|
||||
Partner Link on User
|
||||
====================
|
||||
|
||||
Display partner_id on user form view
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['base'],
|
||||
'data': ['users_view.xml'],
|
||||
'installable': True,
|
||||
'active': False,
|
||||
}
|
||||
24
base_partner_link_on_users/users_view.xml
Normal file
24
base_partner_link_on_users/users_view.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2014 Akretion (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
The licence is in the file __openerp__.py
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="view_users_form" model="ir.ui.view">
|
||||
<field name="name">display.partner_id.on.users.form</field>
|
||||
<field name="model">res.users</field>
|
||||
<field name="inherit_id" ref="base.view_users_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="company_id" position="after">
|
||||
<field name="partner_id"
|
||||
context="{'default_customer': False, 'default_supplier': False, 'default_is_company': False}"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
23
base_title_on_partner/__init__.py
Normal file
23
base_title_on_partner/__init__.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Base Title on Partner module for OpenERP
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
42
base_title_on_partner/__openerp__.py
Normal file
42
base_title_on_partner/__openerp__.py
Normal file
@@ -0,0 +1,42 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Base Title on Partner module for OpenERP
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
{
|
||||
'name': 'Title on Partner',
|
||||
'version': '0.1',
|
||||
'category': 'Partner',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Display title on all the form views of partners',
|
||||
'description': """
|
||||
Title on Partner
|
||||
================
|
||||
|
||||
By default, OpenERP doesn't display the title field on all the partner form views. This module fixes it.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['base'],
|
||||
'data': ['partner_view.xml'],
|
||||
'installable': True,
|
||||
'active': False,
|
||||
}
|
||||
34
base_title_on_partner/partner_view.xml
Normal file
34
base_title_on_partner/partner_view.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2014 Akretion (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
The licence is in the file __openerp__.py
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="view_partner_form" model="ir.ui.view">
|
||||
<field name="name">title.everywhere.on.partner.form</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.view_partner_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='child_ids']/form//field[@name='function']" position="before">
|
||||
<field name="title" domain="[('domain', '=', 'contact')]" options="{'no_open': True}"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_partner_simple_form" model="ir.ui.view">
|
||||
<field name="name">title.on.partner.simplified.form</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.view_partner_simple_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="function" position="before">
|
||||
<field name="title" options="{'no_open': True}"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
3
delivery_carrier_zpl_label_print/__init__.py
Normal file
3
delivery_carrier_zpl_label_print/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import stock
|
||||
48
delivery_carrier_zpl_label_print/__openerp__.py
Normal file
48
delivery_carrier_zpl_label_print/__openerp__.py
Normal file
@@ -0,0 +1,48 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Delivery Carrier ZPL Label Print module for Odoo
|
||||
# Copyright (C) 2015 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
{
|
||||
'name': 'Delivery Carrier ZPL Label Print',
|
||||
'version': '0.1',
|
||||
'category': 'Inventory, Logistic, Storage',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Print ZPL label from delivery order',
|
||||
'description': """
|
||||
Delivery Carrier ZPL Label Print
|
||||
================================
|
||||
|
||||
Add a *Print Label* on Delivery Order that gets the ZPL attached to the picking and sends it to the printer via CUPS.
|
||||
|
||||
It requires this PR: https://github.com/OCA/report-print-send/pull/44
|
||||
|
||||
Please contact Alexis de Lattre from Akretion <alexis.delattre@akretion.com> for any help or question about this module.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['base_delivery_carrier_label', 'base_report_to_printer'],
|
||||
'data': [
|
||||
'stock_view.xml',
|
||||
'users_view.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
137
delivery_carrier_zpl_label_print/stock.py
Normal file
137
delivery_carrier_zpl_label_print/stock.py
Normal file
@@ -0,0 +1,137 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Delivery Carrier ZPL Label Print module for Odoo
|
||||
# Copyright (C) 2015 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import orm, fields
|
||||
from openerp.tools.translate import _
|
||||
import logging
|
||||
import base64
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ResUsers(orm.Model):
|
||||
_inherit = 'res.users'
|
||||
|
||||
_columns = {
|
||||
'label_printer_id': fields.many2one('printing.printer',
|
||||
'Default Label Printer'),
|
||||
}
|
||||
|
||||
|
||||
|
||||
class StockPicking(orm.Model):
|
||||
_inherit = 'stock.picking'
|
||||
|
||||
def _compute_delivery_labels(self, cr, uid, ids, name, arg, context=None):
|
||||
res = {}
|
||||
for picking in self.browse(cr, uid, ids, context=context):
|
||||
label_ids = self.pool['shipping.label'].search(
|
||||
cr, uid, [('res_id', '=', picking.id)], context=context)
|
||||
print "label_ids=", label_ids
|
||||
if label_ids:
|
||||
res[picking.id] = True
|
||||
else:
|
||||
res[picking.id] = False
|
||||
print "res=", res
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'has_delivery_labels': fields.function(
|
||||
_compute_delivery_labels, type='boolean',
|
||||
string='Has Delivery Labels', readonly=True),
|
||||
}
|
||||
|
||||
|
||||
class StockPickingOut(orm.Model):
|
||||
_inherit = 'stock.picking.out'
|
||||
|
||||
def _compute_delivery_labels(self, cr, uid, ids, name, arg, context=None):
|
||||
res = {}
|
||||
for picking in self.browse(cr, uid, ids, context=context):
|
||||
label_ids = self.pool['shipping.label'].search(
|
||||
cr, uid, [('res_id', '=', picking.id)], context=context)
|
||||
print "label_ids=", label_ids
|
||||
if label_ids:
|
||||
res[picking.id] = True
|
||||
else:
|
||||
res[picking.id] = False
|
||||
print "res=", res
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'has_delivery_labels': fields.function(
|
||||
_compute_delivery_labels, type='boolean',
|
||||
string='Has Delivery Labels', readonly=True),
|
||||
}
|
||||
|
||||
def print_zpl_label_picking_list(
|
||||
self, cr, uid, picking_list, context=None):
|
||||
zpl_files = [] # list of tuple (filename, file)
|
||||
# GET ZPL files
|
||||
user = self.pool['res.users'].browse(cr, uid, uid, context=context)
|
||||
if not user.label_printer_id:
|
||||
raise orm.except_orm(
|
||||
_('Erreur:'),
|
||||
_('No Default Label Printer configured for the user %s')
|
||||
% user.name)
|
||||
printer_id = user.label_printer_id.id
|
||||
for picking in picking_list:
|
||||
if picking.state != 'done':
|
||||
raise orm.except_orm(
|
||||
_('Error:'),
|
||||
_("The delivery order %s hasn't been validated.")
|
||||
% picking.name)
|
||||
label_ids = self.pool['shipping.label'].search(
|
||||
cr, uid, [('res_id', '=', picking.id)], context=context)
|
||||
logger.info('%d labels found for picking %s',
|
||||
len(label_ids), picking.name)
|
||||
if not label_ids:
|
||||
raise orm.except_orm(
|
||||
_('Error:'),
|
||||
_("No ZPL file attached to the Delivery order %s."
|
||||
"You should click on the button "
|
||||
"'Create Shipping Label' of the Delivery order.")
|
||||
% picking.name)
|
||||
labels = self.pool['shipping.label'].browse(
|
||||
cr, uid, label_ids, context=context)
|
||||
for label in labels:
|
||||
zpl_files.append(
|
||||
(label.name, base64.decodestring(label.datas)))
|
||||
# NOW PRINT !
|
||||
logger.info('Starting to print %d ZPL files' % len(zpl_files))
|
||||
for zpl_fname, zpl_file in zpl_files:
|
||||
logger.info('Starting to send ZPL file %s' % zpl_fname)
|
||||
self.pool['printing.printer'].print_document(
|
||||
cr, uid, [printer_id], zpl_fname,
|
||||
zpl_file, 'raw', context=context)
|
||||
# 4e arg = nom de report bidon... ça ne sert pas a priori
|
||||
logger.info('ZPL file %s sent' % zpl_fname)
|
||||
logger.info('Printing of ZPL files finished')
|
||||
return True
|
||||
|
||||
def print_zpl_delivery_label(self, cr, uid, ids, context=None):
|
||||
assert len(ids) == 1, "only 1 id"
|
||||
picking = self.browse(cr, uid, ids[0], context=context)
|
||||
return self.print_zpl_label_picking_list(
|
||||
cr, uid, [picking], context=context)
|
||||
|
||||
|
||||
29
delivery_carrier_zpl_label_print/stock_view.xml
Normal file
29
delivery_carrier_zpl_label_print/stock_view.xml
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Copyright (C) 2015 Akretion (http://www.akretion.com/)
|
||||
@author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
The licence is in the file __openerp__.py
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
|
||||
<record id="view_picking_out_form" model="ir.ui.view">
|
||||
<field name="name">delivery_carrier_zpl_label_print.picking.out.form</field>
|
||||
<field name="model">stock.picking.out</field>
|
||||
<field name="inherit_id" ref="base_delivery_carrier_label.view_picking_out_form" />
|
||||
<field name="arch" type="xml">
|
||||
<button name="action_generate_carrier_label" position="after">
|
||||
<button name="print_zpl_delivery_label" type="object" string="Print Delivery Labels" attrs="{'invisible': [('has_delivery_labels', '!=', True)]}"/>
|
||||
</button>
|
||||
<field name="weight_net" position="after">
|
||||
<field name="has_delivery_labels" invisible="0"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
22
delivery_carrier_zpl_label_print/users_view.xml
Normal file
22
delivery_carrier_zpl_label_print/users_view.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 Alexis de Lattre <alexis@via.ecp.fr>
|
||||
The licence is in the file __openerp__.py
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="view_users_form" model="ir.ui.view">
|
||||
<field name="name">delivery.carrier.zpl.label.res.users.form</field>
|
||||
<field name="model">res.users</field>
|
||||
<field name="inherit_id" ref="base_report_to_printer.view_printing_users_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="printing_printer_id" position="after">
|
||||
<field name="label_printer_id"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
23
eradicate_quick_create/__init__.py
Normal file
23
eradicate_quick_create/__init__.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Eradicate Quick Create module for Odoo/OpenERP
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from . import model
|
||||
41
eradicate_quick_create/__openerp__.py
Normal file
41
eradicate_quick_create/__openerp__.py
Normal file
@@ -0,0 +1,41 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Eradicate Quick Create module for OpenERP/Odoo
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
{
|
||||
'name': 'Eradicate Quick Create',
|
||||
'version': '0.1',
|
||||
'category': 'Tools',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Disable quick create on all objects',
|
||||
'description': """
|
||||
Eradicate Quick Create
|
||||
======================
|
||||
|
||||
Disable quick create on all objects of Odoo.
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['base_optional_quick_create'],
|
||||
}
|
||||
38
eradicate_quick_create/model.py
Normal file
38
eradicate_quick_create/model.py
Normal file
@@ -0,0 +1,38 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Eradicate Quick Create module for Odoo/OpenERP
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import orm
|
||||
|
||||
|
||||
class ir_model(orm.Model):
|
||||
_inherit = 'ir.model'
|
||||
|
||||
def init(self, cr):
|
||||
'''Activate 'avoid_quick_create' on all existing models'''
|
||||
cr.execute(
|
||||
"UPDATE ir_model SET avoid_quick_create=true "
|
||||
"WHERE avoid_quick_create is not true")
|
||||
return True
|
||||
|
||||
_defaults = {
|
||||
'avoid_quick_create': True,
|
||||
}
|
||||
BIN
eradicate_quick_create/static/description/icon.png
Normal file
BIN
eradicate_quick_create/static/description/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.4 KiB |
39
hr_holidays_usability/README.rst
Normal file
39
hr_holidays_usability/README.rst
Normal file
@@ -0,0 +1,39 @@
|
||||
HR Holidays Usability
|
||||
=====================
|
||||
|
||||
This module adds what I consider the minimum usability level for the holiday management module in Odoo:
|
||||
|
||||
* By default, if you only use the official *hr_holidays* module, there the number of days is not automatically computed from the start date and end date. This module fixes it : it counts the number of days following a computation method that is defined on the object hr.holiday.status. It also replaces the datetime field for start/end dates by a date field plus a selection field to indicated morning/noon/evening.
|
||||
|
||||
* It depends on the OCA module *hr_public_holidays* to easily define the bank holidays per country. It takes those bank holidays into account when counting the number of days.
|
||||
|
||||
* It sends an email to the manager when the employee submits a holiday requests (with the employee in Cc) and it sends an email to the employee (with the manager in Cc) when the holiday request is validated/refused.
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
This module requires a patch on the official hr_holidays module:
|
||||
in addons/hr_holidays/hr_holidays.py, in the method holidays_validate(), remplace
|
||||
|
||||
.. code::
|
||||
|
||||
if record.holiday_type == 'employee' and record.type == 'remove':
|
||||
|
||||
by
|
||||
|
||||
.. code::
|
||||
|
||||
if record.holiday_type == 'employee' and record.type == 'remove' and record.date_from and record.date_to:
|
||||
|
||||
Known issues / Roadmap
|
||||
======================
|
||||
|
||||
* Beware that this module works for old version of Odoo v7, not with up-to-date versions, because my customer uses an old version. If you use an up-to-date version, you need to adapt the inherit of hr_holidays.edit_holiday_new (required property moved to attrs, and probably other changes)
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
* Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
25
hr_holidays_usability/__init__.py
Normal file
25
hr_holidays_usability/__init__.py
Normal file
@@ -0,0 +1,25 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# HR Holidays Usability module for Odoo
|
||||
# Copyright (C) 2015 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from . import hr_holidays
|
||||
from . import wizard
|
||||
from . import report
|
||||
46
hr_holidays_usability/__openerp__.py
Normal file
46
hr_holidays_usability/__openerp__.py
Normal file
@@ -0,0 +1,46 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# HR Holidays Usability module for Odoo
|
||||
# Copyright (C) 2015 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
{
|
||||
'name': 'HR Holidays Usability',
|
||||
'version': '0.1',
|
||||
'category': 'Human Resources',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Better usability for the management of holidays',
|
||||
'description': '',
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['hr_holidays', 'hr_public_holidays'],
|
||||
'data': [
|
||||
'wizard/hr_holidays_mass_allocation_view.xml',
|
||||
'wizard/hr_holidays_post_view.xml',
|
||||
'report/hr_holidays_employee_counter_view.xml',
|
||||
'hr_holidays_view.xml',
|
||||
'hr_holidays_mail.xml',
|
||||
'res_company_view.xml',
|
||||
'hr_employee_view.xml',
|
||||
'security/holiday_security.xml',
|
||||
'security/ir.model.access.csv',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
22
hr_holidays_usability/hr_employee_view.xml
Normal file
22
hr_holidays_usability/hr_employee_view.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 Akretion (http://www.akretion.com)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
The licence is in the file __openerp__.py
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="view_employee_form_leave_inherit" model="ir.ui.view">
|
||||
<field name="name">hr_holidays_usability.hr.employee.form</field>
|
||||
<field name="model">hr.employee</field>
|
||||
<field name="inherit_id" ref="hr_holidays.view_employee_form_leave_inherit"/>
|
||||
<field name="arch" type="xml">
|
||||
<group string="Leaves" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
369
hr_holidays_usability/hr_holidays.py
Normal file
369
hr_holidays_usability/hr_holidays.py
Normal file
@@ -0,0 +1,369 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# HR Holidays Usability module for Odoo
|
||||
# Copyright (C) 2015 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import orm, fields
|
||||
from openerp.tools.translate import _
|
||||
from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, \
|
||||
DEFAULT_SERVER_DATETIME_FORMAT
|
||||
from openerp.tools import float_compare
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
import pytz
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HrHolidaysStatus(orm.Model):
|
||||
_inherit = 'hr.holidays.status'
|
||||
|
||||
_columns = {
|
||||
'vacation_compute_method': fields.selection([
|
||||
('worked', u'Jours ouvrés'),
|
||||
('business', u'Jours ouvrables'),
|
||||
# TODO find proper English translation
|
||||
], 'Vacation Compute Method', required=True),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'vacation_compute_method': 'worked',
|
||||
}
|
||||
|
||||
|
||||
class HrHolidays(orm.Model):
|
||||
_inherit = 'hr.holidays'
|
||||
_order = 'type desc, date_from desc'
|
||||
# by default : type desc, date_from asc
|
||||
|
||||
# Idea :
|
||||
# For allocation (type = add), we don't change anything
|
||||
# For leave (type = remove), we don't let users enter the number of days, we compute it for them
|
||||
# -> new computed field "number_of_days_remove' that compute the number of days depending on the computation method defined on 'type'
|
||||
# Redefine the field 'number_of_days' to take into accout 'number_of_days_remove' when type == remove
|
||||
# change date time fields by date + selection morning/noon
|
||||
|
||||
# How do we set the dates :
|
||||
# from : premier jour d'absence (et non dernier jour de présence) + time : morning/noon
|
||||
# to : date de fin de congés (et non date de retour au travail) + time : noon/evening
|
||||
|
||||
# which computation methods on the 'hr.holidays.status':
|
||||
# 1) jours ouvrés (sans compter les jours fériés)
|
||||
# 2) jours ouvrables (quid des jours fériés ???) : il faut compter les samedis sauf les samedis fériés. Cas particulier : quand la personne prend le vendredi aprèm, il faut compter 1j (et non 0.5 ni 1.5)
|
||||
# 3) malade : on compte tous les jours -> ptet pas nécessaire pour le moment
|
||||
# 1 for 'unpaid leaves' + repos compensateur + congés conventionnels + maladie
|
||||
# 1 or 2 for normal holidays
|
||||
|
||||
def _compute_number_of_days(
|
||||
self, cr, uid, ids, name, args, context=None):
|
||||
res = {}
|
||||
# depend on the holiday_status_id
|
||||
hhpo = self.pool['hr.holidays.public']
|
||||
for hol in self.browse(cr, uid, ids, context=context):
|
||||
days = 0.0
|
||||
if hol.type == 'remove' and hol.holiday_type == 'employee' and hol.vacation_date_from and hol.vacation_date_to:
|
||||
if hol.holiday_status_id.vacation_compute_method == 'business':
|
||||
business = True
|
||||
else:
|
||||
business = False
|
||||
date_dt = start_date_dt = datetime.strptime(
|
||||
hol.vacation_date_from, DEFAULT_SERVER_DATE_FORMAT)
|
||||
end_date_dt = datetime.strptime(
|
||||
hol.vacation_date_to, DEFAULT_SERVER_DATE_FORMAT)
|
||||
|
||||
while True:
|
||||
# REGULAR COMPUTATION
|
||||
# if it's a bank holidays, don't count
|
||||
if hhpo.is_public_holiday(
|
||||
cr, uid, date_dt, hol.employee_id.id,
|
||||
context=context):
|
||||
logger.info(
|
||||
"%s is a bank holiday, don't count", date_dt)
|
||||
# it it's a saturday/sunday
|
||||
elif date_dt.weekday() in (5, 6):
|
||||
logger.info(
|
||||
"%s is a saturday/sunday, don't count", date_dt)
|
||||
else:
|
||||
days += 1.0
|
||||
# special case for friday when compute_method = business
|
||||
if (
|
||||
business
|
||||
and date_dt.weekday() == 4
|
||||
and not hhpo.is_public_holiday(
|
||||
cr, uid, date_dt + relativedelta(days=1),
|
||||
hol.employee_id.id, context=context)):
|
||||
days += 1.0
|
||||
# PARTICULAR CASE OF THE FIRST DAY
|
||||
if date_dt == start_date_dt:
|
||||
if hol.vacation_time_from == 'noon':
|
||||
if (
|
||||
business
|
||||
and date_dt.weekday() == 4
|
||||
and not hhpo.is_public_holiday(
|
||||
cr, uid, date_dt + relativedelta(days=1),
|
||||
hol.employee_id.id, context=context)):
|
||||
days -= 1.0 # result = 2 - 1 = 1
|
||||
else:
|
||||
days -= 0.5
|
||||
# PARTICULAR CASE OF THE LAST DAY
|
||||
if date_dt == end_date_dt:
|
||||
if hol.vacation_time_to == 'noon':
|
||||
if (
|
||||
business
|
||||
and date_dt.weekday() == 4
|
||||
and not hhpo.is_public_holiday(
|
||||
cr, uid, date_dt + relativedelta(days=1),
|
||||
hol.employee_id.id, context=context)):
|
||||
days -= 1.5 # 2 - 1.5 = 0.5
|
||||
else:
|
||||
days -= 0.5
|
||||
break
|
||||
date_dt += relativedelta(days=1)
|
||||
res[hol.id] = {
|
||||
'number_of_days': days * -1,
|
||||
'number_of_days_remove': days,
|
||||
}
|
||||
|
||||
elif hol.type == 'remove':
|
||||
# When we do a leave and force qty
|
||||
res[hol.id] = {
|
||||
'number_of_days': hol.number_of_days_temp * -1,
|
||||
'number_of_days_remove': hol.number_of_days_temp,
|
||||
}
|
||||
else:
|
||||
# for allocations, we read the native field number_of_days_temp
|
||||
res[hol.id] = {
|
||||
'number_of_days': hol.number_of_days_temp,
|
||||
'number_of_days_remove': 0,
|
||||
}
|
||||
return res
|
||||
|
||||
def _compute_current_leaves(self, cr, uid, ids, name, arg, context=None):
|
||||
res = {}
|
||||
for hol in self.browse(cr, uid, ids, context=context):
|
||||
if (
|
||||
hol.holiday_type == 'employee' and
|
||||
hol.employee_id and
|
||||
hol.holiday_status_id):
|
||||
days = self.pool['hr.holidays.status'].get_days(
|
||||
cr, uid, [hol.holiday_status_id.id], hol.employee_id.id,
|
||||
False, context=context)
|
||||
res[hol.id] = {
|
||||
'total_allocated_leaves':
|
||||
days[hol.holiday_status_id.id]['max_leaves'],
|
||||
'current_leaves_taken':
|
||||
days[hol.holiday_status_id.id]['leaves_taken'],
|
||||
'current_remaining_leaves':
|
||||
days[hol.holiday_status_id.id]['remaining_leaves'],
|
||||
}
|
||||
else:
|
||||
res[hol.id] = {
|
||||
'total_allocated_leaves': 0,
|
||||
'current_leaves_taken': 0,
|
||||
'current_remaining_leaves': 0,
|
||||
}
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'vacation_date_from': fields.date(
|
||||
'First Day of Vacation', track_visibility='onchange',
|
||||
help="Enter the first day of vacation. For example, if "
|
||||
"you leave one full calendar week, the first day of vacation "
|
||||
"is Monday morning (and not Friday of the week before)"),
|
||||
'vacation_time_from': fields.selection([
|
||||
('morning', 'Morning'),
|
||||
('noon', 'Noon'),
|
||||
], "Start of Vacation", track_visibility='onchange',
|
||||
help="For example, if you leave one full calendar week, "
|
||||
"the first day of vacation is Monday Morning"),
|
||||
'vacation_date_to': fields.date(
|
||||
'Last Day of Vacation', track_visibility='onchange',
|
||||
help="Enter the last day of vacation. For example, if you "
|
||||
"leave one full calendar week, the last day of vacation is "
|
||||
"Friday evening (and not Monday of the week after)"),
|
||||
'vacation_time_to': fields.selection([
|
||||
('noon', 'Noon'),
|
||||
('evening', 'Evening'),
|
||||
], "End of Vacation", track_visibility='onchange',
|
||||
help="For example, if you leave one full calendar week, "
|
||||
"the end of vacation is Friday Evening"),
|
||||
'number_of_days_remove': fields.function(
|
||||
_compute_number_of_days,
|
||||
string="Number of Days of Vacation", multi='holdays',
|
||||
type="float", readonly=True),
|
||||
# number_of_days is a native field that I inherit
|
||||
'number_of_days': fields.function(
|
||||
_compute_number_of_days, string='Number of Days',
|
||||
multi='holdays', store=True),
|
||||
'current_leaves_taken': fields.function(
|
||||
_compute_current_leaves, string='Current Leaves Taken',
|
||||
multi='usability', type='float', readonly=True),
|
||||
'current_remaining_leaves': fields.function(
|
||||
_compute_current_leaves, string='Current Remaining Leaves',
|
||||
multi='usability', type='float', readonly=True),
|
||||
'total_allocated_leaves': fields.function(
|
||||
_compute_current_leaves, string='Total Allocated Leaves',
|
||||
multi='usability', type='float', readonly=True),
|
||||
'limit': fields.related(
|
||||
'holiday_status_id', 'limit', type='boolean',
|
||||
string='Allow to Override Limit', readonly=True),
|
||||
'posted_date': fields.date('Posted Date', track_visibility='onchange'),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'vacation_time_from': 'morning',
|
||||
'vacation_time_to': 'evening',
|
||||
}
|
||||
|
||||
def _check_vacation_dates(self, cr, uid, ids):
|
||||
hhpo = self.pool['hr.holidays.public']
|
||||
for hol in self.browse(cr, uid, ids):
|
||||
if hol.type == 'remove' and hol.vacation_date_from and hol.vacation_date_to:
|
||||
if hol.vacation_date_from > hol.vacation_date_to:
|
||||
raise orm.except_orm(
|
||||
_('Error:'),
|
||||
_('The first day cannot be after the last day !'))
|
||||
elif (
|
||||
hol.vacation_date_from == hol.vacation_date_to
|
||||
and hol.vacation_time_from == hol.vacation_time_to):
|
||||
raise orm.except_orm(
|
||||
_('Error:'),
|
||||
_("The start of vacation is exactly the "
|
||||
"same as the end !"))
|
||||
date_from_dt = datetime.strptime(
|
||||
hol.vacation_date_from, DEFAULT_SERVER_DATE_FORMAT)
|
||||
if date_from_dt.weekday() in (5, 6):
|
||||
raise orm.except_orm(
|
||||
_('Error:'),
|
||||
_("The first day of vacation cannot be a "
|
||||
"saturday or sunday !"))
|
||||
date_to_dt = datetime.strptime(
|
||||
hol.vacation_date_to, DEFAULT_SERVER_DATE_FORMAT)
|
||||
if date_to_dt.weekday() in (5, 6):
|
||||
raise orm.except_orm(
|
||||
_('Error:'),
|
||||
_("The last day of Vacation cannot be a "
|
||||
"saturday or sunday !"))
|
||||
if hhpo.is_public_holiday(
|
||||
cr, uid, date_from_dt, hol.employee_id.id):
|
||||
raise orm.except_orm(
|
||||
_('Error:'),
|
||||
_("The first day of vacation cannot be a "
|
||||
"bank holiday !"))
|
||||
if hhpo.is_public_holiday(
|
||||
cr, uid, date_to_dt, hol.employee_id.id):
|
||||
raise orm.except_orm(
|
||||
_('Error:'),
|
||||
_("The last day of vacation cannot be a "
|
||||
"bank holiday !"))
|
||||
return True
|
||||
|
||||
_constraints = [(
|
||||
_check_vacation_dates,
|
||||
'error msg in raise',
|
||||
['vacation_date_from', 'vacation_date_to', 'holiday_type', 'type'],
|
||||
)]
|
||||
|
||||
def vacation_from(
|
||||
self, cr, uid, ids, vacation_date_from, vacation_time_from,
|
||||
context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
hour = 0 # = morning
|
||||
if vacation_time_from and vacation_time_from == 'noon':
|
||||
hour = 13 # noon, LOCAL TIME
|
||||
# Warning : when the vacation STARTs at Noon, it starts at 1 p.m.
|
||||
# to avoid an overlap (which would be blocked by a constraint of
|
||||
# hr_holidays) if a user requests 2 half-days with different
|
||||
# holiday types on the same day
|
||||
datetime_str = False
|
||||
if vacation_date_from:
|
||||
date_dt = datetime.strptime(
|
||||
vacation_date_from, DEFAULT_SERVER_DATE_FORMAT)
|
||||
if context.get('tz'):
|
||||
localtz = pytz.timezone(context['tz'])
|
||||
else:
|
||||
localtz = pytz.utc
|
||||
datetime_dt = localtz.localize(datetime(
|
||||
date_dt.year, date_dt.month, date_dt.day, hour, 0, 0))
|
||||
# we give to odoo a datetime in UTC
|
||||
datetime_str = datetime_dt.astimezone(pytz.utc).strftime(
|
||||
DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
return {'value': {'date_from': datetime_str}}
|
||||
|
||||
def vacation_to(
|
||||
self, cr, uid, ids, vacation_date_to, vacation_time_to,
|
||||
context=None):
|
||||
hour = 23 # = evening
|
||||
if vacation_time_to and vacation_time_to == 'noon':
|
||||
hour = 12 # Noon, LOCAL TIME
|
||||
# Warning : when vacation STOPs at Noon, it stops at 12 a.m.
|
||||
# to avoid an overlap (which would be blocked by a constraint of
|
||||
# hr_holidays) if a user requests 2 half-days with different
|
||||
# holiday types on the same day
|
||||
datetime_str = False
|
||||
if vacation_date_to:
|
||||
date_dt = datetime.strptime(
|
||||
vacation_date_to, DEFAULT_SERVER_DATE_FORMAT)
|
||||
if context.get('tz'):
|
||||
localtz = pytz.timezone(context['tz'])
|
||||
else:
|
||||
localtz = pytz.utc
|
||||
datetime_dt = localtz.localize(datetime(
|
||||
date_dt.year, date_dt.month, date_dt.day, hour, 0, 0))
|
||||
# we give to odoo a datetime in UTC
|
||||
datetime_str = datetime_dt.astimezone(pytz.utc).strftime(
|
||||
DEFAULT_SERVER_DATETIME_FORMAT)
|
||||
return {'value': {'date_to': datetime_str}}
|
||||
|
||||
# Native method that I inherit
|
||||
def check_holidays(self, cr, uid, ids, context=None):
|
||||
holi_status_obj = self.pool.get('hr.holidays.status')
|
||||
for record in self.browse(cr, uid, ids):
|
||||
if record.holiday_type == 'employee' and record.type == 'remove':
|
||||
if record.employee_id and not record.holiday_status_id.limit:
|
||||
leaves_rest = holi_status_obj.get_days(
|
||||
cr, uid, [record.holiday_status_id.id],
|
||||
record.employee_id.id,
|
||||
False)[record.holiday_status_id.id]['remaining_leaves']
|
||||
# here is the code that I modify
|
||||
#if leaves_rest < record.number_of_days_temp:
|
||||
#if leaves_rest < record.number_of_days * -1:
|
||||
if float_compare(leaves_rest, record.number_of_days * -1, precision_digits=2) < 0:
|
||||
raise orm.except_orm(
|
||||
_('Warning!'),
|
||||
_('There are not enough %s allocated for '
|
||||
'employee %s (requesting %s days but only %s '
|
||||
'days left).')
|
||||
% (record.holiday_status_id.name,
|
||||
record.employee_id.name,
|
||||
record.number_of_days * -1,
|
||||
leaves_rest))
|
||||
return True
|
||||
|
||||
|
||||
class ResCompany(orm.Model):
|
||||
_inherit = 'res.company'
|
||||
|
||||
_columns = {
|
||||
'mass_allocation_default_holiday_status_id': fields.many2one(
|
||||
'hr.holidays.status', 'Default Leave Type for Mass Allocation'),
|
||||
}
|
||||
113
hr_holidays_usability/hr_holidays_mail.xml
Normal file
113
hr_holidays_usability/hr_holidays_mail.xml
Normal file
@@ -0,0 +1,113 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="ir_actions_server_hr_holidays_confirm_mail" model="ir.actions.server">
|
||||
<field name="name">Auto-email confirmed leave</field>
|
||||
<field name="code">context.update({
|
||||
'wkf_tracker': 'submitted',
|
||||
'dbname': cr.dbname,
|
||||
})
|
||||
template_id=self.pool.get('ir.model.data').get_object_reference(cr, uid, 'hr_holidays_usability', 'email_template_hr_holidays')[1]
|
||||
self.pool.get('email.template').send_mail(cr, uid, template_id, object.id, force_send=True, context=context)</field>
|
||||
<field name="state">code</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="hr_holidays.model_hr_holidays"/>
|
||||
<field name="condition">True</field>
|
||||
</record>
|
||||
|
||||
<record id="ir_actions_server_hr_holidays_validate_mail" model="ir.actions.server">
|
||||
<field name="name">Auto-email validated leave</field>
|
||||
<field name="code">context.update({
|
||||
'wkf_tracker': 'validated',
|
||||
'dbname': cr.dbname,
|
||||
})
|
||||
template_id=self.pool.get('ir.model.data').get_object_reference(cr, uid, 'hr_holidays_usability', 'email_template_hr_holidays')[1]
|
||||
self.pool.get('email.template').send_mail(cr, uid, template_id, object.id, force_send=True, context=context)</field>
|
||||
<field name="state">code</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="hr_holidays.model_hr_holidays"/>
|
||||
<field name="condition">True</field>
|
||||
</record>
|
||||
|
||||
<record id="ir_actions_server_hr_holidays_refuse_mail" model="ir.actions.server">
|
||||
<field name="name">Auto-email refused leave</field>
|
||||
<field name="code">context.update({
|
||||
'wkf_tracker': 'refused',
|
||||
'dbname': cr.dbname,
|
||||
})
|
||||
template_id=self.pool.get('ir.model.data').get_object_reference(cr, uid, 'hr_holidays_usability', 'email_template_hr_holidays')[1]
|
||||
self.pool.get('email.template').send_mail(cr, uid, template_id, object.id, force_send=True, context=context)</field>
|
||||
<field name="state">code</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="hr_holidays.model_hr_holidays"/>
|
||||
<field name="condition">True</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_holidays.act_confirm" model="workflow.activity">
|
||||
<field name="action_id" ref="ir_actions_server_hr_holidays_confirm_mail"/>
|
||||
</record>
|
||||
|
||||
<record id="hr_holidays.act_validate" model="workflow.activity">
|
||||
<field name="action_id" ref="ir_actions_server_hr_holidays_validate_mail"/>
|
||||
</record>
|
||||
|
||||
<record id="hr_holidays.act_refuse" model="workflow.activity">
|
||||
<field name="action_id" ref="ir_actions_server_hr_holidays_refuse_mail"/>
|
||||
</record>
|
||||
|
||||
<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"/>
|
||||
<field name="email_from">${user.company_id.email}</field>
|
||||
<field name="email_to">${object.employee_id.parent_id.user_id.email or ''}</field>
|
||||
<field name="email_cc">${object.employee_id.user_id.email or ''}</field>
|
||||
<field name="reply_to">${user.email or ''}</field>
|
||||
<field name="subject">${ctx.get('dbname') and 'prod' not in ctx.get('dbname') and '[TEST]' or ''}[${object.type == 'remove' and 'Leave' or 'Allocation'} ${ctx.get('wkf_tracker')}] ${object.name or ''} - ${object.employee_id.name or ''}</field>
|
||||
<field name="auto_delete" eval="False"/>
|
||||
<field name="lang">${user.lang}</field>
|
||||
<field name="body_html"><![CDATA[
|
||||
<div style="font-family: 'Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: #FFF; ">
|
||||
|
||||
% if ctx.get('dbname') and 'prod' not in ctx.get('dbname'):
|
||||
<p>WARNING : THIS IS A TEST E-MAIL sent from a test OpenERP database (${ctx.get('dbname')}). Do not take into account !</p>
|
||||
|
||||
% endif
|
||||
<p>The following ${object.type == 'remove' and 'leave request' or 'ALLOCATION request (i.e. credit of days, not debit !)'} has been ${ctx.get('wkf_tracker') or 'ERROR'} today in OpenERP by ${user.name or ''} :</p>
|
||||
|
||||
<ul>
|
||||
<li>Employee : ${object.employee_id.name or ''}</li>
|
||||
% if object.employee_id.parent_id:
|
||||
<li>Employee's manager : ${object.employee_id.parent_id.name or ''}</li>
|
||||
% endif
|
||||
% if object.type == 'remove':
|
||||
<li>Start date : ${object.vacation_date_from or ''} ${object.vacation_time_from or ''}</li>
|
||||
<li>End date : ${object.vacation_date_to or ''} ${object.vacation_time_to or ''}</li>
|
||||
% endif
|
||||
<li>Number of days : ${object.number_of_days < 0 and object.number_of_days * -1 or object.number_of_days}</li>
|
||||
<li>Leave type : ${object.holiday_status_id.name or ''}</li>
|
||||
<li>Description : ${object.name or ''}</li>
|
||||
% if object.notes:
|
||||
<li>Notes : ${object.notes or ''}</li>
|
||||
% endif
|
||||
</ul>
|
||||
|
||||
% if ctx.get('wkf_tracker') == 'submitted':
|
||||
% if object.type == 'remove':
|
||||
<p>To validate or refuse it, go to the menu Human Resources > Leaves > Leave requests to approve.</p>
|
||||
% else:
|
||||
<p>To validate or refuse it, go to the menu Human Resources > Leaves > Allocation requests.</p>
|
||||
% endif
|
||||
|
||||
% endif
|
||||
<p>
|
||||
-- <br/>
|
||||
Automatic e-mail sent by OpenERP. Do not reply.<br/>
|
||||
Database : ${ctx.get('dbname')}<br/>
|
||||
</p>
|
||||
</div>
|
||||
]]></field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
213
hr_holidays_usability/hr_holidays_view.xml
Normal file
213
hr_holidays_usability/hr_holidays_view.xml
Normal file
@@ -0,0 +1,213 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 Akretion (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
The licence is in the file __openerp__.py
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="edit_holiday_new" model="ir.ui.view">
|
||||
<field name="name">hr_holidays_usability.leave_request_form</field>
|
||||
<field name="model">hr.holidays</field>
|
||||
<field name="inherit_id" ref="hr_holidays.edit_holiday_new"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="date_from" position="attributes">
|
||||
<attribute name="required">0</attribute>
|
||||
</field>
|
||||
<field name="date_to" position="attributes">
|
||||
<attribute name="required">0</attribute>
|
||||
</field>
|
||||
<xpath expr="//field[@name='date_from']/.." position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</xpath>
|
||||
<field name="number_of_days_temp" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</field>
|
||||
<field name="number_of_days_temp" position="after">
|
||||
<field name="number_of_days_remove" class="oe_inline"/>
|
||||
</field>
|
||||
<field name="holiday_status_id" position="after">
|
||||
<field name="vacation_date_from" on_change="vacation_from(vacation_date_from, vacation_time_from, context)" required="1"/>
|
||||
<field name="vacation_time_from" on_change="vacation_from(vacation_date_from, vacation_time_from, context)" required="1"/>
|
||||
<field name="vacation_date_to" on_change="vacation_to(vacation_date_to, vacation_time_to, context)" required="1"/>
|
||||
<field name="vacation_time_to" on_change="vacation_to(vacation_date_to, vacation_time_to, context)" required="1"/>
|
||||
</field>
|
||||
<xpath expr="//field[@name='department_id']/.." position="after">
|
||||
<group string="Counter for this leave type" name="counters" attrs="{'invisible': [('limit', '=', True)]}">
|
||||
<field name="limit" invisible="1"/>
|
||||
<label for="total_allocated_leaves"/>
|
||||
<div>
|
||||
<field name="total_allocated_leaves" class="oe_inline"/>
|
||||
<label string=" days" class="oe_inline"/>
|
||||
</div>
|
||||
<label for="current_leaves_taken"/>
|
||||
<div>
|
||||
<field name="current_leaves_taken" class="oe_inline"/>
|
||||
<label string=" days" class="oe_inline"/>
|
||||
</div>
|
||||
<label for="current_remaining_leaves"/>
|
||||
<div>
|
||||
<field name="current_remaining_leaves" class="oe_inline"/>
|
||||
<label string=" days" class="oe_inline"/>
|
||||
</div>
|
||||
</group>
|
||||
</xpath>
|
||||
<field name="department_id" position="after">
|
||||
<field name="posted_date" groups="base.group_hr_user"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_holiday" model="ir.ui.view">
|
||||
<field name="name">hr_holidays_usability.leave_request_tree</field>
|
||||
<field name="model">hr.holidays</field>
|
||||
<field name="inherit_id" ref="hr_holidays.view_holiday"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="number_of_days" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</field>
|
||||
<field name="number_of_days" position="after">
|
||||
<field name="number_of_days_remove" sum="Total Days of Vacation"/>
|
||||
</field>
|
||||
<field name="date_from" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</field>
|
||||
<field name="date_from" position="after">
|
||||
<field name="vacation_date_from"/>
|
||||
<field name="vacation_time_from"/>
|
||||
</field>
|
||||
<field name="date_to" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</field>
|
||||
<field name="date_to" position="after">
|
||||
<field name="vacation_date_to"/>
|
||||
<field name="vacation_time_to"/>
|
||||
</field>
|
||||
<field name="holiday_status_id" position="attributes">
|
||||
<attribute name="invisible">0</attribute>
|
||||
</field>
|
||||
<field name="holiday_status_id" position="after">
|
||||
<field name="posted_date" groups="base.group_hr_user"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="edit_holiday_status_form" model="ir.ui.view">
|
||||
<field name="name">hr_holidays_usability.hr.holidays.status.form</field>
|
||||
<field name="model">hr.holidays.status</field>
|
||||
<field name="inherit_id" ref="hr_holidays.edit_holiday_status_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="name" position="after">
|
||||
<field name="vacation_compute_method"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_holiday_status_normal_tree" model="ir.ui.view">
|
||||
<field name="name">hr_holidays_usability.hr.holidays.status.normal.tree</field>
|
||||
<field name="model">hr.holidays.status</field>
|
||||
<field name="inherit_id" ref="hr_holidays.view_holiday_status_normal_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="name" position="after">
|
||||
<field name="vacation_compute_method"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- On the leave requests, put tree view by default instead of calendar -->
|
||||
<record id="hr_holidays.action_open_ask_holidays_calendar" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="5"/>
|
||||
</record>
|
||||
|
||||
<record id="resource_calendar_leaves_cal_first_action" model="ir.actions.act_window">
|
||||
<field name="name">Leaves Calendar</field>
|
||||
<field name="res_model">resource.calendar.leaves</field>
|
||||
<field name="view_mode">calendar,tree,form</field>
|
||||
</record>
|
||||
<!-- Warning: when you have mrp installed, there is an ACL that gives write/create access to MRP Users on resource.calendar.leaves You should inherit this ACL with XMLID mrp.access_resource_calendar_leaves_user to give only read access:
|
||||
|
||||
mrp.access_resource_calendar_leaves_user,only read access to manufacuting user,resource.model_resource_calendar_leaves,mrp.group_mrp_user,1,0,0,0
|
||||
|
||||
-->
|
||||
|
||||
<!-- When you have a balance of legal leaves of 0.1 (for example), you cannot 'use'
|
||||
it because this module only allows you to use 0.5, 1, 1.5, ...
|
||||
So, if you want to "cleanup" this balance of 0.1, you should declare a leave of 0.1
|
||||
and an allocation of 0.1 on a newer legal leave
|
||||
This menu entry is designed for this and only accessible to HR Manager -->
|
||||
|
||||
<record id="hr_holidays_leave_force_number_form" model="ir.ui.view">
|
||||
<field name="name">Leave request force qty</field>
|
||||
<field name="model">hr.holidays</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Leave Request Force Qty" version="7.0">
|
||||
<header>
|
||||
<button string="Approve" name="validate" states="confirm" type="workflow" groups="base.group_hr_user" class="oe_highlight"/>
|
||||
<button string="Validate" name="second_validate" states="validate1" type="workflow" groups="base.group_hr_user" class="oe_highlight"/>
|
||||
<button string="Refuse" name="refuse" states="confirm,validate,validate1" type="workflow" groups="base.group_hr_user"/>
|
||||
<button string="Reset to New" name="set_to_draft" states="cancel,refuse" type="object" groups="base.group_hr_user"/>
|
||||
<field name="state" widget="statusbar" statusbar_visible="draft,confirm,validate" statusbar_colors='{"confirm":"blue","validate1":"blue","refuse":"red"}'/>
|
||||
</header>
|
||||
<sheet>
|
||||
<group>
|
||||
<group>
|
||||
<field name="name" required="1" attrs="{'readonly':[('state','!=','draft'),('state','!=','confirm')]}"/>
|
||||
<field name="holiday_status_id" context="{'employee_id':employee_id}"/>
|
||||
<label for="number_of_days_temp" string="Leave"/>
|
||||
<div>
|
||||
<field name="number_of_days_temp" class="oe_inline"/> days
|
||||
</div>
|
||||
</group>
|
||||
<group>
|
||||
<field name="holiday_type" on_change="onchange_type(holiday_type)" context="{'employee_id':employee_id}" />
|
||||
<field name="employee_id" attrs="{'required':[('holiday_type','=','employee')], 'invisible':[('holiday_type','=','category')]}"/>
|
||||
<field name="category_id" attrs="{'required':[('holiday_type','=','category')], 'invisible':[('holiday_type','=','employee')]}"/>
|
||||
<field name="department_id" attrs="{'invisible':[('holiday_type','=','category')]}"/>
|
||||
</group>
|
||||
</group>
|
||||
<field name="notes" nolabel="1" colspan="4" placeholder="Add a reason..."/>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_holidays_leave_force_number_action" model="ir.actions.act_window">
|
||||
<field name="name">Leave Requests Force Qty</field>
|
||||
<field name="res_model">hr.holidays</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{'default_type': 'remove'}</field>
|
||||
<field name="domain">[('type','=','remove')]</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_holidays_leave_force_number_tree_act_window_view" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="view_holiday"/>
|
||||
<field name="act_window_id" ref="hr_holidays_leave_force_number_action"/>
|
||||
</record>
|
||||
|
||||
<record id="hr_holidays_leave_force_number_form_act_window_view" model="ir.actions.act_window.view">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="hr_holidays_leave_force_number_form"/>
|
||||
<field name="act_window_id" ref="hr_holidays_leave_force_number_action"/>
|
||||
</record>
|
||||
|
||||
<menuitem id="hr_holidays_leave_force_number_menu" action="hr_holidays_leave_force_number_action" parent="hr_holidays.menu_open_ask_holidays" sequence="15" groups="base.group_hr_manager"/>
|
||||
|
||||
<menuitem id="resource_calendar_leaves_cal_first_menu"
|
||||
action="resource_calendar_leaves_cal_first_action"
|
||||
parent="hr_holidays.menu_open_ask_holidays" sequence="50"/>
|
||||
|
||||
<record id="hr_holidays.menu_open_company_allocation" model="ir.ui.menu">
|
||||
<field name="groups_id" eval="[(4, ref('base.group_hr_user'))]"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
537
hr_holidays_usability/i18n/fr.po
Normal file
537
hr_holidays_usability/i18n/fr.po
Normal file
@@ -0,0 +1,537 @@
|
||||
# Translation of OpenERP Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * hr_holidays_usability
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: OpenERP Server 7.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-06-19 16:56+0000\n"
|
||||
"PO-Revision-Date: 2015-06-19 16:56+0000\n"
|
||||
"Last-Translator: <>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:email.template,body_html:hr_holidays_usability.email_template_hr_holidays
|
||||
msgid "\n"
|
||||
"<div style=\"font-family: 'Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: #FFF; \">\n"
|
||||
"\n"
|
||||
"% if ctx.get('dbname') and 'prod' not in ctx.get('dbname'):\n"
|
||||
"<p>WARNING : THIS IS A TEST E-MAIL sent from a test OpenERP database (${ctx.get('dbname')}). Do not take into account !</p>\n"
|
||||
"\n"
|
||||
"% endif\n"
|
||||
"<p>La ${object.type == 'remove' and 'demande' or \"demande d'ATTRIBUTION\"} de congé a été ${ctx.get('wkf_tracker') or 'ERROR'} aujourd'hui dans OpenERP par ${user.name or ''} :</p>\n"
|
||||
"\n"
|
||||
"<ul>\n"
|
||||
"<li>Employé : ${object.employee_id.name or ''}</li>\n"
|
||||
"% if object.employee_id.parent_id:\n"
|
||||
"<li>Manager : ${object.employee_id.parent_id.name or ''}</li>\n"
|
||||
"% endif\n"
|
||||
"% if object.type == 'remove':\n"
|
||||
"<li>Début : ${object.vacation_date_from or ''}\n"
|
||||
"% if object.vacation_time_from == 'morning':\n"
|
||||
"au matin\n"
|
||||
"% elif object.vacation_time_from == 'noon':\n"
|
||||
"midi\n"
|
||||
"% endif\n"
|
||||
"</li>\n"
|
||||
"<li>Fin : ${object.vacation_date_to or ''}\n"
|
||||
"% if object.vacation_time_to == 'noon':\n"
|
||||
"midi\n"
|
||||
"% elif object.vacation_time_to == 'evening':\n"
|
||||
"au soir\n"
|
||||
"% endif\n"
|
||||
"</li>\n"
|
||||
"% endif\n"
|
||||
"<li>Nombre de jours : ${object.number_of_days < 0 and object.number_of_days * -1 or object.number_of_days}</li>\n"
|
||||
"<li>Type de congé : ${object.holiday_status_id.name or ''}</li>\n"
|
||||
"<li>Description : ${object.name or ''}</li>\n"
|
||||
"% if object.notes:\n"
|
||||
"<li>Notes : ${object.notes or ''}</li>\n"
|
||||
"% endif\n"
|
||||
"</ul>\n"
|
||||
"\n"
|
||||
"% if ctx.get('wkf_tracker') == 'soumise':\n"
|
||||
"% if object.type == 'remove':\n"
|
||||
"<p>Pour la valider ou la refuser, allez dans le menu Ressources humaines > Congés > Demandes de congé à valider.</p>\n"
|
||||
"% else:\n"
|
||||
"<p>Pour la valider ou la refuser, allez dans le menu Ressources humaines > Congés > Demandes d'attribution de congés à valider.</p>\n"
|
||||
"% endif\n"
|
||||
"% endif\n"
|
||||
"<p>\n"
|
||||
"-- <br/>\n"
|
||||
"Mail envoyé automatiquement par OpenERP. Ne pas répondre.<br/>\n"
|
||||
"Base de donnée : ${ctx.get('dbname')}<br/>\n"
|
||||
"</p>\n"
|
||||
"</div>\n"
|
||||
""
|
||||
msgstr "\n"
|
||||
"<div style=\"font-family: 'Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: #FFF; \">\n"
|
||||
"\n"
|
||||
"% if ctx.get('dbname') and 'prod' not in ctx.get('dbname'):\n"
|
||||
"<p>WARNING : THIS IS A TEST E-MAIL sent from a test OpenERP database (${ctx.get('dbname')}). Do not take into account !</p>\n"
|
||||
"\n"
|
||||
"% endif\n"
|
||||
"<p>La ${object.type == 'remove' and 'demande' or \"demande d'ATTRIBUTION\"} de congé a été ${ctx.get('wkf_tracker') or 'ERROR'} aujourd'hui dans OpenERP par ${user.name or ''} :</p>\n"
|
||||
"\n"
|
||||
"<ul>\n"
|
||||
"<li>Employé : ${object.employee_id.name or ''}</li>\n"
|
||||
"% if object.employee_id.parent_id:\n"
|
||||
"<li>Manager : ${object.employee_id.parent_id.name or ''}</li>\n"
|
||||
"% endif\n"
|
||||
"% if object.type == 'remove':\n"
|
||||
"<li>Début : ${object.vacation_date_from or ''}\n"
|
||||
"% if object.vacation_time_from == 'morning':\n"
|
||||
"au matin\n"
|
||||
"% elif object.vacation_time_from == 'noon':\n"
|
||||
"midi\n"
|
||||
"% endif\n"
|
||||
"</li>\n"
|
||||
"<li>Fin : ${object.vacation_date_to or ''}\n"
|
||||
"% if object.vacation_time_to == 'noon':\n"
|
||||
"midi\n"
|
||||
"% elif object.vacation_time_to == 'evening':\n"
|
||||
"au soir\n"
|
||||
"% endif\n"
|
||||
"</li>\n"
|
||||
"% endif\n"
|
||||
"<li>Nombre de jours : ${object.number_of_days < 0 and object.number_of_days * -1 or object.number_of_days}</li>\n"
|
||||
"<li>Type de congé : ${object.holiday_status_id.name or ''}</li>\n"
|
||||
"<li>Description : ${object.name or ''}</li>\n"
|
||||
"% if object.notes:\n"
|
||||
"<li>Notes : ${object.notes or ''}</li>\n"
|
||||
"% endif\n"
|
||||
"</ul>\n"
|
||||
"\n"
|
||||
"% if ctx.get('wkf_tracker') == 'soumise':\n"
|
||||
"% if object.type == 'remove':\n"
|
||||
"<p>Pour la valider ou la refuser, allez dans le menu Ressources humaines > Congés > Demandes de congé à valider.</p>\n"
|
||||
"% else:\n"
|
||||
"<p>Pour la valider ou la refuser, allez dans le menu Ressources humaines > Congés > Demandes d'attribution de congés à valider.</p>\n"
|
||||
"% endif\n"
|
||||
"% endif\n"
|
||||
"<p>\n"
|
||||
"-- <br/>\n"
|
||||
"Mail envoyé automatiquement par OpenERP. Ne pas répondre.<br/>\n"
|
||||
"Base de donnée : ${ctx.get('dbname')}<br/>\n"
|
||||
"</p>\n"
|
||||
"</div>\n"
|
||||
""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays:0
|
||||
msgid " days"
|
||||
msgstr " jours"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:email.template,subject:hr_holidays_usability.email_template_hr_holidays
|
||||
msgid "${ctx.get('dbname') and 'prod' not in ctx.get('dbname') and '[TEST]' or ''}[${object.type == 'remove' and 'Demande' or 'Attribution'} de congé ${ctx.get('wkf_tracker')}] ${object.name or ''} - ${object.employee_id.name or ''}"
|
||||
msgstr "${ctx.get('dbname') and 'prod' not in ctx.get('dbname') and '[TEST]' or ''}[${object.type == 'remove' and 'Demande' or 'Attribution'} de congé ${ctx.get('wkf_tracker')}] ${object.name or ''} - ${object.employee_id.name or ''}"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays.employee.counter,allocated_leaves:0
|
||||
msgid "Allocated Leaves"
|
||||
msgstr "Congés attribués"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays,limit:0
|
||||
msgid "Allow to Override Limit"
|
||||
msgstr "Allow to Override Limit"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:ir.actions.server,name:hr_holidays_usability.ir_actions_server_hr_holidays_confirm_mail
|
||||
msgid "Auto-email confirmed leave"
|
||||
msgstr "Auto-email confirmed leave"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:ir.actions.server,name:hr_holidays_usability.ir_actions_server_hr_holidays_refuse_mail
|
||||
msgid "Auto-email refused leave"
|
||||
msgstr "Auto-email refused leave"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:ir.actions.server,name:hr_holidays_usability.ir_actions_server_hr_holidays_validate_mail
|
||||
msgid "Auto-email validated leave"
|
||||
msgstr "Auto-email validated leave"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays.mass.allocation,auto_approve:0
|
||||
msgid "Automatic Approval"
|
||||
msgstr "Validation automatique"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays.mass.allocation:0
|
||||
#: view:hr.holidays.post:0
|
||||
msgid "Cancel"
|
||||
msgstr "Annuler"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:ir.model,name:hr_holidays_usability.model_res_company
|
||||
msgid "Companies"
|
||||
msgstr "Sociétés"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays:0
|
||||
msgid "Counter for this leave type"
|
||||
msgstr "Compteur pour ce type de congé"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:ir.actions.act_window,name:hr_holidays_usability.hr_holidays_employee_counter_action
|
||||
#: model:ir.ui.menu,name:hr_holidays_usability.hr_holidays_employee_counter_menu
|
||||
msgid "Counters"
|
||||
msgstr "Compteurs"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:ir.model,name:hr_holidays_usability.model_hr_holidays_employee_counter
|
||||
msgid "Counters for holidays of employees"
|
||||
msgstr "Counters for holidays of employees"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays.mass.allocation:0
|
||||
msgid "Create Allocations"
|
||||
msgstr "Créer des attributions"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays.employee.counter,leaves_validated_current:0
|
||||
msgid "Current Leaves Validated"
|
||||
msgstr "Congés validés"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays,current_remaining_leaves:0
|
||||
#: field:hr.holidays.employee.counter,leaves_remaining_current:0
|
||||
msgid "Current Remaining Leaves"
|
||||
msgstr "Solde de congés"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:res.company,mass_allocation_default_holiday_status_id:0
|
||||
msgid "Default Leave Type for Mass Allocation"
|
||||
msgstr "Type de congé par défaut pour attribution en masse"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays.mass.allocation,name:0
|
||||
msgid "Description"
|
||||
msgstr "Description"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: selection:hr.holidays.post,state:0
|
||||
msgid "Done"
|
||||
msgstr "Done"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: selection:hr.holidays.post,state:0
|
||||
msgid "Draft"
|
||||
msgstr "Draft"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays.employee.counter:0
|
||||
#: field:hr.holidays.employee.counter,employee_id:0
|
||||
msgid "Employee"
|
||||
msgstr "Employé"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays.employee.counter:0
|
||||
msgid "Employee Holidays Counters"
|
||||
msgstr "Compteurs de congé de l'employé"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays.mass.allocation,employee_ids:0
|
||||
msgid "Employees"
|
||||
msgstr "Employés"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays,vacation_time_to:0
|
||||
msgid "End of Vacation"
|
||||
msgstr "Fin du congé"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: help:hr.holidays,vacation_date_from:0
|
||||
msgid "Enter the first day of vacation. For example, if you leave one full calendar week, the first day of vacation is Monday morning (and not Friday of the week before)"
|
||||
msgstr "Entrez le premier jour de congé. Par exemple, si vous partez en congé pendant une semaine calendaire, le premier jour de congé est le lundi matin (et non le vendredi de la semaine précédente)"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: help:hr.holidays,vacation_date_to:0
|
||||
msgid "Enter the last day of vacation. For example, if you leave one full calendar week, the last day of vacation is Friday evening (and not Monday of the week after)"
|
||||
msgstr "Entrez le dernier jour de congé. Par exemple, si vous partez en congé pendant une semaine calendaire, le dernier jour de congé est le vendredi soir (et non le lundi matin de la semaine suivante)"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:237
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:243
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:250
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:257
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:263
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:269
|
||||
#: code:addons/hr_holidays_usability/wizard/hr_holidays_mass_allocation.py:71
|
||||
#: code:addons/hr_holidays_usability/wizard/hr_holidays_mass_allocation.py:75
|
||||
#: code:addons/hr_holidays_usability/wizard/hr_holidays_post.py:84
|
||||
#, python-format
|
||||
msgid "Error:"
|
||||
msgstr "Erreur :"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: selection:hr.holidays,vacation_time_to:0
|
||||
msgid "Evening"
|
||||
msgstr "Soir"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays,vacation_date_from:0
|
||||
msgid "First Day of Vacation"
|
||||
msgstr "Premier jour de congé"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: help:hr.holidays,vacation_time_to:0
|
||||
msgid "For example, if you leave one full calendar week, the end of vacation is Friday Evening"
|
||||
msgstr "Par exemple, si vous partez en congé pendant une semaine calendaire, le dernier jour de congé est le vendredi soir"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: help:hr.holidays,vacation_time_from:0
|
||||
msgid "For example, if you leave one full calendar week, the first day of vacation is Monday Morning"
|
||||
msgstr "Par exemple, si vous partez en congé pendant une semaine calendaire, le premier jour de congé est le lundi matin"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays.post:0
|
||||
msgid "Get Holiday Requests"
|
||||
msgstr "Obtenir les congés"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays.employee.counter:0
|
||||
msgid "Group By"
|
||||
msgstr "Grouper par"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: selection:hr.holidays.status,vacation_compute_method:0
|
||||
msgid "Jours ouvrables"
|
||||
msgstr "Jours ouvrables"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: selection:hr.holidays.status,vacation_compute_method:0
|
||||
msgid "Jours ouvrés"
|
||||
msgstr "Jours ouvrés"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays,vacation_date_to:0
|
||||
msgid "Last Day of Vacation"
|
||||
msgstr "Dernier jour de congé"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:ir.model,name:hr_holidays_usability.model_hr_holidays
|
||||
msgid "Leave"
|
||||
msgstr "Congé"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays.post:0
|
||||
#: field:hr.holidays.post,holidays_to_post_ids:0
|
||||
msgid "Leave Requests to Post"
|
||||
msgstr "Congés à comptabiliser"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays.employee.counter:0
|
||||
#: field:hr.holidays.employee.counter,holiday_status_id:0
|
||||
#: field:hr.holidays.mass.allocation,holiday_status_id:0
|
||||
#: model:ir.model,name:hr_holidays_usability.model_hr_holidays_status
|
||||
msgid "Leave Type"
|
||||
msgstr "Type de congé"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.employee:0
|
||||
#: view:res.company:0
|
||||
msgid "Leaves"
|
||||
msgstr "Congés"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:ir.actions.act_window,name:hr_holidays_usability.resource_calendar_leaves_cal_first_action
|
||||
#: model:ir.ui.menu,name:hr_holidays_usability.resource_calendar_leaves_cal_first_menu
|
||||
msgid "Leaves Calendar"
|
||||
msgstr "Calendrier des absences"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays.employee.counter,leaves_validated_posted:0
|
||||
msgid "Leaves Posted"
|
||||
msgstr "Congés comptabilisés"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:ir.actions.act_window,name:hr_holidays_usability.hr_holidays_mass_allocation_action
|
||||
#: model:ir.ui.menu,name:hr_holidays_usability.hr_holidays_mass_allocation_menu
|
||||
msgid "Mass Allocation"
|
||||
msgstr "Attribution en masse"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays.mass.allocation:0
|
||||
msgid "Mass Allocation of Holidays"
|
||||
msgstr "Attribution de congés en masse"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: selection:hr.holidays,vacation_time_from:0
|
||||
msgid "Morning"
|
||||
msgstr "Matin"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: code:addons/hr_holidays_usability/wizard/hr_holidays_post.py:85
|
||||
#, python-format
|
||||
msgid "No leave request to post."
|
||||
msgstr "Aucun congé à comptabiliser."
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: selection:hr.holidays,vacation_time_from:0
|
||||
#: selection:hr.holidays,vacation_time_to:0
|
||||
msgid "Noon"
|
||||
msgstr "Midi"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays.mass.allocation,number_of_days:0
|
||||
msgid "Number of Days"
|
||||
msgstr "Nombre de jours"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays,number_of_days_remove:0
|
||||
msgid "Number of Days of Vacation"
|
||||
msgstr "Nombre de jours de congé"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays.post:0
|
||||
msgid "Post"
|
||||
msgstr "Comptabiliser"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:ir.actions.act_window,name:hr_holidays_usability.hr_holidays_post_action
|
||||
#: model:ir.ui.menu,name:hr_holidays_usability.hr_holidays_post_menu
|
||||
msgid "Post Leave Requests"
|
||||
msgstr "Comptabiliser les congés"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays.post:0
|
||||
msgid "Post Leaves"
|
||||
msgstr "Comptabiliser les congés"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays,posted_date:0
|
||||
msgid "Posted Date"
|
||||
msgstr "Date de comptabilisation"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays.employee.counter,leaves_remaining_posted:0
|
||||
msgid "Posted Remaining Leaves"
|
||||
msgstr "Solde de congés comptabilisés"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays.post,before_date:0
|
||||
msgid "Select Leave Requests That Ended Before"
|
||||
msgstr "Sélectionner les congés pris avant le"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays,vacation_time_from:0
|
||||
msgid "Start of Vacation"
|
||||
msgstr "Début du congé"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays.post,state:0
|
||||
msgid "State"
|
||||
msgstr "State"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:238
|
||||
#, python-format
|
||||
msgid "The first day cannot be after the last day !"
|
||||
msgstr "Le premier jour de congé ne peut pas être postérieur au dernier jour de congé !"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:264
|
||||
#, python-format
|
||||
msgid "The first day of vacation cannot be a bank holiday !"
|
||||
msgstr "Le premier jour de congé ne peut pas être un jour férié !"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:251
|
||||
#, python-format
|
||||
msgid "The first day of vacation cannot be a saturday or sunday !"
|
||||
msgstr "Le premier jour de congé ne peut pas être un Samedi ou un Dimanche !"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:258
|
||||
#, python-format
|
||||
msgid "The last day of Vacation cannot be a saturday or sunday !"
|
||||
msgstr "Le dernier jour de congé ne peut pas être un Samedi ou un Dimanche !"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:270
|
||||
#, python-format
|
||||
msgid "The last day of vacation cannot be a bank holiday !"
|
||||
msgstr "Le dernier jour de congé ne peut pas être un jour férié !"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: sql_constraint:hr.holidays.mass.allocation:0
|
||||
msgid "The number of days must be positive"
|
||||
msgstr "Le nombre de jours doit être positif"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:244
|
||||
#, python-format
|
||||
msgid "The start of vacation is exactly the same as the end !"
|
||||
msgstr "Le début du congé est égal à la fin du congé !"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: help:hr.holidays.post,before_date:0
|
||||
msgid "The wizard will select the validated holidays that ended before that date (including holidays that ended on that date)."
|
||||
msgstr "L'assistant sélectionnera les congés validés qui se sont terminés avant cette date ou à cette date."
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:347
|
||||
#, python-format
|
||||
msgid "There are not enough %s allocated for employee %s (requesting %s days but only %s days left)."
|
||||
msgstr "Il n'y a pas assez de %s attribués à l'employé %s (demande de %s jours mais il ne reste que %s jours)."
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays,total_allocated_leaves:0
|
||||
msgid "Total Allocated Leaves"
|
||||
msgstr "Total des congés attribués"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays:0
|
||||
msgid "Total Days of Vacation"
|
||||
msgstr "Total des congés pris"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays.employee.counter:0
|
||||
msgid "Total Posted Remaining Leaves"
|
||||
msgstr "Total du solde de congés comptabilisés"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays.status,vacation_compute_method:0
|
||||
msgid "Vacation Compute Method"
|
||||
msgstr "Méthode de calcul des jours de congé"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:346
|
||||
#, python-format
|
||||
msgid "Warning!"
|
||||
msgstr "Warning!"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:ir.model,name:hr_holidays_usability.model_hr_holidays_mass_allocation
|
||||
msgid "Wizard for mass allocation of holidays"
|
||||
msgstr "Assistant pour l'attribution de congés en masse"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:ir.model,name:hr_holidays_usability.model_hr_holidays_post
|
||||
msgid "Wizard for post holidays"
|
||||
msgstr "Assistant pour la comptabilisation des congés"
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: code:addons/hr_holidays_usability/wizard/hr_holidays_mass_allocation.py:76
|
||||
#, python-format
|
||||
msgid "You must select at least one employee."
|
||||
msgstr "Vous devez sélectionner au moins un employé."
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: code:addons/hr_holidays_usability/wizard/hr_holidays_mass_allocation.py:72
|
||||
#, python-format
|
||||
msgid "You must set a value for the number of days."
|
||||
msgstr "Vous devez entrer une valeur pour le nombre de jours."
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: constraint:hr.holidays:0
|
||||
msgid "error msg in raise"
|
||||
msgstr "error msg in raise"
|
||||
|
||||
491
hr_holidays_usability/i18n/hr_holidays_usability.pot
Normal file
491
hr_holidays_usability/i18n/hr_holidays_usability.pot
Normal file
@@ -0,0 +1,491 @@
|
||||
# Translation of OpenERP Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * hr_holidays_usability
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: OpenERP Server 7.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-06-19 16:57+0000\n"
|
||||
"PO-Revision-Date: 2015-06-19 16:57+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: hr_holidays_usability
|
||||
#: model:email.template,body_html:hr_holidays_usability.email_template_hr_holidays
|
||||
msgid "\n"
|
||||
"<div style=\"font-family: 'Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: #FFF; \">\n"
|
||||
"\n"
|
||||
"% if ctx.get('dbname') and 'prod' not in ctx.get('dbname'):\n"
|
||||
"<p>WARNING : THIS IS A TEST E-MAIL sent from a test OpenERP database (${ctx.get('dbname')}). Do not take into account !</p>\n"
|
||||
"\n"
|
||||
"% endif\n"
|
||||
"<p>La ${object.type == 'remove' and 'demande' or \"demande d'ATTRIBUTION\"} de congé a été ${ctx.get('wkf_tracker') or 'ERROR'} aujourd'hui dans OpenERP par ${user.name or ''} :</p>\n"
|
||||
"\n"
|
||||
"<ul>\n"
|
||||
"<li>Employé : ${object.employee_id.name or ''}</li>\n"
|
||||
"% if object.employee_id.parent_id:\n"
|
||||
"<li>Manager : ${object.employee_id.parent_id.name or ''}</li>\n"
|
||||
"% endif\n"
|
||||
"% if object.type == 'remove':\n"
|
||||
"<li>Début : ${object.vacation_date_from or ''}\n"
|
||||
"% if object.vacation_time_from == 'morning':\n"
|
||||
"au matin\n"
|
||||
"% elif object.vacation_time_from == 'noon':\n"
|
||||
"midi\n"
|
||||
"% endif\n"
|
||||
"</li>\n"
|
||||
"<li>Fin : ${object.vacation_date_to or ''}\n"
|
||||
"% if object.vacation_time_to == 'noon':\n"
|
||||
"midi\n"
|
||||
"% elif object.vacation_time_to == 'evening':\n"
|
||||
"au soir\n"
|
||||
"% endif\n"
|
||||
"</li>\n"
|
||||
"% endif\n"
|
||||
"<li>Nombre de jours : ${object.number_of_days < 0 and object.number_of_days * -1 or object.number_of_days}</li>\n"
|
||||
"<li>Type de congé : ${object.holiday_status_id.name or ''}</li>\n"
|
||||
"<li>Description : ${object.name or ''}</li>\n"
|
||||
"% if object.notes:\n"
|
||||
"<li>Notes : ${object.notes or ''}</li>\n"
|
||||
"% endif\n"
|
||||
"</ul>\n"
|
||||
"\n"
|
||||
"% if ctx.get('wkf_tracker') == 'soumise':\n"
|
||||
"% if object.type == 'remove':\n"
|
||||
"<p>Pour la valider ou la refuser, allez dans le menu Ressources humaines > Congés > Demandes de congé à valider.</p>\n"
|
||||
"% else:\n"
|
||||
"<p>Pour la valider ou la refuser, allez dans le menu Ressources humaines > Congés > Demandes d'attribution de congés à valider.</p>\n"
|
||||
"% endif\n"
|
||||
"% endif\n"
|
||||
"<p>\n"
|
||||
"-- <br/>\n"
|
||||
"Mail envoyé automatiquement par OpenERP. Ne pas répondre.<br/>\n"
|
||||
"Base de donnée : ${ctx.get('dbname')}<br/>\n"
|
||||
"</p>\n"
|
||||
"</div>\n"
|
||||
""
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays:0
|
||||
msgid " days"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:email.template,subject:hr_holidays_usability.email_template_hr_holidays
|
||||
msgid "${ctx.get('dbname') and 'prod' not in ctx.get('dbname') and '[TEST]' or ''}[${object.type == 'remove' and 'Demande' or 'Attribution'} de congé ${ctx.get('wkf_tracker')}] ${object.name or ''} - ${object.employee_id.name or ''}"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays.employee.counter,allocated_leaves:0
|
||||
msgid "Allocated Leaves"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays,limit:0
|
||||
msgid "Allow to Override Limit"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:ir.actions.server,name:hr_holidays_usability.ir_actions_server_hr_holidays_confirm_mail
|
||||
msgid "Auto-email confirmed leave"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:ir.actions.server,name:hr_holidays_usability.ir_actions_server_hr_holidays_refuse_mail
|
||||
msgid "Auto-email refused leave"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:ir.actions.server,name:hr_holidays_usability.ir_actions_server_hr_holidays_validate_mail
|
||||
msgid "Auto-email validated leave"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays.mass.allocation,auto_approve:0
|
||||
msgid "Automatic Approval"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays.mass.allocation:0
|
||||
#: view:hr.holidays.post:0
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:ir.model,name:hr_holidays_usability.model_res_company
|
||||
msgid "Companies"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays:0
|
||||
msgid "Counter for this leave type"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:ir.actions.act_window,name:hr_holidays_usability.hr_holidays_employee_counter_action
|
||||
#: model:ir.ui.menu,name:hr_holidays_usability.hr_holidays_employee_counter_menu
|
||||
msgid "Counters"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:ir.model,name:hr_holidays_usability.model_hr_holidays_employee_counter
|
||||
msgid "Counters for holidays of employees"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays.mass.allocation:0
|
||||
msgid "Create Allocations"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays,current_leaves_taken:0
|
||||
msgid "Current Leaves Taken"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays.employee.counter,leaves_validated_current:0
|
||||
msgid "Current Leaves Validated"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays,current_remaining_leaves:0
|
||||
#: field:hr.holidays.employee.counter,leaves_remaining_current:0
|
||||
msgid "Current Remaining Leaves"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:res.company,mass_allocation_default_holiday_status_id:0
|
||||
msgid "Default Leave Type for Mass Allocation"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays.mass.allocation,name:0
|
||||
msgid "Description"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: selection:hr.holidays.post,state:0
|
||||
msgid "Done"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: selection:hr.holidays.post,state:0
|
||||
msgid "Draft"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays.employee.counter:0
|
||||
#: field:hr.holidays.employee.counter,employee_id:0
|
||||
msgid "Employee"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays.employee.counter:0
|
||||
msgid "Employee Holidays Counters"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays.mass.allocation,employee_ids:0
|
||||
msgid "Employees"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays,vacation_time_to:0
|
||||
msgid "End of Vacation"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: help:hr.holidays,vacation_date_from:0
|
||||
msgid "Enter the first day of vacation. For example, if you leave one full calendar week, the first day of vacation is Monday morning (and not Friday of the week before)"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: help:hr.holidays,vacation_date_to:0
|
||||
msgid "Enter the last day of vacation. For example, if you leave one full calendar week, the last day of vacation is Friday evening (and not Monday of the week after)"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:237
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:243
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:250
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:257
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:263
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:269
|
||||
#: code:addons/hr_holidays_usability/wizard/hr_holidays_mass_allocation.py:71
|
||||
#: code:addons/hr_holidays_usability/wizard/hr_holidays_mass_allocation.py:75
|
||||
#: code:addons/hr_holidays_usability/wizard/hr_holidays_post.py:84
|
||||
#, python-format
|
||||
msgid "Error:"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: selection:hr.holidays,vacation_time_to:0
|
||||
msgid "Evening"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays,vacation_date_from:0
|
||||
msgid "First Day of Vacation"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: help:hr.holidays,vacation_time_to:0
|
||||
msgid "For example, if you leave one full calendar week, the end of vacation is Friday Evening"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: help:hr.holidays,vacation_time_from:0
|
||||
msgid "For example, if you leave one full calendar week, the first day of vacation is Monday Morning"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays.post:0
|
||||
msgid "Get Holiday Requests"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays.employee.counter:0
|
||||
msgid "Group By"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: selection:hr.holidays.status,vacation_compute_method:0
|
||||
msgid "Jours ouvrables"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: selection:hr.holidays.status,vacation_compute_method:0
|
||||
msgid "Jours ouvrés"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays,vacation_date_to:0
|
||||
msgid "Last Day of Vacation"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:ir.model,name:hr_holidays_usability.model_hr_holidays
|
||||
msgid "Leave"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays.post:0
|
||||
#: field:hr.holidays.post,holidays_to_post_ids:0
|
||||
msgid "Leave Requests to Post"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays.employee.counter:0
|
||||
#: field:hr.holidays.employee.counter,holiday_status_id:0
|
||||
#: field:hr.holidays.mass.allocation,holiday_status_id:0
|
||||
#: model:ir.model,name:hr_holidays_usability.model_hr_holidays_status
|
||||
msgid "Leave Type"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.employee:0
|
||||
#: view:res.company:0
|
||||
msgid "Leaves"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:ir.actions.act_window,name:hr_holidays_usability.resource_calendar_leaves_cal_first_action
|
||||
#: model:ir.ui.menu,name:hr_holidays_usability.resource_calendar_leaves_cal_first_menu
|
||||
msgid "Leaves Calendar"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays.employee.counter,leaves_validated_posted:0
|
||||
msgid "Leaves Posted"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:ir.actions.act_window,name:hr_holidays_usability.hr_holidays_mass_allocation_action
|
||||
#: model:ir.ui.menu,name:hr_holidays_usability.hr_holidays_mass_allocation_menu
|
||||
msgid "Mass Allocation"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays.mass.allocation:0
|
||||
msgid "Mass Allocation of Holidays"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: selection:hr.holidays,vacation_time_from:0
|
||||
msgid "Morning"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: code:addons/hr_holidays_usability/wizard/hr_holidays_post.py:85
|
||||
#, python-format
|
||||
msgid "No leave request to post."
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: selection:hr.holidays,vacation_time_from:0
|
||||
#: selection:hr.holidays,vacation_time_to:0
|
||||
msgid "Noon"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays.mass.allocation,number_of_days:0
|
||||
msgid "Number of Days"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays,number_of_days_remove:0
|
||||
msgid "Number of Days of Vacation"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays.post:0
|
||||
msgid "Post"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:ir.actions.act_window,name:hr_holidays_usability.hr_holidays_post_action
|
||||
#: model:ir.ui.menu,name:hr_holidays_usability.hr_holidays_post_menu
|
||||
msgid "Post Leave Requests"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays.post:0
|
||||
msgid "Post Leaves"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays,posted_date:0
|
||||
msgid "Posted Date"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays.employee.counter,leaves_remaining_posted:0
|
||||
msgid "Posted Remaining Leaves"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays.post,before_date:0
|
||||
msgid "Select Leave Requests That Ended Before"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays,vacation_time_from:0
|
||||
msgid "Start of Vacation"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays.post,state:0
|
||||
msgid "State"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:238
|
||||
#, python-format
|
||||
msgid "The first day cannot be after the last day !"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:264
|
||||
#, python-format
|
||||
msgid "The first day of vacation cannot be a bank holiday !"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:251
|
||||
#, python-format
|
||||
msgid "The first day of vacation cannot be a saturday or sunday !"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:258
|
||||
#, python-format
|
||||
msgid "The last day of Vacation cannot be a saturday or sunday !"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:270
|
||||
#, python-format
|
||||
msgid "The last day of vacation cannot be a bank holiday !"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: sql_constraint:hr.holidays.mass.allocation:0
|
||||
msgid "The number of days must be positive"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:244
|
||||
#, python-format
|
||||
msgid "The start of vacation is exactly the same as the end !"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: help:hr.holidays.post,before_date:0
|
||||
msgid "The wizard will select the validated holidays that ended before that date (including holidays that ended on that date)."
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:347
|
||||
#, python-format
|
||||
msgid "There are not enough %s allocated for employee %s (requesting %s days but only %s days left)."
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays,total_allocated_leaves:0
|
||||
msgid "Total Allocated Leaves"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays:0
|
||||
msgid "Total Days of Vacation"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: view:hr.holidays.employee.counter:0
|
||||
msgid "Total Posted Remaining Leaves"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: field:hr.holidays.status,vacation_compute_method:0
|
||||
msgid "Vacation Compute Method"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: code:addons/hr_holidays_usability/hr_holidays.py:346
|
||||
#, python-format
|
||||
msgid "Warning!"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:ir.model,name:hr_holidays_usability.model_hr_holidays_mass_allocation
|
||||
msgid "Wizard for mass allocation of holidays"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: model:ir.model,name:hr_holidays_usability.model_hr_holidays_post
|
||||
msgid "Wizard for post holidays"
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: code:addons/hr_holidays_usability/wizard/hr_holidays_mass_allocation.py:76
|
||||
#, python-format
|
||||
msgid "You must select at least one employee."
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: code:addons/hr_holidays_usability/wizard/hr_holidays_mass_allocation.py:72
|
||||
#, python-format
|
||||
msgid "You must set a value for the number of days."
|
||||
msgstr ""
|
||||
|
||||
#. module: hr_holidays_usability
|
||||
#: constraint:hr.holidays:0
|
||||
msgid "error msg in raise"
|
||||
msgstr ""
|
||||
|
||||
2
hr_holidays_usability/report/__init__.py
Normal file
2
hr_holidays_usability/report/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
from . import hr_holidays_employee_counter
|
||||
83
hr_holidays_usability/report/hr_holidays_employee_counter.py
Normal file
83
hr_holidays_usability/report/hr_holidays_employee_counter.py
Normal file
@@ -0,0 +1,83 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# HR Holidays Usability module for Odoo
|
||||
# Copyright (C) 2015 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp import tools
|
||||
from openerp.osv import fields, orm
|
||||
|
||||
|
||||
class HrHolidaysEmployeeCounter(orm.Model):
|
||||
_name = 'hr.holidays.employee.counter'
|
||||
_description = 'Counters for holidays of employees'
|
||||
_auto = False
|
||||
_rec_name = 'employee_id'
|
||||
_order = 'employee_id'
|
||||
|
||||
_columns = {
|
||||
'employee_id': fields.many2one('hr.employee', "Employee"),
|
||||
'holiday_status_id': fields.many2one(
|
||||
"hr.holidays.status", "Leave Type"),
|
||||
'leaves_validated_current': fields.float('Current Leaves Validated'),
|
||||
'leaves_validated_posted': fields.float('Leaves Posted'),
|
||||
'leaves_remaining_current': fields.float('Current Remaining Leaves'),
|
||||
'leaves_remaining_posted': fields.float('Posted Remaining Leaves'),
|
||||
'allocated_leaves': fields.float('Allocated Leaves'),
|
||||
}
|
||||
|
||||
def init(self, cr):
|
||||
tools.drop_view_if_exists(cr, 'hr_holidays_employee_counter')
|
||||
cr.execute("""
|
||||
CREATE or REPLACE view hr_holidays_employee_counter AS (
|
||||
SELECT
|
||||
min(hh.id) AS id,
|
||||
hh.employee_id AS employee_id,
|
||||
hh.holiday_status_id AS holiday_status_id,
|
||||
sum(
|
||||
CASE WHEN hh.type='remove'
|
||||
THEN hh.number_of_days * -1
|
||||
ELSE 0
|
||||
END) AS leaves_validated_current,
|
||||
sum(
|
||||
CASE WHEN hh.type='remove' AND hh.posted_date IS NOT null
|
||||
THEN hh.number_of_days * -1
|
||||
ELSE 0
|
||||
END) AS leaves_validated_posted,
|
||||
sum(hh.number_of_days) AS leaves_remaining_current,
|
||||
sum(
|
||||
CASE WHEN (hh.type='remove' AND hh.posted_date IS NOT null) OR hh.type='add'
|
||||
THEN hh.number_of_days
|
||||
ELSE 0
|
||||
END) as leaves_remaining_posted,
|
||||
sum(
|
||||
CASE WHEN hh.type = 'add'
|
||||
THEN hh.number_of_days
|
||||
ELSE 0
|
||||
END) AS allocated_leaves
|
||||
FROM
|
||||
hr_holidays hh
|
||||
JOIN hr_holidays_status hhs
|
||||
ON (hhs.id=hh.holiday_status_id)
|
||||
WHERE
|
||||
hh.state='validate' AND
|
||||
hhs.limit=False
|
||||
GROUP BY hh.employee_id, hh.holiday_status_id
|
||||
)
|
||||
""")
|
||||
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="hr_holidays_employee_counter_tree" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.employee.counter.tree</field>
|
||||
<field name="model">hr.holidays.employee.counter</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Employee Holidays Counters">
|
||||
<field name="employee_id"
|
||||
invisible="not context.get('hr_holidays_employee_counter_tree_main_view')"/>
|
||||
<field name="holiday_status_id"/>
|
||||
<field name="allocated_leaves"/>
|
||||
<field name="leaves_validated_current"/>
|
||||
<field name="leaves_validated_posted"/>
|
||||
<field name="leaves_remaining_current"/>
|
||||
<field name="leaves_remaining_posted"
|
||||
sum="Total Posted Remaining Leaves"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_holidays_employee_counter_search" model="ir.ui.view">
|
||||
<field name="name">hr.holidays.employee.counter.search</field>
|
||||
<field name="model">hr.holidays.employee.counter</field>
|
||||
<field name="arch" type="xml">
|
||||
<search>
|
||||
<field name="employee_id"/>
|
||||
<group string="Group By" name="groupby">
|
||||
<filter name="employee_groupby" string="Employee" context="{'group_by': 'employee_id'}"/>
|
||||
<filter name="holiday_status_groupby" string="Leave Type"
|
||||
context="{'group_by': 'holiday_status_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_holidays_employee_counter_action" model="ir.actions.act_window">
|
||||
<field name="name">Counters</field>
|
||||
<field name="res_model">hr.holidays.employee.counter</field>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="context">{'hr_holidays_employee_counter_tree_main_view': 1}</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="hr_holidays_employee_counter_menu"
|
||||
action="hr_holidays_employee_counter_action"
|
||||
parent="hr_holidays.menu_open_ask_holidays"
|
||||
sequence="30"/>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
24
hr_holidays_usability/res_company_view.xml
Normal file
24
hr_holidays_usability/res_company_view.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 Akretion (http://www.akretion.com)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
The licence is in the file __openerp__.py
|
||||
-->
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="view_company_form" model="ir.ui.view">
|
||||
<field name="name">hr_holidays_usability.res.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 string="Leaves" name="holidays">
|
||||
<field name="mass_allocation_default_holiday_status_id"/>
|
||||
</group>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
20
hr_holidays_usability/security/holiday_security.xml
Normal file
20
hr_holidays_usability/security/holiday_security.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<record id="hr_holidays_counter_personal_rule" model="ir.rule">
|
||||
<field name="name">Personal Holiday Counters</field>
|
||||
<field name="model_id" ref="model_hr_holidays_employee_counter"/>
|
||||
<field name="domain_force">['|',('employee_id.user_id','=',user.id),('employee_id.user_id','=',False)]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="hr_holidays_counter_see_all" model="ir.rule">
|
||||
<field name="name">All Holiday Counters</field>
|
||||
<field name="model_id" ref="model_hr_holidays_employee_counter"/>
|
||||
<field name="domain_force">[(1,'=',1)]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_hr_user'))]"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
2
hr_holidays_usability/security/ir.model.access.csv
Normal file
2
hr_holidays_usability/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_hr_holidays_employee_counter,Full access on hr.holidays.employee.counter,model_hr_holidays_employee_counter,base.group_user,1,1,1,1
|
||||
|
3
hr_holidays_usability/wizard/__init__.py
Normal file
3
hr_holidays_usability/wizard/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
from . import hr_holidays_mass_allocation
|
||||
from . import hr_holidays_post
|
||||
105
hr_holidays_usability/wizard/hr_holidays_mass_allocation.py
Normal file
105
hr_holidays_usability/wizard/hr_holidays_mass_allocation.py
Normal file
@@ -0,0 +1,105 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# HR Holidays Usability module for Odoo
|
||||
# Copyright (C) 2015 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import orm, fields
|
||||
from openerp.tools.translate import _
|
||||
from openerp import netsvc
|
||||
|
||||
|
||||
class HrHolidaysMassAllocation(orm.TransientModel):
|
||||
_name = 'hr.holidays.mass.allocation'
|
||||
_description = 'Wizard for mass allocation of holidays'
|
||||
|
||||
def _get_all_employees(self, cr, uid, context=None):
|
||||
return self.pool['hr.employee'].search(cr, uid, [], context=context)
|
||||
|
||||
def _get_default_holiday_status(self, cr, uid, context=None):
|
||||
user = self.pool['res.users'].browse(cr, uid, uid, context=context)
|
||||
if user.company_id.mass_allocation_default_holiday_status_id:
|
||||
return user.company_id.mass_allocation_default_holiday_status_id.id
|
||||
else:
|
||||
return False
|
||||
|
||||
_columns = {
|
||||
'number_of_days': fields.float('Number of Days', required=True),
|
||||
'holiday_status_id': fields.many2one(
|
||||
'hr.holidays.status', 'Leave Type', required=True),
|
||||
'employee_ids': fields.many2many(
|
||||
'hr.employee', string='Employees'),
|
||||
'auto_approve': fields.boolean('Automatic Approval'),
|
||||
# size=64 because the name field of hr.holidays is size=64
|
||||
'name': fields.char('Description', size=64),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'number_of_days': 2.08,
|
||||
'employee_ids': _get_all_employees,
|
||||
'auto_approve': True,
|
||||
'holiday_status_id': _get_default_holiday_status,
|
||||
}
|
||||
|
||||
_sql_constraints = [(
|
||||
'number_of_days_positive',
|
||||
'CHECK (number_of_days > 0)',
|
||||
'The number of days must be positive',
|
||||
)]
|
||||
|
||||
def run(self, cr, uid, ids, context=None):
|
||||
assert len(ids) == 1, 'Only 1 ID'
|
||||
wiz = self.browse(cr, uid, ids[0], context=context)
|
||||
if not wiz.number_of_days:
|
||||
raise orm.except_orm(
|
||||
_('Error:'),
|
||||
_('You must set a value for the number of days.'))
|
||||
if not wiz.employee_ids:
|
||||
raise orm.except_orm(
|
||||
_('Error:'),
|
||||
_('You must select at least one employee.'))
|
||||
alloc_hol_ids = []
|
||||
hho = self.pool['hr.holidays']
|
||||
wf_service = netsvc.LocalService("workflow")
|
||||
auto_approve = wiz.auto_approve
|
||||
for employee in wiz.employee_ids:
|
||||
hol_id = hho.create(cr, uid, {
|
||||
'name': wiz.name,
|
||||
'number_of_days_temp': wiz.number_of_days,
|
||||
'employee_id': employee.id,
|
||||
'type': 'add',
|
||||
'holiday_type': 'employee',
|
||||
'holiday_status_id': wiz.holiday_status_id.id,
|
||||
}, context=context)
|
||||
if auto_approve:
|
||||
wf_service.trg_validate(
|
||||
uid, 'hr.holidays', hol_id, 'validate', cr)
|
||||
alloc_hol_ids.append(hol_id)
|
||||
act_model, act_id = self.pool['ir.model.data'].get_object_reference(
|
||||
cr, uid, 'hr_holidays', 'open_allocation_holidays')
|
||||
assert act_model == 'ir.actions.act_window', 'Wrong model'
|
||||
action = self.pool[act_model].read(
|
||||
cr, uid, act_id, context=context)
|
||||
action.update({
|
||||
'target': 'current',
|
||||
'domain': [('id', 'in', alloc_hol_ids)],
|
||||
'nodestroy': True,
|
||||
'context': context,
|
||||
})
|
||||
return action
|
||||
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 Akretion (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
The licence is in the file __openerp__.py
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="hr_holidays_mass_allocation_form" model="ir.ui.view">
|
||||
<field name="name">hr_holidays_mass_allocation_form</field>
|
||||
<field name="model">hr.holidays.mass.allocation</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Mass Allocation of Holidays" version="7.0">
|
||||
<group name="main">
|
||||
<field name="name"/>
|
||||
<field name="holiday_status_id"/>
|
||||
<field name="employee_ids" widget="many2many_tags"/>
|
||||
<field name="number_of_days"/>
|
||||
<field name="auto_approve"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="run" type="object" string="Create Allocations"
|
||||
class="oe_highlight"/>
|
||||
<button special="cancel" string="Cancel" class="oe_link"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_holidays_mass_allocation_action" model="ir.actions.act_window">
|
||||
<field name="name">Mass Allocation</field>
|
||||
<field name="res_model">hr.holidays.mass.allocation</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="hr_holidays_mass_allocation_menu"
|
||||
action="hr_holidays_mass_allocation_action"
|
||||
parent="hr_holidays.menu_open_ask_holidays"
|
||||
groups="base.group_hr_user" sequence="20"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
103
hr_holidays_usability/wizard/hr_holidays_post.py
Normal file
103
hr_holidays_usability/wizard/hr_holidays_post.py
Normal file
@@ -0,0 +1,103 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# HR Holidays Usability module for Odoo
|
||||
# Copyright (C) 2015 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import orm, fields
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
class HrHolidaysPost(orm.TransientModel):
|
||||
_name = 'hr.holidays.post'
|
||||
_description = 'Wizard for post holidays'
|
||||
|
||||
_columns = {
|
||||
'before_date': fields.date(
|
||||
'Select Leave Requests That Ended Before', required=True,
|
||||
help="The wizard will select the validated holidays "
|
||||
"that ended before that date (including holidays that "
|
||||
"ended on that date)."),
|
||||
'holidays_to_post_ids': fields.many2many(
|
||||
'hr.holidays', string='Leave Requests to Post',
|
||||
domain=[
|
||||
('type', '=', 'remove'),
|
||||
('holiday_type', '=', 'employee'),
|
||||
('state', '=', 'validate'),
|
||||
('posted_date', '=', False),
|
||||
]),
|
||||
'state': fields.selection([
|
||||
('draft', 'Draft'),
|
||||
('done', 'Done'),
|
||||
], 'State', readonly=True),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'before_date': fields.date.context_today,
|
||||
'state': 'draft',
|
||||
}
|
||||
|
||||
def select_date(self, cr, uid, ids, context=None):
|
||||
assert len(ids) == 1, 'Only 1 ID'
|
||||
wiz = self.browse(cr, uid, ids[0], context=context)
|
||||
hol_ids = self.pool['hr.holidays'].search(cr, uid, [
|
||||
('type', '=', 'remove'),
|
||||
('holiday_type', '=', 'employee'),
|
||||
('state', '=', 'validate'),
|
||||
('posted_date', '=', False),
|
||||
('vacation_date_to', '<=', wiz.before_date),
|
||||
], context=context)
|
||||
self.write(cr, uid, ids, {
|
||||
'state': 'done',
|
||||
'holidays_to_post_ids': [(6, 0, hol_ids)],
|
||||
}, context=context)
|
||||
act_model, act_id = self.pool['ir.model.data'].get_object_reference(
|
||||
cr, uid, 'hr_holidays_usability', 'hr_holidays_post_action')
|
||||
assert act_model == 'ir.actions.act_window', 'Wrong model'
|
||||
action = self.pool[act_model].read(
|
||||
cr, uid, act_id, context=context)
|
||||
action['res_id'] = ids[0]
|
||||
return action
|
||||
|
||||
def run(self, cr, uid, ids, context=None):
|
||||
assert len(ids) == 1, 'Only 1 ID'
|
||||
wiz = self.browse(cr, uid, ids[0], context=context)
|
||||
today = fields.date.context_today(self, cr, uid, context=context)
|
||||
if not wiz.holidays_to_post_ids:
|
||||
raise orm.except_orm(
|
||||
_('Error:'),
|
||||
_('No leave request to post.'))
|
||||
hol_ids = self.read(
|
||||
cr, uid, ids[0], context=context)['holidays_to_post_ids']
|
||||
self.pool['hr.holidays'].write(
|
||||
cr, uid, hol_ids,
|
||||
{'posted_date': today}, context=context)
|
||||
# On v8, return a graph view !
|
||||
act_model, act_id = self.pool['ir.model.data'].get_object_reference(
|
||||
cr, uid, 'hr_holidays', 'open_ask_holidays')
|
||||
assert act_model == 'ir.actions.act_window', 'Wrong model'
|
||||
action = self.pool[act_model].read(
|
||||
cr, uid, act_id, context=context)
|
||||
action.update({
|
||||
'target': 'current',
|
||||
'domain': [('id', 'in', hol_ids)],
|
||||
'nodestroy': True,
|
||||
'context': {'group_by': ['employee_id', 'holiday_status_id']},
|
||||
})
|
||||
return action
|
||||
47
hr_holidays_usability/wizard/hr_holidays_post_view.xml
Normal file
47
hr_holidays_usability/wizard/hr_holidays_post_view.xml
Normal file
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 Akretion (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
The licence is in the file __openerp__.py
|
||||
-->
|
||||
|
||||
<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="arch" type="xml">
|
||||
<form string="Post Leaves" version="7.0">
|
||||
<group name="main" string="Leave Requests to Post">
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="before_date" states="draft"/>
|
||||
<field name="holidays_to_post_ids" nolabel="1"
|
||||
context="{'tree_view_ref': 'hr_holidays.view_holiday'}"
|
||||
states="done"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="select_date" type="object" string="Get Holiday Requests"
|
||||
class="oe_highlight" states="draft"/>
|
||||
<button name="run" type="object" string="Post"
|
||||
class="oe_highlight" states="done"/>
|
||||
<button special="cancel" string="Cancel" class="oe_link"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_holidays_post_action" model="ir.actions.act_window">
|
||||
<field name="name">Post Leave Requests</field>
|
||||
<field name="res_model">hr.holidays.post</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="hr_holidays_post_menu"
|
||||
action="hr_holidays_post_action"
|
||||
parent="hr_holidays.menu_open_ask_holidays"
|
||||
groups="base.group_hr_user" sequence="30"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
3
intrastat_product_type/__init__.py
Normal file
3
intrastat_product_type/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import intrastat_product_type
|
||||
45
intrastat_product_type/__openerp__.py
Normal file
45
intrastat_product_type/__openerp__.py
Normal file
@@ -0,0 +1,45 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Intrastat Product Type module for Odoo
|
||||
# Copyright (C) 2016 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
{
|
||||
'name': 'Intrastat Product Type',
|
||||
'version': '0.1',
|
||||
'category': 'Accounting & Finance',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Adds a special field Intrastat Type on Products',
|
||||
'description': """
|
||||
Intrastat Product Type
|
||||
======================
|
||||
|
||||
This module is designed for a very special usage scenario. Some companies want to handle the delivery of services the same way as they handle the delivery of goods ; they want to show the services in the delivery note, etc. So, those companies configure the services with Type = *Consumable*. This works well to have the services on the outgoing pickings, but it is a problem for the intrastat declarations.
|
||||
|
||||
This module adds a field *Intrastat Type* on the Product Form with 2 possible options: *Product* or *Service*. The intrastat declaration will use this field instead of the native *Type* field.
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['l10n_fr_intrastat_product', 'l10n_fr_intrastat_service'],
|
||||
'data': ['product_view.xml'],
|
||||
'installable': True,
|
||||
}
|
||||
58
intrastat_product_type/intrastat_product_type.py
Normal file
58
intrastat_product_type/intrastat_product_type.py
Normal file
@@ -0,0 +1,58 @@
|
||||
# -*- 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.osv import orm, fields
|
||||
from openerp.tools.translate import _
|
||||
|
||||
|
||||
class ProductTemplate(orm.Model):
|
||||
_inherit = 'product.template'
|
||||
|
||||
_columns = {
|
||||
'intrastat_type': fields.selection([
|
||||
('product', 'Product'),
|
||||
('service', 'Service'),
|
||||
], string='Intrastat Type', required=True,
|
||||
help="Type of product used for the intrastat declarations. "
|
||||
"For example, you can configure a product with "
|
||||
"'Product Type' = 'Consumable' and 'Intrastat Type' = 'Service'.")
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'intrastat_type': 'product',
|
||||
}
|
||||
|
||||
def _check_intrastat_product(self, cr, uid, ids):
|
||||
for pt in self.browse(cr, uid, ids):
|
||||
if pt.intrastat_type == 'product' and pt.type == 'service':
|
||||
raise orm.except_orm(
|
||||
_("Error"),
|
||||
_("On the product '%s', you cannot set Product Type to "
|
||||
"'Service' and Intrastat Type to 'Product'.") % pt.name)
|
||||
if pt.intrastat_type == 'service' and pt.type == 'product':
|
||||
raise orm.except_orm(
|
||||
_("Error"),
|
||||
_("On the product '%s', you cannot set Intrastat Type to "
|
||||
"'Service' and Product Type to 'Stockable product' "
|
||||
"(but you can set Product Type to 'Consumable' or "
|
||||
"'Service').") % pt.name)
|
||||
return True
|
||||
|
||||
_constraints = [(
|
||||
_check_intrastat_product,
|
||||
'error msg in raise',
|
||||
['type', 'intrastat_type'],
|
||||
)]
|
||||
|
||||
|
||||
class ReportIntrastatCommon(orm.Model):
|
||||
_inherit = "report.intrastat.common"
|
||||
|
||||
def _is_service(self, cr, uid, invoice_line, context=None):
|
||||
if invoice_line.product_id.intrastat_type == 'service':
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
9
intrastat_product_type/post_install_manual.py
Normal file
9
intrastat_product_type/post_install_manual.py
Normal file
@@ -0,0 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# POST-INIT-HOOK doesn't work in v7 (only v8 and above)
|
||||
# So the SQL needs to be executed manually
|
||||
def set_intrastat_type_on_products(cr, pool):
|
||||
cr.execute(
|
||||
"UPDATE product_template SET intrastat_type='service' "
|
||||
"WHERE type='service'")
|
||||
return
|
||||
25
intrastat_product_type/product_view.xml
Normal file
25
intrastat_product_type/product_view.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2016 Akretion (http://www.akretion.com/)
|
||||
@author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
The licence is in the file __openerp__.py
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
|
||||
<record id="product_normal_form_view" model="ir.ui.view">
|
||||
<field name="name">intrastat_product_type.product.product.form</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="inherit_id" ref="product.product_normal_form_view" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="type" position="after">
|
||||
<field name="intrastat_type"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
23
l10n_fr_infogreffe_connector/__init__.py
Normal file
23
l10n_fr_infogreffe_connector/__init__.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# L10n FR infogreffe connector module for OpenERP
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from . import infogreffe
|
||||
49
l10n_fr_infogreffe_connector/__openerp__.py
Normal file
49
l10n_fr_infogreffe_connector/__openerp__.py
Normal file
@@ -0,0 +1,49 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# L10n FR Infogreffe connector module for OpenERP
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
{
|
||||
'name': 'Infogreffe connector',
|
||||
'version': '0.1',
|
||||
'category': 'French Localization',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Download info from infogreffe.fr',
|
||||
'description': """
|
||||
Infogreffe connector
|
||||
====================
|
||||
|
||||
This module adds a button on Partner form view in the *Accounting* tab to download data from Infogreffe. If the Partner has a SIREN in OpenERP, it will check if the company has *Key Figures* in Infogreffe, get the latest *Key Figures* and copy to OpenERP :
|
||||
|
||||
* Turnover
|
||||
|
||||
* Profit
|
||||
|
||||
* Headcount
|
||||
|
||||
Please contact Alexis de Lattre from Akretion <alexis.delattre@akretion.com> for any help or question about this module.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com/',
|
||||
'depends': ['l10n_fr_siret'],
|
||||
'external_dependencies': {'python': ['requests', 'bs4']},
|
||||
'data': ['partner_view.xml'],
|
||||
'active': False,
|
||||
}
|
||||
151
l10n_fr_infogreffe_connector/infogreffe.py
Normal file
151
l10n_fr_infogreffe_connector/infogreffe.py
Normal file
@@ -0,0 +1,151 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# L10n FR infogreffe connector module for OpenERP
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com/)
|
||||
# Copyright (C) 2014 Kiplink (http://www.kiplink.fr/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# @author: Alexandre Fournier <alexandre.fournier@kiplink.fr>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import orm, fields
|
||||
from openerp.tools.translate import _
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
from datetime import datetime
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
URL = 'https://www.infogreffe.fr'
|
||||
|
||||
|
||||
class res_partner(orm.Model):
|
||||
_inherit = 'res.partner'
|
||||
|
||||
_columns = {
|
||||
'infogreffe_date': fields.date('Date', readonly=True),
|
||||
'infogreffe_turnover': fields.integer(u'Turnover (€)', readonly=True),
|
||||
'infogreffe_profit': fields.integer(u'Profit (€)', readonly=True),
|
||||
'infogreffe_headcount': fields.integer('Headcount', readonly=True),
|
||||
}
|
||||
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
if default is None:
|
||||
default = {}
|
||||
default.update({
|
||||
'infogreffe_date': False,
|
||||
'infogreffe_turnover': False,
|
||||
'infogreffe_profit': False,
|
||||
'infogreffe_headcount': False,
|
||||
})
|
||||
return super(res_partner, self).copy(
|
||||
cr, uid, id, default=default, context=context)
|
||||
|
||||
def get_json_company_from_siren(self, cr, uid, siren, context=None):
|
||||
params = {
|
||||
'sirenOuSiret': siren,
|
||||
'etabSecondaire': 'false',
|
||||
'etsRadiees': 'false',
|
||||
'typeEntreprise': 'TOUS'
|
||||
}
|
||||
|
||||
url = URL + '/services/entreprise/rest/recherche/parEntreprise'
|
||||
resp = requests.get(url=url, params=params)
|
||||
data = resp.json()
|
||||
return data
|
||||
|
||||
def get_soup_extrait_from_siren(self, cr, uid, siren, context=None):
|
||||
data = self.get_json_company_from_siren(
|
||||
cr, uid, siren, context=context)
|
||||
data = data['entrepRCSStoreResponse']['items'][0]
|
||||
name = data['libelleEntreprise']['denomination'].lower()
|
||||
url = URL + '/societes/entreprise-societe/%s-%s-%s.html' % (
|
||||
data['siren'], name, data['etablissementChrono'])
|
||||
resp = requests.get(url=url)
|
||||
soup = BeautifulSoup(resp.text)
|
||||
return soup
|
||||
|
||||
def convert_to_integer(self, cr, uid, raw_value, context=None):
|
||||
if not raw_value:
|
||||
return False
|
||||
val1 = raw_value.strip()
|
||||
#print "val1=", val1
|
||||
# Remove short spaces
|
||||
val2 = val1.replace(u'\xA0', '')
|
||||
#print "val2=", val2
|
||||
val3 = val2.replace('K', '000')
|
||||
#print "val3=", val3
|
||||
# Remove euro symbol
|
||||
val4 = val3.replace(u'\u20ac', '')
|
||||
#print "val4=", val4
|
||||
val5 = val4.replace(' ', '')
|
||||
#print "val5=", val5
|
||||
return int(val5)
|
||||
|
||||
def button_get_from_infogreffe(self, cr, uid, ids, context=None):
|
||||
assert len(ids) == 1, 'Only 1 ID'
|
||||
partner = self.browse(cr, uid, ids[0], context=context)
|
||||
if not partner.siren:
|
||||
raise orm.except_orm(
|
||||
_('Error:'),
|
||||
_("Missing SIREN on partner '%s'. It is needed to download "
|
||||
"data from Infogreffe") % partner.name)
|
||||
|
||||
logger.info("Connecting to infogreffe with SIREN %s" % partner.siren)
|
||||
soup = self.get_soup_extrait_from_siren(
|
||||
cr, uid, partner.siren, context=context)
|
||||
trs = soup.find(id='chiffresCles').find('tbody').find_all('tr')
|
||||
vals = {
|
||||
'infogreffe_date': False,
|
||||
'infogreffe_turnover': False,
|
||||
'infogreffe_profit': False,
|
||||
'infogreffe_headcount': False,
|
||||
}
|
||||
|
||||
for tr in trs:
|
||||
tds = tr.find_all('td')
|
||||
if len(tds) != 4:
|
||||
continue
|
||||
try:
|
||||
date = datetime.strptime(tds[0].text.strip(), '%d/%m/%Y')
|
||||
raw_turnover = tds[1].text
|
||||
turnover = self.convert_to_integer(
|
||||
cr, uid, raw_turnover, context=context)
|
||||
raw_profit = tds[2].text
|
||||
profit = self.convert_to_integer(
|
||||
cr, uid, raw_profit, context=context)
|
||||
headcount_raw = tds[3].text.strip()
|
||||
headcount = self.convert_to_integer(
|
||||
cr, uid, headcount_raw, context=context)
|
||||
except:
|
||||
logger.warning('Cannot parse infogreffe results')
|
||||
continue
|
||||
if not vals['infogreffe_date'] or vals['infogreffe_date'] < date:
|
||||
vals = {
|
||||
'infogreffe_date': date,
|
||||
'infogreffe_turnover': turnover,
|
||||
'infogreffe_profit': profit,
|
||||
'infogreffe_headcount': headcount,
|
||||
}
|
||||
logger.debug('Infogreffe result line = %s' % vals)
|
||||
|
||||
self.write(cr, uid, ids[0], vals, context=context)
|
||||
logger.debug(
|
||||
u'Partner %s updated with Infogreffe data %s'
|
||||
% (partner.name, vals))
|
||||
return True
|
||||
30
l10n_fr_infogreffe_connector/partner_view.xml
Normal file
30
l10n_fr_infogreffe_connector/partner_view.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2014 Akretion (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
The licence is in the file __openerp__.py
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="view_partner_form" model="ir.ui.view">
|
||||
<field name="name">infogreffe.partner.form</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="l10n_fr_siret.view_partner_add"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='company_registry']/../.." position="after">
|
||||
<group name="infogreffe" string="Infogreffe" attrs="{'invisible': [('is_company', '=', False)]}">
|
||||
<field name="infogreffe_date"/>
|
||||
<field name="infogreffe_turnover"/>
|
||||
<field name="infogreffe_profit"/>
|
||||
<field name="infogreffe_headcount"/>
|
||||
<button colspan="2" string="Update from Infogreffe"
|
||||
name="button_get_from_infogreffe" type="object"/>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
3
mrp_average_cost/__init__.py
Normal file
3
mrp_average_cost/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import mrp
|
||||
52
mrp_average_cost/__openerp__.py
Normal file
52
mrp_average_cost/__openerp__.py
Normal file
@@ -0,0 +1,52 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# MRP Average Cost module for Odoo
|
||||
# Copyright (C) 2016 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
{
|
||||
'name': 'MRP Average Cost',
|
||||
'version': '0.1',
|
||||
'category': 'Manufactuing',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Update standard_price upon validation of a manufacturing order',
|
||||
'description': """
|
||||
MRP Average Cost
|
||||
================
|
||||
|
||||
By default, the official stock module updates the standard_price of a product that has costing_method = 'average' when validating an incoming picking. But the official 'mrp' module doesn't do that when you validate a manufactuging order.
|
||||
|
||||
This module adds this feature : when you validate a manufacturing order of a product that has costing method = 'average', the standard_price of the product will be updated by taking into account the standard_price of each raw material and also a number of work hours defined on the BOM.
|
||||
|
||||
Together with this module, I recommend the use of my module product_usability, available in the same branch, which contains a backport of the model product.price.history from v8 to v7.
|
||||
|
||||
Please contact Alexis de Lattre from Akretion <alexis.delattre@akretion.com> for any help or question about this module.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['mrp'],
|
||||
'data': [
|
||||
'mrp_view.xml',
|
||||
'mrp_data.xml',
|
||||
'security/labour_cost_profile_security.xml',
|
||||
'security/ir.model.access.csv',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
335
mrp_average_cost/mrp.py
Normal file
335
mrp_average_cost/mrp.py
Normal file
@@ -0,0 +1,335 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# MRP Average Cost module for Odoo
|
||||
# Copyright (C) 2016 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import orm, fields
|
||||
from openerp.tools.translate import _
|
||||
import openerp.addons.decimal_precision as dp
|
||||
from openerp.tools import float_compare, float_is_zero
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MrpBomLabourLine(orm.Model):
|
||||
_name = 'mrp.bom.labour.line'
|
||||
_description = 'Labour lines on BOM'
|
||||
|
||||
_columns = {
|
||||
'bom_id': fields.many2one(
|
||||
'mrp.bom', 'Labour Lines', ondelete='cascade'),
|
||||
'labour_time': fields.float(
|
||||
'Labour Time', required=True,
|
||||
digits_compute=dp.get_precision('Labour Hours'),
|
||||
help="Average labour time for the production of "
|
||||
"items of the BOM, in hours."),
|
||||
'labour_cost_profile_id': fields.many2one(
|
||||
'labour.cost.profile', 'Labour Cost Profile', required=True),
|
||||
'note': fields.text('Note'),
|
||||
}
|
||||
|
||||
_sql_constraints = [(
|
||||
'labour_time_positive',
|
||||
'CHECK (labour_time >= 0)',
|
||||
"The value of the field 'Labour Time' must be positive or 0.")]
|
||||
|
||||
|
||||
class MrpBom(orm.Model):
|
||||
_inherit = 'mrp.bom'
|
||||
|
||||
def _compute_total_labour_cost(
|
||||
self, cr, uid, ids, name, arg, context=None):
|
||||
res = {}
|
||||
for bom in self.browse(cr, uid, ids, context=context):
|
||||
cost = 0.0
|
||||
for lline in bom.labour_line_ids:
|
||||
cost += lline.labour_time * lline.labour_cost_profile_id.hour_cost
|
||||
res[bom.id] = cost
|
||||
return res
|
||||
|
||||
def _get_bom_from_labour_lines(self, cr, uid, ids, context=None):
|
||||
return self.pool['mrp.bom'].search(
|
||||
cr, uid, [('labour_line_ids', 'in', ids)], context=context)
|
||||
|
||||
def _get_bom_from_cost_profile(self, cr, uid, ids, context=None):
|
||||
labour_line_ids = self.pool['mrp.bom.labour.line'].search(
|
||||
cr, uid, [('labour_cost_profile_id', 'in', ids)], context=context)
|
||||
return self.pool['mrp.bom'].search(
|
||||
cr, uid, [('labour_line_ids', 'in', labour_line_ids)], context=context)
|
||||
|
||||
def _compute_total_cost(
|
||||
self, cr, uid, ids, name, arg, context=None):
|
||||
res = {}
|
||||
puo = self.pool['product.uom']
|
||||
for bom in self.browse(cr, uid, ids, context=context):
|
||||
component_cost = 0.0
|
||||
for line in bom.bom_lines:
|
||||
component_price = line.product_id.standard_price
|
||||
component_qty_product_uom = puo._compute_qty_obj(
|
||||
cr, uid, line.product_uom, line.product_qty,
|
||||
line.product_id.uom_id, context=context)
|
||||
component_cost += component_price * component_qty_product_uom
|
||||
total_cost = component_cost + bom.extra_cost + bom.total_labour_cost
|
||||
res[bom.id] = {
|
||||
'total_components_cost': component_cost,
|
||||
'total_cost': total_cost,
|
||||
}
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'labour_line_ids': fields.one2many(
|
||||
'mrp.bom.labour.line', 'bom_id', 'Labour Lines'),
|
||||
'total_labour_cost': fields.function(
|
||||
_compute_total_labour_cost, type='float', readonly=True,
|
||||
digits_compute=dp.get_precision('Product Price'),
|
||||
string="Total Labour Cost", store={
|
||||
'labour.cost.profile': (_get_bom_from_cost_profile, [
|
||||
'hour_cost', 'company_id'], 10),
|
||||
'mrp.bom.labour.line': (_get_bom_from_labour_lines, [
|
||||
'bom_id', 'labour_time', 'labour_cost_profile_id'], 20),
|
||||
}),
|
||||
'extra_cost': fields.float(
|
||||
'Extra Cost', track_visibility='onchange',
|
||||
digits_compute=dp.get_precision('Product Price'),
|
||||
help="Extra cost for the production of the quantity of "
|
||||
"items of the BOM, in company currency. "
|
||||
"You can use this field to enter the cost of the consumables "
|
||||
"that are used to produce the product but are not listed in "
|
||||
"the BOM"),
|
||||
'total_components_cost': fields.function(
|
||||
_compute_total_cost, type='float', readonly=True,
|
||||
digits_compute=dp.get_precision('Product Price'),
|
||||
multi='total-cost', string='Total Components Cost'),
|
||||
'total_cost': fields.function(
|
||||
_compute_total_cost, type='float', readonly=True,
|
||||
multi='total-cost', string='Total Cost',
|
||||
digits_compute=dp.get_precision('Product Price'),
|
||||
help="Total Cost = Total Components Cost + "
|
||||
"Total Labour Cost + Extra Cost"),
|
||||
'company_currency_id': fields.related(
|
||||
'company_id', 'currency_id', readonly=True, type='many2one',
|
||||
relation='res.currency', string='Company Currency'),
|
||||
# to display in bom lines
|
||||
'standard_price': fields.related(
|
||||
'product_id', 'standard_price', readonly=True,
|
||||
type='float', string='Standard Price')
|
||||
}
|
||||
|
||||
def manual_update_product_standard_price(self, cr, uid, ids, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
ctx = context.copy()
|
||||
if 'product_price_history_origin' not in ctx:
|
||||
ctx['product_price_history_origin'] = u'Manual update from BOM'
|
||||
precision = self.pool['decimal.precision'].precision_get(
|
||||
cr, uid, 'Product Price')
|
||||
for bom in self.browse(cr, uid, ids, context=context):
|
||||
if not bom.product_id:
|
||||
continue
|
||||
if float_compare(
|
||||
bom.product_id.standard_price, bom.total_cost,
|
||||
precision_digits=precision):
|
||||
bom.product_id.write(
|
||||
{'standard_price': bom.total_cost}, context=ctx)
|
||||
logger.info(
|
||||
'Cost price updated to %s on product %s',
|
||||
bom.total_cost, bom.product_id.name_get()[0][1])
|
||||
return True
|
||||
|
||||
def _phantom_update_product_standard_price(self, cr, uid, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
ctx = context.copy()
|
||||
ctx['product_price_history_origin'] = 'Automatic update of Phantom BOMs'
|
||||
mbo = self.pool['mrp.bom']
|
||||
bom_ids = mbo.search(
|
||||
cr, uid, [('type', '=', 'phantom')], context=context)
|
||||
self.manual_update_product_standard_price(
|
||||
cr, uid, bom_ids, context=ctx)
|
||||
return True
|
||||
|
||||
|
||||
class LabourCostProfile(orm.Model):
|
||||
_name = 'labour.cost.profile'
|
||||
_inherit = ['mail.thread']
|
||||
_description = 'Labour Cost Profile'
|
||||
|
||||
_columns = {
|
||||
'name': fields.char(
|
||||
'Name', required=True, track_visibility='onchange'),
|
||||
'hour_cost': fields.float(
|
||||
'Cost per Hour', required=True,
|
||||
digits_compute=dp.get_precision('Product Price'),
|
||||
track_visibility='onchange',
|
||||
help="Labour cost per hour per person in company currency"),
|
||||
'company_id': fields.many2one('res.company', 'Company', required=True),
|
||||
'company_currency_id': fields.related(
|
||||
'company_id', 'currency_id', readonly=True, type='many2one',
|
||||
relation='res.currency', string='Company Currency')
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'company_id': lambda self, cr, uid, context:
|
||||
self.pool['res.company']._company_default_get(
|
||||
cr, uid, 'labour.cost.profile', context=context),
|
||||
}
|
||||
|
||||
def name_get(self, cr, uid, ids, context=None):
|
||||
res = []
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
for record in self.browse(cr, uid, ids, context=context):
|
||||
res.append((record.id, u'%s (%s %s)' % (
|
||||
record.name, record.hour_cost,
|
||||
record.company_currency_id.symbol)))
|
||||
return res
|
||||
|
||||
|
||||
class MrpProduction(orm.Model):
|
||||
_inherit = 'mrp.production'
|
||||
|
||||
_columns = {
|
||||
'unit_cost': fields.float(
|
||||
'Unit Cost', readonly=True,
|
||||
digits_compute=dp.get_precision('Product Price'),
|
||||
help="This cost per unit in the unit of measure of the product "
|
||||
"in company currency takes into account "
|
||||
"the cost of the raw materials and the labour cost defined on"
|
||||
"the BOM."),
|
||||
'company_currency_id': fields.related(
|
||||
'company_id', 'currency_id', readonly=True, type='many2one',
|
||||
relation='res.currency', string='Company Currency'),
|
||||
}
|
||||
|
||||
def compute_order_unit_cost(self, cr, uid, order, context=None):
|
||||
puo = self.pool['product.uom']
|
||||
mo_total_price = 0.0 # In the UoM of the M0
|
||||
labor_cost_per_unit = 0.0 # In the UoM of the product
|
||||
extra_cost_per_unit = 0.0 # In the UoM of the product
|
||||
# I read the raw materials MO, not on BOM, in order to make
|
||||
# it work with the "dynamic" BOMs (few raw material are auto-added
|
||||
# on the fly on MO)
|
||||
for raw_smove in order.move_lines + order.move_lines2:
|
||||
# I don't filter on state, in order to make it work with
|
||||
# partial productions
|
||||
# For partial productions, mo.product_qty is not updated
|
||||
# so we compute with fully qty and we compute with all raw
|
||||
# materials (consumed or not), so it gives a good price
|
||||
# per unit at the end
|
||||
raw_price = raw_smove.product_id.standard_price
|
||||
raw_qty_product_uom = puo._compute_qty_obj(
|
||||
cr, uid, raw_smove.product_uom, raw_smove.product_qty,
|
||||
raw_smove.product_id.uom_id, context=context)
|
||||
raw_material_cost = raw_price * raw_qty_product_uom
|
||||
logger.info(
|
||||
'MO %s product %s: raw_material_cost=%s',
|
||||
order.name, raw_smove.product_id.name, raw_material_cost)
|
||||
mo_total_price += raw_material_cost
|
||||
if order.bom_id:
|
||||
bom = order.bom_id
|
||||
#if not bom.total_labour_cost:
|
||||
# raise orm.except_orm(
|
||||
# _('Error:'),
|
||||
# _("Total Labor Cost is 0 on bill of material '%s'.")
|
||||
# % bom.name)
|
||||
if not bom.product_qty:
|
||||
raise orm.except_orm(
|
||||
_('Error:'),
|
||||
_("Missing Product Quantity on bill of material '%s'.")
|
||||
% bom.name)
|
||||
bom_qty_product_uom = puo._compute_qty_obj(
|
||||
cr, uid, bom.product_uom, bom.product_qty,
|
||||
bom.product_id.uom_id, context=context)
|
||||
assert bom_qty_product_uom > 0, 'BoM qty should be positive'
|
||||
labor_cost_per_unit = bom.total_labour_cost / bom_qty_product_uom
|
||||
extra_cost_per_unit = bom.extra_cost / bom_qty_product_uom
|
||||
# mo_standard_price and labor_cost_per_unit are
|
||||
# in the UoM of the product (not of the MO/BOM)
|
||||
mo_qty_product_uom = puo._compute_qty_obj(
|
||||
cr, uid, order.product_uom, order.product_qty,
|
||||
order.product_id.uom_id, context=context)
|
||||
assert mo_qty_product_uom > 0, 'MO qty should be positive'
|
||||
mo_standard_price = mo_total_price / mo_qty_product_uom
|
||||
logger.info(
|
||||
'MO %s: labor_cost_per_unit=%s', order.name, labor_cost_per_unit)
|
||||
logger.info(
|
||||
'MO %s: extra_cost_per_unit=%s', order.name, extra_cost_per_unit)
|
||||
mo_standard_price += labor_cost_per_unit
|
||||
mo_standard_price += extra_cost_per_unit
|
||||
order.write({'unit_cost': mo_standard_price}, context=context)
|
||||
logger.info(
|
||||
'MO %s: unit_cost=%s', order.name, mo_standard_price)
|
||||
return mo_standard_price
|
||||
|
||||
def update_standard_price(self, cr, uid, order, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
puo = self.pool['product.uom']
|
||||
product = order.product_id
|
||||
mo_standard_price = self.compute_order_unit_cost(
|
||||
cr, uid, order, context=context)
|
||||
mo_qty_product_uom = puo._compute_qty_obj(
|
||||
cr, uid, order.product_uom, order.product_qty,
|
||||
order.product_id.uom_id, context=context)
|
||||
# I can't use the native method _update_average_price of stock.move
|
||||
# because it only works on move.picking_id.type == 'in'
|
||||
# As we do the super() at the END of this method,
|
||||
# the qty produced by this MO in NOT counted inside
|
||||
# product.qty_available
|
||||
qty_before_mo = product.qty_available
|
||||
logger.info(
|
||||
'MO %s product %s: standard_price before production: %s',
|
||||
order.name, product.name, product.standard_price)
|
||||
logger.info(
|
||||
'MO %s product %s: qty before production: %s',
|
||||
order.name, product.name, qty_before_mo)
|
||||
# Here, we handle as if we were in v8 (!)
|
||||
# so we consider that standard_price is in company currency
|
||||
# It will not work if you are in multi-company environment
|
||||
# with companies in different currencies
|
||||
if not qty_before_mo + mo_qty_product_uom:
|
||||
new_std_price = mo_standard_price
|
||||
else:
|
||||
new_std_price = (
|
||||
(product.standard_price * qty_before_mo) +
|
||||
(mo_standard_price * mo_qty_product_uom)) / \
|
||||
(qty_before_mo + mo_qty_product_uom)
|
||||
ctx_product = context.copy()
|
||||
ctx_product['product_price_history_origin'] = _(
|
||||
'%s (Qty before: %s - Added qty: %s - Unit price of '
|
||||
'added qty: %s)') % (
|
||||
order.name, qty_before_mo, mo_qty_product_uom, mo_standard_price)
|
||||
product.write({'standard_price': new_std_price}, context=ctx_product)
|
||||
logger.info(
|
||||
'MO %s product %s: standard_price updated to %s',
|
||||
order.name, product.name, new_std_price)
|
||||
return True
|
||||
|
||||
def action_produce(
|
||||
self, cr, uid, production_id, production_qty, production_mode,
|
||||
context=None):
|
||||
if production_mode == 'consume_produce':
|
||||
order = self.browse(cr, uid, production_id, context=context)
|
||||
if order.product_id.cost_method == 'average':
|
||||
self.update_standard_price(cr, uid, order, context=context)
|
||||
return super(MrpProduction, self).action_produce(
|
||||
cr, uid, production_id, production_qty, production_mode,
|
||||
context=context)
|
||||
25
mrp_average_cost/mrp_data.xml
Normal file
25
mrp_average_cost/mrp_data.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<record forcecreate="True" id="labour_hours" model="decimal.precision">
|
||||
<field name="name">Labour Hours</field>
|
||||
<field name="digits">3</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="phantom_update_product_standard_price" model="ir.cron">
|
||||
<field name="name">Update Cost Price of products with Phantom BOM</field>
|
||||
<field name="active" eval="False"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="interval_number">1</field>
|
||||
<field name="interval_type">days</field>
|
||||
<field name="numbercall">-1</field> <!-- don't limit the number of calls -->
|
||||
<field name="doall" eval="False"/>
|
||||
<field name="model" eval="'mrp.bom'"/>
|
||||
<field name="function" eval="'_phantom_update_product_standard_price'"/>
|
||||
<field name="args" eval="'()'"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
130
mrp_average_cost/mrp_view.xml
Normal file
130
mrp_average_cost/mrp_view.xml
Normal file
@@ -0,0 +1,130 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2016 Akretion (http://www.akretion.com/)
|
||||
@author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
The licence is in the file __openerp__.py
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="mrp_bom_form_view" model="ir.ui.view">
|
||||
<field name="name">mrp_average_cost.mrp.bom.form</field>
|
||||
<field name="model">mrp.bom</field>
|
||||
<field name="inherit_id" ref="mrp.mrp_bom_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@groups='mrp.group_mrp_routings']" position="after">
|
||||
<field name="total_components_cost" widget="monetary"
|
||||
options="{'currency_field': 'company_currency_id'}"/>
|
||||
<field name="total_labour_cost" widget="monetary"
|
||||
options="{'currency_field': 'company_currency_id'}"/>
|
||||
<field name="extra_cost" widget="monetary"
|
||||
options="{'currency_field': 'company_currency_id'}"/>
|
||||
<label for="total_cost"/>
|
||||
<div>
|
||||
<field name="total_cost" widget="monetary"
|
||||
options="{'currency_field': 'company_currency_id'}"
|
||||
class="oe_inline"/>
|
||||
<button type="object" name="manual_update_product_standard_price"
|
||||
string="Update Cost Price of Product" class="oe_link"/>
|
||||
</div>
|
||||
<field name="company_currency_id" invisible="1"/>
|
||||
</xpath>
|
||||
<page string="Components" position="after">
|
||||
<page string="Labour" name="labour_lines">
|
||||
<group name="labour_lines_grp">
|
||||
<field name="labour_line_ids" nolabel="1"/>
|
||||
</group>
|
||||
</page>
|
||||
</page>
|
||||
<xpath expr="//field[@name='bom_lines']/tree/field[@name='product_uom']" position="after">
|
||||
<field name="standard_price"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_labour_line_tree" model="ir.ui.view">
|
||||
<field name="name">mrp_bom_labour_line.tree</field>
|
||||
<field name="model">mrp.bom.labour.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Labour Lines" editable="bottom">
|
||||
<field name="bom_id" invisible="not context.get('mrp_bom_labour_line_main_view')"/>
|
||||
<field name="labour_time" string="Labour Time (hours)"/>
|
||||
<field name="labour_cost_profile_id"/>
|
||||
<field name="note"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mrp_bom_labour_line_form" model="ir.ui.view">
|
||||
<field name="name">mrp_bom_labour_line.form</field>
|
||||
<field name="model">mrp.bom.labour.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Labour Line" version="7.0">
|
||||
<group name="main">
|
||||
<field name="bom_id" invisible="not context.get('mrp_bom_labour_line_main_view')"/>
|
||||
<label for="labour_time"/>
|
||||
<div name="labour_time">
|
||||
<field name="labour_time" class="oe_inline"/>
|
||||
<label string="hours"/>
|
||||
</div>
|
||||
<field name="labour_cost_profile_id"/>
|
||||
<field name="note"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
|
||||
<record id="labour_cost_profile_form" model="ir.ui.view">
|
||||
<field name="name">labour_cost_profile_form</field>
|
||||
<field name="model">labour.cost.profile</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Labour Cost Profile" version="7.0">
|
||||
<group name="main">
|
||||
<field name="name"/>
|
||||
<field name="hour_cost" widget="monetary" options="{'currency_field': 'company_currency_id'}"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="company_currency_id" invisible="1"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="labour_cost_profile_tree" model="ir.ui.view">
|
||||
<field name="name">labour_cost_profile_tree</field>
|
||||
<field name="model">labour.cost.profile</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Labour Cost Profiles">
|
||||
<field name="name"/>
|
||||
<field name="hour_cost"/>
|
||||
<field name="company_currency_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="labour_cost_profile_action" model="ir.actions.act_window">
|
||||
<field name="name">Labour Cost Profile</field>
|
||||
<field name="res_model">labour.cost.profile</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="labour_cost_profile_menu" action="labour_cost_profile_action"
|
||||
parent="mrp.menu_mrp_configuration"/>
|
||||
|
||||
<record id="mrp_production_form_view" model="ir.ui.view">
|
||||
<field name="name">mrp_average_cost.mrp_production_form</field>
|
||||
<field name="inherit_id" ref="mrp.mrp_production_form_view"/>
|
||||
<field name="model">mrp.production</field>
|
||||
<field name="arch" type="xml">
|
||||
<field name="date_finished" position="after">
|
||||
<field name="unit_cost" widget="monetary" options="{'currency_field': 'company_currency_id'}" attrs="{'invisible': [('state', '!=', 'done')]}"/>
|
||||
<field name="company_currency_id" invisible="1"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
9
mrp_average_cost/security/ir.model.access.csv
Normal file
9
mrp_average_cost/security/ir.model.access.csv
Normal file
@@ -0,0 +1,9 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_labour_cost_profile_read,Read access on labour.cost.profile to MRP user,model_labour_cost_profile,mrp.group_mrp_user,1,0,0,0
|
||||
access_labour_cost_profile_read_sale,Read access on labour.cost.profile to Sale user,model_labour_cost_profile,base.group_sale_salesman,1,0,0,0
|
||||
access_labour_cost_profile_read_stock,Read access on labour.cost.profile to Stock user,model_labour_cost_profile,stock.group_stock_user,1,0,0,0
|
||||
access_labour_cost_profile_full,Full access on labour.cost.profile to MRP manager,model_labour_cost_profile,mrp.group_mrp_manager,1,1,1,1
|
||||
access_mrp_bom_labour_line_read,Read access on mrp.bom.labour.line to MRP user,model_mrp_bom_labour_line,mrp.group_mrp_user,1,0,0,0
|
||||
access_mrp_bom_labour_line_read_sale,Read access on mrp.bom.labour.line to Sale user,model_mrp_bom_labour_line,base.group_sale_salesman,1,0,0,0
|
||||
access_mrp_bom_labour_line_read_stock,Read access on mrp.bom.labour.line to Stock user,model_mrp_bom_labour_line,stock.group_stock_user,1,0,0,0
|
||||
access_mrp_bom_labour_line_full,Full access on mrp.bom.labour.line to MRP manager,model_mrp_bom_labour_line,mrp.group_mrp_manager,1,1,1,1
|
||||
|
12
mrp_average_cost/security/labour_cost_profile_security.xml
Normal file
12
mrp_average_cost/security/labour_cost_profile_security.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<record id="labour_cost_profile_rule" model="ir.rule">
|
||||
<field name="name">Labour Cost Profile multi-company</field>
|
||||
<field name="model_id" ref="model_labour_cost_profile"/>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
3
mrp_usability/__init__.py
Normal file
3
mrp_usability/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import mrp
|
||||
47
mrp_usability/__openerp__.py
Normal file
47
mrp_usability/__openerp__.py
Normal file
@@ -0,0 +1,47 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# MRP Usability module for Odoo
|
||||
# Copyright (C) 2015 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
{
|
||||
'name': 'MRP Usability',
|
||||
'version': '0.1',
|
||||
'category': 'Manufacturing',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Usability improvements on manufacturing',
|
||||
'description': """
|
||||
MRP Usability
|
||||
=============
|
||||
|
||||
Small usability improvements on MRP:
|
||||
|
||||
* order by id desc
|
||||
|
||||
* show date start and date finished on production order form view
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['mrp'],
|
||||
'data': ['mrp_view.xml'],
|
||||
'installable': True,
|
||||
}
|
||||
28
mrp_usability/mrp.py
Normal file
28
mrp_usability/mrp.py
Normal file
@@ -0,0 +1,28 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# MRP Usability module for Odoo
|
||||
# Copyright (C) 2015 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from openerp.osv import orm
|
||||
|
||||
|
||||
class MrpProduction(orm.Model):
|
||||
_inherit = 'mrp.production'
|
||||
_order = 'id desc'
|
||||
38
mrp_usability/mrp_view.xml
Normal file
38
mrp_usability/mrp_view.xml
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2016 Akretion (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
The licence is in the file __openerp__.py
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="mrp_production_form_view" model="ir.ui.view">
|
||||
<field name="name">usability.mrp.production.form</field>
|
||||
<field name="model">mrp.production</field>
|
||||
<field name="inherit_id" ref="mrp.mrp_production_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="date_start" position="attributes">
|
||||
<attribute name="invisible">0</attribute>
|
||||
</field>
|
||||
<field name="date_finished" position="attributes">
|
||||
<attribute name="invisible">0</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_procurement_form_inherit" model="ir.ui.view">
|
||||
<field name="name">mrp_usability.procurement.order.form</field>
|
||||
<field name="model">procurement.order</field>
|
||||
<field name="inherit_id" ref="mrp.view_procurement_form_inherit"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="production_id" position="attributes">
|
||||
<attribute name="attrs">{}</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
23
partner_default_lang_parent/__init__.py
Normal file
23
partner_default_lang_parent/__init__.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Partner Default Lang Parent module for OpenERP
|
||||
# Copyright (C) 2015 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
38
partner_default_lang_parent/__openerp__.py
Normal file
38
partner_default_lang_parent/__openerp__.py
Normal file
@@ -0,0 +1,38 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Partner Default Lang Parent module for OpenERP
|
||||
# Copyright (C) 2015 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
{
|
||||
'name': 'Partner Default Lang Parent',
|
||||
'version': '0.1',
|
||||
'category': 'Partner',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'A new contact gets the language of the parent by default',
|
||||
'description': """
|
||||
By default, if you create a new contact on a company form, this new contact will have the language of the user that create it. This module changes this behavior : a contact now gets the language of it's parent company by default.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['base'],
|
||||
'data': ['partner_view.xml'],
|
||||
'installable': True,
|
||||
}
|
||||
26
partner_default_lang_parent/partner_view.xml
Normal file
26
partner_default_lang_parent/partner_view.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2015 Akretion (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
The licence is in the file __openerp__.py
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="view_partner_form" model="ir.ui.view">
|
||||
<field name="name">partner_default_lang_parent.partner.form</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.view_partner_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='child_ids']/form//field[@name='function']" position="before">
|
||||
<field name="lang" invisible="1"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='child_ids']" position="attributes">
|
||||
<field name="context">{'default_parent_id': active_id, 'default_street': street, 'default_street2': street2, 'default_city': city, 'default_state_id': state_id, 'default_zip': zip, 'default_country_id': country_id, 'default_supplier': supplier, 'default_customer': customer, 'default_lang': lang}</field>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
22
product_disable_quick_create/__init__.py
Normal file
22
product_disable_quick_create/__init__.py
Normal file
@@ -0,0 +1,22 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Product Disable Quick Create module for OpenERP
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
45
product_disable_quick_create/__openerp__.py
Normal file
45
product_disable_quick_create/__openerp__.py
Normal file
@@ -0,0 +1,45 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Product Disable Quick Create module for OpenERP
|
||||
# Copyright (C) 2014 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
{
|
||||
'name': 'Product Disable Quick Create',
|
||||
'version': '0.1',
|
||||
'category': 'Products & Pricelists',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Disable quick create a many product-related objects',
|
||||
'description': """
|
||||
Product Disable Quick Create
|
||||
============================
|
||||
|
||||
Disable quick create on many product-related objects.
|
||||
|
||||
Please contact Alexis de Lattre from Akretion <alexis.delattre@akretion.com> for any help or question about this module.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['product', 'base_optional_quick_create'],
|
||||
'data': [
|
||||
'model_data.xml',
|
||||
],
|
||||
'active': False,
|
||||
}
|
||||
38
product_disable_quick_create/model_data.xml
Normal file
38
product_disable_quick_create/model_data.xml
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
Copyright (C) 2014 Akretion (http://www.akretion.com/)
|
||||
@author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
The licence is in the file __openerp__.py
|
||||
-->
|
||||
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<record id="product.model_product_product" model="ir.model">
|
||||
<field name="avoid_quick_create" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="product.model_product_template" model="ir.model">
|
||||
<field name="avoid_quick_create" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="product.model_product_uom" model="ir.model">
|
||||
<field name="avoid_quick_create" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="product.model_product_uom_categ" model="ir.model">
|
||||
<field name="avoid_quick_create" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="product.model_product_pricelist" model="ir.model">
|
||||
<field name="avoid_quick_create" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record id="product.model_product_packaging" model="ir.model">
|
||||
<field name="avoid_quick_create" eval="True"/>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user