Compare commits

..

2 Commits

Author SHA1 Message Date
David Beal
0ba12b8812 tmp 2016-12-20 16:31:55 +01:00
David Beal
c867b1d76f ADD module web_sheet_width_custom 2016-12-02 09:00:53 +01:00
132 changed files with 306 additions and 3158 deletions

View File

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

View File

@@ -1,29 +0,0 @@
# -*- coding: utf-8 -*-
# © 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
'name': 'Account Analytic Analysis Usability',
'version': '8.0.1.0.0',
'category': 'Accounting & Finance',
'license': 'AGPL-3',
'summary': 'Usability improvements on Account Analytic Analysis',
'description': """
Account Analytic Analysis Usability
===================================
Usability improvements include:
* add next invoice date in tree view of contrats (and add a group by)
This module has been written by Alexis de Lattre from Akretion
<alexis.delattre@akretion.com>.
""",
'author': 'Akretion',
'website': 'http://www.akretion.com',
'depends': ['account_analytic_analysis'],
'data': [
'analytic_view.xml',
],
'installable': True,
}

View File

@@ -1,14 +0,0 @@
# -*- coding: utf-8 -*-
# © 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields
class AccountAnalyticAccount(models.Model):
_inherit = "account.analytic.account"
recurring_next_date = fields.Date(track_visibility='onchange')
recurring_rule_type = fields.Selection(track_visibility='onchange')
recurring_interval = fields.Integer(track_visibility='onchange')
recurring_invoices = fields.Boolean(track_visibility='onchange')

View File

@@ -1,40 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
© 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<openerp>
<data>
<record id="view_account_analytic_account_tree_c2c_3" model="ir.ui.view">
<field name="name">usability.analytic_analysis.account.analytic.account.tree.contract</field>
<field name="model">account.analytic.account</field>
<field name="inherit_id" ref="account_analytic_analysis.view_account_analytic_account_tree_c2c_3"/>
<field name="groups_id" eval="[(4, ref('account.group_account_invoice'))]"/>
<field name="arch" type="xml">
<field name="date" position="after">
<field name="recurring_rule_type"/>
<field name="recurring_next_date"/>
</field>
</field>
</record>
<record id="view_account_analytic_account_overdue_search" model="ir.ui.view">
<field name="name">usability.analytic_analysis.account.analytic.account.search</field>
<field name="model">account.analytic.account</field>
<field name="inherit_id" ref="account_analytic_analysis.view_account_analytic_account_overdue_search"/>
<field name="arch" type="xml">
<filter context="{'group_by' : 'pricelist_id'}" position="after">
<filter name="recurring_rule_type_groupby" string="Invoicing Frequency" context="{'group_by': 'recurring_rule_type'}"/>
<filter name="recurring_next_date_groupby" string="Next Invoice Date" context="{'group_by': 'recurring_next_date'}"/>
</filter>
<filter name="cancelled" position="after">
<separator/>
<filter name="recurring_invoices" string="Recurring Invoicing" domain="[('recurring_invoices', '=', True)]"/>
</filter>
</field>
</record>
</data>
</openerp>

View File

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

View File

@@ -1,34 +0,0 @@
# -*- coding: utf-8 -*-
# © 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
'name': 'Account Invoice Update Wizard',
'version': '8.0.1.0.0',
'category': 'Accounting & Finance',
'license': 'AGPL-3',
'summary': 'Wizard to update non-legal fields of an open/paid invoice',
'description': """
Account Invoice Update Wizard
=============================
This module adds a button *Update Invoice* on Customer and Supplier invoices in Open or Paid state. This button starts a wizard which allows the user to update non-legal fields of the invoice:
* Source Document
* Reference/Description
* Payment terms (update allowed only to a payment term with same number of terms of the same amount and on invoices without any payment)
* Bank Account
* Salesman
* Notes
* Description of invoice lines
""",
'author': 'Akretion',
'website': 'http://www.akretion.com',
'depends': ['account'],
'data': [
'wizard/account_invoice_update_view.xml',
'views/account_invoice.xml',
],
'installable': True,
}

View File

@@ -1,31 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
© 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<openerp>
<data>
<record id="invoice_supplier_form" model="ir.ui.view">
<field name="model">account.invoice</field>
<field name="inherit_id" ref="account.invoice_supplier_form"/>
<field name="arch" type="xml">
<button name="invoice_cancel" position="before">
<button name="%(account_invoice_update_action)d" type="action" string="Update Invoice" states="open,paid" groups="account.group_account_invoice"/>
</button>
</field>
</record>
<record id="invoice_form" model="ir.ui.view">
<field name="model">account.invoice</field>
<field name="inherit_id" ref="account.invoice_form"/>
<field name="arch" type="xml">
<button name="invoice_cancel" position="before">
<button name="%(account_invoice_update_action)d" type="action" string="Update Invoice" states="open,paid" groups="account.group_account_invoice"/>
</button>
</field>
</record>
</data>
</openerp>

View File

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

View File

@@ -1,206 +0,0 @@
# -*- coding: utf-8 -*-
# © 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields, api, _
from openerp.exceptions import Warning as UserError
import openerp.addons.decimal_precision as dp
class AccountInvoiceUpdate(models.TransientModel):
_name = 'account.invoice.update'
_description = 'Wizard to update non-legal fields of invoice'
invoice_id = fields.Many2one(
'account.invoice', string='Invoice', required=True,
readonly=True)
type = fields.Selection(related='invoice_id.type', readonly=True)
company_id = fields.Many2one(
related='invoice_id.company_id', readonly=True)
commercial_partner_id = fields.Many2one(
related='invoice_id.commercial_partner_id', readonly=True)
user_id = fields.Many2one('res.users', string='Salesperson')
# I use the same field name as the original invoice field name
# even if it the name is "bad"
# Updating payment_term will not work if you use
# the OCA module account_constraints (you will just get an error)
payment_term = fields.Many2one(
'account.payment.term', string='Payment Terms')
reference = fields.Char(string='Invoice Reference')
name = fields.Char(string='Reference/Description')
origin = fields.Char(string='Source Document')
comment = fields.Text('Additional Information')
partner_bank_id = fields.Many2one(
'res.partner.bank', string='Bank Account')
line_ids = fields.One2many(
'account.invoice.line.update', 'parent_id', string='Invoice Lines')
@api.model
def _simple_fields2update(self):
'''List boolean, date, datetime, char, text fields'''
return ['reference', 'name', 'origin', 'comment']
@api.model
def _m2o_fields2update(self):
return ['payment_term', 'user_id', 'partner_bank_id']
@api.model
def _prepare_default_get(self, invoice):
res = {'invoice_id': invoice.id, 'line_ids': []}
for sfield in self._simple_fields2update():
res[sfield] = invoice[sfield]
for m2ofield in self._m2o_fields2update():
res[m2ofield] = invoice[m2ofield].id or False
for line in invoice.invoice_line:
res['line_ids'].append({
'invoice_line_id': line.id,
'name': line.name,
'quantity': line.quantity,
'price_subtotal': line.price_subtotal,
})
return res
@api.model
def default_get(self, fields_list):
res = super(AccountInvoiceUpdate, self).default_get(fields_list)
assert self._context.get('active_model') == 'account.invoice',\
'active_model should be account.invoice'
inv = self.env['account.invoice'].browse(self._context['active_id'])
res = self._prepare_default_get(inv)
return res
@api.onchange('type')
def type_on_change(self):
res = {'domain': {}}
if self.type in ('out_invoice', 'out_refund'):
res['domain']['partner_bank_id'] =\
"[('partner_id.ref_companies', 'in', [company_id])]"
else:
res['domain']['partner_bank_id'] =\
"[('partner_id', '=', commercial_partner_id)]"
return res
@api.multi
def _prepare_invoice(self):
vals = {}
inv = self.invoice_id
for sfield in self._simple_fields2update():
if self[sfield] != inv[sfield]:
vals[sfield] = self[sfield]
for m2ofield in self._m2o_fields2update():
if self[m2ofield] != inv[m2ofield]:
vals[m2ofield] = self[m2ofield].id or False
if 'payment_term' in vals:
pterm_list = self.payment_term.compute(
value=1, date_ref=inv.date_invoice)[0]
if pterm_list:
vals['date_due'] = max(line[0] for line in pterm_list)
return vals
@api.model
def _prepare_invoice_line(self, line):
vals = {}
if line.name != line.invoice_line_id.name:
vals['name'] = line.name
return vals
@api.multi
def _prepare_move(self):
mvals = {}
inv = self.invoice_id
ini_ref = inv.move_id.ref
ref = inv.reference or inv.name
if ini_ref != ref:
mvals['ref'] = ref
return mvals
@api.multi
def _update_payment_term_move(self):
self.ensure_one()
inv = self.invoice_id
if (
self.payment_term and
self.payment_term != inv.payment_term and
inv.move_id and
inv.move_id.period_id.state == 'draft'):
# I don't update pay term when the invoice is partially (or fully)
# paid because if you have a payment term with several lines
# of the same amount, you would also have to take into account
# the reconcile marks to put the new maturity date on the right
# lines
if inv.payment_ids:
raise UserError(_(
"This wizard doesn't support the update of payment "
"terms on an invoice which is partially or fully "
"paid."))
prec = self.env['decimal.precision'].precision_get('Account')
term_res = self.payment_term.compute(
inv.amount_total, inv.date_invoice)[0]
new_pterm = {} # key = int(amount * 100), value = [date1, date2]
for entry in term_res:
amount = int(entry[1] * 10 * prec)
if amount in new_pterm:
new_pterm[amount].append(entry[0])
else:
new_pterm[amount] = [entry[0]]
mlines = {} # key = int(amount * 100), value : [line1, line2]
for line in inv.move_id.line_id:
if line.account_id == inv.account_id:
amount = int(abs(line.credit - line.debit) * 10 * prec)
if amount in mlines:
mlines[amount].append(line)
else:
mlines[amount] = [line]
for iamount, lines in mlines.iteritems():
if len(lines) != len(new_pterm.get(iamount, [])):
raise UserError(_(
"The original payment term '%s' doesn't have the "
"same terms (number of terms and/or amount) as the "
"new payment term '%s'. You can only switch to a "
"payment term that has the same number of terms "
"with the same amount.") % (
inv.payment_term.name, self.payment_term.name))
for line in lines:
line.date_maturity = new_pterm[iamount].pop()
@api.multi
def run(self):
self.ensure_one()
inv = self.invoice_id
updated = False
# re-write date_maturity on move line
self._update_payment_term_move()
ivals = self._prepare_invoice()
if ivals:
updated = True
inv.write(ivals)
for line in self.line_ids:
ilvals = self._prepare_invoice_line(line)
if ilvals:
updated = True
line.invoice_line_id.write(ilvals)
if inv.move_id and inv.move_id.period_id.state == 'draft':
mvals = self._prepare_move()
if mvals:
inv.move_id.write(mvals)
if updated:
inv.message_post(_(
'Non-legal fields of invoice updated via the Invoice Update '
'wizard.'))
return True
class AccountInvoiceLineUpdate(models.TransientModel):
_name = 'account.invoice.line.update'
_description = 'Update non-legal fields of invoice lines'
parent_id = fields.Many2one(
'account.invoice.update', string='Wizard', ondelete='cascade')
invoice_line_id = fields.Many2one(
'account.invoice.line', string='Invoice Line', readonly=True)
name = fields.Text(string='Description', required=True)
quantity = fields.Float(
string='Quantity', digits=dp.get_precision('Product Unit of Measure'),
readonly=True)
price_subtotal = fields.Float(
string='Amount', readonly=True, digits=dp.get_precision('Account'))

View File

@@ -1,54 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
© 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<openerp>
<data>
<record id="account_invoice_update_form" model="ir.ui.view">
<field name="model">account.invoice.update</field>
<field name="arch" type="xml">
<form string="Update Invoice Wizard">
<group name="main">
<field name="invoice_id" invisible="1"/>
<field name="type" invisible="1"/>
<field name="company_id" invisible="1"/>
<field name="commercial_partner_id" invisible="1"/>
<field name="reference" attrs="{'invisible': [('type', 'not in', ('in_invoice', 'in_refund'))]}"/>
<field name="origin"/>
<field name="name"/>
<field name="payment_term" widget="selection"/>
<field name="partner_bank_id"/>
<field name="user_id"/>
<field name="comment"/>
</group>
<group name="lines">
<field name="line_ids" nolabel="1">
<tree editable="bottom">
<field name="invoice_line_id" invisible="1"/>
<field name="name"/>
<field name="quantity"/>
<field name="price_subtotal"/>
</tree>
</field>
</group>
<footer>
<button name="run" type="object" class="oe_highlight" string="Update"/>
or
<button special="cancel" string="Cancel" class="oe_link"/>
</footer>
</form>
</field>
</record>
<record id="account_invoice_update_action" model="ir.actions.act_window">
<field name="name">Invoice Update Wizard</field>
<field name="res_model">account.invoice.update</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</data>
</openerp>

View File

@@ -53,10 +53,7 @@ class AccountMoveLineFilterWizard(models.TransientModel):
self.ensure_one() self.ensure_one()
action = self.env['ir.actions.act_window'].for_xml_id( action = self.env['ir.actions.act_window'].for_xml_id(
'account', 'action_account_moves_all_a') 'account', 'action_account_moves_all_a')
action['context'] = { action['context'] = {'search_default_account_id': [self.account_id.id]}
'search_default_account_id': [self.account_id.id],
'journal_show_code_only': True,
}
if self.partner_id: if self.partner_id:
action['context']['search_default_partner_id'] =\ action['context']['search_default_partner_id'] =\
[self.partner_id.id] [self.partner_id.id]

View File

@@ -21,16 +21,9 @@
############################################################################## ##############################################################################
import xlwt import xlwt
import logging
from openerp import models, api from openerp import models, api
from openerp.addons.report_xls.utils import _render
_logger = logging.getLogger(__name__) from openerp.addons.report_xls.report_xls import report_xls
try:
from openerp.addons.report_xls.utils import _render
from openerp.addons.report_xls.report_xls import report_xls
except (ImportError, IOError) as err:
_logger.debug(err)
class AccountMoveLine(models.Model): class AccountMoveLine(models.Model):

