[MERGE] Sync with trunk.
bzr revid: tde@openerp.com-20121128155246-33vcdcysd47uk4k5
This commit is contained in:
@@ -641,8 +641,7 @@ class account_account(osv.osv):
|
||||
return True
|
||||
|
||||
def _check_allow_type_change(self, cr, uid, ids, new_type, context=None):
|
||||
group1 = ['payable', 'receivable', 'other']
|
||||
group2 = ['consolidation','view']
|
||||
restricted_groups = ['consolidation','view']
|
||||
line_obj = self.pool.get('account.move.line')
|
||||
for account in self.browse(cr, uid, ids, context=context):
|
||||
old_type = account.type
|
||||
@@ -650,14 +649,25 @@ class account_account(osv.osv):
|
||||
if line_obj.search(cr, uid, [('account_id', 'in', account_ids)]):
|
||||
#Check for 'Closed' type
|
||||
if old_type == 'closed' and new_type !='closed':
|
||||
raise osv.except_osv(_('Warning!'), _("You cannot change the type of account from 'Closed' to any other type which contains journal items!"))
|
||||
#Check for change From group1 to group2 and vice versa
|
||||
if (old_type in group1 and new_type in group2) or (old_type in group2 and new_type in group1):
|
||||
raise osv.except_osv(_('Warning!'), _("You cannot change the type of account from '%s' to '%s' type as it contains journal items!") % (old_type,new_type,))
|
||||
raise osv.except_osv(_('Warning !'), _("You cannot change the type of account from 'Closed' to any other type as it contains journal items!"))
|
||||
# Forbid to change an account type for restricted_groups as it contains journal items (or if one of its children does)
|
||||
if (new_type in restricted_groups):
|
||||
raise osv.except_osv(_('Warning !'), _("You cannot change the type of account to '%s' type as it contains journal items!") % (new_type,))
|
||||
|
||||
return True
|
||||
|
||||
# For legal reason (forbiden to modify journal entries which belongs to a closed fy or period), Forbid to modify
|
||||
# the code of an account if journal entries have been already posted on this account. This cannot be simply
|
||||
# 'configurable' since it can lead to a lack of confidence in OpenERP and this is what we want to change.
|
||||
def _check_allow_code_change(self, cr, uid, ids, context=None):
|
||||
line_obj = self.pool.get('account.move.line')
|
||||
for account in self.browse(cr, uid, ids, context=context):
|
||||
account_ids = self.search(cr, uid, [('id', 'child_of', [account.id])], context=context)
|
||||
if line_obj.search(cr, uid, [('account_id', 'in', account_ids)], context=context):
|
||||
raise osv.except_osv(_('Warning !'), _("You cannot change the code of account which contains journal items!"))
|
||||
return True
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
|
||||
if context is None:
|
||||
context = {}
|
||||
if not ids:
|
||||
@@ -677,6 +687,8 @@ class account_account(osv.osv):
|
||||
self._check_moves(cr, uid, ids, "write", context=context)
|
||||
if 'type' in vals.keys():
|
||||
self._check_allow_type_change(cr, uid, ids, vals['type'], context=context)
|
||||
if 'code' in vals.keys():
|
||||
self._check_allow_code_change(cr, uid, ids, context=context)
|
||||
return super(account_account, self).write(cr, uid, ids, vals, context=context)
|
||||
|
||||
def unlink(self, cr, uid, ids, context=None):
|
||||
@@ -1470,6 +1482,11 @@ class account_move(osv.osv):
|
||||
raise osv.except_osv(_('User Error!'),
|
||||
_('You cannot delete a posted journal entry "%s".') % \
|
||||
move['name'])
|
||||
for line in move.line_id:
|
||||
if line.invoice:
|
||||
raise osv.except_osv(_('User Error!'),
|
||||
_("Move cannot be deleted if linked to an invoice. (Invoice: %s - Move ID:%s)") % \
|
||||
(line.invoice.number,move.name))
|
||||
line_ids = map(lambda x: x.id, move.line_id)
|
||||
context['journal_id'] = move.journal_id.id
|
||||
context['period_id'] = move.period_id.id
|
||||
@@ -1678,11 +1695,41 @@ class account_move_reconcile(osv.osv):
|
||||
'line_id': fields.one2many('account.move.line', 'reconcile_id', 'Entry Lines'),
|
||||
'line_partial_ids': fields.one2many('account.move.line', 'reconcile_partial_id', 'Partial Entry lines'),
|
||||
'create_date': fields.date('Creation date', readonly=True),
|
||||
'opening_reconciliation': fields.boolean('Opening Entries Reconciliation', help="Is this reconciliation produced by the opening of a new fiscal year ?."),
|
||||
}
|
||||
_defaults = {
|
||||
'name': lambda self,cr,uid,ctx=None: self.pool.get('ir.sequence').get(cr, uid, 'account.reconcile', context=ctx) or '/',
|
||||
}
|
||||
|
||||
# You cannot unlink a reconciliation if it is a opening_reconciliation one,
|
||||
# you should use the generate opening entries wizard for that
|
||||
def unlink(self, cr, uid, ids, context=None):
|
||||
for move_rec in self.browse(cr, uid, ids, context=context):
|
||||
if move_rec.opening_reconciliation:
|
||||
raise osv.except_osv(_('Error!'), _('You cannot unreconcile journal items if they has been generated by the \
|
||||
opening/closing fiscal year process.'))
|
||||
return super(account_move_reconcile, self).unlink(cr, uid, ids, context=context)
|
||||
|
||||
# Look in the line_id and line_partial_ids to ensure the partner is the same or empty
|
||||
# on all lines. We allow that only for opening/closing period
|
||||
def _check_same_partner(self, cr, uid, ids, context=None):
|
||||
for reconcile in self.browse(cr, uid, ids, context=context):
|
||||
move_lines = []
|
||||
if not reconcile.opening_reconciliation:
|
||||
if reconcile.line_id:
|
||||
first_partner = reconcile.line_id[0].partner_id.id
|
||||
move_lines = reconcile.line_id
|
||||
elif reconcile.line_partial_ids:
|
||||
first_partner = reconcile.line_partial_ids[0].partner_id.id
|
||||
move_lines = reconcile.line_partial_ids
|
||||
if any([line.partner_id.id != first_partner for line in move_lines]):
|
||||
return False
|
||||
return True
|
||||
|
||||
_constraints = [
|
||||
(_check_same_partner, 'You can only reconcile journal items with the same partner.', ['line_id']),
|
||||
]
|
||||
|
||||
def reconcile_partial_check(self, cr, uid, ids, type='auto', context=None):
|
||||
total = 0.0
|
||||
for rec in self.browse(cr, uid, ids, context=context):
|
||||
|
||||
@@ -311,7 +311,7 @@ class account_bank_statement(osv.osv):
|
||||
'statement_id': st_line.statement_id.id,
|
||||
'journal_id': st_line.statement_id.journal_id.id,
|
||||
'period_id': st_line.statement_id.period_id.id,
|
||||
'currency_id': cur_id,
|
||||
'currency_id': amount_currency and cur_id,
|
||||
'amount_currency': amount_currency,
|
||||
'analytic_account_id': analytic_id,
|
||||
}
|
||||
|
||||
@@ -1073,8 +1073,9 @@ class account_invoice(osv.osv):
|
||||
self.message_post(cr, uid, [inv_id], body=message, context=context)
|
||||
return True
|
||||
|
||||
def action_cancel(self, cr, uid, ids, *args):
|
||||
context = {} # TODO: Use context from arguments
|
||||
def action_cancel(self, cr, uid, ids, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
account_move_obj = self.pool.get('account.move')
|
||||
invoices = self.read(cr, uid, ids, ['move_id', 'payment_ids'])
|
||||
move_ids = [] # ones that we will need to remove
|
||||
@@ -1244,12 +1245,15 @@ class account_invoice(osv.osv):
|
||||
ref = invoice.reference
|
||||
else:
|
||||
ref = self._convert_ref(cr, uid, invoice.number)
|
||||
partner = invoice.partner_id
|
||||
if partner.parent_id and not partner.is_company:
|
||||
partner = partner.parent_id
|
||||
# Pay attention to the sign for both debit/credit AND amount_currency
|
||||
l1 = {
|
||||
'debit': direction * pay_amount>0 and direction * pay_amount,
|
||||
'credit': direction * pay_amount<0 and - direction * pay_amount,
|
||||
'account_id': src_account_id,
|
||||
'partner_id': invoice.partner_id.id,
|
||||
'partner_id': partner.id,
|
||||
'ref':ref,
|
||||
'date': date,
|
||||
'currency_id':currency_id,
|
||||
@@ -1260,7 +1264,7 @@ class account_invoice(osv.osv):
|
||||
'debit': direction * pay_amount<0 and - direction * pay_amount,
|
||||
'credit': direction * pay_amount>0 and direction * pay_amount,
|
||||
'account_id': pay_account_id,
|
||||
'partner_id': invoice.partner_id.id,
|
||||
'partner_id': partner.id,
|
||||
'ref':ref,
|
||||
'date': date,
|
||||
'currency_id':currency_id,
|
||||
|
||||
@@ -620,12 +620,34 @@ class account_move_line(osv.osv):
|
||||
return False
|
||||
return True
|
||||
|
||||
def _check_currency_and_amount(self, cr, uid, ids, context=None):
|
||||
for l in self.browse(cr, uid, ids, context=context):
|
||||
if (l.amount_currency and not l.currency_id):
|
||||
return False
|
||||
return True
|
||||
|
||||
def _check_currency_amount(self, cr, uid, ids, context=None):
|
||||
for l in self.browse(cr, uid, ids, context=context):
|
||||
if l.amount_currency:
|
||||
if (l.amount_currency > 0.0 and l.credit > 0.0) or (l.amount_currency < 0.0 and l.debit > 0.0):
|
||||
return False
|
||||
return True
|
||||
|
||||
def _check_currency_company(self, cr, uid, ids, context=None):
|
||||
for l in self.browse(cr, uid, ids, context=context):
|
||||
if l.currency_id.id == l.company_id.currency_id.id:
|
||||
return False
|
||||
return True
|
||||
|
||||
_constraints = [
|
||||
(_check_no_view, 'You cannot create journal items on an account of type view.', ['account_id']),
|
||||
(_check_no_closed, 'You cannot create journal items on closed account.', ['account_id']),
|
||||
(_check_company_id, 'Account and Period must belong to the same company.', ['company_id']),
|
||||
(_check_date, 'The date of your Journal Entry is not in the defined period! You should change the date or remove this constraint from the journal.', ['date']),
|
||||
(_check_currency, 'The selected account of your Journal Entry forces to provide a secondary currency. You should remove the secondary currency on the account or select a multi-currency view on the journal.', ['currency_id']),
|
||||
(_check_currency_and_amount, "You cannot create journal items with a secondary currency without recording both 'currency' and 'amount currency' field.", ['currency_id','amount_currency']),
|
||||
(_check_currency_amount, 'The amount expressed in the secondary currency must be positif when journal item are debit and negatif when journal item are credit.', ['amount_currency']),
|
||||
(_check_currency_company, "You cannot provide a secondary currency if it is the same than the company one." , ['currency_id']),
|
||||
]
|
||||
|
||||
#TODO: ONCHANGE_ACCOUNT_ID: set account_tax_id
|
||||
@@ -1111,7 +1133,7 @@ class account_move_line(osv.osv):
|
||||
'has been confirmed.') % res[2])
|
||||
return res
|
||||
|
||||
def _remove_move_reconcile(self, cr, uid, move_ids=None, context=None):
|
||||
def _remove_move_reconcile(self, cr, uid, move_ids=None, opening_reconciliation=False, context=None):
|
||||
# Function remove move rencocile ids related with moves
|
||||
obj_move_line = self.pool.get('account.move.line')
|
||||
obj_move_rec = self.pool.get('account.move.reconcile')
|
||||
@@ -1126,6 +1148,8 @@ class account_move_line(osv.osv):
|
||||
unlink_ids += rec_ids
|
||||
unlink_ids += part_rec_ids
|
||||
if unlink_ids:
|
||||
if opening_reconciliation:
|
||||
obj_move_rec.write(cr, uid, unlink_ids, {'opening_reconciliation': False})
|
||||
obj_move_rec.unlink(cr, uid, unlink_ids)
|
||||
return True
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ class account_fiscalyear_close(osv.osv_memory):
|
||||
cr.execute('select distinct(company_id) from account_move_line where id in %s',(tuple(ids),))
|
||||
if len(cr.fetchall()) > 1:
|
||||
raise osv.except_osv(_('Warning!'), _('The entries to reconcile should belong to the same company.'))
|
||||
r_id = self.pool.get('account.move.reconcile').create(cr, uid, {'type': 'auto'})
|
||||
r_id = self.pool.get('account.move.reconcile').create(cr, uid, {'type': 'auto', 'opening_reconciliation': True})
|
||||
cr.execute('update account_move_line set reconcile_id = %s where id in %s',(r_id, tuple(ids),))
|
||||
return r_id
|
||||
|
||||
@@ -107,7 +107,7 @@ class account_fiscalyear_close(osv.osv_memory):
|
||||
('journal_id', '=', new_journal.id), ('period_id', '=', period.id)])
|
||||
if move_ids:
|
||||
move_line_ids = obj_acc_move_line.search(cr, uid, [('move_id', 'in', move_ids)])
|
||||
obj_acc_move_line._remove_move_reconcile(cr, uid, move_line_ids, context=context)
|
||||
obj_acc_move_line._remove_move_reconcile(cr, uid, move_line_ids, opening_reconciliation=True, context=context)
|
||||
obj_acc_move_line.unlink(cr, uid, move_line_ids, context=context)
|
||||
obj_acc_move.unlink(cr, uid, move_ids, context=context)
|
||||
|
||||
|
||||
@@ -75,15 +75,21 @@ class account_analytic_account(osv.osv):
|
||||
res[id][f] = 0.0
|
||||
res2 = {}
|
||||
for account in accounts:
|
||||
cr.execute("SELECT product_id, user_id, to_invoice, sum(unit_amount), product_uom_id, name " \
|
||||
"FROM account_analytic_line as line " \
|
||||
"WHERE account_id = %s " \
|
||||
"AND invoice_id is NULL AND to_invoice IS NOT NULL " \
|
||||
"GROUP BY product_id, user_id, to_invoice, product_uom_id, name", (account.id,))
|
||||
cr.execute("""
|
||||
SELECT product_id, sum(amount), user_id, to_invoice, sum(unit_amount), product_uom_id, line.name
|
||||
FROM account_analytic_line line
|
||||
LEFT JOIN account_analytic_journal journal ON (journal.id = line.journal_id)
|
||||
WHERE account_id = %s
|
||||
AND journal.type != 'purchase'
|
||||
AND invoice_id IS NULL
|
||||
AND to_invoice IS NOT NULL
|
||||
GROUP BY product_id, user_id, to_invoice, product_uom_id, line.name""", (account.id,))
|
||||
|
||||
res[account.id][f] = 0.0
|
||||
for product_id, user_id, factor_id, qty, uom, line_name in cr.fetchall():
|
||||
price = self.pool.get('account.analytic.line')._get_invoice_price(cr, uid, account, product_id, user_id, qty, context)
|
||||
for product_id, price, user_id, factor_id, qty, uom, line_name in cr.fetchall():
|
||||
price = -price
|
||||
if product_id:
|
||||
price = self.pool.get('account.analytic.line')._get_invoice_price(cr, uid, account, product_id, user_id, qty, context)
|
||||
factor = self.pool.get('hr_timesheet_invoice.factor').browse(cr, uid, factor_id, context=context)
|
||||
res[account.id][f] += price * qty * (100-factor.factor or 0.0) / 100.0
|
||||
|
||||
|
||||
@@ -20,12 +20,29 @@
|
||||
##############################################################################
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from tools.translate import _
|
||||
from osv import fields, osv
|
||||
|
||||
class Invoice(osv.osv):
|
||||
_inherit = 'account.invoice'
|
||||
|
||||
# Forbid to cancel an invoice if the related move lines have already been
|
||||
# used in a payment order. The risk is that importing the payment line
|
||||
# in the bank statement will result in a crash cause no more move will
|
||||
# be found in the payment line
|
||||
def action_cancel(self, cr, uid, ids, context=None):
|
||||
payment_line_obj = self.pool.get('payment.line')
|
||||
for inv in self.browse(cr, uid, ids, context=context):
|
||||
pl_line_ids = []
|
||||
if inv.move_id and inv.move_id.line_id:
|
||||
inv_mv_lines = [x.id for x in inv.move_id.line_id]
|
||||
pl_line_ids = payment_line_obj.search(cr, uid, [('move_line_id','in',inv_mv_lines)], context=context)
|
||||
if pl_line_ids:
|
||||
pay_line = payment_line_obj.browse(cr, uid, pl_line_ids, context=context)
|
||||
payment_order_name = ','.join(map(lambda x: x.order_id.reference, pay_line))
|
||||
raise osv.except_osv(_('Error!'), _("You cannot cancel an invoice which has already been imported in a payment order. Remove it from the following payment order : %s."%(payment_order_name)))
|
||||
return super(Invoice, self).action_cancel(cr, uid, ids, context=context)
|
||||
|
||||
def _amount_to_pay(self, cursor, user, ids, name, args, context=None):
|
||||
'''Return the amount still to pay regarding all the payment orders'''
|
||||
if not ids:
|
||||
|
||||
@@ -1549,6 +1549,15 @@ class account_bank_statement(osv.osv):
|
||||
return move_line_obj.write(cr, uid, [x.id for x in v.move_ids], {'statement_id': st_line.statement_id.id}, context=context)
|
||||
return super(account_bank_statement, self).create_move_from_st_line(cr, uid, st_line.id, company_currency_id, next_number, context=context)
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
# Restrict to modify the journal if we already have some voucher of reconciliation created/generated.
|
||||
# Because the voucher keeps in memory the journal it was created with.
|
||||
for bk_st in self.browse(cr, uid, ids, context=context):
|
||||
if vals.get('journal_id') and bk_st.line_ids:
|
||||
if any([x.voucher_id and True or False for x in bk_st.line_ids]):
|
||||
raise osv.except_osv(_('Unable to change journal !'), _('You can not change the journal as you already reconciled some statement lines!'))
|
||||
return super(account_bank_statement, self).write(cr, uid, ids, vals, context=context)
|
||||
|
||||
account_bank_statement()
|
||||
|
||||
class account_bank_statement_line(osv.osv):
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
-
|
||||
I create a cash account with currency USD
|
||||
-
|
||||
!record {model: account.account, id: account_cash_usd_id}:
|
||||
!record {model: account.account, id: account_cash_usd_id2}:
|
||||
currency_id: base.USD
|
||||
name: "cash account in usd"
|
||||
code: "Xcash usd"
|
||||
code: "Xcash usd2"
|
||||
type: 'liquidity'
|
||||
user_type: "account.data_account_type_cash"
|
||||
|
||||
@@ -56,8 +56,8 @@
|
||||
type: bank
|
||||
analytic_journal_id: account.sit
|
||||
sequence_id: account.sequence_bank_journal
|
||||
default_debit_account_id: account_cash_usd_id
|
||||
default_credit_account_id: account_cash_usd_id
|
||||
default_debit_account_id: account_cash_usd_id2
|
||||
default_credit_account_id: account_cash_usd_id2
|
||||
currency: base.USD
|
||||
company_id: base.main_company
|
||||
view_id: account.account_journal_bank_view
|
||||
|
||||
@@ -65,39 +65,25 @@ class account_analytic_account(osv.osv):
|
||||
|
||||
def _expense_to_invoice_calc(self, cr, uid, ids, name, arg, context=None):
|
||||
res = {}
|
||||
res_final = {}
|
||||
child_ids = tuple(ids) #We don't want consolidation for each of these fields because those complex computation is resource-greedy.
|
||||
for i in child_ids:
|
||||
res[i] = 0.0
|
||||
if not child_ids:
|
||||
return res
|
||||
#We don't want consolidation for each of these fields because those complex computation is resource-greedy.
|
||||
for account in self.pool.get('account.analytic.account').browse(cr, uid, ids, context=context):
|
||||
cr.execute("""
|
||||
SELECT product_id, sum(amount), user_id, to_invoice, sum(unit_amount), product_uom_id, line.name
|
||||
FROM account_analytic_line line
|
||||
LEFT JOIN account_analytic_journal journal ON (journal.id = line.journal_id)
|
||||
WHERE account_id = %s
|
||||
AND journal.type = 'purchase'
|
||||
AND invoice_id IS NULL
|
||||
AND to_invoice IS NOT NULL
|
||||
GROUP BY product_id, user_id, to_invoice, product_uom_id, line.name""", (account.id,))
|
||||
|
||||
if child_ids:
|
||||
cr.execute("""SELECT account_analytic_account.id, \
|
||||
COALESCE(SUM (product_template.list_price * \
|
||||
account_analytic_line.unit_amount * \
|
||||
((100-hr_timesheet_invoice_factor.factor)/100)), 0.0) \
|
||||
AS ca_to_invoice \
|
||||
FROM product_template \
|
||||
JOIN product_product \
|
||||
ON product_template.id = product_product.product_tmpl_id \
|
||||
JOIN account_analytic_line \
|
||||
ON account_analytic_line.product_id = product_product.id \
|
||||
JOIN account_analytic_journal \
|
||||
ON account_analytic_line.journal_id = account_analytic_journal.id \
|
||||
JOIN account_analytic_account \
|
||||
ON account_analytic_account.id = account_analytic_line.account_id \
|
||||
JOIN hr_timesheet_invoice_factor \
|
||||
ON hr_timesheet_invoice_factor.id = account_analytic_account.to_invoice \
|
||||
WHERE account_analytic_account.id IN %s \
|
||||
AND account_analytic_line.invoice_id IS NULL \
|
||||
AND account_analytic_line.to_invoice IS NOT NULL \
|
||||
AND account_analytic_journal.type = 'purchase' \
|
||||
GROUP BY account_analytic_account.id;""",(child_ids,))
|
||||
for account_id, sum in cr.fetchall():
|
||||
res[account_id] = sum
|
||||
res_final = res
|
||||
return res_final
|
||||
res[account.id] = 0.0
|
||||
for product_id, price, user_id, factor_id, qty, uom, line_name in cr.fetchall():
|
||||
#the amount to reinvoice is the real cost. We don't use the pricelist
|
||||
price = -price
|
||||
factor = self.pool.get('hr_timesheet_invoice.factor').browse(cr, uid, factor_id, context=context)
|
||||
res[account.id] += price * qty * (100 - factor.factor or 0.0) / 100.0
|
||||
return res
|
||||
|
||||
def _expense_invoiced_calc(self, cr, uid, ids, name, arg, context=None):
|
||||
lines_obj = self.pool.get('account.analytic.line')
|
||||
|
||||
@@ -36,6 +36,9 @@ openerp.auth_oauth = function(instance) {
|
||||
ev.preventDefault();
|
||||
var index = $(ev.target).data('index');
|
||||
var provider = this.oauth_providers[index];
|
||||
return this.do_oauth_sign_in(provider);
|
||||
},
|
||||
do_oauth_sign_in: function(provider) {
|
||||
var return_url = _.str.sprintf('%s//%s/auth_oauth/signin', location.protocol, location.host);
|
||||
if (instance.session.debug) {
|
||||
return_url += '?debug';
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
from openerp.osv import osv, fields
|
||||
from openerp.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT
|
||||
from openerp.tools.translate import _
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
@@ -54,6 +55,8 @@ class res_users(osv.osv):
|
||||
template = self.pool.get('ir.model.data').get_object(cr, uid, 'auth_reset_password', 'reset_password_email')
|
||||
assert template._name == 'email.template'
|
||||
for user in self.browse(cr, uid, ids, context):
|
||||
if not user.email:
|
||||
raise osv.except_osv(_("Cannot send email: user has no email address."), user.name)
|
||||
self.pool.get('email.template').send_mail(cr, uid, template.id, user.id, context=context)
|
||||
|
||||
return True
|
||||
|
||||
@@ -7,11 +7,17 @@
|
||||
<field name="model">res.users</field>
|
||||
<field name="inherit_id" ref="base.view_users_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<!-- Reset Password button -->
|
||||
<xpath expr="//sheet/*[1]" position="before">
|
||||
<div class="oe_right oe_button_box">
|
||||
<button string="Reset Password" type="object" name="action_reset_password"/>
|
||||
<button string="Reset Password" type="object" name="action_reset_password"
|
||||
help="Send a special url by email to make the user (re)set their password."/>
|
||||
</div>
|
||||
</xpath>
|
||||
<!-- password is never required; one can use Reset Password -->
|
||||
<field name="new_password" position="attributes">
|
||||
<attribute name="attrs">{}</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -150,8 +150,12 @@ class res_users(osv.Model):
|
||||
_inherit = 'res.users'
|
||||
|
||||
def _get_state(self, cr, uid, ids, name, arg, context=None):
|
||||
return dict((user.id, 'new' if not user.login_date else 'reset' if user.signup_token else 'active')
|
||||
for user in self.browse(cr, uid, ids, context))
|
||||
res = {}
|
||||
for user in self.browse(cr, uid, ids, context):
|
||||
res[user.id] = ('reset' if user.signup_valid else
|
||||
'active' if user.login_date else
|
||||
'new')
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
'state': fields.function(_get_state, string='Status', type='selection',
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<!-- Read/Unread actions -->
|
||||
|
||||
<record id="actions_server_crm_meeting_read" model="ir.actions.server">
|
||||
<field name="name">Mark read</field>
|
||||
<field name="name">CRM Meeting: Mark read</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_crm_meeting"/>
|
||||
@@ -23,7 +23,7 @@
|
||||
</record>
|
||||
|
||||
<record id="actions_server_crm_meeting_unread" model="ir.actions.server">
|
||||
<field name="name">Mark unread</field>
|
||||
<field name="name">CRM Meeting: Mark unread</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_crm_meeting"/>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<!-- Read/Unread actions -->
|
||||
<record id="actions_server_crm_lead_unread" model="ir.actions.server">
|
||||
<field name="name">Mark unread</field>
|
||||
<field name="name">CRM Lead: Mark unread</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_crm_lead"/>
|
||||
@@ -22,7 +22,7 @@
|
||||
</record>
|
||||
|
||||
<record id="actions_server_crm_lead_read" model="ir.actions.server">
|
||||
<field name="name">Mark read</field>
|
||||
<field name="name">CRM Lead: Mark read</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_crm_lead"/>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<!-- Read/Unread actions -->
|
||||
<record id="actions_server_crm_phonecall_unread" model="ir.actions.server">
|
||||
<field name="name">Mark unread</field>
|
||||
<field name="name">CRM Phonecall: Mark unread</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_crm_phonecall"/>
|
||||
@@ -22,7 +22,7 @@
|
||||
</record>
|
||||
|
||||
<record id="actions_server_crm_phonecall_read" model="ir.actions.server">
|
||||
<field name="name">Mark read</field>
|
||||
<field name="name">CRM Phonecall: Mark read</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_crm_phonecall"/>
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
|
||||
<!-- Event Read/Unread actions -->
|
||||
<record id="actions_server_event_event_unread" model="ir.actions.server">
|
||||
<field name="name">Mark unread</field>
|
||||
<field name="name">Event: Mark unread</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_event_event"/>
|
||||
@@ -77,7 +77,7 @@
|
||||
</record>
|
||||
|
||||
<record id="actions_server_event_event_read" model="ir.actions.server">
|
||||
<field name="name">Mark read</field>
|
||||
<field name="name">Event: Mark read</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_event_event"/>
|
||||
@@ -377,7 +377,7 @@
|
||||
|
||||
<!-- Registration Read/Unread actions -->
|
||||
<record id="actions_server_event_registration_unread" model="ir.actions.server">
|
||||
<field name="name">Mark unread</field>
|
||||
<field name="name">Event registration : Mark unread</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_event_registration"/>
|
||||
@@ -395,7 +395,7 @@
|
||||
</record>
|
||||
|
||||
<record id="actions_server_event_registration_read" model="ir.actions.server">
|
||||
<field name="name">Mark read</field>
|
||||
<field name="name">Event registration : Mark read</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_event_registration"/>
|
||||
|
||||
@@ -318,12 +318,7 @@
|
||||
|
||||
</ul>
|
||||
|
||||
<div class="oe_kanban_partner_categories">
|
||||
<span class="oe_kanban_list_many2many">
|
||||
<div modifiers="{}" name="tag_ids" class="oe_form_field oe_tags" model="fleet.vehicle.tag" t-att-data="record.tag_ids.raw_value" />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<field name="tag_ids"/>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<!-- Hr holidays Read/Unread actions -->
|
||||
<record id="actions_server_holidays_unread" model="ir.actions.server">
|
||||
<field name="name">Mark unread</field>
|
||||
<field name="name">Holidays: Mark unread</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_hr_holidays"/>
|
||||
@@ -21,7 +21,7 @@
|
||||
</record>
|
||||
|
||||
<record id="actions_server_holidays_read" model="ir.actions.server">
|
||||
<field name="name">Mark read</field>
|
||||
<field name="name">Holidays: Mark read</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_hr_holidays"/>
|
||||
|
||||
@@ -60,7 +60,6 @@ You can define the different phases of interviews and easily rate the applicant
|
||||
'hr_recruitment_data.xml'
|
||||
],
|
||||
'demo': ['hr_recruitment_demo.yml'],
|
||||
'js': ['static/src/js/hr_recruitment.js'],
|
||||
'test': ['test/recruitment_process.yml'],
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
<!-- Jobs -->
|
||||
<!-- Applicant Read/Unread actions -->
|
||||
<record id="actions_server_applicant_unread" model="ir.actions.server">
|
||||
<field name="name">Mark unread</field>
|
||||
<field name="name">HR Applicant: Mark unread</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_hr_applicant"/>
|
||||
@@ -55,7 +55,7 @@
|
||||
</record>
|
||||
|
||||
<record id="actions_server_applicant_read" model="ir.actions.server">
|
||||
<field name="name">Mark read</field>
|
||||
<field name="name">HR Applicant: Mark read</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_hr_applicant"/>
|
||||
@@ -314,9 +314,7 @@
|
||||
|
||||
</div>
|
||||
<div class="oe_kanban_footer_left" style="margin-top:5px;">
|
||||
<div class="oe_left oe_tags">
|
||||
<field name="categ_ids"/>
|
||||
</div>
|
||||
<field name="categ_ids"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oe_clear"></div>
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
openerp.hr_recruitment = function(openerp) {
|
||||
openerp.web_kanban.KanbanView.include({
|
||||
applicant_display_categ_names: function() {
|
||||
/*
|
||||
* Set proper names to applicant categories.
|
||||
* In kanban views, many2many fields only return a list of ids.
|
||||
* Therefore, we have to fetch the matching data by ourselves.
|
||||
*/
|
||||
var self = this;
|
||||
var categ_ids = [];
|
||||
|
||||
// Collect categories ids
|
||||
self.$el.find('span[data-categ_id]').each(function() {
|
||||
categ_ids.push($(this).data('categ_id'));
|
||||
});
|
||||
|
||||
// Find their matching names
|
||||
var dataset = new openerp.web.DataSetSearch(self, 'hr.applicant_category', self.session.context, [['id', 'in', _.uniq(categ_ids)]]);
|
||||
dataset.read_slice(['id', 'name']).done(function(result) {
|
||||
_.each(result, function(v, k) {
|
||||
// Set the proper value in the DOM and display the element
|
||||
self.$el.find('span[data-categ_id=' + v.id + ']').text(v.name);
|
||||
});
|
||||
});
|
||||
},
|
||||
on_groups_started: function() {
|
||||
var self = this;
|
||||
self._super.apply(self, arguments);
|
||||
|
||||
if (self.dataset.model === 'hr.applicant') {
|
||||
self.applicant_display_categ_names();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -19,8 +19,9 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from osv import fields, osv
|
||||
import time
|
||||
|
||||
from osv import fields, osv
|
||||
from tools.translate import _
|
||||
|
||||
class hr_timesheet_invoice_factor(osv.osv):
|
||||
@@ -172,6 +173,143 @@ class account_analytic_line(osv.osv):
|
||||
return super(account_analytic_line, self).copy(cursor, user, obj_id,
|
||||
default, context=context)
|
||||
|
||||
def _get_invoice_price(self, cr, uid, account, product_id, user_id, qty, context = {}):
|
||||
pro_price_obj = self.pool.get('product.pricelist')
|
||||
if account.pricelist_id:
|
||||
pl = account.pricelist_id.id
|
||||
price = pro_price_obj.price_get(cr,uid,[pl], product_id, qty or 1.0, account.partner_id.id, context=context)[pl]
|
||||
else:
|
||||
price = 0.0
|
||||
return price
|
||||
|
||||
def invoice_cost_create(self, cr, uid, ids, data=None, context=None):
|
||||
analytic_account_obj = self.pool.get('account.analytic.account')
|
||||
account_payment_term_obj = self.pool.get('account.payment.term')
|
||||
invoice_obj = self.pool.get('account.invoice')
|
||||
product_obj = self.pool.get('product.product')
|
||||
invoice_factor_obj = self.pool.get('hr_timesheet_invoice.factor')
|
||||
fiscal_pos_obj = self.pool.get('account.fiscal.position')
|
||||
product_uom_obj = self.pool.get('product.uom')
|
||||
invoice_line_obj = self.pool.get('account.invoice.line')
|
||||
invoices = []
|
||||
if context is None:
|
||||
context = {}
|
||||
if data is None:
|
||||
data = {}
|
||||
|
||||
journal_types = {}
|
||||
for line in self.pool.get('account.analytic.line').browse(cr, uid, ids, context=context):
|
||||
if line.journal_id.type not in journal_types:
|
||||
journal_types[line.journal_id.type] = set()
|
||||
journal_types[line.journal_id.type].add(line.account_id.id)
|
||||
for journal_type, account_ids in journal_types.items():
|
||||
for account in analytic_account_obj.browse(cr, uid, list(account_ids), context=context):
|
||||
partner = account.partner_id
|
||||
if (not partner) or not (account.pricelist_id):
|
||||
raise osv.except_osv(_('Analytic Account incomplete !'),
|
||||
_('Contract incomplete. Please fill in the Customer and Pricelist fields.'))
|
||||
|
||||
date_due = False
|
||||
if partner.property_payment_term:
|
||||
pterm_list= account_payment_term_obj.compute(cr, uid,
|
||||
partner.property_payment_term.id, value=1,
|
||||
date_ref=time.strftime('%Y-%m-%d'))
|
||||
if pterm_list:
|
||||
pterm_list = [line[0] for line in pterm_list]
|
||||
pterm_list.sort()
|
||||
date_due = pterm_list[-1]
|
||||
|
||||
curr_invoice = {
|
||||
'name': time.strftime('%d/%m/%Y') + ' - '+account.name,
|
||||
'partner_id': account.partner_id.id,
|
||||
'company_id': account.company_id.id,
|
||||
'payment_term': partner.property_payment_term.id or False,
|
||||
'account_id': partner.property_account_receivable.id,
|
||||
'currency_id': account.pricelist_id.currency_id.id,
|
||||
'date_due': date_due,
|
||||
'fiscal_position': account.partner_id.property_account_position.id
|
||||
}
|
||||
|
||||
context2 = context.copy()
|
||||
context2['lang'] = partner.lang
|
||||
# set company_id in context, so the correct default journal will be selected
|
||||
context2['force_company'] = curr_invoice['company_id']
|
||||
# set force_company in context so the correct product properties are selected (eg. income account)
|
||||
context2['company_id'] = curr_invoice['company_id']
|
||||
|
||||
last_invoice = invoice_obj.create(cr, uid, curr_invoice, context=context2)
|
||||
invoices.append(last_invoice)
|
||||
|
||||
cr.execute("""SELECT product_id, user_id, to_invoice, sum(unit_amount), product_uom_id
|
||||
FROM account_analytic_line as line LEFT JOIN account_analytic_journal journal ON (line.journal_id = journal.id)
|
||||
WHERE account_id = %s
|
||||
AND line.id IN %s AND journal.type = %s AND to_invoice IS NOT NULL
|
||||
GROUP BY product_id, user_id, to_invoice, product_uom_id""", (account.id, tuple(ids), journal_type))
|
||||
|
||||
for product_id, user_id, factor_id, qty, uom in cr.fetchall():
|
||||
if data.get('product'):
|
||||
product_id = data['product'][0]
|
||||
product = product_obj.browse(cr, uid, product_id, context=context2)
|
||||
if not product:
|
||||
raise osv.except_osv(_('Error!'), _('There is no product defined. Please select one or force the product through the wizard.'))
|
||||
factor = invoice_factor_obj.browse(cr, uid, factor_id, context=context2)
|
||||
factor_name = product_obj.name_get(cr, uid, [product_id], context=context2)[0][1]
|
||||
if factor.customer_name:
|
||||
factor_name += ' - ' + factor.customer_name
|
||||
|
||||
ctx = context.copy()
|
||||
ctx.update({'uom':uom})
|
||||
|
||||
price = self._get_invoice_price(cr, uid, account, product_id, user_id, qty, ctx)
|
||||
|
||||
general_account = product.product_tmpl_id.property_account_income or product.categ_id.property_account_income_categ
|
||||
if not general_account:
|
||||
raise osv.except_osv(_("Configuration Error!"), _("Please define income account for product '%s'.") % product.name)
|
||||
taxes = product.taxes_id or general_account.tax_ids
|
||||
tax = fiscal_pos_obj.map_tax(cr, uid, account.partner_id.property_account_position, taxes)
|
||||
curr_line = {
|
||||
'price_unit': price,
|
||||
'quantity': qty,
|
||||
'discount':factor.factor,
|
||||
'invoice_line_tax_id': [(6,0,tax )],
|
||||
'invoice_id': last_invoice,
|
||||
'name': factor_name,
|
||||
'product_id': product_id,
|
||||
'invoice_line_tax_id': [(6,0,tax)],
|
||||
'uos_id': uom,
|
||||
'account_id': general_account.id,
|
||||
'account_analytic_id': account.id,
|
||||
}
|
||||
|
||||
#
|
||||
# Compute for lines
|
||||
#
|
||||
cr.execute("SELECT * FROM account_analytic_line WHERE account_id = %s and id IN %s AND product_id=%s and to_invoice=%s ORDER BY account_analytic_line.date", (account.id, tuple(ids), product_id, factor_id))
|
||||
|
||||
line_ids = cr.dictfetchall()
|
||||
note = []
|
||||
for line in line_ids:
|
||||
# set invoice_line_note
|
||||
details = []
|
||||
if data.get('date', False):
|
||||
details.append(line['date'])
|
||||
if data.get('time', False):
|
||||
if line['product_uom_id']:
|
||||
details.append("%s %s" % (line['unit_amount'], product_uom_obj.browse(cr, uid, [line['product_uom_id']],context2)[0].name))
|
||||
else:
|
||||
details.append("%s" % (line['unit_amount'], ))
|
||||
if data.get('name', False):
|
||||
details.append(line['name'])
|
||||
note.append(u' - '.join(map(lambda x: unicode(x) or '',details)))
|
||||
|
||||
if note:
|
||||
curr_line['name'] += "\n" + ("\n".join(map(lambda x: unicode(x) or '',note)))
|
||||
invoice_line_obj.create(cr, uid, curr_line, context=context)
|
||||
cr.execute("update account_analytic_line set invoice_id=%s WHERE account_id = %s and id IN %s", (last_invoice, account.id, tuple(ids)))
|
||||
|
||||
invoice_obj.button_reset_taxes(cr, uid, [last_invoice], context)
|
||||
return invoices
|
||||
|
||||
account_analytic_line()
|
||||
|
||||
|
||||
|
||||
@@ -19,163 +19,10 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import time
|
||||
|
||||
from osv import osv, fields
|
||||
from tools.translate import _
|
||||
|
||||
## Create an invoice based on selected timesheet lines
|
||||
#
|
||||
|
||||
class account_analytic_line(osv.osv):
|
||||
_inherit = "account.analytic.line"
|
||||
def _get_invoice_price(self, cr, uid, account, product_id, user_id, qty, context = {}):
|
||||
pro_price_obj = self.pool.get('product.pricelist')
|
||||
if account.pricelist_id:
|
||||
pl = account.pricelist_id.id
|
||||
price = pro_price_obj.price_get(cr,uid,[pl], product_id, qty or 1.0, account.partner_id.id, context=context)[pl]
|
||||
else:
|
||||
price = 0.0
|
||||
return price
|
||||
|
||||
|
||||
#
|
||||
# data = {
|
||||
# 'date': boolean
|
||||
# 'time': boolean
|
||||
# 'name': boolean
|
||||
# 'price': boolean
|
||||
# 'product': many2one id
|
||||
# }
|
||||
def invoice_cost_create(self, cr, uid, ids, data=None, context=None):
|
||||
analytic_account_obj = self.pool.get('account.analytic.account')
|
||||
account_payment_term_obj = self.pool.get('account.payment.term')
|
||||
invoice_obj = self.pool.get('account.invoice')
|
||||
product_obj = self.pool.get('product.product')
|
||||
invoice_factor_obj = self.pool.get('hr_timesheet_invoice.factor')
|
||||
fiscal_pos_obj = self.pool.get('account.fiscal.position')
|
||||
product_uom_obj = self.pool.get('product.uom')
|
||||
invoice_line_obj = self.pool.get('account.invoice.line')
|
||||
invoices = []
|
||||
if context is None:
|
||||
context = {}
|
||||
if data is None:
|
||||
data = {}
|
||||
|
||||
account_ids = [line.account_id.id for line in self.pool.get('account.analytic.line').browse(cr, uid, ids, context=context)]
|
||||
for account in analytic_account_obj.browse(cr, uid, account_ids, context=context):
|
||||
partner = account.partner_id
|
||||
if (not partner) or not (account.pricelist_id):
|
||||
raise osv.except_osv(_('Analytic Account incomplete !'),
|
||||
_('Contract incomplete. Please fill in the Customer and Pricelist fields.'))
|
||||
|
||||
|
||||
|
||||
date_due = False
|
||||
if partner.property_payment_term:
|
||||
pterm_list= account_payment_term_obj.compute(cr, uid,
|
||||
partner.property_payment_term.id, value=1,
|
||||
date_ref=time.strftime('%Y-%m-%d'))
|
||||
if pterm_list:
|
||||
pterm_list = [line[0] for line in pterm_list]
|
||||
pterm_list.sort()
|
||||
date_due = pterm_list[-1]
|
||||
|
||||
curr_invoice = {
|
||||
'name': time.strftime('%d/%m/%Y')+' - '+account.name,
|
||||
'partner_id': account.partner_id.id,
|
||||
'company_id': account.company_id.id,
|
||||
'payment_term': partner.property_payment_term.id or False,
|
||||
'account_id': partner.property_account_receivable.id,
|
||||
'currency_id': account.pricelist_id.currency_id.id,
|
||||
'date_due': date_due,
|
||||
'fiscal_position': account.partner_id.property_account_position.id
|
||||
}
|
||||
|
||||
context2 = context.copy()
|
||||
context2['lang'] = partner.lang
|
||||
# set company_id in context, so the correct default journal will be selected
|
||||
context2['force_company'] = curr_invoice['company_id']
|
||||
# set force_company in context so the correct product properties are selected (eg. income account)
|
||||
context2['company_id'] = curr_invoice['company_id']
|
||||
|
||||
last_invoice = invoice_obj.create(cr, uid, curr_invoice, context=context2)
|
||||
invoices.append(last_invoice)
|
||||
|
||||
cr.execute("SELECT product_id, user_id, to_invoice, sum(unit_amount), product_uom_id " \
|
||||
"FROM account_analytic_line as line " \
|
||||
"WHERE account_id = %s " \
|
||||
"AND id IN %s AND to_invoice IS NOT NULL " \
|
||||
"GROUP BY product_id, user_id, to_invoice, product_uom_id", (account.id, tuple(ids),))
|
||||
|
||||
for product_id, user_id, factor_id, qty, uom in cr.fetchall():
|
||||
if data.get('product'):
|
||||
product_id = data['product'][0]
|
||||
product = product_obj.browse(cr, uid, product_id, context=context2)
|
||||
if not product:
|
||||
raise osv.except_osv(_('Error!'), _('There is no product defined. Please select one or force the product through the wizard.'))
|
||||
factor = invoice_factor_obj.browse(cr, uid, factor_id, context=context2)
|
||||
factor_name = product_obj.name_get(cr, uid, [product_id], context=context2)[0][1]
|
||||
if factor.customer_name:
|
||||
factor_name += ' - ' + factor.customer_name
|
||||
|
||||
ctx = context.copy()
|
||||
ctx.update({'uom':uom})
|
||||
|
||||
price = self._get_invoice_price(cr, uid, account, product_id, user_id, qty, ctx)
|
||||
|
||||
general_account = product.product_tmpl_id.property_account_income or product.categ_id.property_account_income_categ
|
||||
if not general_account:
|
||||
raise osv.except_osv(_("Configuration Error!"), _("Please define income account for product '%s'.") % product.name)
|
||||
taxes = product.taxes_id or general_account.tax_ids
|
||||
tax = fiscal_pos_obj.map_tax(cr, uid, account.partner_id.property_account_position, taxes)
|
||||
curr_line = {
|
||||
'price_unit': price,
|
||||
'quantity': qty,
|
||||
'discount':factor.factor,
|
||||
'invoice_line_tax_id': [(6,0,tax )],
|
||||
'invoice_id': last_invoice,
|
||||
'name': factor_name,
|
||||
'product_id': product_id,
|
||||
'invoice_line_tax_id': [(6,0,tax)],
|
||||
'uos_id': uom,
|
||||
'account_id': general_account.id,
|
||||
'account_analytic_id': account.id,
|
||||
}
|
||||
|
||||
#
|
||||
# Compute for lines
|
||||
#
|
||||
cr.execute("SELECT * FROM account_analytic_line WHERE account_id = %s and id IN %s AND product_id=%s and to_invoice=%s ORDER BY account_analytic_line.date", (account.id, tuple(ids), product_id, factor_id))
|
||||
|
||||
line_ids = cr.dictfetchall()
|
||||
note = []
|
||||
for line in line_ids:
|
||||
# set invoice_line_note
|
||||
details = []
|
||||
if data.get('date', False):
|
||||
details.append(line['date'])
|
||||
if data.get('time', False):
|
||||
if line['product_uom_id']:
|
||||
details.append("%s %s" % (line['unit_amount'], product_uom_obj.browse(cr, uid, [line['product_uom_id']],context2)[0].name))
|
||||
else:
|
||||
details.append("%s" % (line['unit_amount'], ))
|
||||
if data.get('name', False):
|
||||
details.append(line['name'])
|
||||
note.append(u' - '.join(map(lambda x: unicode(x) or '',details)))
|
||||
|
||||
if note:
|
||||
curr_line['name'] += "\n" + ("\n".join(map(lambda x: unicode(x) or '',note)))
|
||||
invoice_line_obj.create(cr, uid, curr_line, context=context)
|
||||
cr.execute("update account_analytic_line set invoice_id=%s WHERE account_id = %s and id IN %s", (last_invoice, account.id, tuple(ids)))
|
||||
|
||||
invoice_obj.button_reset_taxes(cr, uid, [last_invoice], context)
|
||||
return invoices
|
||||
|
||||
#
|
||||
# TODO: check unit of measure !!!
|
||||
#
|
||||
|
||||
class hr_timesheet_invoice_create(osv.osv_memory):
|
||||
|
||||
_name = 'hr.timesheet.invoice.create'
|
||||
@@ -189,8 +36,8 @@ class hr_timesheet_invoice_create(osv.osv_memory):
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'date': lambda *args: 1,
|
||||
'name': lambda *args: 1
|
||||
'date': 1,
|
||||
'name': 1,
|
||||
}
|
||||
|
||||
def view_init(self, cr, uid, fields, context=None):
|
||||
@@ -210,6 +57,7 @@ class hr_timesheet_invoice_create(osv.osv_memory):
|
||||
|
||||
def do_create(self, cr, uid, ids, context=None):
|
||||
data = self.read(cr, uid, ids, [], context=context)[0]
|
||||
# Create an invoice based on selected timesheet lines
|
||||
invs = self.pool.get('account.analytic.line').invoice_cost_create(cr, uid, context['active_ids'], data, context=context)
|
||||
mod_obj = self.pool.get('ir.model.data')
|
||||
act_obj = self.pool.get('ir.actions.act_window')
|
||||
|
||||
@@ -483,16 +483,16 @@ class Invoice(osv.osv):
|
||||
'''Invoice'''
|
||||
_inherit = 'account.invoice'
|
||||
|
||||
def action_cancel(self, cr, uid, ids, *args):
|
||||
def action_cancel(self, cr, uid, ids, context=None):
|
||||
'''Create a 'date_cancel' on the membership_line object'''
|
||||
member_line_obj = self.pool.get('membership.membership_line')
|
||||
today = time.strftime('%Y-%m-%d')
|
||||
for invoice in self.browse(cr, uid, ids):
|
||||
for invoice in self.browse(cr, uid, ids, context=context):
|
||||
mlines = member_line_obj.search(cr, uid,
|
||||
[('account_invoice_line', 'in',
|
||||
[l.id for l in invoice.invoice_line])])
|
||||
member_line_obj.write(cr, uid, mlines, {'date_cancel': today})
|
||||
return super(Invoice, self).action_cancel(cr, uid, ids)
|
||||
return super(Invoice, self).action_cancel(cr, uid, ids, context=context)
|
||||
|
||||
Invoice()
|
||||
|
||||
|
||||
@@ -213,8 +213,10 @@ function openerp_pos_db(instance, module){
|
||||
var stored_products = this.load('products',{});
|
||||
var product_ids = stored_categories[category_id];
|
||||
var list = [];
|
||||
for(var i = 0, len = Math.min(product_ids.length,this.limit); i < len; i++){
|
||||
list.push(stored_products[product_ids[i]]);
|
||||
if (product_ids) {
|
||||
for (var i = 0, len = Math.min(product_ids.length, this.limit); i < len; i++) {
|
||||
list.push(stored_products[product_ids[i]]);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
},
|
||||
|
||||
@@ -24,12 +24,7 @@
|
||||
<field name="version_id"/>
|
||||
</div>
|
||||
<div class="oe_kanban_footer_left">
|
||||
<div class="oe_left oe_tags">
|
||||
<t t-foreach="record.categ_ids.raw_value" t-as="categ_id">
|
||||
<span class="oe_tag" t-att-data-categ_id="categ_id"></span>
|
||||
</t>
|
||||
<field name="categ_ids"/>
|
||||
</div>
|
||||
<field name="categ_ids"/>
|
||||
<div class="oe_right">
|
||||
Creation: <field name="create_date"/>
|
||||
<span class="oe_kanban_highlight">
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
<!-- Project Read/Unread actions -->
|
||||
<record id="actions_server_project_unread" model="ir.actions.server">
|
||||
<field name="name">Mark unread</field>
|
||||
<field name="name">Project: Mark unread</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_project_project"/>
|
||||
@@ -39,7 +39,7 @@
|
||||
</record>
|
||||
|
||||
<record id="actions_server_project_read" model="ir.actions.server">
|
||||
<field name="name">Mark read</field>
|
||||
<field name="name">Project: Mark read</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_project_project"/>
|
||||
@@ -344,7 +344,7 @@
|
||||
|
||||
<!-- Task Read/Unread actions -->
|
||||
<record id="actions_server_project_task_unread" model="ir.actions.server">
|
||||
<field name="name">Mark unread</field>
|
||||
<field name="name">Task: Mark unread</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_project_task"/>
|
||||
@@ -362,7 +362,7 @@
|
||||
</record>
|
||||
|
||||
<record id="actions_server_project_task_read" model="ir.actions.server">
|
||||
<field name="name">Mark read</field>
|
||||
<field name="name">Task: Mark read</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_project_task"/>
|
||||
@@ -546,11 +546,7 @@
|
||||
</span>
|
||||
</div>
|
||||
<div class="oe_kanban_footer_left" style="margin-top:5px;">
|
||||
<div class="oe_left oe_tags">
|
||||
<t t-foreach="record.categ_ids.raw_value" t-as="categ_id">
|
||||
<span class="oe_tag" t-att-data-categ_id="categ_id"></span>
|
||||
</t>
|
||||
</div>
|
||||
<field name="categ_ids"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oe_clear"></div>
|
||||
|
||||
@@ -25,37 +25,12 @@ openerp.project = function(openerp) {
|
||||
});
|
||||
});
|
||||
},
|
||||
project_display_categ_names: function() {
|
||||
/*
|
||||
* Set proper names to project categories.
|
||||
* In kanban views, many2many fields only return a list of ids.
|
||||
* Therefore, we have to fetch the matching data by ourselves.
|
||||
*/
|
||||
var self = this;
|
||||
var categ_ids = [];
|
||||
|
||||
// Collect categories ids
|
||||
self.$el.find('span[data-categ_id]').each(function() {
|
||||
categ_ids.push($(this).data('categ_id'));
|
||||
});
|
||||
|
||||
// Find their matching names
|
||||
var dataset = new openerp.web.DataSetSearch(self, 'project.category', self.session.context, [['id', 'in', _.uniq(categ_ids)]]);
|
||||
dataset.read_slice(['id', 'name']).done(function(result) {
|
||||
_.each(result, function(v, k) {
|
||||
// Set the proper value in the DOM and display the element
|
||||
self.$el.find('span[data-categ_id=' + v.id + ']').text(v.name);
|
||||
});
|
||||
});
|
||||
},
|
||||
on_groups_started: function() {
|
||||
var self = this;
|
||||
self._super.apply(self, arguments);
|
||||
|
||||
if (self.dataset.model === 'project.project') {
|
||||
self.project_display_members_names();
|
||||
} else if (self.dataset.model === 'project.task') {
|
||||
self.project_display_categ_names();
|
||||
}
|
||||
},
|
||||
on_record_moved: function(record, old_group, old_index, new_group, new_index){
|
||||
@@ -74,9 +49,5 @@ openerp.project = function(openerp) {
|
||||
this._super.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
bind_events: function() {
|
||||
this._super();
|
||||
this.view.project_display_categ_names();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -61,7 +61,6 @@ It allows the manager to quickly check the issues, assign them and decide on the
|
||||
'installable': True,
|
||||
'auto_install': False,
|
||||
'application': True,
|
||||
'js': ['static/src/js/project_issue.js'],
|
||||
}
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<!-- Project issue Read/Unread actions -->
|
||||
<record id="actions_server_project_issue_unread" model="ir.actions.server">
|
||||
<field name="name">Mark unread</field>
|
||||
<field name="name">Issue: Mark unread</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_project_issue"/>
|
||||
@@ -24,7 +24,7 @@
|
||||
</record>
|
||||
|
||||
<record id="actions_server_project_issue_read" model="ir.actions.server">
|
||||
<field name="name">Mark read</field>
|
||||
<field name="name">Issue: Mark read</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_project_issue"/>
|
||||
@@ -264,9 +264,7 @@
|
||||
<field name="version_id"/>
|
||||
</div>
|
||||
<div class="oe_kanban_footer_left">
|
||||
<div class="oe_left oe_tags">
|
||||
<field name="categ_ids"/>
|
||||
</div>
|
||||
<field name="categ_ids"/>
|
||||
<div class="oe_right">
|
||||
<span class="oe_kanban_highlight">
|
||||
<t t-set="priority" t-value="record.priority.raw_value || 5"/>
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
openerp.portal_project_issue = function(openerp) {
|
||||
openerp.web_kanban.KanbanView.include({
|
||||
on_groups_started: function() {
|
||||
var self = this;
|
||||
self._super.apply(this, arguments);
|
||||
|
||||
if (self.dataset.model === 'project.issue') {
|
||||
// Load project's categories names from m2m field
|
||||
self.project_display_categ_names();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -134,7 +134,7 @@
|
||||
|
||||
<!-- Purchase order Read/Unread actions -->
|
||||
<record id="actions_server_purchase_order_unread" model="ir.actions.server">
|
||||
<field name="name">Mark unread</field>
|
||||
<field name="name">Purchase: Mark unread</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_purchase_order"/>
|
||||
@@ -152,7 +152,7 @@
|
||||
</record>
|
||||
|
||||
<record id="actions_server_purchase_order_read" model="ir.actions.server">
|
||||
<field name="name">Mark read</field>
|
||||
<field name="name">Purchase: Mark read</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_purchase_order"/>
|
||||
|
||||
@@ -149,11 +149,6 @@
|
||||
<para style="terp_default_Right_9">[[ (order_line.product_uom and order_line.product_uom.name) or '' ]]</para>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<para style="terp_default_8_italic">[[ format(order_line.notes or removeParentNode('tr')) ]]</para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
</section>
|
||||
<para style="terp_default_9">
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
|
||||
<!-- Sale order Read/Unread actions -->
|
||||
<record id="actions_server_sale_order_unread" model="ir.actions.server">
|
||||
<field name="name">Mark unread</field>
|
||||
<field name="name">Sale: Mark unread</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_sale_order"/>
|
||||
@@ -86,7 +86,7 @@
|
||||
</record>
|
||||
|
||||
<record id="actions_server_sale_order_read" model="ir.actions.server">
|
||||
<field name="name">Mark read</field>
|
||||
<field name="name">Sale: Mark read</field>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="model_id" ref="model_sale_order"/>
|
||||
|
||||
Reference in New Issue
Block a user