Compare commits

...

89 Commits
18.0 ... 7.0

Author SHA1 Message Date
Alexis de Lattre
c1d0fd885d Code clean-up in purchase_auto_invoice_method 2018-04-24 16:55:30 +02:00
Alexis de Lattre
4ee0d18712 FIX hr_holidays_usability use float_compare 2017-06-09 13:09:37 +02:00
Alexis de Lattre
6f8ffc403a Add menu to force qty on leave request 2017-04-07 14:26:16 +02:00
Alexis de Lattre
c492904e2b Minor update 2016-10-13 17:06:48 +02:00
Alexis de Lattre
64e08b93de Add constraint 2016-05-18 15:08:51 +02:00
Alexis de Lattre
e3793989c0 Update to sync with new-report-intrastat 2016-05-12 18:46:44 +02:00
Alexis de Lattre
158648e604 Backport intrastat_product_type from 8 to 7 2016-05-12 17:38:04 +02:00
Alexis de Lattre
38dd25f471 Avoid a division by zero 2016-04-26 23:53:35 +02:00
Alexis de Lattre
81d97b2981 Add possibility to make a manual update of standard_price from BOM
Add script to automate the update of standard_price for phantom BOM
Add user_id on price.history
2016-04-13 22:41:08 +02:00
Alexis de Lattre
87ec05e5ef Inherit copy() 2016-03-23 21:57:58 +01:00
Alexis de Lattre
237c0e484a Small usability stuff 2016-03-22 17:57:56 +01:00
Alexis de Lattre
cc1efeafdb Add components cost and total cost on BOM
Add standard price in BOM lines
2016-03-22 17:57:13 +01:00
Alexis de Lattre
753333521f Add ability to put a key in ctx to disable generation of a price history line 2016-03-11 14:41:42 +01:00
Alexis de Lattre
e22b56c7a9 FIX computation for products partially produced
Disable raise when labor cost is null
2016-03-11 14:40:58 +01:00
Alexis de Lattre
a93a203f2d Add mrp.bom.labour.line, to be able to have several labor cost profile on a single BOM 2016-03-10 12:21:05 +01:00
Alexis de Lattre
698327c5a1 Add mrp_usability 2016-02-26 19:24:00 +01:00
Alexis de Lattre
4f566a8ff8 Add Extra cost on BOM
Split the method to write standard_price on product in 2: one to compute the unit price of the MO, another one to update the standard_price on the product
2016-02-26 19:22:45 +01:00
Alexis de Lattre
f80e8117fe Add module account_invoice_margin 2016-02-26 15:16:54 +01:00
Alexis de Lattre
0331fb1290 Add module product_usability 2016-02-26 10:21:46 +01:00
Alexis de Lattre
941366ee47 Add module mrp_average_cost 2016-02-26 10:20:56 +01:00
Alexis de Lattre
cb3942f501 Update description 2015-12-19 01:38:11 +01:00
Alexis de Lattre
c030d20c68 Add module delivery_carrier_zpl_label_print 2015-12-18 18:45:26 +01:00
Alexis de Lattre
84c6b03e09 Add module purchase_line_move_state 2015-12-17 19:56:14 +01:00
Alexis de Lattre
07a90ce45f Add module purchase_date_planned_update 2015-12-17 19:55:28 +01:00
Florian da Costa
7d5efb1c49 add possibility to search supplier code in stock.picking.in 2015-11-04 16:25:12 +01:00
Florian da Costa
fea48b5738 add french translation to product search supplier code 2015-10-30 13:58:10 +01:00
Florian da Costa
fe28781b9f add product_search_supplier_code 2015-10-30 11:52:22 +01:00
Alexis de Lattre
ca6bfa9227 Add readonly=True on related field 2015-06-29 16:23:53 +02:00
Alexis de Lattre
55589c52c2 Update translation 2015-06-19 19:02:07 +02:00
Alexis de Lattre
b2a259308d Rename fields and update translation 2015-06-19 18:56:27 +02:00
Alexis de Lattre
b2a0e44121 Add posted counters + update translation 2015-06-19 18:29:57 +02:00
Alexis de Lattre
1108f79664 FIX record rule 2015-06-19 17:56:29 +02:00
Alexis de Lattre
085aeb62c5 Update strings, POT file and FR translation 2015-06-12 09:41:17 +02:00
Alexis de Lattre
94c693a06f MAJ POT files 2015-06-12 00:20:13 +02:00
Alexis de Lattre
7a07d438e4 Introduce new wizard and counters 2015-06-12 00:06:36 +02:00
Alexis de Lattre
7831277c14 Add default value for mass allocation wizard 2015-06-11 14:47:57 +02:00
Alexis de Lattre
2dbf95cb97 Add mass allocation wizard
Add counter info on form view of hr.holidays
Fix an issue when checking counter
2015-06-11 12:43:43 +02:00
Alexis de Lattre
edcd3c7637 FIX an overlap issue when a user requests 2 half-days on the same day with different types 2015-06-11 09:47:26 +02:00
Alexis de Lattre
7d0f3976dd Add warning 2015-06-10 17:31:33 +02:00
Alexis de Lattre
10c8a2e681 hr_holidays_usability: various fixes + usability improvements 2015-06-10 14:44:18 +02:00
Alexis de Lattre
6702381665 Add module hr_holidays_usability 2015-05-22 18:06:41 +02:00
Alexis de Lattre
753d4b5d5d Better default options 2015-05-20 21:57:35 +02:00
Alexis de Lattre
810a7d795b Add module account_banking_payment_transfer_simple 2015-04-08 18:28:32 +02:00
Alexis de Lattre
1230dbb711 add module eradicate_quick_create 2015-04-08 15:29:16 +02:00
Alexis de Lattre
8756bc4b24 Adapt to changes in stock module 2015-04-08 11:32:17 +02:00
Alexis de Lattre
8973d4bf98 Add module account_invoice_del_attachment_cancel
Add .gitignore
2015-01-20 18:05:46 +01:00
Alexis de Lattre
7130581012 Add module partner_default_lang_parent 2015-01-19 13:01:32 +01:00
Alexis de Lattre
898b1e6d2e Backport module sale_stock_show_delivery_address to v7 2015-01-19 12:09:37 +01:00
Alexis de Lattre
a330ae1711 Small improvement 2014-12-12 16:55:45 +01:00
Alexis de Lattre
c6e8c79d45 Update comments 2014-12-12 12:31:00 +01:00
Alexis de Lattre
bdf4a7e15d Add module stock_tracking_ul 2014-11-15 00:06:14 +01:00
Alexis de Lattre
560beb826b Add currency in PO tree view. 2014-10-16 23:34:41 +02:00
Alexis de Lattre
80145000d8 Add currency_id in sale tree view 2014-10-16 23:12:48 +02:00
Alexis de Lattre
2ef4a5946c Add module account_invoice_overdue_filter 2014-10-15 10:43:57 +02:00
Alexis de Lattre
b7d902aa2d Order inventory: latest first 2014-10-14 17:26:31 +02:00
Alexis de Lattre
48a720f8dd Add module stock_inventory_usability 2014-10-14 12:55:02 +02:00
Alexis de Lattre
64ab60d350 Remove asterisk_click2dial_project_issue following update of the Asterisk connector 2014-08-30 00:07:34 +02:00
Alexis de Lattre
14bacaeba5 Add module base_partner_link_on_users. 2014-06-11 10:06:28 +02:00
Alexis de Lattre
fe08942e39 Move button. 2014-05-23 19:25:34 +02:00
Alexis de Lattre
bc4dd21316 Add € symbol. 2014-05-23 19:24:02 +02:00
Alexis de Lattre
0c5a496ba2 Add module l10n_fr_infogreffe_connector. 2014-05-23 17:43:06 +02:00
Alexis de Lattre
0a626f39ae Add module asterisk_click2dial_project_issue. 2014-05-23 09:09:07 +02:00
Alexis de Lattre
e9806b73c6 Add module base_partner_always_multi_contacts. 2014-05-15 23:20:03 +02:00
Alexis de Lattre
2b522f5702 Add base_title_on_partner module. 2014-05-15 11:29:34 +02:00
Alexis de Lattre
082c133128 Add link to issues on partner form. 2014-04-23 16:32:54 +02:00
Alexis de Lattre
c33ef19086 Add module stock_hide_journal_id. 2014-04-23 16:20:44 +02:00
Alexis de Lattre
6f07d50d90 Add translation files. 2014-04-18 18:18:17 +02:00
Alexis de Lattre
037e4d4214 Add module project_issue_extension. 2014-04-18 18:08:17 +02:00
Alexis de Lattre
53b1ff6ed4 Add module product_disable_quick_create. 2014-04-18 17:06:43 +02:00
Alexis de Lattre
2847f14dc7 Add module account_invoice_sale_link. 2014-04-10 18:26:19 +02:00
Alexis de Lattre
4fb4ed9ca4 Add module sale_markup_group_user to address this issue : https://bugs.launchpad.net/sale-financial/+bug/1305987 2014-04-10 18:23:11 +02:00
Alexis de Lattre
98bc291b54 Add module base_fix_display_address. 2014-04-10 12:52:03 +02:00
Alexis de Lattre
532b9cb53c Remove the module sale_auto_order_policy, which was in fact useless because the feature was native ! 2014-04-10 12:44:43 +02:00
Alexis de Lattre
5075221428 Remove code... it was native ! 2014-04-09 12:13:58 +02:00
Alexis de Lattre
3ee3edb8ce Add module stock_display_sale_id 2014-03-25 00:10:01 +01:00
Alexis de Lattre
f3085a163f Add module account_payment_hide_communication2. 2014-03-22 01:48:30 +01:00
Alexis de Lattre
7b04e578af Add ship_except to list of states. 2014-03-07 16:01:47 +01:00
Alexis de Lattre
9daeeca997 Better label on the second tab of PO. 2014-02-20 17:32:53 +01:00
Alexis de Lattre
0c5366420f Add purchase_usability_extension and sale_usability_extension. 2014-02-20 16:47:28 +01:00
Alexis de Lattre
f388d0d10f Add module account_payment_security. 2014-02-19 11:02:40 +01:00
Alexis de Lattre
e588686d5f Add module account_move_line_start_end_dates_xls. 2014-02-17 14:46:01 +01:00
Alexis de Lattre
2e6e1c07bf Add module stock_display_destination_move. 2014-01-17 17:16:56 +01:00
Alexis de Lattre
a98dbc0b1c Cosmetic. 2014-01-08 23:56:40 +01:00
Alexis de Lattre
529b585d07 Add module sale_auto_order_policy. 2014-01-08 23:30:47 +01:00
Alexis de Lattre
46d177fb9f Add sale_fiscal_position_update_button. 2014-01-08 23:29:59 +01:00
Alexis de Lattre
24abaec406 Add module purchase_auto_invoice_method. 2013-12-16 18:50:27 +01:00
Alexis de Lattre
673afbac0f FIX module description. 2013-12-12 11:16:02 +01:00
Alexis de Lattre
5dc05f3c81 Add module stock_invoice_try_again 2013-12-09 18:12:45 +01:00
Alexis de Lattre
dce0604e7d Add module stock_invoice_service_from_delivery 2013-12-09 18:12:38 +01:00
180 changed files with 9031 additions and 1 deletions