View File

@@ -1,4 +1,3 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
from . import account from . import account
from . import wizard

View File

@@ -49,9 +49,6 @@ This module has been written by Alexis de Lattre from Akretion <alexis.delattre@
'website': 'http://www.akretion.com', 'website': 'http://www.akretion.com',
'depends': ['account'], 'depends': ['account'],
'conflicts': ['account_invoice_overdue_filter'], 'conflicts': ['account_invoice_overdue_filter'],
'data': [ 'data': ['account_view.xml'],
'account_view.xml',
'wizard/account_invoice_mark_sent_view.xml',
],
'installable': True, 'installable': True,
} }

View File

@@ -23,13 +23,10 @@
from openerp import models, fields, api, _ from openerp import models, fields, api, _
from openerp.tools import float_compare from openerp.tools import float_compare
from openerp.exceptions import Warning as UserError from openerp.exceptions import Warning as UserError
import logging
logger = logging.getLogger(__name__)
class AccountInvoice(models.Model): class AccountInvoice(models.Model):
_inherit = 'account.invoice' _inherit = 'account.invoice'
_order = "date_invoice desc, number desc, id desc"
origin = fields.Char(track_visibility='onchange') origin = fields.Char(track_visibility='onchange')
supplier_invoice_number = fields.Char(track_visibility='onchange') supplier_invoice_number = fields.Char(track_visibility='onchange')
@@ -44,41 +41,9 @@ class AccountInvoice(models.Model):
journal_id = fields.Many2one(track_visibility='onchange') journal_id = fields.Many2one(track_visibility='onchange')
partner_bank_id = fields.Many2one(track_visibility='onchange') partner_bank_id = fields.Many2one(track_visibility='onchange')
fiscal_position = fields.Many2one(track_visibility='onchange') fiscal_position = fields.Many2one(track_visibility='onchange')
# has_attachment is useful for those who use attachment to archive
# supplier invoices. It allows them to find supplier invoices
# that don't have any attachment
has_attachment = fields.Boolean(
compute='_compute_has_attachment',
search='_search_has_attachment', readonly=True)
@api.multi @api.multi
def _compute_has_attachment(self): def onchange_payment_term_date_invoice(self, payment_term_id, date_invoice):
iao = self.env['ir.attachment']
for inv in self:
if iao.search([
('res_model', '=', 'account.invoice'),
('res_id', '=', inv.id),
('type', '=', 'binary'),
('company_id', '=', inv.company_id.id)], limit=1):
inv.has_attachment = True
else:
inv.has_attachment = False
def _search_has_attachment(self, operator, value):
att_inv_ids = {}
if operator == '=':
search_res = self.env['ir.attachment'].search_read([
('res_model', '=', 'account.invoice'),
('type', '=', 'binary'),
('res_id', '!=', False)], ['res_id'])
for att in search_res:
att_inv_ids[att['res_id']] = True
res = [('id', value and 'in' or 'not in', att_inv_ids.keys())]
return res
@api.multi
def onchange_payment_term_date_invoice(
self, payment_term_id, date_invoice):
res = super(AccountInvoice, self).onchange_payment_term_date_invoice( res = super(AccountInvoice, self).onchange_payment_term_date_invoice(
payment_term_id, date_invoice) payment_term_id, date_invoice)
if res and isinstance(res, dict) and 'value' in res: if res and isinstance(res, dict) and 'value' in res:
@@ -89,8 +54,8 @@ class AccountInvoice(models.Model):
# generated from customer invoices linked to the partners' account because: # generated from customer invoices linked to the partners' account because:
# 1) the label of an account move line is an important field, we can't # 1) the label of an account move line is an important field, we can't
# write a rubbish '/' in it ! # write a rubbish '/' in it !
# 2) the 'name' field of the account.move.line is used in the overdue # 2) the 'name' field of the account.move.line is used in the overdue letter,
# letter and '/' is not meaningful for our customer ! # and '/' is not meaningful for our customer !
@api.multi @api.multi
def action_number(self): def action_number(self):
res = super(AccountInvoice, self).action_number() res = super(AccountInvoice, self).action_number()
@@ -104,28 +69,6 @@ class AccountInvoice(models.Model):
return res return res
class AccountInvoiceLine(models.Model):
_inherit = 'account.invoice.line'
# In the 'account' module, we have related stored field for:
# company_id, partner_id
currency_id = fields.Many2one(
related='invoice_id.currency_id', readonly=True, store=True)
invoice_type = fields.Selection(
related='invoice_id.type', store=True, readonly=True)
date_invoice = fields.Date(
related='invoice_id.date_invoice', store=True, readonly=True)
commercial_partner_id = fields.Many2one(
related='invoice_id.partner_id.commercial_partner_id',
store=True, readonly=True)
state = fields.Selection(
related='invoice_id.state', store=True, readonly=True,
string='Invoice State')
invoice_number = fields.Char(
related='invoice_id.move_id.name', store=True, readonly=True,
string='Invoice Number')
class AccountFiscalYear(models.Model): class AccountFiscalYear(models.Model):
_inherit = 'account.fiscalyear' _inherit = 'account.fiscalyear'
@@ -162,51 +105,10 @@ class AccountAccount(models.Model):
else: else:
return super(AccountAccount, self).name_get() return super(AccountAccount, self).name_get()
def _check_account_type(self, cr, uid, ids, context=None):
'''Disable this native python constraint, because we want to be able
to configure payable/receivable accounts with an account type
with close_method == 'balance' in order to have opening entries with
fewer lines. It is not a problem because we always use
account_financial_report_webkit which doesn't take the detailed
opening entries into account.'''
return True
_constraints = [
# The method name must be exactly the same as the native
# method, in order to override it
(_check_account_type, 'No error message', ['user_type', 'type']),
]
@api.model
def check_account_hierarchy(self):
'''designed to be called by a script'''
accounts = self.env['account.account'].search([])
parent_accounts = self
for account in accounts:
if account.parent_id and account.parent_id not in parent_accounts:
parent_accounts += account.parent_id
err_msg = []
view_user_type = self.env.ref('account.data_account_type_view')
for pacc in parent_accounts:
if pacc.type != 'view':
err_msg.append(_(
'Parent account %s should have type=view '
'(current type=%s)') % (pacc.code, pacc.type))
if pacc.user_type != view_user_type:
err_msg.append(_(
'Parent account %s should have user_type=view (current '
'(user_type=%s)') % (pacc.code, pacc.user_type.name))
if err_msg:
raise UserError('\n'.join(err_msg))
class AccountAnalyticAccount(models.Model): class AccountAnalyticAccount(models.Model):
_inherit = 'account.analytic.account' _inherit = 'account.analytic.account'
invoice_line_ids = fields.One2many(
'account.invoice.line', 'account_analytic_id', 'Invoice Lines',
readonly=True)
@api.multi @api.multi
def name_get(self): def name_get(self):
if self._context.get('analytic_account_show_code_only'): if self._context.get('analytic_account_show_code_only'):
@@ -223,55 +125,11 @@ class AccountAnalyticAccount(models.Model):
class AccountMove(models.Model): class AccountMove(models.Model):
_inherit = 'account.move' _inherit = 'account.move'
# When ref is too long, the PDF general ledger report becomes
# unreadable
ref = fields.Char(size=32)
# If you want to migrate existing data :
# update account_move set ref=left(ref,32) where ref is not null;
# update account_move_line set ref=left(ref,32) where ref is not null;
# Allow to duplicate an account.move that belongs to a closed period
period_id = fields.Many2one(copy=False)
date = fields.Date(copy=False)
@api.onchange('date') @api.onchange('date')
def date_onchange(self): def date_onchange(self):
if self.date: if self.date:
self.period_id = self.env['account.period'].find(self.date) self.period_id = self.env['account.period'].find(self.date)
@api.model
def delete_move_no_lines(self):
'''designed to be called by a script'''
moves_no_lines = self.search([('line_id', '=', False)])
inv_moves_sr = self.env['account.invoice'].search_read(
[('move_id', '!=', False)], ['move_id'])
move2inv = {} # key=move_id, value=invoice_id
invoice_move_no_line = {} # key=ID, value=number
deleted_move_ids = []
for inv_move_sr in inv_moves_sr:
move2inv[inv_move_sr['move_id'][0]] = inv_move_sr['id']
for move in moves_no_lines:
for l in move.line_id:
raise UserError(_('Move %d has a line !') % move.id)
if move.id not in move2inv:
if move.state == 'posted':
move.state = 'draft'
deleted_move_ids.append(move.id)
move.unlink()
else:
invoice_move_no_line[move2inv[move.id]] = move.name
if deleted_move_ids:
logger.info(
'Account move IDs %s have been deleted because they '
'had 0 lines', deleted_move_ids)
else:
logger.info('0 moves without lines found')
if invoice_move_no_line:
for inv_id, inv_number in invoice_move_no_line.iteritems():
logger.info(
'Invoice ID %d number %s has a move with 0 lines',
inv_id, inv_number)
class AccountMoveLine(models.Model): class AccountMoveLine(models.Model):
_inherit = 'account.move.line' _inherit = 'account.move.line'
@@ -305,28 +163,6 @@ class AccountMoveLine(models.Model):
else: else:
self.credit = amount_company_currency self.credit = amount_company_currency
analytic_account_id = fields.Many2one(
domain=[('type', 'not in', ('view', 'template'))])
class AccountBankStatement(models.Model):
_inherit = 'account.bank.statement'
start_date = fields.Date(
compute='_compute_dates', string='Start Date', readonly=True,
store=True)
end_date = fields.Date(
compute='_compute_dates', string='End Date', readonly=True,
store=True)
@api.multi
@api.depends('line_ids.date')
def _compute_dates(self):
for st in self:
dates = [line.date for line in st.line_ids]
st.start_date = dates and min(dates) or False
st.end_date = dates and max(dates) or False
class AccountBankStatementLine(models.Model): class AccountBankStatementLine(models.Model):
_inherit = 'account.bank.statement.line' _inherit = 'account.bank.statement.line'
@@ -374,7 +210,6 @@ class AccountBankStatementLine(models.Model):
raise UserError(_( raise UserError(_(
'No journal entry linked to this bank statement line.')) 'No journal entry linked to this bank statement line.'))
class ResPartner(models.Model): class ResPartner(models.Model):
_inherit = 'res.partner' _inherit = 'res.partner'

View File

