diff --git a/addons/account/account_bank_statement.py b/addons/account/account_bank_statement.py
index 572cb9d04fd..e0d31b9cf18 100644
--- a/addons/account/account_bank_statement.py
+++ b/addons/account/account_bank_statement.py
@@ -159,7 +159,7 @@ class account_bank_statement(osv.osv):
'period_id': _get_period,
}
- def button_confirm(self, cr, uid, ids, context={}):
+ def button_confirm_bank(self, cr, uid, ids, context={}):
done = []
res_currency_obj = self.pool.get('res.currency')
res_users_obj = self.pool.get('res.users')
diff --git a/addons/account/account_cash_statement.py b/addons/account/account_cash_statement.py
index 8380a19b411..896b71e9f25 100644
--- a/addons/account/account_cash_statement.py
+++ b/addons/account/account_cash_statement.py
@@ -67,19 +67,25 @@ class account_cash_statement(osv.osv):
_inherit = 'account.bank.statement'
- def _get_starting_balance(self, cr, uid, ids, name, arg, context=None):
+ def _get_starting_balance(self, cr, uid, ids, context=None):
- """ Find starting balance "
+ """ Find starting balance
@param name: Names of fields.
@param arg: User defined arguments
@return: Dictionary of values.
- """
+ """
res ={}
for statement in self.browse(cr, uid, ids):
amount_total=0.0
+
+ if statement.journal_id.type not in('cash'):
+ continue
+
for line in statement.starting_details_ids:
amount_total+= line.pieces * line.number
- res[statement.id]=amount_total
+ res[statement.id] = {
+ 'balance_start':amount_total
+ }
return res
def _balance_end_cash(self, cr, uid, ids, name, arg, context=None):
@@ -116,7 +122,7 @@ class account_cash_statement(osv.osv):
""" To get default journal for the object"
@param name: Names of fields.
@return: journal
- """
+ """
company_id = self.pool.get('res.users').browse(cr, uid, uid).company_id.id
journal = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'cash'), ('company_id', '=', company_id)])
if journal:
@@ -166,11 +172,10 @@ class account_cash_statement(osv.osv):
company_id = company_pool.search(cr, uid, [])[0]
return company_id
-
+
_columns = {
'company_id':fields.many2one('res.company', 'Company', required=False),
'journal_id': fields.many2one('account.journal', 'Journal', required=True),
- 'balance_start': fields.function(_get_starting_balance, store=True, method=True, string='Opening Balance', type='float',digits=(16,2), help="Opening balance based on cashBox"),
'balance_end_real': fields.float('Closing Balance', digits=(16,2), states={'confirm':[('readonly', True)]}, help="closing balance entered by the cashbox verifier"),
'state': fields.selection(
[('draft', 'Draft'),
@@ -178,7 +183,7 @@ class account_cash_statement(osv.osv):
('open','Open')], 'State', required=True, states={'confirm': [('readonly', True)]}, readonly="1"),
'total_entry_encoding':fields.function(_get_sum_entry_encoding, method=True, store=True, string="Cash Transaction", help="Total cash transactions"),
'closing_date':fields.datetime("Closed On"),
- 'balance_end': fields.function(_end_balance, method=True, store=True, string='Balance', help="Closing balance based on transactions"),
+ 'balance_end': fields.function(_end_balance, method=True, store=True, string='Balance', help="Closing balance based on Opening Balance and Transactions"),
'balance_end_cash': fields.function(_balance_end_cash, method=True, store=True, string='Balance', help="Closing balance based on cashBox"),
'starting_details_ids': fields.one2many('account.cashbox.line', 'starting_id', string='Opening Cashbox'),
'ending_details_ids': fields.one2many('account.cashbox.line', 'ending_id', string='Closing Cashbox'),
@@ -205,8 +210,31 @@ class account_cash_statement(osv.osv):
for i in starting_details_ids:
if i and i[0] and i[1]:
i[0], i[1] = 0, 0
- res = super(account_cash_statement, self).create(cr, uid, vals, context=context)
- return res
+ res_id = super(account_cash_statement, self).create(cr, uid, vals, context=context)
+ res = self._get_starting_balance(cr, uid, [res_id])
+ for rs in res:
+ super(account_cash_statement, self).write(cr, uid, rs, res.get(rs))
+ return res_id
+
+ def write(self, cr, uid, ids, vals, context=None):
+ """
+ Update redord(s) comes in {ids}, with new value comes as {vals}
+ return True on success, False otherwise
+
+ @param cr: cursor to database
+ @param user: id of current user
+ @param ids: list of record ids to be update
+ @param vals: dict of new values to be set
+ @param context: context arguments, like lang, time zone
+
+ @return: True on success, False otherwise
+ """
+
+ super(account_cash_statement, self).write(cr, uid, ids, vals)
+ res = self._get_starting_balance(cr, uid, ids)
+ for rs in res:
+ super(account_cash_statement, self).write(cr, uid, rs, res.get(rs))
+ return True
def onchange_journal_id(self, cr, uid, statement_id, journal_id, context={}):
""" Changes balance start and starting details if journal_id changes"
@@ -285,7 +313,7 @@ class account_cash_statement(osv.osv):
self.write(cr, uid, ids, vals)
return True
- def button_confirm(self, cr, uid, ids, context={}):
+ def button_confirm_cash(self, cr, uid, ids, context={}):
""" Check the starting and ending detail of statement
@return: True
@@ -296,20 +324,24 @@ class account_cash_statement(osv.osv):
account_move_obj = self.pool.get('account.move')
account_move_line_obj = self.pool.get('account.move.line')
account_bank_statement_line_obj = self.pool.get('account.bank.statement.line')
-
+
company_currency_id = res_users_obj.browse(cr, uid, uid, context=context).company_id.currency_id.id
for st in self.browse(cr, uid, ids, context):
+
+ self.write(cr, uid, [st.id], {'balance_end_real':st.balance_end})
+ st.balance_end_real = st.balance_end
+
if not st.state == 'open':
continue
if not self._equal_balance(cr, uid, ids, st, context):
- raise osv.except_osv(_('Error !'), _('Cash balance is not matching with closing balance !'))
-
- if not (abs((st.balance_end or 0.0) - st.balance_end_real) < 0.0001):
- raise osv.except_osv(_('Error !'),
- _('The statement balance is incorrect !\n') +
- _('The expected balance (%.2f) is different than the computed one. (%.2f)') % (st.balance_end_real, st.balance_end))
+ raise osv.except_osv(_('Error !'), _('CashBox Balance is not matching with Calculated Balance !'))
+
+# if not (abs((st.balance_end or 0.0) - st.balance_end_real) < 0.0001):
+# raise osv.except_osv(_('Error !'),
+# _('The statement balance is incorrect !\n') +
+# _('The expected balance (%.2f) is different than the computed one. (%.2f)') % (st.balance_end_real, st.balance_end))
if (not st.journal_id.default_credit_account_id) \
or (not st.journal_id.default_debit_account_id):
raise osv.except_osv(_('Configuration Error !'),
@@ -435,7 +467,7 @@ class account_cash_statement(osv.osv):
if move.reconcile_id and move.reconcile_id.line_ids:
torec += map(lambda x: x.id, move.reconcile_id.line_ids)
- #try:
+
if abs(move.reconcile_amount-move.amount)<0.0001:
writeoff_acc_id = False
@@ -447,13 +479,16 @@ class account_cash_statement(osv.osv):
account_move_line_obj.reconcile(cr, uid, torec, 'statement', writeoff_acc_id=writeoff_acc_id, writeoff_period_id=st.period_id.id, writeoff_journal_id=st.journal_id.id, context=context)
else:
account_move_line_obj.reconcile_partial(cr, uid, torec, 'statement', context)
- #except:
- # raise osv.except_osv(_('Error !'), _('Unable to reconcile entry "%s": %.2f') % (move.name, move.amount))
if st.journal_id.entry_posted:
account_move_obj.write(cr, uid, [move_id], {'state':'posted'})
done.append(st.id)
- self.write(cr, uid, done, {'state':'confirm'}, context=context)
+
+ vals = {
+ 'state':'confirm',
+ 'closing_date':time.strftime("%Y-%m-%d %H:%M:%S")
+ }
+ self.write(cr, uid, done, vals, context=context)
return True
def button_cancel(self, cr, uid, ids, context={}):
diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml
index 80fb20e1fad..de8bc843faa 100644
--- a/addons/account/account_view.xml
+++ b/addons/account/account_view.xml
@@ -427,6 +427,9 @@
+
+
+
@@ -465,7 +468,7 @@
-
+
@@ -505,7 +508,7 @@
-
+
@@ -518,6 +521,18 @@
tree,form[('journal_id.type', '=', 'bank')]
+
+
+ tree
+
+
+
+
+
+ form
+
+
+
@@ -2267,7 +2282,7 @@
-
+
@@ -2285,7 +2300,7 @@
-
+
@@ -2318,7 +2333,7 @@
-
+
@@ -2349,7 +2364,7 @@
-
+
@@ -2360,18 +2375,18 @@
-
+
-
-
+
+
-
+
diff --git a/addons/account/invoice.py b/addons/account/invoice.py
index 0030d36d896..423c39deea1 100644
--- a/addons/account/invoice.py
+++ b/addons/account/invoice.py
@@ -223,7 +223,7 @@ class account_invoice(osv.osv):
_log_create = True
_columns = {
'name': fields.char('Description', size=64, select=True, readonly=True, states={'draft':[('readonly',False)]}),
- 'origin': fields.char('Source Document', size=64, help="Reference of the document that produced this invoice."),
+ 'origin': fields.char('Source Document', size=64, help="Reference of the document that produced this invoice.", readonly=True, states={'draft':[('readonly',False)]}),
'type': fields.selection([
('out_invoice','Customer Invoice'),
('in_invoice','Supplier Invoice'),
@@ -250,8 +250,8 @@ class account_invoice(osv.osv):
\n* The \'Open\' state is used when user create invoice,a invoice number is generated.Its in open state till user does not pay invoice. \
\n* The \'Done\' state is set automatically when invoice is paid.\
\n* The \'Cancelled\' state is used when user cancel invoice.'),
- 'date_invoice': fields.date('Date Invoiced', states={'open':[('readonly',True)], 'close':[('readonly',True)]}, help="Keep empty to use the current date"),
- 'date_due': fields.date('Due Date', states={'open':[('readonly',True)], 'close':[('readonly',True)]},
+ 'date_invoice': fields.date('Date Invoiced', states={'paid':[('readonly',True)], 'open':[('readonly',True)], 'close':[('readonly',True)]}, help="Keep empty to use the current date"),
+ 'date_due': fields.date('Due Date', states={'paid':[('readonly',True)], 'open':[('readonly',True)], 'close':[('readonly',True)]},
help="If you use payment terms, the due date will be computed automatically at the generation "\
"of accounting entries. If you keep the payment term and the due date empty, it means direct payment. The payment term may compute several due dates, for example 50% now, 50% in one month."),
'partner_id': fields.many2one('res.partner', 'Partner', change_default=True, readonly=True, required=True, states={'draft':[('readonly',False)]}),
@@ -291,7 +291,7 @@ class account_invoice(osv.osv):
multi='all'),
'currency_id': fields.many2one('res.currency', 'Currency', required=True, readonly=True, states={'draft':[('readonly',False)]}),
'journal_id': fields.many2one('account.journal', 'Journal', required=True, readonly=True, states={'draft':[('readonly',False)]}),
- 'company_id': fields.many2one('res.company', 'Company', required=True, change_default=True),
+ 'company_id': fields.many2one('res.company', 'Company', required=True, change_default=True, readonly=True, states={'draft':[('readonly',False)]}),
'check_total': fields.float('Total', digits_compute=dp.get_precision('Account'), states={'open':[('readonly',True)],'close':[('readonly',True)]}),
'reconciled': fields.function(_reconciled, method=True, string='Paid/Reconciled', type='boolean',
store={
@@ -300,7 +300,7 @@ class account_invoice(osv.osv):
'account.move.reconcile': (_get_invoice_from_reconcile, None, 50),
}, help="The Ledger Postings of the invoice have been reconciled with Ledger Postings of the payment(s)."),
'partner_bank': fields.many2one('res.partner.bank', 'Bank Account',
- help='The bank account to pay to or to be paid from'),
+ help='The bank account to pay to or to be paid from', readonly=True, states={'draft':[('readonly',False)]}),
'move_lines':fields.function(_get_lines , method=True, type='many2many', relation='account.move.line', string='Entry Lines'),
'residual': fields.function(_amount_residual, method=True, digits_compute=dp.get_precision('Account'), string='Residual',
store={
@@ -314,7 +314,7 @@ class account_invoice(osv.osv):
'payment_ids': fields.function(_compute_lines, method=True, relation='account.move.line', type="many2many", string='Payments'),
'move_name': fields.char('Ledger Posting', size=64, readonly=True, states={'draft':[('readonly',False)]}),
'user_id': fields.many2one('res.users', 'Salesman', readonly=True, states={'draft':[('readonly',False)]}),
- 'fiscal_position': fields.many2one('account.fiscal.position', 'Fiscal Position')
+ 'fiscal_position': fields.many2one('account.fiscal.position', 'Fiscal Position', readonly=True, states={'draft':[('readonly',False)]})
}
_defaults = {
'type': _get_type,
diff --git a/addons/account/report/account_invoice_report_view.xml b/addons/account/report/account_invoice_report_view.xml
index ca89cd10852..d03e977336b 100644
--- a/addons/account/report/account_invoice_report_view.xml
+++ b/addons/account/report/account_invoice_report_view.xml
@@ -28,12 +28,12 @@
-
+
-
+
-
-
+
+
@@ -93,24 +93,24 @@
-
+
-
+
-
-
+
+
-
-
+
+
-
-
+
+
-
+
-
-
-
+
+
+
diff --git a/addons/account/wizard/account_change_currency.py b/addons/account/wizard/account_change_currency.py
index d027559cdce..66c6ee55c10 100644
--- a/addons/account/wizard/account_change_currency.py
+++ b/addons/account/wizard/account_change_currency.py
@@ -35,7 +35,7 @@ class account_change_currency(osv.osv_memory):
context = {}
state = obj_inv.browse(cr, uid, context['active_id']).state
if obj_inv.browse(cr, uid, context['active_id']).state != 'draft':
- raise osv.except_osv(_('Error'), _('You can not change currency for Open Invoice !'))
+ raise osv.except_osv(_('Error'), _('You can only change currency for Draft Invoice !'))
pass
def change_currency(self, cr, uid, ids, context=None):
diff --git a/addons/account/wizard/account_invoice_refund.py b/addons/account/wizard/account_invoice_refund.py
index 41baac36f89..6a19dc988df 100644
--- a/addons/account/wizard/account_invoice_refund.py
+++ b/addons/account/wizard/account_invoice_refund.py
@@ -61,7 +61,8 @@ class account_invoice_refund(osv.osv_memory):
date = False
period = False
description = False
- for inv in inv_obj.browse(cr, uid, context['active_ids'], context=context):
+ company = self.pool.get('res.users').browse(cr, uid, uid).company_id
+ for inv in inv_obj.browse(cr, uid, context.get('active_ids'), context=context):
if inv.state in ['draft', 'proforma2', 'cancel']:
raise osv.except_osv(_('Error !'), _('Can not %s draft/proforma/cancel invoice.') % (mode))
if form['period'] :
@@ -77,11 +78,8 @@ class account_invoice_refund(osv.osv_memory):
and name = 'company_id'")
result_query = cr.fetchone()
if result_query:
- cr.execute("""SELECT id
- from account_period where date(%s)
- between date_start AND date_stop \
- and company_id = %s limit 1 """,
- (date, self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id,))
+ cr.execute("""select p.id from account_fiscalyear y, account_period p where y.id=p.fiscalyear_id \
+ and date(%s) between p.date_start AND p.date_stop and y.company_id = %s limit 1""", (date, company.id,))
else:
cr.execute("""SELECT id
from account_period where date(%s)
@@ -154,7 +152,7 @@ class account_invoice_refund(osv.osv_memory):
'tax_line': tax_lines,
'period_id': period,
'name': description
- })
+ })
for field in ('address_contact_id', 'address_invoice_id', 'partner_id',
'account_id', 'currency_id', 'payment_term', 'journal_id'):
@@ -192,4 +190,4 @@ class account_invoice_refund(osv.osv_memory):
account_invoice_refund()
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/account_cancel/account_cancel_view.xml b/addons/account_cancel/account_cancel_view.xml
index bcb9fb4d34e..5f63b6cf6d7 100644
--- a/addons/account_cancel/account_cancel_view.xml
+++ b/addons/account_cancel/account_cancel_view.xml
@@ -1,16 +1,17 @@
-
+ account.journal.formaccount.journalform
-
+
+
-
+
-
-
-
\ No newline at end of file
+
+
+
diff --git a/addons/account_report/i18n/bs.po b/addons/account_report/i18n/bs.po
index 3fd898408ff..bd0c14775ad 100644
--- a/addons/account_report/i18n/bs.po
+++ b/addons/account_report/i18n/bs.po
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
-"PO-Revision-Date: 2010-07-07 09:59+0000\n"
+"PO-Revision-Date: 2010-07-09 06:46+0000\n"
"Last-Translator: Bojan Markovic \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-07-08 03:50+0000\n"
+"X-Launchpad-Export-Date: 2010-07-10 04:02+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: account_report
@@ -26,17 +26,17 @@ msgstr ""
#. module: account_report
#: wizard_field:print.indicators.pdf,init,file:0
msgid "Select a PDF File"
-msgstr ""
+msgstr "Odaberi PDF datoteku"
#. module: account_report
#: constraint:ir.actions.act_window:0
msgid "Invalid model name in the action definition."
-msgstr ""
+msgstr "Neispravan naziv modela u definiciji zadatka."
#. module: account_report
#: view:account.report.report:0
msgid "Operators:"
-msgstr ""
+msgstr "Operatori:"
#. module: account_report
#: field:account.report.report,parent_id:0
@@ -46,12 +46,12 @@ msgstr "Sintetika"
#. module: account_report
#: field:account.report.report,disp_graph:0
msgid "Display As Graph"
-msgstr ""
+msgstr "Prikaži kao grafikon"
#. module: account_report
#: view:account.report.report:0
msgid "Account Debit:"
-msgstr ""
+msgstr "Dugovanje konta:"
#. module: account_report
#: selection:account.report.report,type:0
@@ -66,12 +66,12 @@ msgstr ""
#. module: account_report
#: rml:print.indicators:0
msgid "Tabular Summary"
-msgstr ""
+msgstr "Tablični sažetak"
#. module: account_report
#: view:account.report.report:0
msgid "Notes"
-msgstr ""
+msgstr "Bilješke"
#. module: account_report
#: view:account.report.report:0
diff --git a/addons/account_voucher_payment/wizard/account_voucher_unreconcile.py b/addons/account_voucher_payment/wizard/account_voucher_unreconcile.py
index 2bfffb372b7..ef30e1af69f 100644
--- a/addons/account_voucher_payment/wizard/account_voucher_unreconcile.py
+++ b/addons/account_voucher_payment/wizard/account_voucher_unreconcile.py
@@ -49,7 +49,7 @@ class account_voucher_unreconcile(osv.osv_memory):
recs = [line.reconcile_id.id]
for rec in recs:
- obj_reconcile.unlink(cr, uid, rec)
+ reconcile_pool.unlink(cr, uid, rec)
if res.remove:
wf_service = netsvc.LocalService("workflow")
diff --git a/addons/base_action_rule/base_action_rule.py b/addons/base_action_rule/base_action_rule.py
index be1a53046a7..79b883c0236 100644
--- a/addons/base_action_rule/base_action_rule.py
+++ b/addons/base_action_rule/base_action_rule.py
@@ -22,7 +22,8 @@
from datetime import datetime
from osv import fields, osv, orm
from tools.translate import _
-import mx.DateTime
+from datetime import datetime
+from datetime import timedelta
import pooler
import re
import time
@@ -105,7 +106,9 @@ the rule to mark CC(mail to any other person defined in actions)."),
'act_mail_to_email': fields.char('Mail to these Emails', size=128, \
help="Email-id of the persons whom mail is to be sent"),
'act_mail_body': fields.text('Mail body', help="Content of mail"),
- 'regex_name': fields.char('Regular Expression on Model Name', size=128),
+ 'regex_name': fields.char('Regex on Resource Name', size=128, help="Regular expression for mathching name of the resource\
+\ne.g.: urgent.* will search for records having name starting with urgent\
+\nNote: This is case sensitive search."),
'server_action_id': fields.many2one('ir.actions.server', 'Server Action', help="Describes the action name.\neg:on which object which action to be taken on basis of which condition"),
'filter_id':fields.many2one('ir.filters', 'Filter', required=False),
'domain':fields.char('Domain', size=124, required=False, readonly=False),
@@ -352,23 +355,23 @@ the rule to mark CC(mail to any other person defined in actions)."),
base = False
if hasattr(obj, 'create_date') and action.trg_date_type=='create':
- base = mx.DateTime.strptime(obj.create_date[:19], '%Y-%m-%d %H:%M:%S')
+ base = datetime.strptime(obj.create_date[:19], '%Y-%m-%d %H:%M:%S')
elif hasattr(obj, 'create_date') and action.trg_date_type=='action_last':
if hasattr(obj, 'date_action_last') and obj.date_action_last:
- base = mx.DateTime.strptime(obj.date_action_last, '%Y-%m-%d %H:%M:%S')
+ base = datetime.strptime(obj.date_action_last, '%Y-%m-%d %H:%M:%S')
else:
- base = mx.DateTime.strptime(obj.create_date[:19], '%Y-%m-%d %H:%M:%S')
+ base = datetime.strptime(obj.create_date[:19], '%Y-%m-%d %H:%M:%S')
elif hasattr(obj, 'date_deadline') and action.trg_date_type=='deadline' \
and obj.date_deadline:
- base = mx.DateTime.strptime(obj.date_deadline, '%Y-%m-%d %H:%M:%S')
+ base = datetime.strptime(obj.date_deadline, '%Y-%m-%d %H:%M:%S')
elif hasattr(obj, 'date') and action.trg_date_type=='date' and obj.date:
- base = mx.DateTime.strptime(obj.date, '%Y-%m-%d %H:%M:%S')
+ base = datetime.strptime(obj.date, '%Y-%m-%d %H:%M:%S')
if base:
fnct = {
- 'minutes': lambda interval: mx.DateTime.RelativeDateTime(minutes=interval),
- 'day': lambda interval: mx.DateTime.RelativeDateTime(days=interval),
- 'hour': lambda interval: mx.DateTime.RelativeDateTime(hours=interval),
- 'month': lambda interval: mx.DateTime.RelativeDateTime(months=interval),
+ 'minutes': lambda interval: timedelta(minutes=interval),
+ 'day': lambda interval: timedelta(days=interval),
+ 'hour': lambda interval: timedelta(hours=interval),
+ 'month': lambda interval: timedelta(months=interval),
}
d = base + fnct[action.trg_date_range_type](action.trg_date_range)
dt = d.strftime('%Y-%m-%d %H:%M:%S')
diff --git a/addons/base_action_rule/base_action_rule_view.xml b/addons/base_action_rule/base_action_rule_view.xml
index c9164962439..36140e62649 100644
--- a/addons/base_action_rule/base_action_rule_view.xml
+++ b/addons/base_action_rule/base_action_rule_view.xml
@@ -24,7 +24,7 @@
-
+
diff --git a/addons/base_calendar/base_calendar.py b/addons/base_calendar/base_calendar.py
index 7896dfae1ae..85ec16bda8d 100644
--- a/addons/base_calendar/base_calendar.py
+++ b/addons/base_calendar/base_calendar.py
@@ -317,7 +317,7 @@ class calendar_attendee(osv.osv):
obj = self.pool.get('res.lang')
ids = obj.search(cr, uid, [])
res = obj.read(cr, uid, ids, ['code', 'name'], context=context)
- res = [((r['code']).replace('_', '-'), r['name']) for r in res]
+ res = [((r['code']).replace('_', '-').lower(), r['name']) for r in res]
return res
_columns = {
@@ -378,6 +378,10 @@ property or property parameter."),
}
_defaults = {
'state': 'needs-action',
+ 'user_id': lambda self, cr, uid, ctx: uid,
+ 'role': 'req-participant',
+ 'rsvp': True,
+ 'cutype': 'individual',
}
def copy(self, cr, uid, id, default=None, context=None):
@@ -542,13 +546,13 @@ property or property parameter."),
context = {}
for vals in self.browse(cr, uid, ids, context=context):
- user = vals.user_id
- if user:
- mod_obj = self.pool.get(vals.ref._name)
- if vals.ref:
- if vals.ref.user_id.id != user.id:
- defaults = {'user_id': user.id}
- new_event = mod_obj.copy(cr, uid, vals.ref.id, default=defaults, context=context)
+ #user = vals.user_id
+ #if user:
+ # mod_obj = self.pool.get(vals.ref._name)
+ # if vals.ref:
+ # if vals.ref.user_id.id != user.id:
+ # defaults = {'user_id': user.id}
+ # new_event = mod_obj.copy(cr, uid, vals.ref.id, default=defaults, context=context)
self.write(cr, uid, vals.id, {'state': 'accepted'}, context)
return True
@@ -1416,6 +1420,8 @@ true, it will allow you to hide the event alarm information without removing it.
until_date = arg[2]
res = super(calendar_event, self).search(cr, uid, args_without_date, \
offset, limit, order, context, count)
+ #Search Event ID which are invitted
+
return self.get_recurrent_ids(cr, uid, res, start_date, until_date, limit)
diff --git a/addons/base_calendar/base_calendar_view.xml b/addons/base_calendar/base_calendar_view.xml
index 7e2368658df..cb2ca806afa 100644
--- a/addons/base_calendar/base_calendar_view.xml
+++ b/addons/base_calendar/base_calendar_view.xml
@@ -76,13 +76,26 @@
tree
-
-
-
-
+
+
+
-
-
+
+
+
+
+
@@ -103,7 +116,7 @@
separator="1" help="Declined Invitations" />
-
+
diff --git a/addons/base_calendar/wizard/base_calendar_invite_attendee.py b/addons/base_calendar/wizard/base_calendar_invite_attendee.py
index ebbfe6c48d2..15763da202d 100644
--- a/addons/base_calendar/wizard/base_calendar_invite_attendee.py
+++ b/addons/base_calendar/wizard/base_calendar_invite_attendee.py
@@ -75,7 +75,8 @@ send an Email to Invited Person')
obj = self.pool.get(model)
res_obj = obj.browse(cr, uid, context_id)
att_obj = self.pool.get('calendar.attendee')
-
+ user_obj = self.pool.get('res.users')
+ current_user = user_obj.browse(cr, uid, uid, context=context)
for datas in self.read(cr, uid, ids, context=context):
type = datas.get('type')
vals = []
@@ -89,7 +90,7 @@ send an Email to Invited Person')
else:
return {}
if type == 'internal':
- user_obj = self.pool.get('res.users')
+
if not datas.get('user_ids'):
raise osv.except_osv(_('Error!'), ("Please select any User"))
for user_id in datas.get('user_ids'):
@@ -139,7 +140,7 @@ send an Email to Invited Person')
self._columns['type'].selection))
raise osv.except_osv(_('Error!'), ("%s must have an email Address to send mail") %(name[0]))
att_obj._send_mail(cr, uid, attendees, mail_to, \
- email_from= tools.config.get('email_from', False))
+ email_from = current_user.user_email or tools.config.get('email_from', False))
return {}
diff --git a/addons/caldav/calendar.py b/addons/caldav/calendar.py
index c9f40e418a1..6dc1e23ea66 100644
--- a/addons/caldav/calendar.py
+++ b/addons/caldav/calendar.py
@@ -528,6 +528,7 @@ class Calendar(CalDAV, osv.osv):
})
self.__attribute__ = get_attribute_mapping(cr, uid, child.name.lower(), context=context)
val = self.parse_ics(cr, uid, child, cal_children=cal_children, context=context)
+ val.update({'user_id': uid})
vals.append(val)
obj = self.pool.get(cal_children[child.name.lower()])
if hasattr(obj, 'check_import'):
@@ -1052,7 +1053,8 @@ class Attendee(CalDAV, osv.osv_memory):
if cn_val:
attendee_add.params['CN'] = cn_val
if not attendee['email']:
- raise osv.except_osv(_('Error !'), _('Attendee must have an Email Id'))
+ attendee_add.value = 'MAILTO:'
+ #raise osv.except_osv(_('Error !'), _('Attendee must have an Email Id'))
elif attendee['email']:
attendee_add.value = 'MAILTO:' + attendee['email']
return vevent
diff --git a/addons/crm/__openerp__.py b/addons/crm/__openerp__.py
index 973bb12dc5c..a490a800beb 100644
--- a/addons/crm/__openerp__.py
+++ b/addons/crm/__openerp__.py
@@ -121,7 +121,7 @@ Create dashboard for CRM that includes:
],
'test': [
'test/test_crm_lead.yml',
- 'test/test_crm_meeting.yml',
+ #'test/test_crm_meeting.yml',
'test/test_crm_opportunity.yml',
'test/test_crm_phonecall.yml',
],
diff --git a/addons/crm/board_crm_statistical_view.xml b/addons/crm/board_crm_statistical_view.xml
index 1baf673990d..b23fdeac1cd 100644
--- a/addons/crm/board_crm_statistical_view.xml
+++ b/addons/crm/board_crm_statistical_view.xml
@@ -4,53 +4,69 @@
-
- Leads By Stage - Graph
- crm.lead.report
- graph
-
-
-
-
-
-
-
-
- report.crm.opportunity.categ.graph
+
+ Opportunities By Categories - Graphcrm.lead.reportgraph
-
+
-
+
+ Opportunities By Stage - Graph
+ crm.lead.report
+ graph
+
+
+
+
+
+
+
+
+
+ Opportunities By Stage Per User - Graph
+ crm.lead.report
+ graph
+
+
+
+
+
+
+
+
-
+
+ Opportunities By Categoriescrm.lead.reportformgraph,tree,form
-
+ [('state','!=','done'),('state','!=','cancel')]
-
+
+ crm.lead.report
+ form
+ graph,tree,form
+
+ [('state','!=','done'),('state','!=','cancel')]
+
+
+
+ Number of Opportunities by stage
+ crm.lead.report
+ form
+ graph,tree,form
+
+ [('state','!=','cancel')]
+ CRM - Statistical Dashboard Form
@@ -68,8 +84,8 @@
width="250"/>
@@ -77,8 +93,8 @@
diff --git a/addons/crm/board_crm_view.xml b/addons/crm/board_crm_view.xml
index c90ecb28e03..ed6044a6fd6 100644
--- a/addons/crm/board_crm_view.xml
+++ b/addons/crm/board_crm_view.xml
@@ -4,23 +4,38 @@
CRM Configuration
+
crm.opportunity.user.graph1crm.lead.reportgraph
-
-
+
+
+
-
+
+
+ crm.lead.report.graph
+ crm.lead.report
+ graph
+
+
+
+
+
+
+
+
+ crm.leadformtree,form
- [('user_id','=',uid),('state','!=','pending'),('state','!=','cancel')]
+ [('user_id','=',uid),('state','=','open'), ('type', '=', 'opportunity')]
@@ -31,12 +46,12 @@
[('user_id','=',uid),('state','!=','cancel'),('date','ilike',time.strftime("%Y-%m"))]
-
+ crm.lead.reportformgraph,tree,form
-
- [('user_id','=',uid),('state','!=','pending'),('state','!=','cancel')]
+
+ ['&', ('user_id','=',uid), '!' , '&', ('state', '=', 'done'), ('date_closed','>',(datetime.date.today()-datetime.timedelta(days=30)).strftime('%Y-%m-%d'))]
@@ -44,7 +59,7 @@
formgraph,tree,form
- [('user_id','=',uid),('state','!=','pending'),('state','!=','cancel'),('type', '=', 'opportunity')]
+ ['&', ('state', '=', 'done') , '&', ('create_date','>',(datetime.date.today()-datetime.timedelta(days=365)).strftime('%Y-%m-%d')), ('type', '=', 'opportunity')]
@@ -56,8 +71,8 @@
@@ -70,10 +85,10 @@
diff --git a/addons/crm/crm.py b/addons/crm/crm.py
index 5cee0052297..575c2a8a3e3 100644
--- a/addons/crm/crm.py
+++ b/addons/crm/crm.py
@@ -268,12 +268,13 @@ class crm_case(object):
"""
cases = self.browse(cr, uid, ids)
for case in cases:
- data = {'active': True, 'user_id': False}
+ data = {'active': True}
if case.section_id.parent_id:
data['section_id'] = case.section_id.parent_id.id
- if case.section_id.parent_id.user_id:
- data['user_id'] = case.section_id.parent_id.user_id.id
+ if case.section_id.parent_id.change_responsible:
+ if case.section_id.parent_id.user_id:
+ data['user_id'] = case.section_id.parent_id.user_id.id
else:
raise osv.except_osv(_('Error !'), _('You can not escalate, You are already at the top level regarding your sales-team category.'))
self.write(cr, uid, [case.id], data)
@@ -439,6 +440,7 @@ class crm_case_section(osv.osv):
'active': fields.boolean('Active', help="If the active field is set to \
true, it will allow you to hide the sales team without removing it."),
'allow_unlink': fields.boolean('Allow Delete', help="Allows to delete non draft cases"),
+ 'change_responsible': fields.boolean('Change Responsible', help="Set responsible of this Sales team on escalation to this team"),
'user_id': fields.many2one('res.users', 'Responsible User'),
'member_ids':fields.many2many('res.users', 'sale_member_rel', 'section_id', 'member_id', 'Team Members'),
'reply_to': fields.char('Reply-To', size=64, help="The email address put \
diff --git a/addons/crm/crm_action_rule.py b/addons/crm/crm_action_rule.py
index 1f11f2c4c0c..1ca37a426a2 100644
--- a/addons/crm/crm_action_rule.py
+++ b/addons/crm/crm_action_rule.py
@@ -24,7 +24,6 @@ import re
import os
import base64
import tools
-import mx.DateTime
from tools.translate import _
from osv import fields
@@ -80,6 +79,26 @@ this if you want the rule to send an email to the partner."),
if hasattr(obj, 'categ_id'):
ok = ok and (not action.trg_categ_id or action.trg_categ_id.id==obj.categ_id.id)
+ #Cheking for history
+ regex = action.regex_history
+ result_history = True
+ if regex:
+ res = False
+ ptrn = re.compile(str(regex))
+ for history in obj.message_ids:
+ _result = ptrn.search(str(history.name))
+ if _result:
+ res = True
+ break
+ result_history = res
+ ok = ok and (not regex or result_history)
+
+ res_count = True
+ if action.trg_max_history:
+ res_count = False
+ if len(obj.message_ids) >= action.trg_max_history:
+ res_count = True
+ ok = ok and res_count
return ok
def do_action(self, cr, uid, action, model_obj, obj, context={}):
diff --git a/addons/crm/crm_lead_data.xml b/addons/crm/crm_lead_data.xml
index 2b47140e396..41eeb529154 100644
--- a/addons/crm/crm_lead_data.xml
+++ b/addons/crm/crm_lead_data.xml
@@ -1,81 +1,105 @@
-
+
-
-
- New
-
-
-
-
- Assigned
-
-
-
-
- In Process
-
-
-
-
- Converted
-
-
-
-
- Recycled
-
-
-
-
- Dead
-
-
-
+
+
+ New
+
+
+
+
+
-
-
- Telesales
-
-
-
-
- Mail
-
-
-
-
- Email
-
-
-
-
- Print
-
-
-
-
- Web
-
-
-
-
- Radio
-
-
-
-
- Television
-
-
-
-
- Newsletter
-
-
-
+
+ Qualification
+
+
+
+
+
-
+
+ Proposition
+
+
+
+
+
+
+
+ Negotiation
+
+
+
+
+
+
+
+ Win
+
+
+
+
+
+
+
+ Lost
+
+
+
+
+
+
+
+
+ Telesales
+
+
+
+
+
+ Mail
+
+
+
+
+
+ Email
+
+
+
+
+
+ Print
+
+
+
+
+
+ Web
+
+
+
+
+
+ Radio
+
+
+
+
+
+ Television
+
+
+
+
+
+ Newsletter
+
+
+
+
+
diff --git a/addons/crm/crm_meeting.py b/addons/crm/crm_meeting.py
index 3ed7cf1f1fe..1bc5948fe73 100644
--- a/addons/crm/crm_meeting.py
+++ b/addons/crm/crm_meeting.py
@@ -80,7 +80,8 @@ class crm_meeting(osv.osv, crm_case):
_defaults = {
'state': lambda *a: 'draft',
- 'active': lambda *a: 1,
+ 'active': lambda *a: 1,
+ 'user_id': lambda self, cr, uid, ctx: uid,
}
def open_meeting(self, cr, uid, ids, context=None):
diff --git a/addons/crm/crm_meeting_menu.xml b/addons/crm/crm_meeting_menu.xml
index bf1a8459655..027ebed0a7a 100644
--- a/addons/crm/crm_meeting_menu.xml
+++ b/addons/crm/crm_meeting_menu.xml
@@ -105,7 +105,7 @@
tree,form[('ref','like','crm.meeting,')]
- {'default_sent_by_uid': uid}
+ {"search_default_user_id":uid}
-
-
-
-
- calendar.attendee.tree.inherit
- calendar.attendee
- tree
-
-
-
-
-
-
-
+
diff --git a/addons/crm/crm_opportunity_data.xml b/addons/crm/crm_opportunity_data.xml
index a7cfd2d46ca..fd4d76d5865 100644
--- a/addons/crm/crm_opportunity_data.xml
+++ b/addons/crm/crm_opportunity_data.xml
@@ -1,6 +1,6 @@
-
+
Existing Customer
@@ -42,43 +42,6 @@
-
-
- Prospecting
-
-
-
-
- Needs Analysis
-
-
-
-
- Value Proposition
-
-
-
-
- Proposal/Price Quote
-
-
-
-
- Negotiation/Review
-
-
-
-
- Closed Won
-
-
-
-
- Closed Lost
-
-
-
-
Existing Business
diff --git a/addons/crm/crm_opportunity_demo.xml b/addons/crm/crm_opportunity_demo.xml
index 3c06d16dc19..48812b17cf0 100644
--- a/addons/crm/crm_opportunity_demo.xml
+++ b/addons/crm/crm_opportunity_demo.xml
@@ -20,7 +20,7 @@
-
+
@@ -36,7 +36,7 @@
-
+
@@ -53,7 +53,7 @@
-
+
@@ -70,7 +70,7 @@
-
+
@@ -86,7 +86,7 @@
-
+
diff --git a/addons/crm/crm_phonecall_view.xml b/addons/crm/crm_phonecall_view.xml
index 479e73fe8fb..c61ec1ff0b5 100644
--- a/addons/crm/crm_phonecall_view.xml
+++ b/addons/crm/crm_phonecall_view.xml
@@ -69,17 +69,14 @@
form
@@ -36,4 +38,4 @@
-
\ No newline at end of file
+
diff --git a/addons/document/security/ir.model.access.csv b/addons/document/security/ir.model.access.csv
index 245bcbffeab..9684932b2a6 100644
--- a/addons/document/security/ir.model.access.csv
+++ b/addons/document/security/ir.model.access.csv
@@ -9,6 +9,7 @@
"access_document_directory_content_type_group_system","document.directory.content.type group system","model_document_directory_content_type","base.group_user",1,0,0,0
"access_document_storage_group_document_manager","document.storage document manager","model_document_storage","group_document_manager",1,1,1,1
"access_document_storage_group_system","document.storage group system","model_document_storage","base.group_user",1,0,0,0
+"access_document_directory_dctx_all","document.directory.dctx all","model_document_directory_dctx",,1,0,0,0
"access_document_directory_dctx_group_document_manager","document.directory.dctx document manager","model_document_directory_dctx","group_document_manager",1,1,1,1
"access_document_directory_dctx_group_system","document.directory.dctx group system","model_document_directory_dctx","base.group_system",1,1,1,1
"access_report_document_user_group_document_manager","report.document.user document manager","model_report_document_user","document.group_document_manager",1,0,0,0
diff --git a/addons/event/__init__.py b/addons/event/__init__.py
index 275c10657ff..ce8b64ed9a9 100644
--- a/addons/event/__init__.py
+++ b/addons/event/__init__.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
-#
+#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL ().
#
@@ -15,12 +15,13 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
+# along with this program. If not, see .
#
##############################################################################
import event
import wizard
import report
+import res_partner
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/event/__openerp__.py b/addons/event/__openerp__.py
index 7cd7d4ae2c6..634484deecb 100644
--- a/addons/event/__openerp__.py
+++ b/addons/event/__openerp__.py
@@ -53,6 +53,7 @@
'wizard/event_make_invoice_view.xml',
'wizard/partner_event_registration_view.xml',
'board_association_view.xml',
+ 'res_partner_view.xml',
],
'demo_xml': ['event_demo.xml', 'board_association_demo.xml'],
'test': ['test/test_event.yml'],
diff --git a/addons/event/event.py b/addons/event/event.py
index b74f874e6b5..73ff7f6755a 100644
--- a/addons/event/event.py
+++ b/addons/event/event.py
@@ -176,11 +176,13 @@ class event_event(osv.osv):
'note': fields.text('Notes', help="Description or Summary of Event"),
'currency_id': fields.many2one('res.currency', 'Currency', required=True, readonly=True, states={'draft':[('readonly',False)]}),
"unit_price": fields.float('Cost'),
- 'partner_id': fields.many2one('res.partner','Teacher'),
+ 'main_speaker_id': fields.many2one('res.partner','Main Speaker'),
+ 'speaker_ids':fields.many2many('res.partner', 'event_speaker_rel', 'speaker_id', 'partner_id', 'Other Speakers'),
'address_id': fields.many2one('res.partner.address','Location Room'),
- 'teacher_confirmed': fields.boolean('Teacher Confirmed'),
+ 'speaker_confirmed': fields.boolean('Speaker Confirmed'),
'country_id': fields.related('address_id', 'country_id',
type='many2one', relation='res.country', string='Country'),
+ 'language': fields.char('Language',size=64),
}
diff --git a/addons/event/event_view.xml b/addons/event/event_view.xml
index 20047d00f73..97b122d5c6a 100644
--- a/addons/event/event_view.xml
+++ b/addons/event/event_view.xml
@@ -57,18 +57,20 @@
-
-
+
+
-
+
+
+
-
+
@@ -120,9 +122,11 @@
-
+
+
+
diff --git a/addons/event/report/report_event_registration.py b/addons/event/report/report_event_registration.py
index d9232136c3a..9af9347a76d 100644
--- a/addons/event/report/report_event_registration.py
+++ b/addons/event/report/report_event_registration.py
@@ -43,6 +43,7 @@ class report_event_registration(osv.osv):
'type': fields.many2one('event.type', 'Event Type'),
'state': fields.selection([('draft', 'Draft'), ('confirm', 'Confirmed'), ('done', 'Done'), ('cancel', 'Cancelled')], 'State', readonly=True, required=True),
'user_id':fields.many2one('res.users', 'Responsible', readonly=True),
+ 'speaker_id':fields.many2one('res.partner', 'Speaker', readonly=True),
}
_order = 'date desc'
def init(self, cr):
@@ -57,6 +58,7 @@ class report_event_registration(osv.osv):
c.event_id as event_id,
e.date_begin as date,
e.user_id as user_id,
+ e.main_speaker_id as speaker_id,
to_char(e.date_begin, 'YYYY') as year,
to_char(e.date_begin, 'MM') as month,
to_char(e.date_begin, 'YYYY-MM-DD') as day,
@@ -75,7 +77,7 @@ class report_event_registration(osv.osv):
group by
to_char(e.date_begin, 'YYYY'),
to_char(e.date_begin, 'MM'),
- t.id, e.id, e.date_begin,
+ t.id, e.id, e.date_begin,e.main_speaker_id,
e.register_max, e.type, e.state, c.event_id, e.user_id,
to_char(e.date_begin, 'YYYY-MM-DD')
)""")
diff --git a/addons/event/report/report_event_registration_view.xml b/addons/event/report/report_event_registration_view.xml
index 2931bc28aa8..9e00040fa97 100644
--- a/addons/event/report/report_event_registration_view.xml
+++ b/addons/event/report/report_event_registration_view.xml
@@ -10,6 +10,7 @@
+
@@ -85,7 +86,8 @@
-
+
+
diff --git a/addons/procurement/scripts/scheduler.py b/addons/event/res_partner.py
similarity index 69%
rename from addons/procurement/scripts/scheduler.py
rename to addons/event/res_partner.py
index 648da5cdddc..23075ba1927 100644
--- a/addons/procurement/scripts/scheduler.py
+++ b/addons/event/res_partner.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
-#
+#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL ().
#
@@ -15,16 +15,22 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
+# along with this program. If not, see .
#
##############################################################################
-import xmlrpclib
+from osv import fields,osv
-sock = xmlrpclib.ServerProxy('http://localhost:8069/xmlrpc/wizard')
-wiz_id = sock.create('trunk', 1, 'admin', 'procurement.order.compute.all')
-sock.execute('trunk', 1, 'admin', wiz_id, {'form': {'po_cycle': 1.0, 'po_lead': 1.0, 'user_id': 3, 'schedule_cycle': 1.0, 'picking_lead': 1.0, 'security_lead': 50.0, 'automatic': False}, 'ids': [], 'report_type': 'pdf', 'model': 'ir.ui.menu', 'id': False}, 'compute', {})
+class res_partner(osv.osv):
+ _inherit = 'res.partner'
+ _columns = {
+ 'speaker': fields.boolean('Speaker'),
+ 'event_ids': fields.one2many('event.event','main_speaker_id',readonly=True),
+ 'event_registration_ids': fields.one2many('event.registration','partner_id',readonly=True),
+ }
+
+res_partner()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/event/res_partner_view.xml b/addons/event/res_partner_view.xml
new file mode 100644
index 00000000000..0b6ace47b19
--- /dev/null
+++ b/addons/event/res_partner_view.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+ res.partner.speaker.info.inherit
+ res.partner
+ form
+
+
+
+
+
+
+
+
+ res.partner.event.info.inherit
+ res.partner
+ form
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/mail_gateway/mail_gateway.py b/addons/mail_gateway/mail_gateway.py
index 2c778241daf..7187de5d1a5 100644
--- a/addons/mail_gateway/mail_gateway.py
+++ b/addons/mail_gateway/mail_gateway.py
@@ -158,9 +158,9 @@ class mailgate_message(osv.osv):
'user_id': fields.many2one('res.users', 'User Responsible', readonly=True),
'message': fields.text('Description'),
'email_from': fields.char('From', size=128, help="Email From"),
- 'email_to': fields.text('To', help="Email Recipients"),
- 'email_cc': fields.text('Cc', help="Carbon Copy Email Recipients"),
- 'email_bcc': fields.text('Bcc', help='Blind Carbon Copy Email Recipients'),
+ 'email_to': fields.char('To', help="Email Recipients", size=256),
+ 'email_cc': fields.char('Cc', help="Carbon Copy Email Recipients", size=256),
+ 'email_bcc': fields.char('Bcc', help='Blind Carbon Copy Email Recipients', size=256),
'message_id': fields.char('Message Id', size=1024, readonly=True, help="Message Id on Email.", select=True),
'references': fields.text('References', readonly=True, help="References emails."),
'description': fields.text('Description'),
diff --git a/addons/mrp_repair/mrp_repair.py b/addons/mrp_repair/mrp_repair.py
index a3eac181231..819acffd4ae 100644
--- a/addons/mrp_repair/mrp_repair.py
+++ b/addons/mrp_repair/mrp_repair.py
@@ -372,7 +372,7 @@ class mrp_repair(osv.osv):
name = operation.name
if operation.product_id.property_account_income:
- account_id = operation.product_id.property_account_income
+ account_id = operation.product_id.property_account_income.id
elif operation.product_id.categ_id.property_account_income_categ:
account_id = operation.product_id.categ_id.property_account_income_categ.id
else:
diff --git a/addons/procurement/schedulers.py b/addons/procurement/schedulers.py
index dc66d9e3e8b..c0cc0f736b6 100644
--- a/addons/procurement/schedulers.py
+++ b/addons/procurement/schedulers.py
@@ -31,7 +31,15 @@ class procurement_order(osv.osv):
def _procure_confirm(self, cr, uid, ids=None, use_new_cursor=False, context=None):
'''
- use_new_cursor: False or the dbname
+ Call the scheduler to check the procurement order
+
+ @param self: The object pointer
+ @param cr: The current row, from the database cursor,
+ @param uid: The current user ID for security checks
+ @param ids: List of selected IDs
+ @param use_new_cursor: False or the dbname
+ @param context: A standard dictionary for contextual values
+ @return: Dictionary of values
'''
if not context:
context = {}
@@ -126,6 +134,15 @@ class procurement_order(osv.osv):
return {}
def create_automatic_op(self, cr, uid, context=None):
+ """
+ Create procurement of virtual stock < 0
+
+ @param self: The object pointer
+ @param cr: The current row, from the database cursor,
+ @param uid: The current user ID for security checks
+ @param context: A standard dictionary for contextual values
+ @return: Dictionary of values
+ """
if not context:
context = {}
product_obj = self.pool.get('product.product')
@@ -167,7 +184,16 @@ class procurement_order(osv.osv):
def _procure_orderpoint_confirm(self, cr, uid, automatic=False,\
use_new_cursor=False, context=None, user_id=False):
'''
+ Create procurement based on Orderpoint
use_new_cursor: False or the dbname
+
+ @param self: The object pointer
+ @param cr: The current row, from the database cursor,
+ @param user_id: The current user ID for security checks
+ @param context: A standard dictionary for contextual values
+ @param param: False or the dbname
+ @return: Dictionary of values
+ """
'''
if not context:
context = {}
diff --git a/addons/product/product_data.xml b/addons/product/product_data.xml
index 4fada46aeef..05a57126402 100644
--- a/addons/product/product_data.xml
+++ b/addons/product/product_data.xml
@@ -39,13 +39,13 @@
smaller
- hour
+ Hoursmaller
- day
+ Day
diff --git a/addons/project/__init__.py b/addons/project/__init__.py
index 44154c8ae05..3f65abca376 100644
--- a/addons/project/__init__.py
+++ b/addons/project/__init__.py
@@ -27,5 +27,4 @@ import report
import wizard
import res_partner
-
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/project/__openerp__.py b/addons/project/__openerp__.py
index c3784c457b1..726e87b5979 100644
--- a/addons/project/__openerp__.py
+++ b/addons/project/__openerp__.py
@@ -26,8 +26,8 @@
"author": "Tiny",
"website": "http://www.openerp.com",
"category": "Generic Modules/Projects & Services",
- "depends": ["product", "analytic", "process", "mail_gateway","board"],
- "description": """Project management module that track multi-level projects, tasks,
+ "depends": ["product", "analytic", "mail_gateway", "board"],
+ "description": """Project management module tracks multi-level projects, tasks,
work done on tasks, eso. It is able to render planning, order tasks, eso.
Dashboard for project members that includes:
* List of my open tasks
@@ -41,7 +41,6 @@ work done on tasks, eso. It is able to render planning, order tasks, eso.
"wizard/project_task_delegate_view.xml",
"security/ir.model.access.csv",
"project_data.xml",
- "project_wizard.xml",
"project_view.xml",
"project_report.xml",
"process/task_process.xml",
diff --git a/addons/project/board_project_demo.xml b/addons/project/board_project_demo.xml
index 2a160b4454f..99c9c4a23ff 100644
--- a/addons/project/board_project_demo.xml
+++ b/addons/project/board_project_demo.xml
@@ -1,8 +1,7 @@
-
-
+
+
diff --git a/addons/project/board_project_view.xml b/addons/project/board_project_view.xml
index f9e2dc5dd52..6258c85f689 100644
--- a/addons/project/board_project_view.xml
+++ b/addons/project/board_project_view.xml
@@ -6,22 +6,6 @@
Project
-
- project.task.tree
- project.task
- tree
-
-
-
-
-
-
-
-
-
-
-
- project.task.tree
@@ -39,6 +23,7 @@
+
My Open Tasksproject.task
@@ -47,6 +32,7 @@
[('user_id','=',uid),('state','=','open')]
+
My Pending Tasksproject.task
@@ -55,6 +41,7 @@
[('user_id','=',uid),('state','=','pending')]
+
My Task's Deadlinesproject.task
@@ -125,17 +112,20 @@
menu
+
+
+
diff --git a/addons/project/installer.py b/addons/project/installer.py
index e35e1b72a6c..23ab9630570 100644
--- a/addons/project/installer.py
+++ b/addons/project/installer.py
@@ -18,6 +18,7 @@
# along with this program. If not, see .
#
##############################################################################
+
from osv import fields, osv
class project_installer(osv.osv_memory):
@@ -26,7 +27,8 @@ class project_installer(osv.osv_memory):
_columns = {
# Project Management
- 'project_long_term': fields.boolean('Long Term Planning',
+ 'project_long_term': fields.boolean(
+ 'Long Term Planning',
help="Enables long-term projects tracking, including "
"multiple-phase projects and resource allocation handling."),
'project_wiki': fields.boolean('Specifications in a Wiki',
@@ -35,7 +37,7 @@ class project_installer(osv.osv_memory):
help="Tracks and helps employees encode and validate timesheets "
"and attendance."),
'hr_timesheet_invoice': fields.boolean('Invoice Based on Hours',
- help="Helps generate invoice based on based on human resources "
+ help="Helps generate invoice based on human resources "
"costs and general expenses."),
'account_budget': fields.boolean('Budgets',
help="Helps accountants manage analytic and crossover budgets."),
@@ -49,12 +51,14 @@ class project_installer(osv.osv_memory):
help="Implements and tracks the concepts and task types defined "
"in the SCRUM methodology."),
'project_gtd': fields.boolean('Getting Things Done',
- help="Embeds the Getting Things Done concepts into OpenERP's "
+ help="Embeds the 'Getting Things Done concepts' into OpenERP's "
"project management."),
}
+
_defaults={
- 'project_crm': True,
+ 'project_crm': True,
}
+
project_installer()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
diff --git a/addons/project/project.py b/addons/project/project.py
index 0d62929416e..5ed5f9641ab 100644
--- a/addons/project/project.py
+++ b/addons/project/project.py
@@ -18,8 +18,8 @@
# along with this program. If not, see .
#
##############################################################################
+
from lxml import etree
-import datetime
import time
from tools.translate import _
@@ -38,6 +38,7 @@ class project_task_type(osv.osv):
_defaults = {
'sequence': 1
}
+
project_task_type()
class project(osv.osv):
@@ -46,10 +47,8 @@ class project(osv.osv):
_inherits = {'account.analytic.account':"category_id"}
def search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False):
- if context is None:
- context = {}
if user == 1:
- return super(project, self).search(cr, user, args, offset=offset, limit=limit, order=order, context=context, count=count)
+ return super(project, self).search(cr, user, args, offset=offset, limit=limit, order=order, context=context, count=count)
if context and context.has_key('user_prefence') and context['user_prefence']:
cr.execute("""SELECT project.id FROM project_project project
LEFT JOIN account_analytic_account account ON account.id = project.category_id
@@ -61,8 +60,6 @@ class project(osv.osv):
context=context, count=count)
def _complete_name(self, cr, uid, ids, name, args, context=None):
- if context is None:
- context = {}
res = {}
for m in self.browse(cr, uid, ids, context=context):
res[m.id] = (m.parent_id and (m.parent_id.name + '/') or '') + m.name
@@ -73,8 +70,6 @@ class project(osv.osv):
parent=parent)
def onchange_partner_id(self, cr, uid, ids, part=False, context=None):
- if context is None:
- context = {}
partner_obj = self.pool.get('res.partner')
if not part:
return {'value':{'contact_id': False, 'pricelist_id': False}}
@@ -84,8 +79,6 @@ class project(osv.osv):
return {'value':{'contact_id': addr['contact'], 'pricelist_id': pricelist_id}}
def _progress_rate(self, cr, uid, ids, names, arg, context=None):
- if context is None:
- context = {}
res = {}.fromkeys(ids, 0.0)
progress = {}
if not ids:
@@ -143,13 +136,16 @@ class project(osv.osv):
'type_ids': fields.many2many('project.task.type', 'project_task_type_rel', 'project_id', 'type_id', 'Tasks Stages'),
'project_escalation_id': fields.many2one('project.project','Project Escalation', help='If any issue is escalated from the current Project, it will be listed under the project selected here.'),
}
+
_order = "sequence"
+
_defaults = {
'active': True,
'priority': 1,
'sequence': 10,
'warn_manager': True,
}
+
def _check_dates(self, cr, uid, ids):
leave = self.read(cr, uid, ids[0], ['date_start', 'date'])
if leave['date_start'] and leave['date']:
@@ -168,6 +164,7 @@ class project(osv.osv):
(_check_dates, 'Error! project start-date must be lower then project end-date.', ['date_start', 'date']),
(_check_escalation, 'Error! You cannot assign escalation to the same project!', ['project_escalation_id'])
]
+
def set_template(self, cr, uid, ids, context=None):
res = self.setActive(cr, uid, ids, value=False, context=context)
return res
@@ -255,16 +252,11 @@ class project(osv.osv):
'search_view_id': search_view['res_id'],
'nodestroy': True
}
-# return result
# set active value for a project, its sub projects and its tasks
def setActive(self, cr, uid, ids, value=True, context=None):
- if context is None:
- context = {}
task_obj = self.pool.get('project.task')
for proj in self.browse(cr, uid, ids, context=None):
- if context is None:
- context = {}
self.write(cr, uid, [proj.id], {'state': value and 'open' or 'template'}, context)
cr.execute('select id from project_task where project_id=%s', (proj.id,))
tasks_id = [x[0] for x in cr.fetchall()]
@@ -273,9 +265,8 @@ class project(osv.osv):
child_ids = self.search(cr, uid, [('parent_id','=', proj.id)])
if child_ids:
self.setActive(cr, uid, child_ids, value, context=None)
- if context is None:
- context = {}
return True
+
project()
class task(osv.osv):
@@ -285,16 +276,12 @@ class task(osv.osv):
_date_name = "date_start"
def _str_get(self, task, level=0, border='***', context=None):
- if context is None:
- context = {}
return border+' '+(task.user_id and task.user_id.name.upper() or '')+(level and (': L'+str(level)) or '')+(' - %.1fh / %.1fh'%(task.effective_hours or 0.0,task.planned_hours))+' '+border+'\n'+ \
border[0]+' '+(task.name or '')+'\n'+ \
(task.description or '')+'\n\n'
# Compute: effective_hours, total_hours, progress
def _hours_get(self, cr, uid, ids, field_names, args, context=None):
- if context is None:
- context = {}
res = {}
cr.execute("SELECT task_id, COALESCE(SUM(hours),0) FROM project_task_work WHERE task_id IN %s GROUP BY task_id",(tuple(ids),))
hours = dict(cr.fetchall())
@@ -314,6 +301,8 @@ class task(osv.osv):
return {'value':{'remaining_hours': planned - effective}}
def _default_project(self, cr, uid, context=None):
+ if context is None:
+ context = {}
if 'project_id' in context and context['project_id']:
return int(context['project_id'])
return False
@@ -323,15 +312,11 @@ class task(osv.osv):
#]
def copy_data(self, cr, uid, id, default={}, context=None):
- if context is None:
- context = {}
default = default or {}
default['work_ids'] = []
return super(task, self).copy_data(cr, uid, id, default, context)
def _check_dates(self, cr, uid, ids, context=None):
- if context is None:
- context = {}
task = self.read(cr, uid, ids[0], ['date_start', 'date_end'])
if task['date_start'] and task['date_end']:
if task['date_start'] > task['date_end']:
@@ -346,7 +331,7 @@ class task(osv.osv):
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of tasks."),
'type': fields.many2one('project.task.type', 'Stage',),
'state': fields.selection([('draft', 'Draft'),('open', 'In Progress'),('pending', 'Pending'), ('cancelled', 'Cancelled'), ('done', 'Done')], 'State', readonly=True, required=True,
- help='If the task is created the state \'Draft\'.\n If the task is started, the state becomes \'In Progress\'.\n If review is needed the task is in \'Pending\' state.\
+ help='If the task is created the state is \'Draft\'.\n If the task is started, the state becomes \'In Progress\'.\n If review is needed the task is in \'Pending\' state.\
\n If the task is over, the states is set to \'Done\'.'),
'date_start': fields.datetime('Starting Date'),
'date_end': fields.datetime('Ending Date'),
@@ -370,6 +355,7 @@ class task(osv.osv):
'manager_id': fields.related('project_id', 'category_id', 'user_id', type='many2one', relation='res.users', string='Project Manager'),
'company_id': fields.many2one('res.company', 'Company'),
}
+
_defaults = {
'state': 'draft',
'priority': '2',
@@ -380,6 +366,7 @@ class task(osv.osv):
'project_id': _default_project,
'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'project.task', context=c)
}
+
_order = "sequence, priority, date_start, id"
_constraints = [
@@ -388,10 +375,9 @@ class task(osv.osv):
#
# Override view according to the company definition
#
+
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
users_obj = self.pool.get('res.users')
- if context is None:
- context = {}
obj_tm = users_obj.browse(cr, uid, uid, context).company_id.project_time_mode_id
tm = obj_tm and obj_tm.name or 'Hours'
@@ -424,6 +410,10 @@ class task(osv.osv):
mod_obj = self.pool.get('ir.model.data')
request = self.pool.get('res.request')
tasks = self.browse(cr, uid, ids)
+ task_id = ids[0]
+ cntx = {}
+ if len(args):
+ cntx = args[0]
for task in tasks:
project = task.project_id
if project:
@@ -437,8 +427,7 @@ class task(osv.osv):
'ref_doc1': 'project.task,%d'% (task.id,),
'ref_doc2': 'project.project,%d'% (project.id,),
})
- elif project.warn_manager:
- task_id = ids[0]
+ elif project.warn_manager and cntx.get('mail_send',False):
mail_send = True
message = _('Task ') + " '" + task.name + "' "+ _("is Done.")
self.log(cr, uid, task.id, message)
@@ -454,11 +443,11 @@ class task(osv.osv):
if mail_send:
model_data_ids = mod_obj.search(cr,uid,[('model','=','ir.ui.view'),('name','=','view_project_close_task')])
resource_id = mod_obj.read(cr, uid, model_data_ids, fields=['res_id'])[0]['res_id']
- args[0].update({'task_id': task_id})
+ cntx.update({'task_id': task_id})
return {
'name': _('Email Send to Customer'),
'view_type': 'form',
- 'context': args[0], # improve me
+ 'context': cntx, # improve me
'view_mode': 'tree,form',
'res_model': 'close.task',
'views': [(resource_id,'form')],
@@ -466,7 +455,9 @@ class task(osv.osv):
'target': 'new',
'nodestroy': True
}
- return True
+ else:
+ self.write(cr, uid, [task_id], {'state': 'done', 'date_end':time.strftime('%Y-%m-%d %H:%M:%S'), 'remaining_hours': 0.0})
+ return False
def do_reopen(self, cr, uid, ids, *args):
request = self.pool.get('res.request')
@@ -562,11 +553,14 @@ class project_work(osv.osv):
'user_id': fields.many2one('res.users', 'Done by', required=True),
'company_id': fields.related('task_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True)
}
+
_defaults = {
'user_id': lambda obj, cr, uid, context: uid,
'date': time.strftime('%Y-%m-%d %H:%M:%S')
}
+
_order = "date desc"
+
def create(self, cr, uid, vals, *args, **kwargs):
if 'hours' in vals and (not vals['hours']):
vals['hours'] = 0.00
@@ -588,10 +582,12 @@ class project_work(osv.osv):
for work in self.browse(cr, uid, ids):
cr.execute('update project_task set remaining_hours=remaining_hours + %s where id=%s', (work.hours, work.task_id.id))
return super(project_work,self).unlink(cr, uid, ids, *args, **kwargs)
+
project_work()
class config_compute_remaining(osv.osv_memory):
_name='config.compute.remaining'
+
def _get_remaining(self,cr, uid, ctx):
task_obj = self.pool.get('project.task')
if 'active_id' in ctx:
@@ -638,6 +634,7 @@ config_compute_remaining()
class message(osv.osv):
_name = "project.message"
_description = "Message"
+
_columns = {
'subject': fields.char('Subject', size=128, required="True"),
'project_id': fields.many2one('project.project', 'Project', ondelete='cascade'),
@@ -655,7 +652,7 @@ class message(osv.osv):
_defaults = {
'user_id': lambda self,cr,uid,ctx: uid,
- 'date': lambda self,cr,uid,ctx: time.strftime('%Y-%m-%d'),
+ 'date': time.strftime('%Y-%m-%d'),
'project_id': _default_project
}
@@ -667,6 +664,7 @@ class users(osv.osv):
_columns = {
'context_project_id': fields.many2one('project.project', 'Project')
}
+
users()
class account_analytic_account(osv.osv):
diff --git a/addons/project/project_data.xml b/addons/project/project_data.xml
index a931c96f635..7c5b40f3ddf 100644
--- a/addons/project/project_data.xml
+++ b/addons/project/project_data.xml
@@ -1,6 +1,7 @@
+
diff --git a/addons/project/project_demo.xml b/addons/project/project_demo.xml
index 973194e0e31..43f01c2120d 100644
--- a/addons/project/project_demo.xml
+++ b/addons/project/project_demo.xml
@@ -45,7 +45,7 @@
20
- Specific Developements
+ Specific Developments
@@ -64,7 +64,7 @@
- BoM, After sales returns, interventions. Tracability.
+ BoM, After sales returns, interventions. Traceability.Specific adaptation to MRP
@@ -146,7 +146,7 @@
24.0
- MRP; functionnal layer
+ MRP; functional layerdone
@@ -172,7 +172,7 @@
32.0
- Customer docs
+ Customer doc30
@@ -266,5 +266,6 @@
- Create Users
Configuration steps
+
diff --git a/addons/project/project_installer.xml b/addons/project/project_installer.xml
index 12510f8b944..c989ab50aab 100644
--- a/addons/project/project_installer.xml
+++ b/addons/project/project_installer.xml
@@ -1,12 +1,13 @@
+
project.installer.viewproject.installerform
-
+
Project Modules Installation
@@ -16,12 +17,11 @@
-
- Various OpenERP applications are available to bring your project management to the next levels of control and flexibility.
+
+ Various OpenERP applications are available to bring your project management to the next levels of control and flexibility.
- Configure
+ Configure
@@ -65,5 +65,6 @@
+
diff --git a/addons/project/project_mailgate.py b/addons/project/project_mailgate.py
index b057c98b03d..8c1004b52fa 100644
--- a/addons/project/project_mailgate.py
+++ b/addons/project/project_mailgate.py
@@ -19,24 +19,13 @@
#
##############################################################################
-import time
-import re
-import os
-
-import mx.DateTime
-import base64
-
-from tools.translate import _
-
-import tools
-from osv import fields,osv,orm
-from osv.orm import except_orm
+from osv import fields,osv
class project_tasks(osv.osv):
_name = "project.task"
_inherit = "project.task"
- def msg_new(self, cr, uid, msg):
+ def msg_new(self, cr, uid, msg):
mailgate_obj = self.pool.get('mail.gateway')
msg_body = mailgate_obj.msg_body_get(msg)
data = {
@@ -72,14 +61,11 @@ class project_tasks(osv.osv):
if msg_actions['priority'] in ('1','2','3','4','5'):
data['priority'] = msg_actions['priority']
-
self.write(cr, uid, [id], data)
getattr(self,act)(cr, uid, [id])
return True
def message_followers(self, cr, uid, ids, context=None):
- if context is None:
- context = {}
res = []
if isinstance(ids, (str, int, long)):
select = [ids]
@@ -93,6 +79,8 @@ class project_tasks(osv.osv):
return res
def msg_send(self, cr, uid, id, *args, **argv):
- return True
+ return True
project_tasks()
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
diff --git a/addons/project/project_resource.py b/addons/project/project_resource.py
index 8ff68c94ea8..1295ea9e64a 100644
--- a/addons/project/project_resource.py
+++ b/addons/project/project_resource.py
@@ -1,10 +1,29 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
import pooler
import datetime
-def timeformat_convert(cr, uid, time_string, context=None):
+def timeformat_convert(cr, uid, time_string):
# Function to convert input time string:: 8.5 to output time string 8:30
- if context is None:
- context = {}
split_list = str(time_string).split('.')
hour_part = split_list[0]
mins_part = split_list[1]
@@ -12,7 +31,7 @@ def timeformat_convert(cr, uid, time_string, context=None):
converted_string = hour_part + ':' + str(round_mins)[0:2]
return converted_string
-def leaves_resource(cr,uid,calendar_id,resource_id=False,resource_calendar=False):
+def leaves_resource(cr, uid, calendar_id, resource_id=False, resource_calendar=False):
# To get the leaves for the resource_ids working on phase
pool = pooler.get_pool(cr.dbname)
@@ -31,20 +50,20 @@ def leaves_resource(cr,uid,calendar_id,resource_id=False,resource_calendar=False
leaves.sort()
return leaves
-def compute_working_calendar(cr,uid,calendar_id):
+def compute_working_calendar(cr, uid, calendar_id):
# To change the format of working calendar to bring it into 'faces' format
pool = pooler.get_pool(cr.dbname)
resource_week_pool = pool.get('resource.calendar.week')
time_range = "8:00-8:00"
non_working = ""
- wk = {"0":"mon","1":"tue","2":"wed","3":"thu","4":"fri","5":"sat","6":"sun"}
+ wk = {"0":"mon", "1":"tue", "2":"wed", "3":"thu", "4":"fri", "5":"sat", "6":"sun"}
wk_days = {}
wk_time = {}
wktime_list = []
wktime_cal = []
week_ids = resource_week_pool.search(cr, uid, [('calendar_id','=',calendar_id)])
- week_obj = resource_week_pool.read(cr, uid, week_ids, ['dayofweek','hour_from','hour_to'])
+ week_obj = resource_week_pool.read(cr, uid, week_ids, ['dayofweek', 'hour_from', 'hour_to'])
# Converting time formats into appropriate format required
# and creating a list like [('mon', '8:00-12:00'), ('mon', '13:00-18:00')]
@@ -80,3 +99,5 @@ def compute_working_calendar(cr,uid,calendar_id):
wktime_cal.append((non_working[:-1],time_range))
return wktime_cal
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml
index 006d32b8b68..0c9b2f671ce 100644
--- a/addons/project/project_view.xml
+++ b/addons/project/project_view.xml
@@ -1,6 +1,7 @@
+
+
@@ -252,18 +254,19 @@
+
+
+
+
-
-
-
-
-
+
+
@@ -647,5 +650,6 @@
+
diff --git a/addons/project/project_wizard.xml b/addons/project/project_wizard.xml
deleted file mode 100644
index 25001605210..00000000000
--- a/addons/project/project_wizard.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/addons/project/report/__init__.py b/addons/project/report/__init__.py
index 295b8c9674d..f35064b9752 100644
--- a/addons/project/report/__init__.py
+++ b/addons/project/report/__init__.py
@@ -18,6 +18,7 @@
# along with this program. If not, see .
#
##############################################################################
+
import project_report
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/project/report/project_report.py b/addons/project/report/project_report.py
index fec1052b28b..a3ecf0f4ba1 100644
--- a/addons/project/report/project_report.py
+++ b/addons/project/report/project_report.py
@@ -118,6 +118,7 @@ class report_project_task_user(osv.osv):
t.type
""")
+
report_project_task_user()
#This class is generated for project deshboard purpose
@@ -162,6 +163,7 @@ class project_vs_remaining_hours(osv.osv):
GROUP BY pur.uid,aaa.state,aaa.name
)
""")
+
project_vs_remaining_hours()
class task_by_days(osv.osv):
@@ -192,6 +194,7 @@ class task_by_days(osv.osv):
to_char(pt.create_date, 'YYYY-MM-DD'),pt.state,pt.project_id
)
""")
+
task_by_days()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/project/report/project_report_view.xml b/addons/project/report/project_report_view.xml
index 9df6bd1f8ab..f22875cee4d 100644
--- a/addons/project/report/project_report_view.xml
+++ b/addons/project/report/project_report_view.xml
@@ -1,6 +1,7 @@
+
@@ -42,13 +43,13 @@
report.project.task.usergraph
-
-
-
-
-
-
-
+
+
+
+
+
+
+
report.project.task.user.search
@@ -174,7 +175,7 @@
-
+ Project and remaining hoursproject.vs.remaining.hoursform
@@ -184,7 +185,7 @@
-
+ task.by.days.treetask.by.daystree
diff --git a/addons/project/res_partner.py b/addons/project/res_partner.py
index 351f28cb283..3e2ff83f078 100644
--- a/addons/project/res_partner.py
+++ b/addons/project/res_partner.py
@@ -23,7 +23,7 @@ from osv import fields,osv
class res_partner(osv.osv):
- """ Inherits partner and adds CRM information in the partner form """
+ """ Inherits partner and adds Tasks information in the partner form """
_inherit = 'res.partner'
_columns = {
'task_ids': fields.one2many('project.task', 'partner_id', 'Tasks'),
diff --git a/addons/project/res_partner_view.xml b/addons/project/res_partner_view.xml
index 4778c0f1017..b130b057062 100644
--- a/addons/project/res_partner_view.xml
+++ b/addons/project/res_partner_view.xml
@@ -20,6 +20,7 @@
+
diff --git a/addons/project/wizard/project_close_task.py b/addons/project/wizard/project_close_task.py
index b1cd933a4f7..715e70e59d0 100644
--- a/addons/project/wizard/project_close_task.py
+++ b/addons/project/wizard/project_close_task.py
@@ -19,8 +19,9 @@
#
##############################################################################
-from osv import fields, osv
+import time
+from osv import fields, osv
from tools.translate import _
from tools import email_send as email
@@ -42,7 +43,7 @@ class project_close_task(osv.osv_memory):
if 'task_id' in context:
task = self.pool.get('project.task').browse(cr, uid, context['task_id'])
partner_id = task.partner_id or task.project_id.partner_id
- if partner_id and partner_id.address[0].email:
+ if partner_id and len(partner_id.address) and partner_id.address[0].email:
email = partner_id.address[0].email
return email
@@ -54,10 +55,15 @@ class project_close_task(osv.osv_memory):
return task.description or task.name
return ''
- _defaults={
+ _defaults = {
'email': _get_email,
'description': _get_desc,
}
+
+ def close(self, cr, uid, ids, context=None):
+ if 'task_id' in context:
+ self.pool.get('project.task').write(cr, uid, [context['task_id']], {'state': 'done', 'date_end':time.strftime('%Y-%m-%d %H:%M:%S'), 'remaining_hours': 0.0})
+ return {}
def confirm(self, cr, uid, ids, context=None):
if context is None:
@@ -67,8 +73,10 @@ class project_close_task(osv.osv_memory):
close_task = self.read(cr, uid, ids[0], [])
to_adr = close_task['email']
description = close_task['description']
+
if 'task_id' in context:
- for task in self.pool.get('project.task').browse(cr, uid, [context['task_id']], context=context):
+ task_obj = self.pool.get('project.task')
+ for task in task_obj.browse(cr, uid, [context['task_id']], context=context):
project = task.project_id
subject = "Task '%s' closed" % task.name
if task.user_id and task.user_id.address_id and task.user_id.address_id.email:
@@ -89,9 +97,11 @@ class project_close_task(osv.osv_memory):
footer = (project.warn_footer or '') % val
body = u'%s\n%s\n%s\n\n-- \n%s' % (header, description, footer, signature)
email(from_adr, [to_adr], subject, body.encode('utf-8'), email_bcc=[from_adr])
+ task_obj.write(cr, uid, [task.id], {'state': 'done', 'date_end':time.strftime('%Y-%m-%d %H:%M:%S'), 'remaining_hours': 0.0})
else:
- raise osv.except_osv(_('Error'), _("Couldn't send mail because the contact for this task (%s) has no email address!") % contact.name)
+ raise osv.except_osv(_('Error'), _("Please specify the email address of partner."))
return {}
project_close_task()
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/project/wizard/project_close_task_view.xml b/addons/project/wizard/project_close_task_view.xml
index f9206152b25..e46ddf7d6da 100644
--- a/addons/project/wizard/project_close_task_view.xml
+++ b/addons/project/wizard/project_close_task_view.xml
@@ -16,9 +16,11 @@
-
-
-
+
+
+
+
+
diff --git a/addons/project/wizard/project_task_delegate.py b/addons/project/wizard/project_task_delegate.py
index 779909273df..850f27b99d4 100644
--- a/addons/project/wizard/project_task_delegate.py
+++ b/addons/project/wizard/project_task_delegate.py
@@ -102,19 +102,20 @@ class project_task_delegate(osv.osv_memory):
'description': delegate_data['new_task_description'] or '',
'child_ids': [],
'work_ids': []
- })
+ }, context)
task_obj.write(cr, uid, [task.id], {
'remaining_hours': delegate_data['planned_hours_me'],
'planned_hours': delegate_data['planned_hours_me'] + (task.effective_hours or 0.0),
'name': newname,
- })
+ }, context)
if delegate_data['state'] == 'pending':
- task_obj.do_pending(cr, uid, [task.id])
+ task_obj.do_pending(cr, uid, [task.id], context)
else:
- task_obj.do_close(cr, uid, [task.id])
- delegrate_user = user_obj.browse(cr, uid, delegate_data['user_id'], context=context)
- message = _('Task ') + " '" + delegate_data['name'] + "' "+ _("is Delegated to User:") +" '"+ delegrate_user.name +"' "
- self.log(cr, uid, task.id, message)
+ context.update({'mail_send': False} )
+ task_obj.do_close(cr, uid, [task.id], context)
+ delegrate_user = user_obj.browse(cr, uid, delegate_data['user_id'], context=context)
+ message = _('Task ') + " '" + delegate_data['name'] + "' "+ _("is Delegated to User:") +" '"+ delegrate_user.name +"' "
+ self.log(cr, uid, task.id, message)
return {}
project_task_delegate()
diff --git a/addons/project_issue/__openerp__.py b/addons/project_issue/__openerp__.py
index ff90c5c131b..84414cf8a1b 100644
--- a/addons/project_issue/__openerp__.py
+++ b/addons/project_issue/__openerp__.py
@@ -34,7 +34,6 @@
'crm',
'project',
'hr_timesheet_sheet',
- 'resource'
],
'init_xml': [
'project_issue_data.xml'
diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py
index a67ca004f09..ed648fb2969 100644
--- a/addons/project_issue/project_issue.py
+++ b/addons/project_issue/project_issue.py
@@ -144,7 +144,6 @@ class project_issue(osv.osv, crm.crm_case):
'create_date': fields.datetime('Creation Date', readonly=True),
'write_date': fields.datetime('Update Date', readonly=True),
'date_deadline': fields.date('Deadline'),
- 'date_closed': fields.datetime('Closed', readonly=True),
'section_id': fields.many2one('crm.case.section', 'Sales Team', \
select=True, help='Sales team to which Case belongs to.\
Define Responsible user and Email account for mail gateway.'),
@@ -160,7 +159,7 @@ class project_issue(osv.osv, crm.crm_case):
\nWhen the case is over, the state is set to \'Done\'.\
\nIf the case needs to be reviewed then the state is set to \'Pending\'.'),
'email_from': fields.char('Email', size=128, help="These people will receive email."),
- 'email_cc': fields.text('Watchers Emails', size=252, help="These people\
+ 'email_cc': fields.char('Watchers Emails', size=256, help="These people\
will receive a copy of the future" \
" communication between partner and users by email"),
'date_open': fields.datetime('Opened', readonly=True),
@@ -391,7 +390,6 @@ class project_issue(osv.osv, crm.crm_case):
res = self.write(cr, uid, ids, vals)
return res
-
def msg_send(self, cr, uid, id, *args, **argv):
""" Send The Message
diff --git a/addons/project_issue/project_issue_view.xml b/addons/project_issue/project_issue_view.xml
index 0bdee911cee..cbf24b18f76 100644
--- a/addons/project_issue/project_issue_view.xml
+++ b/addons/project_issue/project_issue_view.xml
@@ -154,9 +154,9 @@
-
+
@@ -142,10 +142,11 @@
- Purchase Orders
+ Purchase Analysispurchase.reportformtree,graph
+ {'search_default_month':1,'search_default_group_partner_id':1,'search_default_group_product_id': 1, 'search_default_orders': 1, 'group_by_no_leaf':1,'group_by':[]}
diff --git a/addons/purchase_requisition/purchase_requisition.py b/addons/purchase_requisition/purchase_requisition.py
index db05650354b..532c9918b60 100644
--- a/addons/purchase_requisition/purchase_requisition.py
+++ b/addons/purchase_requisition/purchase_requisition.py
@@ -129,10 +129,14 @@ class purchase_order(osv.osv):
}
def wkf_confirm_order(self, cr, uid, ids, context={}):
res = super(purchase_order, self).wkf_confirm_order(cr, uid, ids, context)
+ proc_obj=self.pool.get('procurement.order')
for po in self.browse(cr, uid, ids, context):
if po.requisition_id and (po.requisition_id.exclusive=='exclusive'):
for order in po.requisition_id.purchase_ids:
if order.id<>po.id:
+ proc_ids = proc_obj.search(cr, uid, [('purchase_id', '=', order.id)])
+ if proc_ids and po.state=='confirmed':
+ proc_obj.wirte(cr,uid,proc_ids,{'purchase_id':po.id})
wf_service = netsvc.LocalService("workflow")
wf_service.trg_validate(uid, 'purchase.order', order.id, 'purchase_cancel', cr)
self.pool.get('purchase.requisition').write(cr, uid, [po.requisition_id.id], {'state':'done','date_end':time.strftime('%Y-%m-%d %H:%M:%S')})
@@ -155,14 +159,17 @@ product_product()
class procurement_order(osv.osv):
_inherit = 'procurement.order'
-
+ _columns = {
+ 'requisition_id' : fields.many2one('purchase.requisition','Latest Requisition')
+ }
def make_po(self, cr, uid, ids, context=None):
sequence_obj = self.pool.get('ir.sequence')
res = super(procurement_order, self).make_po(cr, uid, ids, context=context)
for proc_id, po_id in res.items():
procurement = self.browse(cr, uid, proc_id)
+ requisition_id=False
if procurement.product_id.purchase_requisition:
- self.pool.get('purchase.requisition').create(cr, uid, {
+ requisition_id=self.pool.get('purchase.requisition').create(cr, uid, {
'name': sequence_obj.get(cr, uid, 'purchase.order.requisition'),
'origin': procurement.name,
'date_end': procurement.date_planned,
@@ -174,6 +181,7 @@ class procurement_order(osv.osv):
})],
'purchase_ids': [(6,0,[po_id])]
})
+ self.write(cr,uid,proc_id,{'requisition_id':requisition_id})
return res
procurement_order()
diff --git a/addons/purchase_requisition/purchase_requisition_view.xml b/addons/purchase_requisition/purchase_requisition_view.xml
index 76aa70aaf42..b8e488ac0cf 100644
--- a/addons/purchase_requisition/purchase_requisition_view.xml
+++ b/addons/purchase_requisition/purchase_requisition_view.xml
@@ -168,6 +168,17 @@
-
+
+
+ procurement.form.inherit
+ form
+ procurement.order
+
+
+
+
+
+
+
diff --git a/addons/purchase_requisition/test/purchase_requisition.yml b/addons/purchase_requisition/test/purchase_requisition.yml
index 0ace2312034..ce5f9635574 100644
--- a/addons/purchase_requisition/test/purchase_requisition.yml
+++ b/addons/purchase_requisition/test/purchase_requisition.yml
@@ -63,7 +63,7 @@
proc_obj = self.pool.get('procurement.order')
proc_obj._procure_confirm(cr,uid)
-
- On the purchase tender, I create a new purchase order for the supplier 'DistriPC' by clicking on
+ On the purchase requisition, I create a new purchase order for the supplier 'DistriPC' by clicking on
the button 'New RfQ'. This opens a window to ask me the supplier and I set DistriPC .
-
!record {model: purchase.requisition.partner, id: purchase_requisition_partner_0}:
@@ -74,23 +74,25 @@
-
!python {model: purchase.requisition.partner}: |
req_obj = self.pool.get('purchase.requisition')
- ids =req_obj.search(cr, uid, [('origin','=','TEST/TENDER/0001')])
+ ids =req_obj.search(cr, uid, [('origin','=','Laptop ACER')])
self.create_order(cr, uid, [ref("purchase_requisition_partner_0")], {"lang":
'en_US', "active_model": "purchase.requisition", "tz": False, "record_id":
1, "active_ids": ids, "active_id": ids[0], })
-
- I check that I have two purchase orders on the purchase tender.
+ I check that I have two purchase orders on the purchase requisition.
-
!python {model: purchase.order}: |
+ from tools.translate import _
order_ids =self.search(cr, uid, [('origin','=','TEST/TENDER/0001')])
ids=len(order_ids)
- assert (ids==2), "Purchase order hasn't Created"
+ assert(ids == 2), _('Purchase Order not Created')
+
-
I set the purchase requisition as 'Not Exclusive'.
-
!python {model: purchase.requisition}: |
- ids =self.search(cr, uid, [('origin','=','TEST/TENDER/0001')])
+ ids =self.search(cr, uid, [('origin','=','Laptop ACER')])
self.write(cr,uid,ids[0],{'exclusive': 'multiple' })
-
I change the quantities so that the purchase order for DistriPC includes 3 pieces and the
@@ -100,7 +102,7 @@
line_obj=self.pool.get('purchase.order.line')
partner_obj=self.pool.get('res.partner')
requistion_obj=self.pool.get('purchase.requisition')
- requistion_ids =requistion_obj.search(cr, uid, [('origin','=','TEST/TENDER/0001')])
+ requistion_ids =requistion_obj.search(cr, uid, [('origin','=','Laptop ACER')])
partner_id1=partner_obj.search(cr,uid,[('name','=','ASUStek')])[0]
partner_id2=partner_obj.search(cr,uid,[('name','=','Distrib PC')])[0]
purchase_id1= self.search(cr, uid, [('partner_id','=',partner_id1),('requisition_id','in',requistion_ids)])
@@ -123,11 +125,13 @@
I check that the delivery order of the customer is in state 'Waiting Goods'.
-
!python {model: stock.picking }: |
+ from tools.translate import _
picking_id = self.search(cr, uid, [('origin','=','TEST/TENDER/0001'),('type','=','delivery')])
if picking_id:
pick=self.browse(cr,uid,picking_id[0])
- assert (pick.state) =='confirmed'," Order is not confirm"
- assert(pick.move_lines[0].state=='wating'),'Order is not wating"'
+ assert (pick.state =='confirmed'),_('Picking is not in confirm state.')
+ assert (pick.move_lines[0].state == 'waiting'), _('Stock Move is not Waiting state.')
+
-
I receive the order of the supplier Asustek from the Incoming Products menu.
-
@@ -176,8 +180,10 @@
I check that the delivery order of the customer is in the state Available.
-
!python {model: stock.picking }: |
+ from tools.translate import _
picking_id = self.search(cr, uid, [('origin','=','TEST/TENDER/0001'),('type','=','out')])
if picking_id:
pick=self.browse(cr,uid,picking_id[0])
- assert (pick.state) =='available'," Order is not available"
+ print pick.state
+ assert(pick.state == 'assigned'), _('Picking is not in available state')
diff --git a/addons/purchase_requisition/test/purchase_requisition_exclusive.yml b/addons/purchase_requisition/test/purchase_requisition_exclusive.yml
index 641fd740de3..84a6bb0d68f 100644
--- a/addons/purchase_requisition/test/purchase_requisition_exclusive.yml
+++ b/addons/purchase_requisition/test/purchase_requisition_exclusive.yml
@@ -60,11 +60,11 @@
5 Laptop ACER, and a purchase order on the default supplier for this product.
-
!python {model: purchase.requisition}: |
- requisition_ids =self.search(cr, uid, [('origin','=','TEST/TENDER/0002')])
+ requisition_ids =self.search(cr, uid, [('origin','=','Laptop ACER1')])
ids=len(requisition_ids)
assert len(requisition_ids), "Purchase requisition hasn't Created"
-
- On the purchase tender, I create a new purchase order for the supplier 'DistriPC' by clicking on
+ On the purchase requisition, I create a new purchase order for the supplier 'DistriPC' by clicking on
the button 'New Request for Quotation'. This opens a window to ask me the supplier and I set DistriPC .
-
I Create purchase.requisition.partner .
@@ -77,15 +77,15 @@
-
!python {model: purchase.requisition.partner}: |
req_obj = self.pool.get('purchase.requisition')
- ids =req_obj.search(cr, uid, [('origin','=','TEST/TENDER/0002')])
+ ids =req_obj.search(cr, uid, [('origin','=','Laptop ACER1')])
self.create_order(cr, uid, [ref("purchase_requisition_partner_0")], {"lang":
'en_US', "active_model": "purchase.requisition", "tz": False, "record_id":
1, "active_ids": ids, "active_id": ids[0], })
-
- I set the purchase tender as 'Exclusive'
+ I set the purchase requisition as 'Exclusive'
-
!python {model: purchase.requisition}: |
- ids =self.search(cr, uid, [('origin','=','TEST/TENDER/0002')])
+ ids =self.search(cr, uid, [('origin','=','Laptop ACER1')])
self.write(cr,uid,ids[0],{'exclusive': 'exclusive' })
-
I confirm and validate the Request for Quotation of ASUStek.
@@ -93,7 +93,7 @@
!python {model: purchase.order}: |
partner_id=self.pool.get('res.partner').search(cr,uid,[('name','=','ASUStek')])[0]
req_obj = self.pool.get('purchase.requisition')
- ids =req_obj.search(cr, uid, [('origin','=','TEST/TENDER/0002')])
+ ids =req_obj.search(cr, uid, [('origin','=','Laptop ACER1')])
purchase_id= self.search(cr, uid, [('partner_id','=',partner_id),('requisition_id','in',ids)])[0]
import netsvc
wf_service = netsvc.LocalService("workflow")
@@ -106,7 +106,7 @@
!python {model: purchase.order}: |
partner_id=self.pool.get('res.partner').search(cr,uid,[('name','=','Distrib PC')])[0]
req_obj = self.pool.get('purchase.requisition')
- ids =req_obj.search(cr, uid, [('origin','=','TEST/TENDER/0002')])
+ ids =req_obj.search(cr, uid, [('origin','=','Laptop ACER1')])
purchase_id= self.search(cr, uid, [('partner_id','=',partner_id),('requisition_id','in',ids)])[0]
state=self.browse(cr,uid,purchase_id).state
assert (state=='cancel')
\ No newline at end of file
diff --git a/addons/sale/report/sale_report.py b/addons/sale/report/sale_report.py
index 8c24b5000ee..0880cdb76d1 100644
--- a/addons/sale/report/sale_report.py
+++ b/addons/sale/report/sale_report.py
@@ -74,7 +74,7 @@ class sale_report(osv.osv):
tools.drop_view_if_exists(cr, 'sale_report')
cr.execute("""
create or replace view sale_report as (
- select el.*,
+ select el.*,
-- (select count(1) from sale_order_line where order_id = s.id) as nbr,
(select 1) as nbr,
s.date_order as date,
@@ -86,28 +86,46 @@ class sale_report(osv.osv):
s.user_id as user_id,
s.shop_id as shop_id,
s.company_id as company_id,
- extract(epoch from (s.date_confirm-s.create_date))/(24*60*60)::decimal(16,2) as delay,
+ extract(epoch from avg(date_trunc('day',s.date_confirm)-date_trunc('day',s.create_date)))/(24*60*60)::decimal(16,2) as delay,
s.state,
s.shipped,
s.shipped::integer as shipped_qty_1,
s.pricelist_id as pricelist_id,
s.project_id as analytic_account_id
- from
- sale_order s,
- (
- select l.id as id,
- l.product_id as product_id,
- u.name as uom_name,
- sum(l.product_uom_qty * u.factor) as product_uom_qty,
- sum(l.product_uom_qty*l.price_unit) as price_total,
- (sum(l.product_uom_qty*l.price_unit)/sum(l.product_uom_qty * u.factor)*count(l.product_id))::decimal(16,2) as price_average,
- pt.categ_id, l.order_id
- from
- sale_order_line l
- left join product_uom u on (u.id=l.product_uom)
- left join product_template pt on (pt.id=l.product_id)
- group by l.id, l.order_id, l.product_id, u.name, pt.categ_id) el
- where s.id = el.order_id
+ from
+ sale_order s,
+ (
+ select l.id as id,
+ l.product_id as product_id,
+ u.name as uom_name,
+ sum(l.product_uom_qty * u.factor) as product_uom_qty,
+ sum(l.product_uom_qty*l.price_unit) as price_total,
+ (sum(l.product_uom_qty*l.price_unit)/sum(l.product_uom_qty * u.factor)*count(l.product_id))::decimal(16,2) as price_average,
+ pt.categ_id, l.order_id
+ from
+ sale_order_line l
+ left join product_uom u on (u.id=l.product_uom)
+ left join product_template pt on (pt.id=l.product_id)
+ group by l.id, l.order_id, l.product_id, u.name, pt.categ_id) el
+ where s.id = el.order_id
+ group by el.id,
+ el.product_id,
+ el.uom_name,
+ el.product_uom_qty,
+ el.price_total,
+ el.price_average,
+ el.categ_id,
+ el.order_id,
+ s.date_order,
+ s.date_confirm,
+ s.partner_id,
+ s.user_id,
+ s.shop_id,
+ s.company_id,
+ s.state,
+ s.shipped,
+ s.pricelist_id,
+ s.project_id
)
""")
sale_report()
diff --git a/addons/sale/report/sale_report_view.xml b/addons/sale/report/sale_report_view.xml
index 6ab414aad8b..a4658bc3a1c 100644
--- a/addons/sale/report/sale_report_view.xml
+++ b/addons/sale/report/sale_report_view.xml
@@ -20,11 +20,11 @@
-
-
-
+
+
+
-
+
@@ -122,6 +122,7 @@
formtree,graph
+ {'search_default_month':1,'search_default_User':1,'group_by_no_leaf':1,'group_by':[]}
diff --git a/addons/scrum/scrum.py b/addons/scrum/scrum.py
index d4434968c51..673c47850d6 100644
--- a/addons/scrum/scrum.py
+++ b/addons/scrum/scrum.py
@@ -254,7 +254,7 @@ class scrum_product_backlog(osv.osv):
'tasks_id': fields.one2many('project.task', 'product_backlog_id', 'Tasks Details'),
'state': fields.selection([('draft','Draft'),('open','Open'),('pending','Pending'),('done','Done'),('cancel','Cancelled')], 'State', required=True),
'progress': fields.function(_calc_progress, method=True, string='Progress', help="Computed as: Time Spent / Total Time."),
- 'effective_hours': fields.function(_calc_effective, method=True, string='Effective hours', help="Computed using the sum of the task work done (Time spent on tasks)"),
+ 'effective_hours': fields.function(_calc_effective, method=True, string='Spent Hours', help="Computed using the sum of the time spent on every related tasks"),
'expected_hours': fields.float('Planned Hours', help='Estimated total time to do the Backlog'),
'create_date': fields.datetime("Creation Date", readonly=True),
'task_hours': fields.function(_calc_task, method=True, string='Task Hours', help='Estimated time of the total hours of the tasks')