56
.gitignore vendored Normal file
View 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

View File

@@ -0,0 +1 @@
from . import model

View 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,
}

View File

@@ -0,0 +1,4 @@
from . import account_payment
from . import payment_line
from . import payment_mode
from . import account_move_line

View File

@@ -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

View 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',
# }

View 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)

View File

@@ -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',
}

View File

@@ -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>

View File

@@ -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>

View 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

View 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,
}

View 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

View File

@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import account_invoice

View 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,
}

View 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),
}),
}

View 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>

View 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/>.
#
##############################################################################

View 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,
}

View 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', '&lt;', current_date)]"/>
</filter>
</field>
</record>
</data>
</openerp>

View File

@@ -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.
""",

View 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

View 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,
}

View 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."),
}

View 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

View 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,
}

View 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

View 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/>.
#
##############################################################################

View 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,
}

View 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>

View 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/>.
#
##############################################################################

View 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,
}

View 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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 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
3 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
4 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
5 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

View 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>

View 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

View 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,
}

View 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

View 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,
}

View 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>

View 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/>.
#
##############################################################################

View 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,
}

View 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>

View 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/>.
#
##############################################################################

View 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,
}

View 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>

View File

@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import stock

View 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,
}

View 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)

View 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>

View 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>

View 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

View 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'],
}

View 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,
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

View 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>

View 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

View 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,
}

View 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>

View 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'),
}

View 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>

View 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>

View 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"

View 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 ""

View File

@@ -0,0 +1,2 @@
# -*- encoding: utf-8 -*-
from . import hr_holidays_employee_counter

View 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
)
""")

View File

@@ -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>

View 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>

View 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>

View 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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_hr_holidays_employee_counter Full access on hr.holidays.employee.counter model_hr_holidays_employee_counter base.group_user 1 1 1 1

View File

@@ -0,0 +1,3 @@
# -*- encoding: utf-8 -*-
from . import hr_holidays_mass_allocation
from . import hr_holidays_post

View 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

View File

@@ -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>

View 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

View 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>

View File

@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import intrastat_product_type

View 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,
}

View 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

View 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

View 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>

View 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

View 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,
}

View 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

View 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>

View File

@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import mrp

View 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
View 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)

View 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>

View 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>

View 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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 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
3 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
4 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
5 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
6 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
7 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
8 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
9 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

View 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>

View File

@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import mrp

View 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
View 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'

View 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>

View 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/>.
#
##############################################################################

View 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,
}

View 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>

View 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/>.
#
##############################################################################

View 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,
}

View 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