@@ -38,11 +38,6 @@
<field name="period_id" position="attributes"> <field name="period_id" position="attributes">
<attribute name="groups"></attribute> <attribute name="groups"></attribute>
</field> </field>
<!-- move sent field and make it visible -->
<field name="sent" position="replace"/>
<field name="move_id" position="after">
<field name="sent"/>
</field>
</field> </field>
</record> </record>
@@ -66,123 +61,6 @@
<filter name="unpaid" position="after"> <filter name="unpaid" position="after">
<filter name="overdue" string="Overdue" <filter name="overdue" string="Overdue"
domain="[('state', '=', 'open'), ('date_due', '&lt;', current_date)]"/> domain="[('state', '=', 'open'), ('date_due', '&lt;', current_date)]"/>
<separator/>
<filter name="to_send" string="To Send" domain="[('sent', '=', False), ('state', 'in', ('open', 'paid'))]"/>
<filter name="sent" string="Sent" domain="[('sent', '=', True)]"/>
<separator/>
<filter name="no_attachment" string="Missing Attachment" domain="[('has_attachment', '=', False)]"/>
</filter>
</field>
</record>
<!-- Having a menu entry on invoice lines is often very usefull for odoo user:
they can search in their lines, etc...
So I enhance the generic views and add actions, but I don't add menu entries here ;
the creation of the corresponding menu entry should be done in the customer-specific
module -->
<record id="view_invoice_line_tree" model="ir.ui.view">
<field name="name">account_usability.invoice_line_tree</field>
<field name="model">account.invoice.line</field>
<field name="inherit_id" ref="account.view_invoice_line_tree"/>
<field name="arch" type="xml">
<field name="name" position="before">
<field name="partner_id" invisible="not context.get('show_invoice_fields')"/>
<field name="date_invoice" invisible="not context.get('show_invoice_fields')"/>
<field name="invoice_number" invisible="not context.get('show_invoice_fields')"/>
</field>
<field name="price_subtotal" position="after">
<field name="currency_id"/>
<field name="state" invisible="not context.get('show_invoice_fields')"/>
<field name="invoice_type" invisible="1"/>
</field>
<xpath expr="/tree" position="attributes">
<attribute name="edit">0</attribute>
<attribute name="create">0</attribute>
</xpath>
</field>
</record>
<record id="account_invoice_line_search" model="ir.ui.view">
<field name="name">account_usability.invoice_line_search</field>
<field name="model">account.invoice.line</field>
<field name="arch" type="xml">
<search string="Search Invoice Lines">
<field name="partner_id"/>
<field name="product_id"/>
<field name="account_id"/>
<field name="invoice_number"/>
<field name="name"/>
<filter name="out_invoice" string="Customer Invoices"
domain="[('invoice_type', '=', 'out_invoice')]"/>
<filter name="out_refund" string="Customer Refunds"
domain="[('invoice_type', '=', 'out_refund')]"/>
<filter name="in_invoice" string="Supplier Invoices"
domain="[('invoice_type', '=', 'in_invoice')]"/>
<filter name="in_refund" string="Supplier Refunds"
domain="[('invoice_type', '=', 'in_refund')]"/>
<separator/>
<filter name="draft" string="Draft" domain="[('state', '=', 'draft')]"/>
<filter name="unpaid" string="Not Paid" domain="[('state', '=', 'open')]"/>
<filter name="paid" string="Paid" domain="[('state', '=', 'paid')]"/>
<group string="Group By" name="groupby">
<filter name="partner_groupby" string="Partner"
context="{'group_by': 'partner_id'}"/>
<filter name="commercial_partner_group_by" string="Commercial Partner"
context="{'group_by': 'commercial_partner_id'}"/>
<filter name="date_groupby" string="Invoice Date"
context="{'group_by': 'date_invoice'}"/>
<filter name="product_groupby" string="Product"
context="{'group_by': 'product_id'}"/>
<filter name="account_groupby" string="Account"
context="{'group_by': 'account_id'}"/>
</group>
</search>
</field>
</record>
<record id="out_invoice_line_action" model="ir.actions.act_window">
<field name="name">Customer Invoice Lines</field>
<field name="res_model">account.invoice.line</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('invoice_type', '=', 'out_invoice')]</field>
<field name="context">{'show_invoice_fields': True}</field>
</record>
<record id="out_refund_line_action" model="ir.actions.act_window">
<field name="name">Customer Refund Lines</field>
<field name="res_model">account.invoice.line</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('invoice_type', '=', 'out_refund')]</field>
<field name="context">{'show_invoice_fields': True}</field>
</record>
<record id="in_invoice_line_action" model="ir.actions.act_window">
<field name="name">Supplier Invoice Lines</field>
<field name="res_model">account.invoice.line</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('invoice_type', '=', 'in_invoice')]</field>
<field name="context">{'show_invoice_fields': True}</field>
</record>
<record id="in_refund_line_action" model="ir.actions.act_window">
<field name="name">Supplier Refund Lines</field>
<field name="res_model">account.invoice.line</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('invoice_type', '=', 'in_refund')]</field>
<field name="context">{'show_invoice_fields': True}</field>
</record>
<record id="view_account_invoice_report_search" model="ir.ui.view">
<field name="name">usability.account.invoice.report.search</field>
<field name="model">account.invoice.report</field>
<field name="inherit_id" ref="account.view_account_invoice_report_search"/>
<field name="arch" type="xml">
<field name="categ_id" position="after">
<field name="product_id"/>
</field>
<filter name="category_product" position="after">
<filter string="Product" name="product_group_by" context="{'group_by': 'product_id'}"/>
</filter> </filter>
</field> </field>
</record> </record>
@@ -190,24 +68,10 @@ module -->
<!-- model account.move.line / Journal Items --> <!-- model account.move.line / Journal Items -->
<record id="account.action_account_moves_all_a" model="ir.actions.act_window"> <record id="account.action_account_moves_all_a" model="ir.actions.act_window">
<field name="limit">200</field> <field name="limit">200</field>
<!-- add graph -->
<field name="view_mode">tree_account_move_line_quickadd,form,graph</field>
<!-- Win space, because there are already many columns --> <!-- Win space, because there are already many columns -->
<field name="context">{'journal_show_code_only': True}</field> <field name="context">{'journal_show_code_only': True}</field>
</record> </record>
<record id="account_move_line_graph" model="ir.ui.view">
<field name="name">usability.account.move.line.graph</field>
<field name="model">account.move.line</field>
<field name="inherit_id" ref="account.account_move_line_graph"/>
<field name="arch" type="xml">
<graph position="attributes">
<!-- pivot by default instead of bar -->
<attribute name="type">pivot</attribute>
</graph>
</field>
</record>
<!-- model account.move / Journal Entries --> <!-- model account.move / Journal Entries -->
<record id="account.action_move_journal_line" model="ir.actions.act_window"> <record id="account.action_move_journal_line" model="ir.actions.act_window">
<field name="limit">200</field> <field name="limit">200</field>
@@ -237,7 +101,6 @@ module -->
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="partner_id" position="after"> <field name="partner_id" position="after">
<field name="reconcile_ref" /> <field name="reconcile_ref" />
<field name="debit" filter_domain="['|', ('debit', '=', self), ('credit', '=', self)]" string="Debit or Credit"/>
</field> </field>
<filter name="unreconciled" position="before"> <filter name="unreconciled" position="before">
<filter name="reconciled" string="Fully Reconciled" domain="[('reconcile_id', '!=', False)]"/> <filter name="reconciled" string="Fully Reconciled" domain="[('reconcile_id', '!=', False)]"/>
@@ -265,7 +128,6 @@ module -->
<field name="name">account_usability.account_move_line_tree</field> <field name="name">account_usability.account_move_line_tree</field>
<field name="model">account.move.line</field> <field name="model">account.move.line</field>
<field name="inherit_id" ref="account.view_move_line_tree"/> <field name="inherit_id" ref="account.view_move_line_tree"/>
<field name="priority">1</field> <!-- to be compatible with account_analytic_plans which removes the field analytic_account_id and has a priority of 2 -->
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="analytic_account_id" position="attributes"> <field name="analytic_account_id" position="attributes">
<attribute name="invisible"></attribute> <attribute name="invisible"></attribute>
@@ -317,10 +179,9 @@ module -->
</button> </button>
</button> </button>
<button name="%(account.action_account_moves_all_tree)d" position="attributes"> <button name="%(account.action_account_moves_all_tree)d" position="attributes">
<attribute name="invisible">True</attribute> <attribute name="type">object</attribute>
</button> <attribute name="name">show_receivable_account</attribute>
<button name="%(account.action_account_moves_all_tree)d" position="after"> <attribute name="attrs">{'invisible': [('customer', '=', False)]}</attribute>
<button type="object" class="oe_stat_button" name="show_receivable_account" icon="fa-list" attrs="{'invisible': [('customer', '=', False)]}"/>
</button> </button>
<field name="journal_item_count" position="attributes"> <field name="journal_item_count" position="attributes">
<attribute name="string">Receivable Account</attribute> <attribute name="string">Receivable Account</attribute>
@@ -328,12 +189,6 @@ module -->
</field> </field>
</record> </record>
<!-- When you click on the "Contract" button of partner form view,
the newly created analytic accounts should be of type contract ! -->
<record id="account.action_open_partner_analytic_accounts" model="ir.actions.act_window">
<field name="context">{'search_default_partner_id': [active_id], 'default_partner_id': active_id, 'default_type': 'contract'}</field>
</record>
<record id="view_bank_statement_form" model="ir.ui.view"> <record id="view_bank_statement_form" model="ir.ui.view">
<field name="name">usability.account.bank.statement.form</field> <field name="name">usability.account.bank.statement.form</field>
<field name="model">account.bank.statement</field> <field name="model">account.bank.statement</field>
@@ -345,65 +200,6 @@ the newly created analytic accounts should be of type contract ! -->
string="View Account Move" icon="gtk-redo" string="View Account Move" icon="gtk-redo"
attrs="{'invisible': [('journal_entry_id', '=', False)]}"/> attrs="{'invisible': [('journal_entry_id', '=', False)]}"/>
</xpath> </xpath>
<field name="company_id" position="before">
<field name="start_date"/>
<field name="end_date"/>
</field>
</field>
</record>
<record id="view_bank_statement_tree" model="ir.ui.view">
<field name="name">usability.account.bank.statement.tree</field>
<field name="model">account.bank.statement</field>
<field name="inherit_id" ref="account.view_bank_statement_tree"/>
<field name="arch" type="xml">
<field name="period_id" position="attributes">
<attribute name="invisible">1</attribute>
</field>
<field name="date" position="attributes">
<attribute name="invisible">1</attribute>
</field>
<field name="journal_id" position="after">
<field name="start_date"/>
<field name="end_date"/>
</field>
</field>
</record>
<record id="view_bank_statement_search" model="ir.ui.view">
<field name="name">usability.account.bank.statement.search</field>
<field name="model">account.bank.statement</field>
<field name="inherit_id" ref="account.view_bank_statement_search"/>
<field name="arch" type="xml">
<field name="date" position="attributes">
<attribute name="invisible">1</attribute>
</field>
<filter context="{'group_by': 'period_id'}" position="attributes">
<attribute name="invisible">1</attribute>
</filter>
<filter context="{'group_by': 'period_id'}" position="after">
<filter name="start_date_groupby" string="Start Date"
context="{'group_by': 'start_date'}"/>
<filter name="end_date_groupby" string="End Date"
context="{'group_by': 'end_date'}"/>
</filter>
<field name="date" position="after">
<field name="start_date"/>
<field name="end_date"/>
</field>
</field>
</record>
<record id="view_account_analytic_account_form" model="ir.ui.view">
<field name="name">analytic.analytic.account.form</field>
<field name="model">account.analytic.account</field>
<field name="inherit_id" ref="analytic.view_account_analytic_account_form"/>
<field name="arch" type="xml">
<notebook position="inside">
<page name="invoice_lines" string="Related Invoice Lines" attrs="{'invisible': [('type', 'not in', ('contract', 'normal'))]}">
<field name="invoice_line_ids" nolabel="1" context="{'show_invoice_fields': 1}"/>
</page>
</notebook>
</field> </field>
</record> </record>

View File

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

View File

@@ -1,23 +0,0 @@
# -*- coding: utf-8 -*-
# © 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, api
import logging
logger = logging.getLogger(__name__)
class AccountInvoiceMarkSent(models.TransientModel):
_name = 'account.invoice.mark.sent'
_description = 'Mark invoices as sent'
@api.multi
def run(self):
assert self.env.context.get('active_model') == 'account.invoice',\
'Source model must be invoices'
assert self.env.context.get('active_ids'), 'No invoices selected'
invoices = self.env['account.invoice'].browse(
self.env.context.get('active_ids'))
invoices.write({'sent': True})
logger.info('Marking invoices with ID %s as sent', invoices.ids)
return

View File

@@ -1,36 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
© 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
The licence is in the file __openerp__.py
-->
<openerp>
<data>
<record id="account_invoice_mark_sent_form" model="ir.ui.view">
<field name="name">account.invoice.mark.sent.form</field>
<field name="model">account.invoice.mark.sent</field>
<field name="arch" type="xml">
<form string="Mark invoices as sent">
<p>
This wizard will mark as sent all the selected invoices.
</p>
<footer>
<button type="object" name="run" string="Mark as Sent" class="oe_highlight"/>
<button special="cancel" string="Cancel" class="oe_link"/>
</footer>
</form>
</field>
</record>
<act_window id="account_invoice_mark_sent_action"
multi="True"
key2="client_action_multi"
name="Mark as Sent"
res_model="account.invoice.mark.sent"
src_model="account.invoice"
view_mode="form"
target="new" />
</data>
</openerp>

View File

@@ -7,45 +7,8 @@
<field name="view_mode">tree,form</field> <field name="view_mode">tree,form</field>
</record> </record>
<record id="product_attribute_view_form" model="ir.ui.view">
<field name="model">product.attribute</field>
<field name="arch" type="xml">
<form string="Product Attribute">
<sheet>
<div class="oe_title" style="width: 390px;">
<label class="oe_edit_only" for="name" string="Product Name"/>
<h1><field name="name" class="oe_inline"/></h1>
</div>
<group>
<field name="value_ids" colspan="4" nolabel="1"
context="{'hide_attribute_id': True}"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="attribute_tree_view" model="ir.ui.view">
<field name="model">product.attribute</field>
<field name="inherit_id" ref="product.attribute_tree_view"/>
<field name="arch" type="xml">
<xpath expr="//tree" position="attributes">
<attribute name="editable"></attribute>
</xpath>
</field>
</record>
<record id="variants_tree_view" model="ir.ui.view">
<field name="model">product.attribute.value</field>
<field name="inherit_id" ref="product.variants_tree_view"/>
<field name="arch" type="xml">
<field name="attribute_id" position="attributes">
<attribute name="invisible">context.get('hide_attribute_id')</attribute>
</field>
</field>
</record>
<record id="product.attribute_action" model="ir.actions.act_window"> <record id="product.attribute_action" model="ir.actions.act_window">
<field name="res_model">product.attribute</field>
<field name="view_mode">tree,form</field> <field name="view_mode">tree,form</field>
</record> </record>

View File

@@ -12,9 +12,6 @@
<field name="model">ir.module.module</field> <field name="model">ir.module.module</field>
<field name="inherit_id" ref="base.view_module_filter"/> <field name="inherit_id" ref="base.view_module_filter"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//filter[@name='extra']" position="after">
<filter name="installable" string="Installable" domain="[('state', '!=', 'uninstallable')]"/>
</xpath>
<xpath expr="//filter[@string='Category']" position="after"> <xpath expr="//filter[@string='Category']" position="after">
<filter string="State" domain="[]" context="{'group_by':'state'}"/> <filter string="State" domain="[]" context="{'group_by':'state'}"/>
</xpath> </xpath>
@@ -23,7 +20,7 @@
<record id="base.open_module_tree" model="ir.actions.act_window"> <record id="base.open_module_tree" model="ir.actions.act_window">
<field name="res_model">ir.module.module</field> <field name="res_model">ir.module.module</field>
<field name="context">{'search_default_installable': 1}</field> <field name="context">{}</field>
</record> </record>
</data> </data>

View File

@@ -60,21 +60,3 @@ class Partner(models.Model):
else: else:
name_title = ' '.join([title, name_title]) name_title = ' '.join([title, name_title])
self.name_title = name_title self.name_title = name_title
@api.model
def name_search(self, name, args=None, operator='ilike', limit=100):
if args is None:
args = []
if name:
# only filter on name and ref not in email
args += [
'|', ('display_name', 'ilike', name), ('ref', 'ilike', name)]
res = super(Partner, self).name_search(
name, args=args, operator=operator, limit=limit)
return [(pid, val.replace('\n', ' ')) for pid, val in res]
class ResPartnerCategory(models.Model):
_inherit = 'res.partner.category'
name = fields.Char(translate=False)

View File

@@ -1,4 +1,3 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from . import wizard from . import wizard
from . import crm

View File

@@ -5,7 +5,7 @@
{ {
'name': 'CRM Usability', 'name': 'CRM Usability',
'version': '8.0.1.0.1', 'version': '8.0.1.0.0',
'category': 'Customer Relationship Management', 'category': 'Customer Relationship Management',
'license': 'AGPL-3', 'license': 'AGPL-3',
'summary': 'CRM usability enhancements', 'summary': 'CRM usability enhancements',
@@ -13,12 +13,10 @@
CRM Usability CRM Usability
============= =============
The usability improvements include : Some enhancements in the *Merge Partners* wizard:
* Adds multi-company record rules on crm.lead. * take into account the unaccent option of the server config file
* Some enhancements in the *Merge Partners* wizard: * add optional group by on 'customer' and 'supplier' (active by default)
* take into account the unaccent option of the server config file
* add optional group by on 'customer' and 'supplier' (active by default)
This module has been written by Alexis de Lattre from Akretion This module has been written by Alexis de Lattre from Akretion
<alexis.delattre@akretion.com>. <alexis.delattre@akretion.com>.
@@ -26,10 +24,6 @@ This module has been written by Alexis de Lattre from Akretion
'author': 'Akretion', 'author': 'Akretion',
'website': 'http://www.akretion.com', 'website': 'http://www.akretion.com',
'depends': ['crm'], 'depends': ['crm'],
'data': [ 'data': ['wizard/base_partner_merge_view.xml'],
'crm_view.xml',
'wizard/base_partner_merge_view.xml',
'security/rule.xml',
],
'installable': True, 'installable': True,
} }

View File

@@ -1,12 +0,0 @@
# -*- coding: utf-8 -*-
# © 2017 Akretion (http://www.akretion.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
# @author Alexis de Lattre <alexis.delattre@akretion.com>
from openerp import models, fields
class CrmCaseCateg(models.Model):
_inherit = 'crm.case.categ'
name = fields.Char(translate=False)

View File

@@ -1,37 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
© 2017 Akretion (http://www.akretion.com/)
@author: Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<openerp>
<data>
<record id="crm_case_form_view_oppor" model="ir.ui.view">
<field name="name">usability.crm.opportunity.form</field>
<field name="model">crm.lead</field>
<field name="inherit_id" ref="crm.crm_case_form_view_oppor"/>
<field name="arch" type="xml">
<field name="active" position="before">
<field name="company_id" groups="base.group_multi_company"
widget="selection"/>
</field>
</field>
</record>
<record id="crm_case_inbound_phone_tree_view" model="ir.ui.view">
<field name="name">crm_usability.crm.phonecall.tree.inbound</field>
<field name="model">crm.phonecall</field>
<field name="inherit_id" ref="crm.crm_case_inbound_phone_tree_view"/>
<field name="arch" type="xml">
<field name="state" position="attributes">
<attribute name="invisible">0</attribute>
</field>
</field>
</record>
</data>
</openerp>

View File

@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record id="crm_lead_company_rule" model="ir.rule">
<field name="name">Lead/opportunity multi-company rule</field>
<field name="model_id" ref="crm.model_crm_lead"/>
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
</record>
</data>
</openerp>

View File

@@ -1 +0,0 @@
# -*- coding: utf-8 -*-

View File

@@ -1,30 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Akretion (http://www.akretion.com).
# @author Sébastien BEAU <sebastien.beau@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "Delivery usability",
"summary": "Delivery Usability",
"version": "8.0.1.0.0",
"category": "Warehouse",
"website": "www.akretion.com",
"author": " Akretion",
"license": "AGPL-3",
"application": False,
"installable": True,
"external_dependencies": {
"python": [],
"bin": [],
},
"depends": [
"delivery",
],
"data": [
"views/stock_picking_view.xml",
],
"demo": [
],
"qweb": [
]
}

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<record id="view_picking_withcarrier_out_form" model="ir.ui.view">
<field name="model">stock.picking</field>
<field name="inherit_id" ref="delivery.view_picking_withcarrier_out_form"/>
<field name="priority" eval="100"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='carrier_id']/.." position="replace">
</xpath>
<field name="backorder_id" position="after">
<field name="carrier_id"/>
<field name="carrier_tracking_ref"/>
</field>
</field>
</record>
</data>
</openerp>

View File

@@ -1,7 +0,0 @@
# -*- coding: utf-8 -*-
from . import company
from . import hr_holidays
from . import hr_employee
from . import lunch_voucher_attribution
from . import wizard

View File

@@ -1,28 +0,0 @@
# -*- coding: utf-8 -*-
# © 2017 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
'name': 'HR Holidays Lunch Voucher',
'version': '10.0.1.0.0',
'category': 'Human Resources',
'license': 'AGPL-3',
'summary': 'Manage lunch vouchers in holidays requests',
'description': '',
'author': 'Akretion',
'website': 'http://www.akretion.com',
'depends': ['hr_holidays_usability', 'purchase'],
'data': [
'security/ir.model.access.csv',
'security/lunch_voucher_security.xml',
'product_data.xml',
'company_view.xml',
'wizard/lunch_voucher_purchase_view.xml',
'lunch_voucher_attribution_view.xml',
'hr_employee_view.xml',
'hr_holidays_view.xml',
'wizard/hr_holidays_post_view.xml',
],
'installable': True,
}

View File

@@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# © 2017 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields
import openerp.addons.decimal_precision as dp
class ResCompany(models.Model):
_inherit = 'res.company'
lunch_voucher_product_id = fields.Many2one(
'product.product', string='Lunch Voucher Product',
ondelete='restrict')
lunch_voucher_employer_price = fields.Float(
'Lunch Voucher Employer Price', digits=dp.get_precision('Account'))
# Add constrain to check that lunch_voucher_employer_price is between
# 50% and 60% of the price of lunch_voucher_product_id for France

View File

@@ -1,29 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
© 2017 Akretion France (www.akretion.com)
@author: Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<openerp>
<data>
<record id="view_company_form" model="ir.ui.view">
<field name="name">lunch_voucher.company.form</field>
<field name="model">res.company</field>
<field name="inherit_id" ref="base.view_company_form"/>
<field name="arch" type="xml">
<group name="account_grp" position="after">
<group name="lunch_voucher" string="Lunch Vouchers">
<field name="lunch_voucher_product_id"/>
<!-- <field name="lunch_voucher_po_type"/> -->
<field name="lunch_voucher_employer_price"/>
</group>
</group>
</field>
</record>
</data>
</openerp>

View File

@@ -1,12 +0,0 @@
# -*- coding: utf-8 -*-
# © 2017 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields
class HrEmployee(models.Model):
_inherit = 'hr.employee'
lunch_voucher = fields.Boolean(string="Has Lunch Vouchers", default=True)

View File

@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
© 2017 Akretion France (www.akretion.com)
@author: Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<openerp>
<data>
<record id="view_employee_form_leave_inherit" model="ir.ui.view">
<field name="name">lunch_voucher.hr.employee.form</field>
<field name="model">hr.employee</field>
<field name="inherit_id" ref="hr_holidays_usability.view_employee_form_leave_inherit"/>
<field name="arch" type="xml">
<group name="holidays" position="inside">
<field name="lunch_voucher"/>
</group>
</field>
</record>
</data>
</openerp>

View File

@@ -1,45 +0,0 @@
# -*- coding: utf-8 -*-
# © 2017 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields, api
from dateutil.relativedelta import relativedelta
class HrHolidays(models.Model):
_inherit = 'hr.holidays'
lunch_voucher_id = fields.Many2one(
'lunch.voucher.attribution',
string="Related Lunch Voucher Attribution")
lunch_voucher_remove_qty = fields.Integer(
compute='_compute_lunch_voucher_remove_qty', readonly=True,
store=True, string='Lunch Vouchers to Deduct')
@api.depends('employee_id', 'vacation_date_from', 'vacation_date_to')
@api.multi
def _compute_lunch_voucher_remove_qty(self):
hhpo = self.env['hr.holidays.public']
for hol in self:
qty = 0
if (
hol.type == 'remove' and
hol.vacation_date_from and
hol.vacation_date_to):
start_date_dt = fields.Date.from_string(hol.vacation_date_from)
end_date_str = hol.vacation_date_to
date_dt = start_date_dt
# Remove 1 full LV when vacation_time_from == noon
# and also when vacation_time_to == noon
while True:
if (
date_dt.weekday() not in (5, 6) and
not hhpo.is_public_holiday(
date_dt, hol.employee_id.id)):
qty += 1
date_dt += relativedelta(days=1)
date_str = fields.Date.to_string(date_dt)
if date_str > end_date_str:
break
hol.lunch_voucher_remove_qty = qty

View File

@@ -1,39 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
© 2017 Akretion (http://www.akretion.com/)
@author: Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<openerp>
<data>
<record id="edit_holiday_new" model="ir.ui.view">
<field name="name">hr_holidays_lunch_voucher.leave_request_form</field>
<field name="model">hr.holidays</field>
<field name="inherit_id" ref="hr_holidays_usability.edit_holiday_new"/>
<field name="arch" type="xml">
<group name="counters" position="after">
<group name="lunch_vouchers" string="Lunch Vouchers" attrs="{'invisible': [('type', '!=', 'remove')]}">
<field name="lunch_voucher_remove_qty"/>
<field name="lunch_voucher_id"/>
</group>
</group>
</field>
</record>
<record id="view_holiday" model="ir.ui.view">
<field name="name">hr_holidays_lunch_voucher.leave_request_tree</field>
<field name="model">hr.holidays</field>
<field name="inherit_id" ref="hr_holidays_usability.view_holiday"/>
<field name="arch" type="xml">
<field name="number_of_days" position="after">
<field name="lunch_voucher_remove_qty" string="Lunch Vouchers -=" sum="Total"/>
</field>
</field>
</record>
</data>
</openerp>

View File

@@ -1,45 +0,0 @@
# -*- coding: utf-8 -*-
# © 2017 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields, api
class LunchVoucherAttribution(models.Model):
_name = 'lunch.voucher.attribution'
_description = 'Lunch Voucher Attribution'
_order = 'date desc'
employee_id = fields.Many2one(
'hr.employee', string='Employee', ondelete='restrict',
required=True, readonly=True)
company_id = fields.Many2one(
related='employee_id.resource_id.company_id', readonly=True,
store=True)
date = fields.Date('Attribution Date', readonly=True)
purchase_id = fields.Many2one(
'purchase.order', 'Purchase Order',
readonly=True)
month_work_days = fields.Integer(
'Month Work Days',
help="Number of work days of the month (without taking into "
"account the holidays)")
no_lunch_days = fields.Integer(
compute='_compute_qty', string='No Lunch Days',
readonly=True, store=True)
qty = fields.Integer(
compute='_compute_qty', readonly=True, store=True,
string='Lunch Voucher Quantity')
holiday_ids = fields.One2many(
'hr.holidays', 'lunch_voucher_id', readonly=True)
@api.depends('month_work_days', 'holiday_ids.lunch_voucher_remove_qty')
@api.multi
def _compute_qty(self):
for rec in self:
no_lunch_days = 0
for hol in rec.holiday_ids:
no_lunch_days += hol.lunch_voucher_remove_qty
rec.no_lunch_days = no_lunch_days
rec.qty = rec.month_work_days - no_lunch_days

View File

@@ -1,97 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
© 2017 Akretion France (www.akretion.com)
@author: Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<openerp>
<data>
<record id="lunch_voucher_attribution_form" model="ir.ui.view">
<field name="name">lunch.voucher.attribution.form</field>
<field name="model">lunch.voucher.attribution</field>
<field name="arch" type="xml">
<form string="Lunch Vouchers Attribution">
<group name="main">
<field name="employee_id"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="date"/>
<field name="month_work_days"/>
<field name="no_lunch_days"/>
<field name="qty"/>
<field name="purchase_id"/>
</group>
<group name="holidays" string="Related Holidays">
<field name="holiday_ids" nolabel="1" context="{'tree_view_ref': 'hr_holidays_lunch_voucher.view_holiday', 'form_view_ref': 'hr_holidays_lunch_voucher.edit_holiday_new'}"/>
</group>
</form>
</field>
</record>
<record id="lunch_voucher_attribution_tree" model="ir.ui.view">
<field name="name">lunch.voucher.attribution.tree</field>
<field name="model">lunch.voucher.attribution</field>
<field name="arch" type="xml">
<tree string="Lunch Vouchers Attribution">
<field name="date"/>
<field name="employee_id"/>
<field name="month_work_days"/>
<field name="no_lunch_days" sum="Total"/>
<field name="qty" sum="Total"/>
<field name="purchase_id"/>
<field name="company_id" groups="base.group_multi_company"/>
</tree>
</field>
</record>
<record id="lunch_voucher_attribution_search" model="ir.ui.view">
<field name="name">lunch.voucher.attribution.search</field>
<field name="model">lunch.voucher.attribution</field>
<field name="arch" type="xml">
<search string="Search Lunch Vouchers Attribution">
<field name="date"/>
<field name="employee_id"/>
<filter name="purchased" string="Purchased" domain="[('purchase_id', '!=', False)]"/>
<filter name="to_purchase" string="To Purchase" domain="[('purchase_id', '=', False)]"/>
<group string="Group By" name="groupby">
<filter name="employee_groupby" string="Employee" context="{'group_by': 'employee_id'}"/>
<filter name="purchase_order_groupby" string="Purchase Order" context="{'group_by': 'purchase_id'}"/>
</group>
</search>
</field>
</record>
<record id="lunch_voucher_attribution_graph" model="ir.ui.view">
<field name="name">lunch.voucher.attribution.graph</field>
<field name="model">lunch.voucher.attribution</field>
<field name="arch" type="xml">
<graph string="Lunch Vouchers Attribution" type="pivot">
<field name="date" type="row" interval="month"/>
<field name="qty" type="measure"/>
</graph>
</field>
</record>
<record id="lunch_voucher_attribution_action" model="ir.actions.act_window">
<field name="name">Lunch Voucher Attribution</field>
<field name="res_model">lunch.voucher.attribution</field>
<field name="view_mode">tree,form,graph</field>
</record>
<menuitem id="lunch_voucher_attribution_menu"
action="lunch_voucher_attribution_action"
parent="hr_holidays.menu_open_ask_holidays" sequence="200"/>
<act_window id="lunch_voucher_attribution_action_create_po"
multi="True"
key2="client_action_multi"
name="Create Purchase Order"
res_model="lunch.voucher.purchase"
src_model="lunch.voucher.attribution"
view_mode="form"
target="new" />
</data>
</openerp>

View File

@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record id="lunch_voucher_product" model="product.product">
<field name="name">Lunch Vouchers</field>
<field name="categ_id" ref="product.product_category_all"/>
<field name="sale_ok" eval="False"/>
<field name="purchase_ok" eval="True"/>
<field name="list_price">0</field>
<field name="standard_price">8</field>
<field name="type">service</field> <!-- For those who want to manage stock of lunch vouchers, they can switch type to product manually -->
<field name="uom_id" ref="product.product_uom_unit"/>
<field name="uom_po_id" ref="product.product_uom_unit"/>
<field name="supplier_taxes_id" eval="False"/>
<field name="taxes_id" eval="False"/>
</record>
<record id="base.main_company" model="res.company">
<field name="lunch_voucher_product_id" ref="lunch_voucher_product"/>
</record>
</data>
</openerp>

View File

@@ -1,3 +0,0 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_lunch_voucher_attribution_full,Full access on lunch_voucher_attribution,model_lunch_voucher_attribution,base.group_hr_manager,1,1,1,1
access_lunch_voucher_attribution_read,Read access on lunch_voucher_attribution,model_lunch_voucher_attribution,base.group_user,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_lunch_voucher_attribution_full Full access on lunch_voucher_attribution model_lunch_voucher_attribution base.group_hr_manager 1 1 1 1
3 access_lunch_voucher_attribution_read Read access on lunch_voucher_attribution model_lunch_voucher_attribution base.group_user 1 0 0 0

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record id="lunch_voucher_attribution_employee" model="ir.rule">
<field name="name">Personal Lunch Voucher Attributions</field>
<field name="model_id" ref="hr_holidays_lunch_voucher.model_lunch_voucher_attribution"/>
<field name="domain_force">[('employee_id.user_id', '=', user.id)]</field>
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
</record>
<record id="lunch_voucher_attribution_officer" model="ir.rule">
<field name="name">HR Officer sees all Lunch Voucher Attributions</field>
<field name="model_id" ref="hr_holidays_lunch_voucher.model_lunch_voucher_attribution"/>
<field name="domain_force">[(1, '=', 1)]</field>
<field name="groups" eval="[(4, ref('base.group_hr_manager'))]"/>
</record>
<record id="lunch_voucher_attribution_multicompany_rule" model="ir.rule">
<field name="name">Lunch Voucher Attribution multi-company</field>
<field name="model_id" ref="hr_holidays_lunch_voucher.model_lunch_voucher_attribution"/>
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
</record>
</data>
</openerp>

View File

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

View File

@@ -1,74 +0,0 @@
# -*- coding: utf-8 -*-
# © 2017 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields, api
from dateutil.relativedelta import relativedelta
import logging
logger = logging.getLogger(__name__)
class HrHolidaysPost(models.TransientModel):
_inherit = 'hr.holidays.post'
lunch_voucher_po = fields.Boolean(
string='Generate Lunch Voucher Purchase Order')
work_days = fields.Integer(string='Work Days')
@api.model
def default_get(self, fields_list):
res = super(HrHolidaysPost, self).default_get(fields_list)
hhpo = self.env['hr.holidays.public']
company = self.env.user.company_id
if company.lunch_voucher_product_id:
res['lunch_voucher_po'] = True
today = fields.Date.context_today(self)
today_dt = fields.Date.from_string(today)
cur_month = today_dt.month
# last day of month
date_dt = today_dt + relativedelta(day=31)
work_days = date_dt.day
logger.info('Number of days in the month: %d', work_days)
# from last day of month to the first
while date_dt.month == cur_month:
if hhpo.is_public_holiday(date_dt):
work_days -= 1
logger.info(
"%s is a bank holiday, don't count", date_dt)
# if it's a saturday/sunday
elif date_dt.weekday() in (5, 6):
work_days -= 1
logger.info(
"%s is a saturday/sunday, don't count", date_dt)
date_dt += relativedelta(days=-1)
logger.info('Number of work days in the month: %d', work_days)
res['work_days'] = work_days
return res
@api.multi
def run(self):
self.ensure_one()
lvao = self.env['lunch.voucher.attribution']
today = fields.Date.context_today(self)
employees = self.env['hr.employee'].search([
('lunch_voucher', '=', True),
('company_id', '=', self.env.user.company_id.id),
])
lv_dict = {}
for employee in employees:
lv_dict[employee.id] = []
for hol in self.holidays_to_post_ids:
if not hol.lunch_voucher_id and hol.employee_id.id in lv_dict:
lv_dict[hol.employee_id.id].append(hol.id)
for employee_id, hol_ids in lv_dict.iteritems():
vals = {
'employee_id': employee_id,
'date': today,
'month_work_days': self.work_days,
}
if hol_ids:
vals['holiday_ids'] = [(6, 0, hol_ids)]
lvao.create(vals)
return super(HrHolidaysPost, self).run()

View File

@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
© 2017 Akretion (http://www.akretion.com/)
@author: Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<openerp>
<data>
<record id="hr_holidays_post_form" model="ir.ui.view">
<field name="name">hr_holidays_post_form</field>
<field name="model">hr.holidays.post</field>
<field name="inherit_id" ref="hr_holidays_usability.hr_holidays_post_form"/>
<field name="arch" type="xml">
<field name="holidays_to_post_ids" position="before">
<field name="lunch_voucher_po" states="done"/>
<field name="work_days"
attrs="{'invisible': ['|', ('state', '!=', 'done'), ('lunch_voucher_po', '=', False)]}"/>
</field>
</field>
</record>
</data>
</openerp>

View File

@@ -1,77 +0,0 @@
# -*- coding: utf-8 -*-
# © 2017 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, api, _
from openerp.exceptions import Warning as UserError
class LunchVoucherPurchase(models.TransientModel):
_name = 'lunch.voucher.purchase'
_description = 'Purchase Lunch Vouchers Wizard'
@api.multi
def run(self):
self.ensure_one()
company = self.env.user.company_id
if not company.lunch_voucher_product_id:
raise UserError(_(
"Lunch Voucher Product not configured on company %s")
% company.name)
if not company.lunch_voucher_product_id.seller_id:
raise UserError(_(
"Missing supplier on Product '%s'.")
% company.lunch_voucher_product_id.name)
poo = self.env['purchase.order']
polo = self.env['purchase.order.line']
lvao = self.env['lunch.voucher.attribution']
assert self._context.get('active_model') ==\
'lunch.voucher.attribution', 'wrong source model'
assert self._context.get('active_ids'), 'missing active_ids in ctx'
lvouchers = lvao.browse(self._context['active_ids'])
total_qty = 0
for lvoucher in lvouchers:
if lvoucher.purchase_id:
raise UserError(_(
"One of the Lunch Voucher Attributions you selected "
"related to employee '%s' is already linked to a "
"purchase order.") % lvoucher.employee_id.name)
if lvoucher.qty < 0:
raise UserError(_(
"One of the Lunch Voucher Attributions you selected "
"related to employee '%s' has a negative quantity.")
% lvoucher.employee_id.name)
total_qty += lvoucher.qty
supplier = company.lunch_voucher_product_id.seller_id
pick_type_id = poo.default_get(['picking_type_id'])['picking_type_id']
onchange_ptype_vals = poo.browse(False).onchange_picking_type_id(
pick_type_id)
vals = onchange_ptype_vals['value']
onchange_vals = poo.browse(False).onchange_partner_id(supplier.id)
vals.update(onchange_vals['value'])
vals['partner_id'] = supplier.id
product = company.lunch_voucher_product_id
onchange_product_vals = polo.browse(False).onchange_product_id(
vals.get('pricelist_id'), product.id, total_qty, False,
supplier.id, fiscal_position_id=vals.get('fiscal_position_id'))
lvals = onchange_product_vals['value']
lvals['product_id'] = product.id
lvals['product_qty'] = total_qty
if lvals['taxes_id']:
lvals['taxes_id'] = [(6, 0, lvals['taxes_id'])]
vals['order_line'] = [(0, 0, lvals)]
po = poo.create(vals)
lvouchers.write({'purchase_id': po.id})
action = self.env['ir.actions.act_window'].for_xml_id(
'purchase', 'purchase_rfq')
action.update({
'res_id': po.id,
'view_mode': 'form,tree',
'views': False,
})
return action

View File

@@ -1,36 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
© 2017 Akretion (http://www.akretion.com/)
@author Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<openerp>
<data>
<record id="lunch_voucher_purchase_form" model="ir.ui.view">
<field name="name">lunch_voucher_purchase_form</field>
<field name="model">lunch.voucher.purchase</field>
<field name="arch" type="xml">
<form string="Create Purchase Order of Lunch Vouchers">
<group name="main">
<label string="Click on the button below to create the purchase order for the selected lunch vouchers attributions." colspan="2"/>
</group>
<footer>
<button name="run" type="object" string="Create"
class="oe_highlight"/>
<button special="cancel" string="Cancel" class="oe_link"/>
</footer>
</form>
</field>
</record>
<record id="lunch_voucher_purchase_action" model="ir.actions.act_window">
<field name="name">Create PO for Lunch Vouchers</field>
<field name="res_model">lunch.voucher.purchase</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</data>
</openerp>

View File

@@ -1,4 +0,0 @@
# -*- coding: utf-8 -*-
from . import company
from . import wizard

View File

@@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# © 2017 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
'name': 'HR Holidays Lunch Voucher Natixis',
'version': '10.0.1.0.0',
'category': 'Human Resources',
'license': 'AGPL-3',
'summary': 'Generate order file for Natixis lunch vouchers',
'description': '',
'author': 'Akretion',
'website': 'http://www.akretion.com',
'depends': ['hr_holidays_lunch_voucher'],
'data': [
'company_view.xml',
],
'installable': True,
}

View File

@@ -1,15 +0,0 @@
# -*- coding: utf-8 -*-
# © 2017 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields
class ResCompany(models.Model):
_inherit = 'res.company'
lunch_voucher_natixis_customer_code = fields.Char(
string='Natixis Customer Ref', size=7)
lunch_voucher_natixis_delivery_code = fields.Char(
string='Natixis Delivery Code', size=7)

View File

@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
© 2017 Akretion France (www.akretion.com)
@author: Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<openerp>
<data>
<record id="view_company_form" model="ir.ui.view">
<field name="name">natixis.lunch_voucher.company.form</field>
<field name="model">res.company</field>
<field name="inherit_id" ref="hr_holidays_lunch_voucher.view_company_form"/>
<field name="arch" type="xml">
<group name="lunch_voucher" position="inside">
<field name="lunch_voucher_natixis_customer_code"/>
<field name="lunch_voucher_natixis_delivery_code"/>
</group>
</field>
</record>
</data>
</openerp>

View File

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

View File

@@ -1,92 +0,0 @@
# -*- coding: utf-8 -*-
# © 2017 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields, api, _
from openerp.exceptions import Warning as UserError
from openerp.tools import float_is_zero
class LunchVoucherPurchase(models.TransientModel):
_inherit = 'lunch.voucher.purchase'
@api.multi
def run(self):
self.ensure_one()
action = super(LunchVoucherPurchase, self).run()
company = self.env.user.company_id
# force_company to read standard_price properly
company = company.with_context(force_company=company.id)
lvao = self.env['lunch.voucher.attribution']
assert self._context.get('active_model')\
== 'lunch.voucher.attribution', 'wrong source model'
assert self._context.get('active_ids'), 'missing active_ids in ctx'
if not company.lunch_voucher_natixis_customer_code:
raise UserError(_(
"Missing Natixis Customer Ref on company '%s'.")
% company.name)
if not company.lunch_voucher_natixis_delivery_code:
raise UserError(_(
"Missing Natixis Delivery Code on company '%s'.")
% company.name)
if len(company.lunch_voucher_natixis_customer_code) != 7:
raise UserError(_(
"Natixis Customer Ref '%s' on company '%s' should "
"have 7 characters/digits.")
% (company.lunch_voucher_natixis_customer_code, company.name))
if len(company.lunch_voucher_natixis_delivery_code) != 7:
raise UserError(_(
"Natixis Delivery Code on company '%s' should "
"have 7 characters/digits.")
% (company.lunch_voucher_natixis_delivery_code, company.name))
if float_is_zero(
company.lunch_voucher_employer_price,
precision_digits=2):
raise UserError(_(
"Lunch Voucher Employer Price not set on company '%s'.")
% company.name)
if float_is_zero(
company.lunch_voucher_product_id.standard_price,
precision_digits=2):
raise UserError(_(
"Lunch Voucher Standard Price is not set on product '%s'.")
% company.lunch_voucher_product_id.display_name)
lvouchers = lvao.browse(self._context['active_ids'])
of = u''
tmp = {}
for lvoucher in lvouchers:
if lvoucher.qty > 0:
if lvoucher.qty not in tmp:
tmp[lvoucher.qty] = 1
else:
tmp[lvoucher.qty] += 1
for vouchers_per_pack, pack_qty in tmp.iteritems():
if vouchers_per_pack > 99:
raise UserError(_(
"Cannot order more than 99 vouchers per pack"))
line = u'%s%s%s%s%s%s%s%s\n' % (
company.lunch_voucher_natixis_delivery_code,
company.lunch_voucher_natixis_customer_code,
unicode(pack_qty).zfill(3),
unicode(vouchers_per_pack).zfill(2),
unicode(pack_qty * vouchers_per_pack).zfill(5),
'{:05.2f}'.format(
company.lunch_voucher_product_id.standard_price),
'{:05.2f}'.format(company.lunch_voucher_employer_price),
' ' * 64)
of += line
today_dt = fields.Date.from_string(
fields.Date.context_today(self))
filename = 'E%s_%s.txt' % (
company.lunch_voucher_natixis_customer_code,
today_dt.strftime('%d%m%Y'))
self.env['ir.attachment'].create({
'name': filename,
'res_id': action['res_id'],
'res_model': 'purchase.order',
'datas': of.encode('base64'),
'datas_fname': filename,
'type': 'binary',
})
return action

View File

@@ -241,10 +241,6 @@ class HrHolidays(models.Model):
string='Public Title', string='Public Title',
help="Warning: this title is shown publicly in the " help="Warning: this title is shown publicly in the "
"calendar. Don't write private/personnal information in this field.") "calendar. Don't write private/personnal information in this field.")
# by default, there is no company_id field on hr.holidays !
company_id = fields.Many2one(
related='employee_id.resource_id.company_id', store=True,
readonly=True)
@api.one @api.one
@api.constrains( @api.constrains(

View File

@@ -61,7 +61,6 @@ hr_holidays.edit_holiday_new is used for both leaves and allocation -->
</group> </group>
</field> </field>
<field name="department_id" position="after"> <field name="department_id" position="after">
<field name="company_id" groups="base.group_multi_company"/>
<field name="posted_date" groups="base.group_hr_manager"/> <field name="posted_date" groups="base.group_hr_manager"/>
</field> </field>
</field> </field>
@@ -91,7 +90,6 @@ hr_holidays.edit_holiday_new is used for both leaves and allocation -->
</field> </field>
<field name="holiday_status_id" position="after"> <field name="holiday_status_id" position="after">
<field name="posted_date" groups="base.group_hr_manager"/> <field name="posted_date" groups="base.group_hr_manager"/>
<field name="company_id" groups="base.group_multi_company"/>
</field> </field>
</field> </field>
</record> </record>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<openerp> <openerp>
<data noupdate="1"> <data noupdate="0">
<!-- <!--
Employee : only see his holidays Employee : only see his holidays
@@ -41,12 +41,5 @@ Manager = person that administrates the holidays process : can see everything, d
<field name="groups" eval="[(4, ref('base.group_hr_manager'))]"/> <field name="groups" eval="[(4, ref('base.group_hr_manager'))]"/>
</record> </record>
<record id="hr_holidays_multicompany_rule" model="ir.rule">
<field name="name">Holidays multi-company</field>
<field name="model_id" ref="hr_holidays.model_hr_holidays"/>
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
</record>
</data> </data>
</openerp> </openerp>

View File

@@ -31,9 +31,7 @@ class HrHolidaysMassAllocation(models.TransientModel):
@api.model @api.model
def _default_employees(self): def _default_employees(self):
return self.env['hr.employee'].search([ return self.env['hr.employee'].search([
('holiday_exclude_mass_allocation', '=', False), ('holiday_exclude_mass_allocation', '=', False)])
('company_id', '=', self.env.user.company_id.id),
])
@api.model @api.model
def _get_default_holiday_status(self): def _get_default_holiday_status(self):

View File

@@ -56,7 +56,6 @@ class HrHolidaysPost(models.TransientModel):
('state', '=', 'validate'), ('state', '=', 'validate'),
('posted_date', '=', False), ('posted_date', '=', False),
('vacation_date_to', '<=', self.before_date), ('vacation_date_to', '<=', self.before_date),
('company_id', '=', self.env.user.company_id.id),
]) ])
self.write({ self.write({
'state': 'done', 'state': 'done',
@@ -74,11 +73,9 @@ class HrHolidaysPost(models.TransientModel):
# because, after the write, it doesn't have a value any more !!! # because, after the write, it doesn't have a value any more !!!
holidays_to_post = self.holidays_to_post_ids holidays_to_post = self.holidays_to_post_ids
today = fields.Date.context_today(self) today = fields.Date.context_today(self)
# Disable the raise below to make the module "hr_holidays_lunch_voucher" if not self.holidays_to_post_ids:
# work even when nobody took holidays on the current month raise Warning(
# if not self.holidays_to_post_ids: _('No leave request to post.'))
# raise Warning(
# _('No leave request to post.'))
self.holidays_to_post_ids.write({'posted_date': today}) self.holidays_to_post_ids.write({'posted_date': today})
view_id = self.env.ref('hr_holidays_usability.hr_holiday_graph').id view_id = self.env.ref('hr_holidays_usability.hr_holiday_graph').id
action = { action = {

View File

@@ -12,13 +12,13 @@
<field name="name">hr_holidays_post_form</field> <field name="name">hr_holidays_post_form</field>
<field name="model">hr.holidays.post</field> <field name="model">hr.holidays.post</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form string="Post Leaves"> <form string="Post Leaves" version="7.0">
<group name="main" string="Leave Requests to Post"> <group name="main" string="Leave Requests to Post">
<field name="state" invisible="1"/> <field name="state" invisible="1"/>
<field name="before_date" states="draft"/> <field name="before_date" states="draft"/>
<field name="holidays_to_post_ids" nolabel="1" <field name="holidays_to_post_ids" nolabel="1"
context="{'tree_view_ref': 'hr_holidays.view_holiday'}" context="{'tree_view_ref': 'hr_holidays.view_holiday'}"
states="done" colspan="2"/> states="done"/>
</group> </group>
<footer> <footer>
<button name="select_date" type="object" string="Get Holiday Requests" <button name="select_date" type="object" string="Get Holiday Requests"

View File

@@ -23,7 +23,7 @@
{ {
'name': 'Mail Usability', 'name': 'Mail Usability',
'version': '8.0.1.0.0', 'version': '0.1',
'category': 'Base', 'category': 'Base',
'license': 'AGPL-3', 'license': 'AGPL-3',
'summary': 'Usability improvements on mails', 'summary': 'Usability improvements on mails',
@@ -37,11 +37,10 @@ Small usability improvements on mails:
* remove 'sent by' in notification footer * remove 'sent by' in notification footer
* add a new entry *All Messages Except Notifications* to the field *Receive Inbox Notifications by Email* of partners (becomes the default value)
""", """,
'author': 'Akretion', 'author': 'Akretion',
'website': 'http://www.akretion.com', 'website': 'http://www.akretion.com',
'depends': ['mail'], 'depends': ['mail'],
'data': ['views/mail.xml'], 'data': [],
'installable': True, 'installable': True,
} }

View File

@@ -20,16 +20,7 @@
# #
############################################################################## ##############################################################################
from openerp import models, fields, api from openerp import models, api
class ResPartner(models.Model):
_inherit = 'res.partner'
notify_email = fields.Selection(
selection_add=[
('all_except_notification', 'All Messages Except Notifications')],
default='all_except_notification')
class MailMail(models.Model): class MailMail(models.Model):
@@ -56,19 +47,6 @@ class MailNotification(models.Model):
footer = super(MailNotification, self).get_signature_footer( footer = super(MailNotification, self).get_signature_footer(
cr, uid, user_id, res_model=res_model, res_id=res_id, cr, uid, user_id, res_model=res_model, res_id=res_id,
context=context, user_signature=user_signature) context=context, user_signature=user_signature)
footer = footer[:footer.find('\n<br /><small>Sent by ')] footer = footer[:footer.find('\n\n<br /><small>Sent by ')]
footer = footer[:footer.find(u'\n<br /><small>Envoyé par ')] footer = footer[:footer.find(u'\n\n<br /><small>Envoyé par ')]
return footer return footer
@api.multi
def get_partners_to_email(self, message):
notify_pids = super(MailNotification, self).get_partners_to_email(
message)
for notif in self:
if (
notif.partner_id.id in notify_pids and
message.type == 'notification' and
notif.partner_id.notify_email ==
'all_except_notification'):
notify_pids.remove(notif.partner_id.id)
return notify_pids

View File

@@ -1,92 +0,0 @@
openerp_FieldMany2ManyTagsEmail = function(instance) {
var _t = instance.web._t;
/**
* Extend of FieldMany2ManyTags widget method.
* When the user add a partner and the partner don't have an email, open a popup to purpose to add an email.
* The user can choose to add an email or cancel and close the popup.
*/
instance.web.form.FieldMany2ManyTagsEmail = instance.web.form.FieldMany2ManyTags.extend({
start: function() {
this.mutex = new openerp.Mutex();
// This widget will indirectly trigger a change:value to it's parent widget
// when setting the value of valid partners. For this reason we have to keep an
// internal state of the last value in order to compute the effective value changes.
this.last_processed_value = [];
this.on("change:value", this, this.on_change_value_check);
// Restore pop-up when trying to send to a partner without email
this.on_change_value_check();
this._super.apply(this, arguments);
},
on_change_value_check : function () {
var self = this;
var values = this.get('value').slice(0); // Clone the array
// We only validate partners emails in case the value is not empty
// and is different from the last processed value
var effective_change = _.difference(values, self.last_processed_value).length;
if (values.length && effective_change) {
this.mutex.exec(function() {
return self._check_email_popup(values);
});
}
},
_check_email_popup: function (ids) {
var self = this;
var valid_partners;
new instance.web.Model('res.partner').call("search", [[
["id", "in", ids],
["email", "=", false],
["notify_email", "in", ['always', 'all_except_notification']]]],
{context: this.build_context()})
.then(function (record_ids) {
var popups_deferreds = [];
self.valid_partners = _.difference(ids, record_ids);
// Propose the user to correct invalid partners
_.each(record_ids, function (id) {
var popup_def = $.Deferred();
popups_deferreds.push(popup_def);
var pop = new instance.web.form.FormOpenPopup(self);
pop.show_element(
'res.partner',
id,
self.build_context(),
{
title: _t("Please complete partner's informations and Email"),
}
);
pop.on('write_completed', self, function () {
self.valid_partners.push(id);
});
pop.on('closed', self, function () {
popup_def.resolve();
});
});
return $.when.apply($, popups_deferreds).then(function() {
// All popups have been processed for the given ids
// It is now time to set the final value with valid partners ids.
var filtered_value = _.uniq(self.valid_partners);
self.last_processed_value = filtered_value;
self.set({'value': filtered_value});
});
});
},
});
/**
* Registry of form fields
*/
instance.web.form.widgets = instance.web.form.widgets.extend({
'many2many_tags_email' : 'instance.web.form.FieldMany2ManyTagsEmail',
});
};

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<template id="assets_backend" name="mail usability assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<script type="text/javascript" src="/mail_usability/static/src/js/many2many_tags_email.js"></script>
</xpath>
</template>
</data>
</openerp>

View File

@@ -40,27 +40,31 @@ class ResPartner(models.Model):
def open_aged_open_invoices_report(self): def open_aged_open_invoices_report(self):
aoiwo = self.env['aged.open.invoices.webkit'] aoiwo = self.env['aged.open.invoices.webkit']
afo = self.env['account.fiscalyear'] afo = self.env['account.fiscalyear']
# Filter by period (and not by date) to get # Force 'date_from' to the first day of the company's life
# the report à nouveau # in order to get the full picture of the partner's account
# (we could also do that via a filter by period, but, in this case,
# account_financial_report_webkit doesn't accept "until_date = today" ;
# until_date has to be the end date of the last period
fy_years = afo.search([], order='date_start') fy_years = afo.search([], order='date_start')
date_from = fy_years[0].date_start date_from = fy_years[0].date_start
fy_id = aoiwo._get_fiscalyear() fy_id = aoiwo._get_fiscalyear()
filter_change = aoiwo.onchange_filter( filter_change = aoiwo.onchange_filter(
filter='filter_period', fiscalyear_id=fy_id) filter='filter_date', fiscalyear_id=fy_id)
vals = { vals = {
'fiscalyear_id': fy_id, 'fiscalyear_id': fy_id,
'filter': 'filter_period', 'filter': 'filter_date',
'partner_ids': [(6, 0, [self.commercial_partner_id.id])], 'partner_ids': [(6, 0, [self.commercial_partner_id.id])],
'target_move': 'all', 'target_move': 'all',
} }
vals.update(filter_change['value']) vals.update(filter_change['value'])
vals['date_from'] = date_from
wizard = aoiwo.create(vals) wizard = aoiwo.create(vals)
data = {'form': { data = {'form': {
'chart_account_id': wizard.chart_account_id.id, 'chart_account_id': wizard.chart_account_id.id,
'filter': vals['filter'], 'filter': vals['filter'],
'period_from': vals['period_from'], 'date_from': vals['date_from'],
'period_to': vals['period_to'], 'date_to': vals['date_to'],
'date_to': False, 'period_to': False,
'fiscalyear_id': vals['fiscalyear_id'], 'fiscalyear_id': vals['fiscalyear_id'],
'partner_ids': vals['partner_ids'][0][2], 'partner_ids': vals['partner_ids'][0][2],
'target_move': vals['target_move'], 'target_move': vals['target_move'],

View File

@@ -14,20 +14,10 @@
<field name="phone" string="Phones" <field name="phone" string="Phones"
filter_domain="['|', ('phone', 'like', self), ('mobile', 'like', self)]"/> filter_domain="['|', ('phone', 'like', self), ('mobile', 'like', self)]"/>
</field> </field>
<!-- Display the real field names of the search -->
<!-- We split the search of name, ref / email in two
as searching in email can return a lot of unwanted result
for exemple when you sell on marketplace and search for a customer
amazon you will have all customer that have bought throught the marketplace -->
<field name="name" position="attributes"> <field name="name" position="attributes">
<attribute name="string">Name, Ref</attribute> <attribute name="string">Name, Ref, Email</attribute>
<attribute name="filter_domain">['|', ('display_name','ilike',self), ('ref','=',self)]</attribute>
</field> </field>
<field name="name" position="after">
<field name="email"/>
</field>
</field> </field>
</record> </record>

View File

@@ -1 +0,0 @@
# -*- coding: utf-8 -*-

View File

@@ -1,32 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Akretion (http://www.akretion.com).
# @author Sébastien BEAU <sebastien.beau@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "Partner Menu Split",
"summary": "Split the customer menu in two",
"version": "8.0.0.0",
"category": "Uncategorized",
"website": "www.akretion.com",
"author": " Akretion",
"license": "AGPL-3",
"application": False,
"installable": True,
"external_dependencies": {
"python": [],
"bin": [],
},
"depends": [
"base",
"purchase",
],
"data": [
"views/res_partner_view.xml",
],
"demo": [
],
"qweb": [
]
}

View File

@@ -1,81 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<record id="base.action_partner_customer_form" model="ir.actions.act_window">
<field name="domain">[('parent_id', '=', False)]</field>
<field name="view_mode">tree,form,kanban</field>
</record>
<record id="base.action_partner_form" model="ir.actions.act_window">
<field name="domain">[('parent_id', '=', False)]</field>
<field name="view_mode">tree,form,kanban</field>
</record>
<record id="base.action_partner_form_view1" model="ir.actions.act_window.view">
<field eval="3" name="sequence"/>
</record>
<record id="action_partner_customer_contact_form" model="ir.actions.act_window">
<field name="name">Contact</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">res.partner</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form,kanban</field>
<field name="domain">[('parent_id', '!=', False)]</field>
<field name="context">{'default_customer':1, 'search_default_customer':1}</field>
<field name="filter" eval="True"/>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to add a contact in your address book.
</p><p>
Odoo helps you easily track all activities related to
a customer: discussions, history of business opportunities,
documents, etc.
</p>
</field>
</record>
<menuitem
id="menu_partner_form"
parent="base.menu_sales"
action="action_partner_customer_contact_form"
sequence="2"/>
<record id="base.action_partner_supplier_form" model="ir.actions.act_window">
<field name="domain">[('parent_id', '=', False)]</field>
<field name="view_mode">tree,form,kanban</field>
</record>
<record id="action_partner_supplier_contact_form" model="ir.actions.act_window">
<field name="name">Contact</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">res.partner</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form,kanban</field>
<field name="domain">[('parent_id', '!=', False)]</field>
<field name="context">{'default_supplier':1, 'search_default_supplier':1}</field>
<field name="filter" eval="True"/>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to add a contact in your address book.
</p><p>
Odoo helps you easily track all activities related to
a supplier: discussions, history of business opportunities,
documents, etc.
</p>
</field>
</record>
<menuitem
id="menu_partner_supplier_form"
parent="purchase.menu_procurement_management"
action="action_partner_supplier_contact_form"
sequence="20"/>
</data>
</openerp>

View File

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

View File

@@ -1,34 +0,0 @@
# -*- coding: utf-8 -*-
# © 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
'name': 'Product Expiry Simple',
'version': '8.0.1.0.0',
'category': 'Product',
'license': 'AGPL-3',
'summary': 'Simpler and better alternative to the official product_expiry module',
'description': """
Product Expiry Simple
=====================
This module is similar to the official *product_expiry* modules, but much simpler and much better:
* Only one expiry date field instead of 4 !
* date field instead of datetime
* No automatic computing of expiry date based on a delay configured on product (not needed in most companies)
* colored production lot and stock quant tree views depending on expiry dates
* ability to show stats about expiry dates on quants pivot table (thanks to related stored field on stock.quant)
This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>.
""",
'author': 'Akretion',
'website': 'http://www.akretion.com',
'depends': ['stock'],
'conflicts': ['product_expiry'],
'data': [
'stock_view.xml',
'product_removal_data.xml',
],
'installable': True,
}

View File

@@ -1,53 +0,0 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_expiry_simple
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-02-14 13:19+0000\n"
"PO-Revision-Date: 2017-02-14 13:19+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: product_expiry_simple
#: view:stock.production.lot:product_expiry_simple.search_product_lot_filter
#: view:stock.quant:product_expiry_simple.quant_search_view
msgid "Expired"
msgstr "Périmé"
#. module: product_expiry_simple
#: view:stock.production.lot:product_expiry_simple.search_product_lot_filter
#: field:stock.production.lot,expiry_date:0
#: view:stock.quant:product_expiry_simple.quant_search_view
#: field:stock.quant,expiry_date:0
msgid "Expiry Date"
msgstr "Date de péremption"
#. module: product_expiry_simple
#: model:ir.model,name:product_expiry_simple.model_stock_production_lot
msgid "Lot/Serial"
msgstr "Lot/N° série"
#. module: product_expiry_simple
#: view:stock.production.lot:product_expiry_simple.search_product_lot_filter
#: view:stock.quant:product_expiry_simple.quant_search_view
msgid "Not Expired"
msgstr "Non périmé"
#. module: product_expiry_simple
#: model:ir.model,name:product_expiry_simple.model_stock_quant
msgid "Quants"
msgstr "Quants"
#. module: product_expiry_simple
#: view:stock.production.lot:product_expiry_simple.view_production_lot_tree
#: view:stock.quant:product_expiry_simple.view_stock_quant_tree
msgid "red:expiry_date and expiry_date < current_date;green:expiry_date >= current_date"
msgstr "red:expiry_date and expiry_date < current_date;green:expiry_date >= current_date"

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" ?>
<openerp>
<data>
<record id="removal_fefo" model="product.removal">
<field name="name">First Expiry First Out (FEFO)</field>
<field name="method">fefo</field>
</record>
</data>
</openerp>

View File

@@ -1,43 +0,0 @@
# -*- coding: utf-8 -*-
# © 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields, api
class StockProductionLot(models.Model):
_inherit = 'stock.production.lot'
_rec_name = 'display_name'
expiry_date = fields.Date(string='Expiry Date')
display_name = fields.Char(
compute='compute_display_name_field',
string='Lot/Serial Number Display', store=True, readonly=True)
@api.multi
@api.depends('name', 'expiry_date')
def compute_display_name_field(self):
for lot in self:
dname = lot.name
if lot.expiry_date:
dname = '[%s] %s' % (lot.expiry_date, dname)
lot.display_name = dname
class StockQuant(models.Model):
_inherit = 'stock.quant'
expiry_date = fields.Date(
related='lot_id.expiry_date', store=True, readonly=True)
# method copy/pasted from the official product_expiry module
# © Odoo SA
@api.model
def apply_removal_strategy(
self, location, product, qty, domain, removal_strategy):
if removal_strategy == 'fefo':
order = 'expiry_date, location_id, package_id, lot_id, in_date, id'
return self._quants_get_order(
location, product, qty, domain, order)
return super(StockQuant, self).apply_removal_strategy(
location, product, qty, domain, removal_strategy)

View File

@@ -1,94 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
© 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<openerp>
<data>
<!-- LOTS -->
<record id="view_production_lot_form" model="ir.ui.view">
<field name="name">product_expiry_simple.stock.production.lot.form</field>
<field name="model">stock.production.lot</field>
<field name="inherit_id" ref="stock.view_production_lot_form"/>
<field name="arch" type="xml">
<field name="ref" position="after">
<field name="expiry_date"/>
</field>
</field>
</record>
<record id="view_production_lot_tree" model="ir.ui.view">
<field name="name">product_expiry_simple.stock.production.lot.tree</field>
<field name="model">stock.production.lot</field>
<field name="inherit_id" ref="stock.view_production_lot_tree"/>
<field name="arch" type="xml">
<field name="product_id" position="after">
<field name="expiry_date"/>
</field>
<xpath expr="/tree" position="attributes">
<attribute name="colors">red:expiry_date and expiry_date &lt; current_date;green:expiry_date &gt;= current_date</attribute>
</xpath>
</field>
</record>
<record id="search_product_lot_filter" model="ir.ui.view">
<field name="name">product_expiry_simple.stock.production.lot.search</field>
<field name="model">stock.production.lot</field>
<field name="inherit_id" ref="stock.search_product_lot_filter"/>
<field name="arch" type="xml">
<field name="product_id" position="after">
<filter string="Expired" name="expired"
domain="[('expiry_date', '&lt;', context_today().strftime('%Y-%m-%d'))]"/>
<filter string="Not Expired" name="no-expired"
domain="[('expiry_date', '&gt;=', context_today().strftime('%Y-%m-%d'))]"/>
</field>
<group expand="0" position="inside">
<filter name="expiry_date_groupby" string="Expiry Date"
context="{'group_by': 'expiry_date:month'}"/>
</group>
</field>
</record>
<!-- QUANTS -->
<!-- No need to inherit the form view, because the expiry date is shown in the lot_id via display_name field -->
<record id="view_stock_quant_tree" model="ir.ui.view">
<field name="name">product_expiry_simple.stock.quant.tree</field>
<field name="model">stock.quant</field>
<field name="inherit_id" ref="stock.view_stock_quant_tree"/>
<field name="arch" type="xml">
<field name="lot_id" position="after">
<field name="expiry_date"/>
</field>
<xpath expr="/tree" position="attributes">
<attribute name="colors">red:expiry_date and expiry_date &lt; current_date;green:expiry_date &gt;= current_date</attribute>
</xpath>
</field>
</record>
<record id="quant_search_view" model="ir.ui.view">
<field name="name">product_expiry_simple.stock.quant.search</field>
<field name="model">stock.quant</field>
<field name="inherit_id" ref="stock.quant_search_view"/>
<field name="arch" type="xml">
<filter name="internal_loc" position="after">
<separator/>
<filter string="Expired" name="expired"
domain="[('expiry_date', '&lt;', context_today().strftime('%Y-%m-%d'))]"
groups="stock.group_production_lot"/>
<filter string="Not Expired" name="no-expired"
domain="[('expiry_date', '&gt;=', context_today().strftime('%Y-%m-%d'))]"
groups="stock.group_production_lot"/>
</filter>
<filter context="{'group_by' : 'lot_id'}" position="after">
<filter name="expiry_date_groupby" string="Expiry Date"
context="{'group_by': 'expiry_date:month'}" groups="stock.group_production_lot"/>
</filter>
</field>
</record>
</data>
</openerp>

View File

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

View File

@@ -1,31 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Akretion (http://www.akretion.com).
# @author Sébastien BEAU <sebastien.beau@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "Product Simple Accounting",
"summary": "Simplify the accounting on product, remove accounting tab",
"version": "8.0.1.0.0",
"category": "Uncategorized",
"website": "www.akretion.com",
"author": " Akretion",
"license": "AGPL-3",
"application": False,
"installable": True,
"external_dependencies": {
"python": [],
"bin": [],
},
"depends": [
"product_profile",
"account_product_fiscal_classification",
],
"data": [
"views/product_view.xml",
],
"demo": [
],
"qweb": [
]
}

View File

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

View File

@@ -1,24 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Akretion (http://www.akretion.com).
# @author Sébastien BEAU <sebastien.beau@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import fields, models
class ProductProfile(models.Model):
_inherit = 'product.profile'
def _get_types(self):
return [('product', 'Stockable Product'),
('consu', 'Consumable'),
('service', 'Service')]
property_account_income = fields.Many2one(
'account.account',
'Property Account Income',
company_dependent=True)
property_account_expense = fields.Many2one(
'account.account',
'Property Account Expense',
company_dependent=True)

View File

@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<record id="product_template_view_form" model="ir.ui.view">
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_form_view"/>
<field name="priority" eval="64"/>
<field name="arch" type="xml">
<page string="Accounting" position="replace"/>
<field name="profile_id" position="after">
<field name="categ_id"/>
<field name="fiscal_classification_id" widget="selection"/>
</field>
<field name="standard_price" position="after">
<field name="valuation" attrs="{'invisible':[('type', 'in', ('service', 'consu'))]}"/>
</field>
</field>
</record>
</data>
</openerp>

View File

@@ -1,3 +0,0 @@
# -*- coding: utf-8 -*-
# © 2017 Chafique DELLI @ Akretion
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

View File

@@ -1,23 +0,0 @@
# -*- coding: utf-8 -*-
# © 2017 Chafique DELLI @ Akretion
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
'name': 'Product Unit Manager Group',
'summary': 'Add a group Product Unit of Measure Manager',
'version': '8.0.1.0.0',
'category': 'Product',
'website': 'http://akretion.com',
'author': 'Akretion',
'license': 'AGPL-3',
'installable': True,
'depends': [
'sale',
'purchase',
'mrp',
],
'data': [
'security/product_security.xml',
'security/ir.model.access.csv',
'views/product_view.xml',
],
}

View File

@@ -1,29 +0,0 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_unit_manager_group
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-03-13 15:35+0000\n"
"PO-Revision-Date: 2017-03-13 15:35+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: product_unit_manager_group
#: model:res.groups,comment:product_unit_manager_group.group_uom_manager
#: model:res.groups,name:product_unit_manager_group.group_uom_manager
msgid "Manage Multiple Units of Measure"
msgstr "Gérer plusieurs unités de mesure"
#. module: product_unit_manager_group
#: model:res.groups,comment:product.group_uom
#: model:res.groups,name:product.group_uom
msgid "Use Multiple Units of Measure"
msgstr "Utiliser plusieurs unités de mesure"

View File

@@ -1,13 +0,0 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_product_uom_manager,product.uom.manager,product.model_product_uom,group_uom_manager,1,1,1,1
access_product_uom_categ_manager,product.uom.categ.manager,product.model_product_uom_categ,group_uom_manager,1,1,1,1
access_product_uom_user,product.uom.user,product.model_product_uom,product.group_uom,1,0,0,0
access_product_uom_categ_user,product.uom.categ.user,product.model_product_uom_categ,product.group_uom,1,0,0,0
sale.access_product_uom_sale_manager,product.uom salemanager,product.model_product_uom,base.group_sale_manager,1,0,0,0
sale.access_product_uom_categ_sale_manager,product.uom.categ salemanager,product.model_product_uom_categ,base.group_sale_manager,1,0,0,0
purchase.access_product_uom_purchase_manager,product.uom purchase_manager,product.model_product_uom,purchase.group_purchase_manager,1,0,0,0
purchase.access_product_uom_categ_purchase_manager,product.uom.categ purchase_manager,product.model_product_uom_categ,purchase.group_purchase_manager,1,0,0,0
mrp.access_product_uom_mrp_manager,product.uom mrp_manager,product.model_product_uom,mrp.group_mrp_manager,1,0,0,0
mrp.access_product_uom_categ_mrp_manager,product.uom.categ mrp_manager,product.model_product_uom_categ,mrp.group_mrp_manager,1,0,0,0
stock.access_product_uom_stock_manager,product.uom stock_manager,product.model_product_uom,stock.group_stock_manager,1,0,0,0
stock.access_product_uom_categ_stock_manager,product.uom.categ stock_manager,product.model_product_uom_categ,stock.group_stock_manager,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_product_uom_manager product.uom.manager product.model_product_uom group_uom_manager 1 1 1 1
3 access_product_uom_categ_manager product.uom.categ.manager product.model_product_uom_categ group_uom_manager 1 1 1 1
4 access_product_uom_user product.uom.user product.model_product_uom product.group_uom 1 0 0 0
5 access_product_uom_categ_user product.uom.categ.user product.model_product_uom_categ product.group_uom 1 0 0 0
6 sale.access_product_uom_sale_manager product.uom salemanager product.model_product_uom base.group_sale_manager 1 0 0 0
7 sale.access_product_uom_categ_sale_manager product.uom.categ salemanager product.model_product_uom_categ base.group_sale_manager 1 0 0 0
8 purchase.access_product_uom_purchase_manager product.uom purchase_manager product.model_product_uom purchase.group_purchase_manager 1 0 0 0
9 purchase.access_product_uom_categ_purchase_manager product.uom.categ purchase_manager product.model_product_uom_categ purchase.group_purchase_manager 1 0 0 0
10 mrp.access_product_uom_mrp_manager product.uom mrp_manager product.model_product_uom mrp.group_mrp_manager 1 0 0 0
11 mrp.access_product_uom_categ_mrp_manager product.uom.categ mrp_manager product.model_product_uom_categ mrp.group_mrp_manager 1 0 0 0
12 stock.access_product_uom_stock_manager product.uom stock_manager product.model_product_uom stock.group_stock_manager 1 0 0 0
13 stock.access_product_uom_categ_stock_manager product.uom.categ stock_manager product.model_product_uom_categ stock.group_stock_manager 1 0 0 0

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="0">
<record id="product.group_uom" model="res.groups">
<field name="name">Use Multiple Units of Measure</field>
<field name="comment">Use multiple units of measure</field>
</record>
<record id="group_uom_manager" model="res.groups">
<field name="name">Manage Multiple Units of Measure</field>
<field name="comment">Manage Multiple Units of Measure</field>
<field name="category_id" ref="base.module_category_hidden"/>
<field name="users" eval="[(4, ref('base.user_root'))]"/>
<field name="implied_ids" eval="[(6, 0, [ref('product.group_uom')])]"/>
</record>
</data>
</openerp>

View File

@@ -1,43 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="product.next_id_16" model="ir.ui.menu">
<field name="groups_id" eval="[(6, 0, [ref('product_unit_manager_group.group_uom_manager')])]"/>
</record>
<record id="product.menu_product_uom_form_action" model="ir.ui.menu">
<field name="groups_id" eval="[(6, 0, [ref('product_unit_manager_group.group_uom_manager')])]"/>
</record>
<record id="product.menu_product_uom_categ_form_action" model="ir.ui.menu">
<field name="groups_id" eval="[(6, 0, [ref('product_unit_manager_group.group_uom_manager')])]"/>
</record>
<record id="stock.menu_stock_unit_measure_stock" model="ir.ui.menu">
<field name="groups_id" eval="[(6, 0, [ref('product_unit_manager_group.group_uom_manager')])]"/>
</record>
<record id="stock.menu_stock_uom_categ_form_action" model="ir.ui.menu">
<field name="groups_id" eval="[(6, 0, [ref('product_unit_manager_group.group_uom_manager')])]"/>
</record>
<record id="stock.menu_stock_uom_form_action" model="ir.ui.menu">
<field name="groups_id" eval="[(6, 0, [ref('product_unit_manager_group.group_uom_manager')])]"/>
</record>
<record id="purchase.menu_purchase_unit_measure_purchase" model="ir.ui.menu">
<field name="groups_id" eval="[(6, 0, [ref('product_unit_manager_group.group_uom_manager')])]"/>
</record>
<record id="purchase.menu_purchase_uom_categ_form_action" model="ir.ui.menu">
<field name="groups_id" eval="[(6, 0, [ref('product_unit_manager_group.group_uom_manager')])]"/>
</record>
<record id="purchase.menu_purchase_uom_form_action" model="ir.ui.menu">
<field name="groups_id" eval="[(6, 0, [ref('product_unit_manager_group.group_uom_manager')])]"/>
</record>
</data>
</openerp>

View File

@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*- # -*- encoding: utf-8 -*-
############################################################################## ##############################################################################
# #
# Product Usability module for Odoo # Product Usability module for Odoo
@@ -29,20 +29,3 @@ class ProductTemplate(models.Model):
price_history_ids = fields.One2many( price_history_ids = fields.One2many(
'product.price.history', 'product_template_id', 'product.price.history', 'product_template_id',
string='Product Price History') string='Product Price History')
name = fields.Char(track_visibility='onchange')
type = fields.Selection(track_visibility='onchange')
categ_id = fields.Many2one(track_visibility='onchange')
list_price = fields.Float(track_visibility='onchange')
sale_ok = fields.Boolean(track_visibility='onchange')
active = fields.Boolean(track_visibility='onchange')
state = fields.Selection(track_visibility='onchange')
weight = fields.Float(track_visibility='onchange')
weight_net = fields.Float(track_visibility='onchange')
class ProductProduct(models.Model):
_inherit = 'product.product'
default_code = fields.Char(track_visibility='onchange')
ean13 = fields.Char(track_visibility='onchange')
active = fields.Boolean(track_visibility='onchange')

View File

@@ -85,6 +85,9 @@
<field name="name" position="attributes"> <field name="name" position="attributes">
<attribute name="class"></attribute> <attribute name="class"></attribute>
</field> </field>
<field name="description" position="attributes">
<attribute name="attrs">{'invisible': True}</attribute>
</field>
<!-- END for wider 'name' field --> <!-- END for wider 'name' field -->
</field> </field>
</record> </record>
@@ -125,78 +128,6 @@
</field> </field>
</record> </record>
<record id="product_ul_form_view" model="ir.ui.view">
<field name="name">usability.product.ul.form</field>
<field name="model">product.ul</field>
<field name="inherit_id" ref="product.product_ul_form_view"/>
<field name="arch" type="xml">
<!-- Useusally, the size of packaging is written in cm,
so I propose to use that UoM for size of packaging.
Nothing is written in the native product module about this -->
<field name="height" position="replace">
<label for="height"/>
<div name="height">
<field name="height" class="oe_inline"/>
<label string=" cm" class="oe_inline"/>
</div>
</field>
<field name="width" position="replace">
<label for="width"/>
<div name="width">
<field name="width" class="oe_inline"/>
<label string=" cm" class="oe_inline"/>
</div>
</field>
<field name="length" position="replace">
<label for="length"/>
<div name="length">
<field name="length" class="oe_inline"/>
<label string=" cm" class="oe_inline"/>
</div>
</field>
<field name="weight" position="replace">
<label for="weight"/>
<div name="weight">
<field name="weight" class="oe_inline"/>
<label string=" kg" class="oe_inline"/>
</div>
</field>
</field>
</record>
<record id="product_ul_tree" model="ir.ui.view">
<field name="name">usability.product.ul.tree</field>
<field name="model">product.ul</field>
<field name="inherit_id" ref="product.product_ul_tree"/>
<field name="arch" type="xml">
<field name="type" position="after">
<!-- not so important, but we have room in the tree view, so let's use it -->
<field name="height"/>
<field name="width"/>
<field name="length"/>
<field name="weight"/>
</field>
</field>
</record>
<!-- Add missing search view on product.ul -->
<!-- It doesn't work: when you activate the group by type, it gives a JS error
TypeError: key.indexOf is not a function
-->
<!--
<record id="product_ul_search" model="ir.ui.view">
<field name="name">usability.product.ul.search</field>
<field name="model">product.ul</field>
<field name="arch" type="xml">
<search string="Search Logistic Units">
<field name="name"/>
<group string="Group By" name="groupby">
<filter name="type_groupby" string="Type" context="{'group_by': 'type'}"/>
</group>
</search>
</field>
</record>
-->
</data> </data>
</openerp> </openerp>

View File

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

View File

@@ -1,31 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Akretion (http://www.akretion.com).
# @author Sébastien BEAU <sebastien.beau@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "Product Variant Usability",
"summary": "Improve the product variant usability",
"version": "8.0.1.0.0",
"category": "Uncategorized",
"website": "www.akretion.com",
"author": " Akretion",
"license": "AGPL-3",
"application": False,
"installable": True,
"external_dependencies": {
"python": [],
"bin": [],
},
"depends": [
"attribute_usability",
"product_variant_inactive",
],
"data": [
"views/product_view.xml",
],
"demo": [
],
"qweb": [
]
}

View File

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

View File

@@ -1,16 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright 2017 Akretion (http://www.akretion.com).
# @author Sébastien BEAU <sebastien.beau@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import fields, models
class ProductTemplate(models.Model):
_inherit = 'product.template'
all_product_variant_ids = fields.One2many(
'product.product',
'product_tmpl_id',
'All Product Variant',
domain=['|', ('active', '=', False), ('active', '=', True)])

View File

@@ -1,35 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<openerp>
<data>
<record id="product_template_view_form" model="ir.ui.view">
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_only_form_view"/>
<field name="priority" eval="64"/>
<field name="arch" type="xml">
<field name="attribute_line_ids" position="after">
<field name="all_product_variant_ids" nolabel="1" required="0">
<tree create="0">
<field name="default_code"/>
<field name="attribute_value_ids" widget="many2many_tags"/>
<field name="qty_available"/>
<field name="active" invisible="1"/>
<button type="object"
name="button_activate"
attrs="{'invisible': [('active','=',True)]}"
icon="gtk-stop"/>
<button type="object"
name="button_deactivate"
attrs="{'invisible': [('active','=',False)]}"
icon="gtk-apply"/>
</tree>
</field>
</field>
<xpath expr="//field[@name='product_variant_count']/../.." position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
</field>
</record>
</data>
</openerp>

View File

@@ -277,16 +277,12 @@ class PurchaseSuggestPoCreate(models.TransientModel):
('warehouse_id.company_id', '=', company.id)] ('warehouse_id.company_id', '=', company.id)]
pick_types = spto.search( pick_types = spto.search(
pick_type_dom + [( pick_type_dom + [(
'default_location_dest_id', 'child_of', location.id)]) 'default_location_dest_id',
'child_of',
location.location_id.id)])
# I use location.parent_id.id to support 2 step-receptions # I use location.parent_id.id to support 2 step-receptions
# where the stock.location .type is linked to Warehouse > Receipt # where the stock.location .type is linked to Warehouse > Receipt
# but location is Warehouse > Stock # but location is Warehouse > Stock
if not pick_types:
pick_types = spto.search(
pick_type_dom + [(
'default_location_dest_id',
'child_of',
location.location_id.id)])
if not pick_types: if not pick_types:
pick_types = spto.search(pick_type_dom) pick_types = spto.search(pick_type_dom)
if not pick_types: if not pick_types:

View File

@@ -26,7 +26,6 @@ for any help or question about this module.
'depends': ['purchase'], 'depends': ['purchase'],
'data': [ 'data': [
'purchase_view.xml', 'purchase_view.xml',
'stock_view.xml',
'supplierinfo_view.xml', 'supplierinfo_view.xml',
], ],
'active': False, 'active': False,

View File

@@ -70,7 +70,7 @@ msgstr "Partenaire"
#. module: purchase_usability_extension #. module: purchase_usability_extension
#: view:product.supplierinfo:purchase_usability_extension.product_supplierinfo_view_filter #: view:product.supplierinfo:purchase_usability_extension.product_supplierinfo_view_filter
msgid "Product" msgid "Product"
msgstr "Article" msgstr "Article :"
#. module: purchase_usability_extension #. module: purchase_usability_extension
#: view:product.supplierinfo:purchase_usability_extension.product_supplierinfo_view_filter #: view:product.supplierinfo:purchase_usability_extension.product_supplierinfo_view_filter

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # coding: utf-8
# © 2015-2017 Akretion (http://www.akretion.com) # Copyright (C) 2015 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com> # @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from openerp import models, fields, api from openerp import models, fields, api
@@ -30,15 +30,6 @@ class PurchaseOrder(models.Model):
partner_ref = fields.Char(track_visibility='onchange') partner_ref = fields.Char(track_visibility='onchange')
class StockPicking(models.Model):
_inherit = 'stock.picking'
# Field added to have a clickable link from picking to PO
purchase_id = fields.Many2one(
related='move_lines.purchase_line_id.order_id', readonly=True,
string='Purchase Order')
class ResPartner(models.Model): class ResPartner(models.Model):
_inherit = 'res.partner' _inherit = 'res.partner'
@@ -64,9 +55,3 @@ class ResPartner(models.Model):
compute='_purchase_stats', string='# of Purchase Order') compute='_purchase_stats', string='# of Purchase Order')
supplier_invoice_count = fields.Integer( supplier_invoice_count = fields.Integer(
compute='_purchase_stats', string='# Supplier Invoices') compute='_purchase_stats', string='# Supplier Invoices')
class ProductTemplate(models.Model):
_inherit = 'product.template'
purchase_ok = fields.Boolean(track_visibility='onchange')

View File

@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
© 2017 Akretion (http://www.akretion.com/)
@author: Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<openerp>
<data>
<record id="view_picking_form" model="ir.ui.view">
<field name="name">purchase_usability.stock.picking.form</field>
<field name="model">stock.picking</field>
<field name="inherit_id" ref="stock.view_picking_form"/>
<field name="arch" type="xml">
<field name="origin" position="after">
<field name="purchase_id" attrs="{'invisible': [('picking_type_code', '!=', 'incoming')]}"/>
</field>
</field>
</record>
</data>
</openerp>

View File

@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*- # coding: utf-8
# © 2015 David BEAL @ Akretion # © 2015 David BEAL @ Akretion
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
@@ -8,8 +8,5 @@ from openerp import models, fields
class ProductSupplierinfo(models.Model): class ProductSupplierinfo(models.Model):
_inherit = 'product.supplierinfo' _inherit = 'product.supplierinfo'
# Change product_tmpl_id to required=False supplier_is_company = fields.Boolean(
# because I added that field to form view and it blocks when you save comodel_name='res.partner', related='name.is_company')
# the product form with a new supplier info
# This field is now required in the form view
product_tmpl_id = fields.Many2one(required=False)

Some files were not shown because too many files have changed in this diff Show More