diff --git a/addons/account/report/account_analytic_entries_report.py b/addons/account/report/account_analytic_entries_report.py
index 2a1b4ad993b..ec813b8ecd8 100644
--- a/addons/account/report/account_analytic_entries_report.py
+++ b/addons/account/report/account_analytic_entries_report.py
@@ -35,6 +35,7 @@ class analytic_entries_report(osv.osv):
('10','October'), ('11','November'), ('12','December')], 'Month',readonly=True),
'user_id' : fields.many2one('res.users', 'User',readonly=True),
'name': fields.char('Description', size=64, readonly=True),
+ 'partner_id': fields.many2one('res.partner', 'Partner'),
'company_id': fields.many2one('res.company', 'Company', required=True),
'currency_id': fields.many2one('res.currency', 'Currency', required=True),
'account_id': fields.many2one('account.analytic.account', 'Account', required=True),
@@ -44,8 +45,7 @@ class analytic_entries_report(osv.osv):
'product_id': fields.many2one('product.product', 'Product', required=True),
'product_uom_id': fields.many2one('product.uom', 'Product UOM', required=True),
'amount': fields.float('Amount', readonly=True),
- 'unit_amount': fields.float('Unit Amount', readonly=True),
- 'amount_currency': fields.float('Amount Currency', readonly=True),
+ 'unit_amount': fields.float('Quantity', readonly=True),
'nbr': fields.integer('#Entries', readonly=True),
}
def init(self, cr):
@@ -61,6 +61,7 @@ class analytic_entries_report(osv.osv):
to_char(a.create_date, 'YYYY-MM-DD') as day,
a.user_id as user_id,
a.name as name,
+ analytic.partner_id as partner_id,
a.company_id as company_id,
a.currency_id as currency_id,
a.account_id as account_id,
@@ -70,12 +71,12 @@ class analytic_entries_report(osv.osv):
a.product_id as product_id,
a.product_uom_id as product_uom_id,
sum(a.amount) as amount,
- sum(a.unit_amount) as unit_amount,
- sum(a.amount_currency) as amount_currency
+ sum(a.unit_amount) as unit_amount
from
- account_analytic_line a
+ account_analytic_line a, account_analytic_account analytic
+ where analytic.id = a.account_id
group by
- a.create_date, a.user_id,a.name,company_id,a.currency_id,
+ a.create_date, a.user_id,a.name,analytic.partner_id,a.company_id,a.currency_id,
a.account_id,a.general_account_id,a.journal_id,
a.move_id,a.product_id,a.product_uom_id
)
diff --git a/addons/account/report/account_analytic_entries_report_view.xml b/addons/account/report/account_analytic_entries_report_view.xml
index 1df0cf011fd..da08d56af0d 100644
--- a/addons/account/report/account_analytic_entries_report_view.xml
+++ b/addons/account/report/account_analytic_entries_report_view.xml
@@ -13,6 +13,7 @@
+
@@ -21,9 +22,8 @@
+
-
-
@@ -48,8 +48,10 @@
domain="[('day','<=', time.strftime('%%Y-%%m-%%d')), ('day','>',(datetime.date.today()-datetime.timedelta(days=7)).strftime('%%Y-%%m-%%d'))]"
help="Analytic Entries during last 7 days"/>
+
+
-
+
@@ -67,18 +69,18 @@
-
-
+
+
-
-
+
+
-
+
@@ -91,9 +93,8 @@
-
-
+
@@ -102,7 +103,7 @@
analytic.entries.reportformtree,graph
- {'search_default_month':1,'search_default_User':1,'group_by_no_leaf':1,'group_by':[]}
+ {'search_default_month':1, 'group_by_no_leaf':1, 'search_default_Account':1, 'search_default_Month':1, 'group_by':[]}A tool search lets you know statistics on your analytics records that match your needs.
diff --git a/addons/account/report/account_balance.rml b/addons/account/report/account_balance.rml
index 5d71ef95c39..fac1983ef25 100644
--- a/addons/account/report/account_balance.rml
+++ b/addons/account/report/account_balance.rml
@@ -287,15 +287,15 @@
Code
Account
-
Debit([[ company.currency_id.code]])
-
Credit([[ company.currency_id.code]])
-
Balance([[ company.currency_id.code]])
+
Debit
+
Credit
+
Balance
[[ repeatIn(lines(data['form']), 'a') ]][[ (a['type']<>'view' and setTag('para','para',{'fontName':"Helvetica"})) or removeParentNode('font') ]][[ a['code'] or removeParentNode('tr') ]]
[[ (a['type']<>'view' and setTag('para','para',{'fontName':"Helvetica"})) or removeParentNode('font') ]][[ '..'*(a['level']-1) ]][[ a['name'] ]]
-
[[ (a['type']<>'view' and setTag('para','para',{'fontName':"Helvetica"})) or removeParentNode('font') ]][[ a['type']=='view' and removeParentNode('font') ]][[ formatLang(a['debit']) ]] [[ company.currency_id.symbol ]][[ a['type']<>'view' and removeParentNode('font') ]] [[formatLang(a['debit']) ]] [[ company.currency_id.symbol ]]
-
[[ (a['type']<>'view' and setTag('para','para',{'fontName':"Helvetica"})) or removeParentNode('font')]][[ a['type']=='view' and removeParentNode('font') ]][[ formatLang(a['credit']) ]] [[ company.currency_id.symbol ]][[ a['type']<>'view' and removeParentNode('font') ]] [[ formatLang(a['credit']) ]] [[ company.currency_id.symbol ]]
+
[[ (a['type']<>'view' and setTag('para','para',{'fontName':"Helvetica"})) or removeParentNode('font') ]][[ a['type']=='view' and removeParentNode('font') ]][[ formatLang(a['debit']) ]][[ a['type']<>'view' and removeParentNode('font') ]] [[formatLang(a['debit']) ]]
+
[[ (a['type']<>'view' and setTag('para','para',{'fontName':"Helvetica"})) or removeParentNode('font')]][[ a['type']=='view' and removeParentNode('font') ]][[ formatLang(a['credit']) ]][[ a['type']<>'view' and removeParentNode('font') ]] [[ formatLang(a['credit']) ]]
[[ (a['type']<>'view' and setTag('para','para',{'fontName':"Helvetica"})) or removeParentNode('font') ]][[ a['type']=='view' and removeParentNode('font') ]][[ formatLang(a['balance']) ]] [[ company.currency_id.symbol ]][[ a['type']<>'view' and removeParentNode('font') ]] [[ formatLang(a['balance']) ]] [[ company.currency_id.symbol ]]
diff --git a/addons/account/report/account_invoice_report.py b/addons/account/report/account_invoice_report.py
index d09be0fb331..39a1709d503 100644
--- a/addons/account/report/account_invoice_report.py
+++ b/addons/account/report/account_invoice_report.py
@@ -72,6 +72,7 @@ class account_invoice_report(osv.osv):
'partner_bank_id': fields.many2one('res.partner.bank', 'Bank Account',readonly=True),
'residual': fields.float('Total Residual', readonly=True),
'delay_to_pay': fields.float('Avg. Delay To Pay', readonly=True, group_operator="avg"),
+ 'due_delay': fields.float('Avg. Due Delay', readonly=True, group_operator="avg"),
}
_order = 'date desc'
def init(self, cr):
@@ -134,6 +135,11 @@ class account_invoice_report(osv.osv):
left join account_invoice as a ON (a.move_id=aml.move_id)
left join account_invoice_line as l ON (a.id=l.invoice_id)
where a.id=ai.id)) as delay_to_pay,
+ sum((select extract(epoch from avg(date_trunc('day',a.date_due)-date_trunc('day',a.date_invoice)))/(24*60*60)::decimal(16,2)
+ from account_move_line as aml
+ left join account_invoice as a ON (a.move_id=aml.move_id)
+ left join account_invoice_line as l ON (a.id=l.invoice_id)
+ where a.id=ai.id)) as due_delay,
(case when ai.type in ('out_refund','in_invoice') then
ai.residual * -1
else
@@ -145,7 +151,7 @@ class account_invoice_report(osv.osv):
left join account_invoice as ai ON (ai.id=ail.invoice_id)
left join product_template pt on (pt.id=ail.product_id)
left join product_uom u on (u.id=ail.uos_id),
- res_currency_rate cr
+ res_currency_rate cr
where cr.id in (select id from res_currency_rate cr2 where (cr2.currency_id = ai.currency_id)
and ((ai.date_invoice is not null and cr.name <= ai.date_invoice) or (ai.date_invoice is null and cr.name <= NOW())) limit 1)
group by ail.product_id,
diff --git a/addons/account/report/account_invoice_report_view.xml b/addons/account/report/account_invoice_report_view.xml
index 80985fb3d6a..12f8b23e550 100644
--- a/addons/account/report/account_invoice_report_view.xml
+++ b/addons/account/report/account_invoice_report_view.xml
@@ -34,6 +34,7 @@
+
diff --git a/addons/account/report/account_journal.rml b/addons/account/report/account_journal.rml
index 41261a12c1a..e153ae20adb 100644
--- a/addons/account/report/account_journal.rml
+++ b/addons/account/report/account_journal.rml
@@ -253,9 +253,9 @@
[[ repeatIn(lines(), 'a') ]][[ (a['type']==3 and setTag('para','para',{'fontName':'Helvetica-Bold'})) or removeParentNode('font') ]][[ a['ref'] ]] [[ a['type']==3 and a['code'] ]]
[[ (a['type']==3 and setTag('para','para',{'fontName':'Helvetica-Bold'})) or removeParentNode('font') ]][[ a['name'] ]]
-
[[ (a['type']==3 and setTag('para','para',{'fontName':'Helvetica-Bold'})) or removeParentNode('font') ]][[ formatLang(a['debit']) ]] [[ company.currency_id.symbol ]]
-
[[ (a['type']==3 and setTag('para','para',{'fontName':'Helvetica-Bold'})) or removeParentNode('font') ]][[ formatLang(a['credit']) ]] [[ company.currency_id.symbol ]]
+
[[ (a['type']==3 and setTag('para','para',{'fontName':'Helvetica-Bold'})) or removeParentNode('font') ]][[ formatLang(a['debit']) ]]
+
[[ (a['type']==3 and setTag('para','para',{'fontName':'Helvetica-Bold'})) or removeParentNode('font') ]][[ formatLang(a['credit']) ]]
[[ (a['type']==3 and setTag('para','para',{'fontName':'Helvetica-Bold'})) or removeParentNode('font') ]][[ formatLang(a['balance']) ]] [[ company.currency_id.symbol ]]
[[ (a['type']==3 and setTag('para','para',{'fontName':'Helvetica-Bold'})) or removeParentNode('font') ]][[ formatLang(a['enlitige'] or 0.0) ]] [[ company.currency_id.symbol ]]
- [[ (data['form']['format_perc'] or not data['form']['show_columns']) and removeParentNode('blockTable') ]] [[ a['level']<4 and ( setTag('para','para',{'style':'terp_default_Bold_9'})) or removeParentNode('font')]][[ a['code'] ]]
-
-
- [['...'*(a['level']-1) ]] [[ a['level']<4 and ( setTag('para','para',{'style':'terp_default_Bold_9'})) or removeParentNode('font')]][[ a['name'] ]]
-
-
- [[ a['level']<4 and ( setTag('para','para',{'style':'terp_default_Bold_9'})) or removeParentNode('font')]][[ a['pattern'] ]]
-
-
- [[ a['level']<4 and ( setTag('para','para',{'style':'terp_default_Right_9_Bold'})) or removeParentNode('font')]][[ a['debit'] ]]
-
-
- [[ a['level']<4 and ( setTag('para','para',{'style':'terp_default_Right_9_Bold'})) or removeParentNode('font')]][[ a['credit'] ]]
-
-
- [[ a['level']<4 and ( setTag('para','para',{'style':'terp_default_Right_9_Bold'})) or removeParentNode('font')]][[ a['balance'] ]]
-
-
-
-
-
-
- [[ (not data['form']['format_perc'] or not data['form']['show_columns']) and removeParentNode('blockTable') ]] [[ a['level']<4 and ( setTag('para','para',{'style':'terp_default_Bold_9'})) or removeParentNode('font')]][[ a['code'] ]]
-
-
- [['...'*(a['level']-1) ]] [[ a['level']<4 and ( setTag('para','para',{'style':'terp_default_Bold_9'})) or removeParentNode('font')]][[ a['name'] ]]
-
-
- [[ a['level']<4 and ( setTag('para','para',{'style':'terp_default_Bold_9'})) or removeParentNode('font')]][[ a['pattern'] ]]
-
-
- [[ a['level']<4 and ( setTag('para','para',{'style':'terp_default_Right_9_Bold'})) or removeParentNode('font')]][[ a['debit'] ]]
-
-
- [[ a['level']<4 and ( setTag('para','para',{'style':'terp_default_Right_9_Bold'})) or removeParentNode('font')]][[ a['credit'] ]]
-
-
- [[ a['level']<4 and ( setTag('para','para',{'style':'terp_default_Right_9_Bold'})) or removeParentNode('font')]][[ a['balance'] ]]
-
-
- [[ a['level']<4 and ( setTag('para','para',{'style':'terp_default_Right_9_Bold'})) or removeParentNode('font')]][[ a['balance_perc'] ]]
-
-
-
-
-
-
- [[ (data['form']['format_perc'] or data['form']['show_columns']) and removeParentNode('blockTable') ]] [[ a['level']<4 and ( setTag('para','para',{'style':'terp_default_Bold_9'})) or removeParentNode('font')]][[ a['code'] ]]
-
-
- [['...'*(a['level']-1) ]] [[ a['level']<4 and ( setTag('para','para',{'style':'terp_default_Bold_9'})) or removeParentNode('font')]][[ a['name'] ]]
-
-
- [[ a['level']<4 and ( setTag('para','para',{'style':'terp_default_Bold_9'})) or removeParentNode('font')]][[ a['pattern'] ]]
-
-
- [[ a['level']<4 and ( setTag('para','para',{'style':'terp_default_Right_9_Bold'})) or removeParentNode('font')]][[ a['balance'] ]]
-
-
-
-
-
-
- [[ (not data['form']['format_perc'] or data['form']['show_columns']) and removeParentNode('blockTable') ]][[ a['level']<4 and ( setTag('para','para',{'style':'terp_default_Bold_9'})) or removeParentNode('font')]] [[ a['code'] ]]
-
-
- [['...'*(a['level']-1) ]] [[ a['level']<4 and ( setTag('para','para',{'style':'terp_default_Bold_9'})) or removeParentNode('font')]][[ a['name'] ]]
-
-
- [[ a['level']<4 and ( setTag('para','para',{'style':'terp_default_Bold_9'})) or removeParentNode('font')]][[ a['pattern'] ]]
-
-
- [[ a['level']<4 and ( setTag('para','para',{'style':'terp_default_Right_9_Bold'})) or removeParentNode('font')]][[ a['balance'] ]]
-
-
- [[ a['level']<4 and ( setTag('para','para',{'style':'terp_default_Right_9_Bold'})) or removeParentNode('font')]][[ a['balance_perc'] ]]
-
-
-
-
-
-
-
-
-
-
- [[ not data['form']['show_columns'] and removeParentNode('blockTable') ]]
-
-
- Total :
-
-
- [[ total_dr() ]]
-
-
- [[ total_cr() ]]
-
-
-
-
-
-
-
-
-
-
-
- [[ data['form']['compare_pattern']!='none' and "C.S.Y.T.(C./P) : Compare Selected Years In Terms of Cash/Perc" or removeParentNode('font') ]]
-
-
\ No newline at end of file
diff --git a/addons/account/report/invoice.rml b/addons/account/report/invoice.rml
index 741e4544e7b..6c3c6fc01c3 100644
--- a/addons/account/report/invoice.rml
+++ b/addons/account/report/invoice.rml
@@ -180,7 +180,7 @@
- [[ (t.tax_code_id and t.tax_code_id.notprintable) and removeParentNode('blockTable') or '' ]] [[ formatLang(t.amount) ]]
+ [[ (t.tax_code_id and t.tax_code_id.notprintable) and removeParentNode('blockTable') or '' ]] [[ formatLang(t.amount) ]] [[ o.currency_id.symbol ]]
diff --git a/addons/account/report/overdue.rml b/addons/account/report/overdue.rml
index fad5c27ec79..a0748e281ac 100644
--- a/addons/account/report/overdue.rml
+++ b/addons/account/report/overdue.rml
@@ -151,13 +151,13 @@
Maturity date
Li.
@@ -181,10 +181,10 @@
[[ line['date_maturity'] and formatLang(line['date_maturity'],date=True) or '' ]]
- [[ (line['account_id']['type'] == 'receivable' and formatLang(line['debit']) or 0) or (line['account_id']['type'] == 'payable' and formatLang(line['credit'] * -1) or ' ') ]] [[ company.currency_id.symbol ]]
+ [[ (line['account_id']['type'] == 'receivable' and formatLang(line['debit']) or 0) or (line['account_id']['type'] == 'payable' and formatLang(line['credit'] * -1) or ' ') ]]
- [[ (line['account_id']['type'] == 'receivable' and formatLang(line['credit']) or 0) or (line['account_id']['type'] == 'payable' and formatLang(line['debit'] * -1) or 0) ]] [[ company.currency_id.symbol ]]
+ [[ (line['account_id']['type'] == 'receivable' and formatLang(line['credit']) or 0) or (line['account_id']['type'] == 'payable' and formatLang(line['debit'] * -1) or 0) ]]
- [[ formatLang((reduce(lambda x, y: x + ((y['account_id']['type'] == 'receivable' and y['debit'] or 0) or (y['account_id']['type'] == 'payable' and y['credit'] * -1 or 0)), getLines(o), 0))) ]] [[ company.currency_id.symbol ]]
+ [[ formatLang((reduce(lambda x, y: x + ((y['account_id']['type'] == 'receivable' and y['debit'] or 0) or (y['account_id']['type'] == 'payable' and y['credit'] * -1 or 0)), getLines(o), 0))) ]]
- [[ formatLang((reduce(lambda x, y: x + ((y['account_id']['type'] == 'receivable' and y['credit'] or 0) or (y['account_id']['type'] == 'payable' and y['debit'] * -1 or 0)), getLines(o), 0))) ]] [[ company.currency_id.symbol ]]
+ [[ formatLang((reduce(lambda x, y: x + ((y['account_id']['type'] == 'receivable' and y['credit'] or 0) or (y['account_id']['type'] == 'payable' and y['debit'] * -1 or 0)), getLines(o), 0))) ]]
[[ repeatIn(get_lines(data['form']['based_on'],data['form']['periods'],data['form']['company_id']), 'o') ]][[ (o['level']) ]] [[ (len(o['level'])<5 and setTag('para','para',{'fontName':'Helvetica-Bold'})) or removeParentNode('font') ]][[ o['code'] ]] [[ o['name'] ]]
-
[[ len(o['level'])<5 and setTag('para','para',{'fontName':"Helvetica-Bold"}) or removeParentNode('font')]][[ o['type']=='view' and removeParentNode('font') ]][[ formatLang(o['debit']) ]] [[ company.currency_id.symbol ]][[ o['type']<>'view' and removeParentNode('font') ]][[ formatLang(o['debit']) ]] [[ company.currency_id.symbol ]]
-
[[ len(o['level'])<5 and setTag('para','para',{'fontName':"Helvetica-Bold"}) or removeParentNode('font')]][[ o['type']=='view' and removeParentNode('font') ]][[ formatLang(o['credit']) ]] [[ company.currency_id.symbol ]][[ o['type']<>'view' and removeParentNode('font') ]][[ formatLang(o['credit'])]] [[ company.currency_id.symbol ]]
+
[[ len(o['level'])<5 and setTag('para','para',{'fontName':"Helvetica-Bold"}) or removeParentNode('font')]][[ o['type']=='view' and removeParentNode('font') ]][[ formatLang(o['debit']) ]][[ o['type']<>'view' and removeParentNode('font') ]][[ formatLang(o['debit']) ]]
+
[[ len(o['level'])<5 and setTag('para','para',{'fontName':"Helvetica-Bold"}) or removeParentNode('font')]][[ o['type']=='view' and removeParentNode('font') ]][[ formatLang(o['credit']) ]][[ o['type']<>'view' and removeParentNode('font') ]][[ formatLang(o['credit'])]]
[[ len(o['level'])<5 and setTag('para','para',{'fontName':"Helvetica-Bold"}) or removeParentNode('font')]][[ o['type']=='view' and removeParentNode('font') ]][[ formatLang(o['tax_amount']) ]] [[ company.currency_id.symbol ]][[ o['type']<>'view' and removeParentNode('font') ]][[ formatLang(o['tax_amount']) ]] [[ company.currency_id.symbol ]]
diff --git a/addons/account/security/account_security.xml b/addons/account/security/account_security.xml
index adf3571f406..326584d1b6b 100644
--- a/addons/account/security/account_security.xml
+++ b/addons/account/security/account_security.xml
@@ -19,7 +19,7 @@
-
+
@@ -35,7 +35,7 @@
-
+
@@ -87,7 +87,7 @@
-
+
@@ -138,6 +138,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Account Entry
diff --git a/addons/account/test/account_change_currency.yml b/addons/account/test/account_change_currency.yml
index 4fe89534ce5..479afd2f2e2 100644
--- a/addons/account/test/account_change_currency.yml
+++ b/addons/account/test/account_change_currency.yml
@@ -50,7 +50,7 @@
!assert {model: account.invoice, id: account_invoice_currency}:
- state == 'proforma2'
-
- I can't change the currency of invoice when it is not in draft state so i change the state to cancel
+ I can't change the currency of invoice when it is not in draft state so I change the state to cancel
-
!workflow {model: account.invoice, action: invoice_cancel, ref: account_invoice_currency}
-
diff --git a/addons/account/test/account_fiscalyear_close.yml b/addons/account/test/account_fiscalyear_close.yml
index 59cbfdafc0b..c69e11abd6b 100644
--- a/addons/account/test/account_fiscalyear_close.yml
+++ b/addons/account/test/account_fiscalyear_close.yml
@@ -1,21 +1,21 @@
-
- In order to test Generate Fiscalyear Opening Entries wizard of OpenERP I first create a fiscalyear "Fiscal Year 2011" to which the entries will move
+ In order to test Generate Fiscalyear Opening Entries wizard of OpenERP I first create a fiscalyear to which the entries will move
-
!record {model: account.fiscalyear, id: account_fiscalyear_fiscalyear0}:
- code: FY2011
+ code: !eval "'FY%s'% (datetime.now().year+1)"
company_id: base.main_company
- date_start: '2011-01-01'
- date_stop: '2011-12-31'
- name: Fiscal Year 2011
+ date_start: !eval "'%s-01-01' %(datetime.now().year+1)"
+ date_stop: !eval "'%s-12-31' %(datetime.now().year+1)"
+ name: !eval "'Fiscal Year %s' %(datetime.now().year+1)"
-
- I create a period "Jan2011" for the new fiscalyear
+ I create a period for the month of january for the new fiscalyear
-
!record {model: account.period, id: account_period_jan11}:
company_id: base.main_company
- date_start: '2011-01-01'
- date_stop: '2011-12-31'
+ date_start: !eval "'%s-01-01'% (datetime.now().year+1)"
+ date_stop: !eval "'%s-12-31'% (datetime.now().year+1)"
fiscalyear_id: account_fiscalyear_fiscalyear0
- name: Jan2011
+ name: !eval "'Jan%s' %(datetime.now().year+1)"
special: 1
-
@@ -25,6 +25,7 @@
name: End of Year
code: NEW
type: situation
+ analytic_journal_id: sit
sequence_id: sequence_journal
default_debit_account_id: cash
default_credit_account_id: cash
@@ -90,7 +91,4 @@
# self.action_open_window(cr, uid, [ref("account_move_journal_2")], {"lang": 'en_US',
# "active_model": "ir.ui.menu", "active_ids": [ref("account.menu_action_move_journal_line_form")],
# "tz": False, "active_id": ref("account.menu_action_move_journal_line_form"),
-# })
-
-
-
+# })
\ No newline at end of file
diff --git a/addons/account/test/account_fiscalyear_close_state.yml b/addons/account/test/account_fiscalyear_close_state.yml
index 6d4d5353a19..af4d05eba76 100644
--- a/addons/account/test/account_fiscalyear_close_state.yml
+++ b/addons/account/test/account_fiscalyear_close_state.yml
@@ -3,11 +3,11 @@
In order to check the Close a Fiscal Year wizard in OpenERP I first create a Fiscalyear
-
!record {model: account.fiscalyear, id: account_fiscalyear_fiscalyear0}:
- code: FY2011
+ code: !eval "'FY%s'% (datetime.now().year+1)"
company_id: base.main_company
- date_start: '2011-01-01'
- date_stop: '2011-12-31'
- name: Fiscal Year 2011
+ date_start: !eval "'%s-01-01' %(datetime.now().year+1)"
+ date_stop: !eval "'%s-12-31' %(datetime.now().year+1)"
+ name: !eval "'Fiscal Year %s' %(datetime.now().year+1)"
-
I create monthly Periods for this fiscalyear
-
diff --git a/addons/account/test/account_report.yml b/addons/account/test/account_report.yml
index a02635d0fc1..7e4295da45b 100644
--- a/addons/account/test/account_report.yml
+++ b/addons/account/test/account_report.yml
@@ -1,5 +1,5 @@
-
- In order to test the PDF reports defined on an invoice, we will print an invoice
+ In order to test the PDF reports defined on an invoice, we will print an Invoice Report
-
!python {model: account.invoice}: |
import netsvc, tools, os
@@ -93,27 +93,6 @@
if tools.config['test_report_directory']:
file(os.path.join(tools.config['test_report_directory'], 'account-aged_partner_balance.'+format), 'wb+').write(data)
--
- Print the Compare Account Balance Report in Normal mode
--
- !python {model: account.account}: |
- import netsvc, tools, os, time
- data_dict = {'model': 'account.account', 'form': {'id':ref('account.bal'),'chart_account_id':ref('account.chart0'),'select_account': False,'format_perc':0,'show_columns' :0, 'compare_pattern': 'none','account_choice': 'moves','landscape':0,'period_manner': 'actual','fiscalyear': [ref('account.data_fiscalyear')] ,'target_move': 'all','periods': [],'context':{'state':'all'}}}
- (data, format) = netsvc.LocalService('report.account.balance.account.balance').create(cr, uid, [ref('account.bal'),ref('account.gpf')], data_dict, {'periods': []})
- if tools.config['test_report_directory']:
- file(os.path.join(tools.config['test_report_directory'], 'account-compare-account_balance.'+format), 'wb+').write(data)
-
--
- Print the Compare Account Balance Report in Landscape mode
--
- !python {model: account.account}: |
- import netsvc, tools, os, time
- data_dict = {'model': 'account.account', 'form': {'id':ref('account.bal'),'chart_account_id':ref('account.chart0'),'select_account': False,'format_perc':0,'show_columns' :0, 'compare_pattern': 'none','account_choice': 'moves','landscape':1,'period_manner': 'actual','fiscalyear': [ref('account.data_fiscalyear')] ,'target_move': 'all','periods': [],'context':{'state':'all'}}}
- (data, format) = netsvc.LocalService('report.account.account.balance.landscape').create(cr, uid, [ref('account.bal'),ref('account.gpf')], data_dict, {'periods': []})
- if tools.config['test_report_directory']:
- file(os.path.join(tools.config['test_report_directory'], 'account-compare-account_balance-landscape.'+format), 'wb+').write(data)
-
-
-
Print the Account Balance Sheet in Horizontal mode
-
diff --git a/addons/account/test/account_sequence_test.yml b/addons/account/test/account_sequence_test.yml
index 3be824d2ca0..4748175c118 100644
--- a/addons/account/test/account_sequence_test.yml
+++ b/addons/account/test/account_sequence_test.yml
@@ -32,7 +32,7 @@
reference_type: none
period_id: period_1
-- I create the invoice, as is I clicked on the "Create" button
+- I create the invoice, as I clicked on the "Create" button
- !workflow {model: account.invoice, action: invoice_open, ref: invoice_seq_test}
- I check that the invoice state is "Open"
diff --git a/addons/account/test/test_parent_structure.yml b/addons/account/test/test_parent_structure.yml
index aed40e6f0f3..3c4db5c3ff4 100644
--- a/addons/account/test/test_parent_structure.yml
+++ b/addons/account/test/test_parent_structure.yml
@@ -1,5 +1,5 @@
-
- We retrieve all accounts and test they are in a tree data structure.
+ We retrieve all accounts and test that those are in a tree data structure.
-
!python {model: account.account}: |
ids = self.search(cr, uid, [])
diff --git a/addons/account/wizard/__init__.py b/addons/account/wizard/__init__.py
index 06d77249f96..caed6fc3977 100644
--- a/addons/account/wizard/__init__.py
+++ b/addons/account/wizard/__init__.py
@@ -44,7 +44,6 @@ import account_fiscalyear_close_state
import account_vat
import account_open_closed_fiscalyear
-import account_compare_account_balance_report
import account_invoice_state
import account_chart
import account_tax_chart
@@ -56,8 +55,6 @@ import account_use_model
import account_state_open
-import account_statement_from_invoice
-
import account_report_print_journal
import account_report_central_journal
import account_report_general_journal
diff --git a/addons/account/wizard/account_automatic_reconcile.py b/addons/account/wizard/account_automatic_reconcile.py
index e9a8ab04aac..efce4bc4da4 100644
--- a/addons/account/wizard/account_automatic_reconcile.py
+++ b/addons/account/wizard/account_automatic_reconcile.py
@@ -30,8 +30,7 @@ class account_automatic_reconcile(osv.osv_memory):
_description = 'Automatic Reconcile'
_columns = {
- 'account_ids': fields.many2many('account.account', 'reconcile_account_rel', 'reconcile_id', 'account_id', 'Accounts to Reconcile', domain = [('reconcile','=',1)], \
- help = 'If no account is specified, the reconciliation will be made using every accounts that can be reconcilied'),
+ 'account_ids': fields.many2many('account.account', 'reconcile_account_rel', 'reconcile_id', 'account_id', 'Accounts to Reconcile', domain = [('reconcile','=',1)],),
'writeoff_acc_id': fields.many2one('account.account', 'Account'),
'journal_id': fields.many2one('account.journal', 'Journal'),
'period_id': fields.many2one('account.period', 'Period'),
@@ -142,25 +141,25 @@ class account_automatic_reconcile(osv.osv_memory):
if context is None:
context = {}
form = self.read(cr, uid, ids, [])[0]
- max_amount = form.get('max_amount', 0.0)
+ max_amount = form.get('max_amount', False) and form.get('max_amount') or 0.0
power = form['power']
allow_write_off = form['allow_write_off']
reconciled = unreconciled = 0
if not form['account_ids']:
raise osv.except_osv(_('UserError'), _('You must select accounts to reconcile'))
for account_id in form['account_ids']:
+ params = (account_id,)
if not allow_write_off:
- query = "SELECT partner_id FROM account_move_line WHERE account_id=%s AND reconcile_id IS NULL \
- AND state <> 'draft' GROUP BY partner_id \
- HAVING ABS(SUM(debit-credit)) = %s AND count(*)>0"%(account_id, 0.0)
-# HAVING ABS(SUM(debit-credit)) <> %s AND count(*)>0"%(account_id, 0.0)
-# HAVING count(*)>0"%(account_id,)
+ query = """SELECT partner_id FROM account_move_line WHERE account_id=%s AND reconcile_id IS NULL
+ AND state <> 'draft' GROUP BY partner_id
+ HAVING ABS(SUM(debit-credit)) = 0.0 AND count(*)>0"""
else:
- query = "SELECT partner_id FROM account_move_line WHERE account_id=%s AND reconcile_id IS NULL \
- AND state <> 'draft' GROUP BY partner_id \
- HAVING ABS(SUM(debit-credit)) < %s AND count(*)>0"%(account_id, max_amount or 0.0)
+ query = """SELECT partner_id FROM account_move_line WHERE account_id=%s AND reconcile_id IS NULL
+ AND state <> 'draft' GROUP BY partner_id
+ HAVING ABS(SUM(debit-credit)) < %s AND count(*)>0"""
+ params += (max_amount,)
# reconcile automatically all transactions from partners whose balance is 0
- cr.execute(query)
+ cr.execute(query, params)
partner_ids = [id for (id,) in cr.fetchall()]
for partner_id in partner_ids:
cr.execute(
@@ -176,65 +175,63 @@ class account_automatic_reconcile(osv.osv_memory):
reconciled += len(line_ids)
if allow_write_off:
move_line_obj.reconcile(cr, uid, line_ids, 'auto', form['writeoff_acc_id'], form['period_id'], form['journal_id'], context)
-# move_line_obj.reconcile_partial(cr, uid, line_ids, 'manual', context={})
else:
move_line_obj.reconcile_partial(cr, uid, line_ids, 'manual', context={})
-# move_line_obj.reconcile(cr, uid, line_ids, 'auto', form['writeoff_acc_id'], form['period_id'], form['journal_id'], context)
- # get the list of partners who have more than one unreconciled transaction
- cr.execute(
- "SELECT partner_id " \
- "FROM account_move_line " \
- "WHERE account_id=%s " \
- "AND reconcile_id IS NULL " \
- "AND state <> 'draft' " \
- "AND partner_id IS NOT NULL " \
- "GROUP BY partner_id " \
- "HAVING count(*)>1",
- (account_id,))
- partner_ids = [id for (id,) in cr.fetchall()]
- #filter?
- for partner_id in partner_ids:
- # get the list of unreconciled 'debit transactions' for this partner
- cr.execute(
- "SELECT id, debit " \
- "FROM account_move_line " \
- "WHERE account_id=%s " \
- "AND partner_id=%s " \
- "AND reconcile_id IS NULL " \
- "AND state <> 'draft' " \
- "AND debit > 0",
- (account_id, partner_id))
- debits = cr.fetchall()
+ # get the list of partners who have more than one unreconciled transaction
+ cr.execute(
+ "SELECT partner_id " \
+ "FROM account_move_line " \
+ "WHERE account_id=%s " \
+ "AND reconcile_id IS NULL " \
+ "AND state <> 'draft' " \
+ "AND partner_id IS NOT NULL " \
+ "GROUP BY partner_id " \
+ "HAVING count(*)>1",
+ (account_id,))
+ partner_ids = [id for (id,) in cr.fetchall()]
+ #filter?
+ for partner_id in partner_ids:
+ # get the list of unreconciled 'debit transactions' for this partner
+ cr.execute(
+ "SELECT id, debit " \
+ "FROM account_move_line " \
+ "WHERE account_id=%s " \
+ "AND partner_id=%s " \
+ "AND reconcile_id IS NULL " \
+ "AND state <> 'draft' " \
+ "AND debit > 0",
+ (account_id, partner_id))
+ debits = cr.fetchall()
- # get the list of unreconciled 'credit transactions' for this partner
- cr.execute(
- "SELECT id, credit " \
- "FROM account_move_line " \
- "WHERE account_id=%s " \
- "AND partner_id=%s " \
- "AND reconcile_id IS NULL " \
- "AND state <> 'draft' " \
- "AND credit > 0",
- (account_id, partner_id))
- credits = cr.fetchall()
+ # get the list of unreconciled 'credit transactions' for this partner
+ cr.execute(
+ "SELECT id, credit " \
+ "FROM account_move_line " \
+ "WHERE account_id=%s " \
+ "AND partner_id=%s " \
+ "AND reconcile_id IS NULL " \
+ "AND state <> 'draft' " \
+ "AND credit > 0",
+ (account_id, partner_id))
+ credits = cr.fetchall()
- (rec, unrec) = self.do_reconcile(cr, uid, credits, debits, max_amount, power, form['writeoff_acc_id'], form['period_id'], form['journal_id'], context)
- reconciled += rec
- unreconciled += unrec
+ (rec, unrec) = self.do_reconcile(cr, uid, credits, debits, max_amount, power, form['writeoff_acc_id'], form['period_id'], form['journal_id'], context)
+ reconciled += rec
+ unreconciled += unrec
- # add the number of transactions for partners who have only one
- # unreconciled transactions to the unreconciled count
- partner_filter = partner_ids and 'AND partner_id not in (%s)' % ','.join(map(str, filter(None, partner_ids))) or ''
- cr.execute(
- "SELECT count(*) " \
- "FROM account_move_line " \
- "WHERE account_id=%s " \
- "AND reconcile_id IS NULL " \
- "AND state <> 'draft' " + partner_filter,
- (account_id,))
- additional_unrec = cr.fetchone()[0]
- unreconciled = unreconciled + additional_unrec
+ # add the number of transactions for partners who have only one
+ # unreconciled transactions to the unreconciled count
+ partner_filter = partner_ids and 'AND partner_id not in (%s)' % ','.join(map(str, filter(None, partner_ids))) or ''
+ cr.execute(
+ "SELECT count(*) " \
+ "FROM account_move_line " \
+ "WHERE account_id=%s " \
+ "AND reconcile_id IS NULL " \
+ "AND state <> 'draft' " + partner_filter,
+ (account_id,))
+ additional_unrec = cr.fetchone()[0]
+ unreconciled = unreconciled + additional_unrec
context.update({'reconciled': reconciled, 'unreconciled': unreconciled})
model_data_ids = obj_model.search(cr,uid,[('model','=','ir.ui.view'),('name','=','account_automatic_reconcile_view1')])
resource_id = obj_model.read(cr, uid, model_data_ids, fields=['res_id'])[0]['res_id']
@@ -250,4 +247,4 @@ class account_automatic_reconcile(osv.osv_memory):
account_automatic_reconcile()
-# 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/wizard/account_compare_account_balance_report.py b/addons/account/wizard/account_compare_account_balance_report.py
deleted file mode 100644
index 05e441c5baa..00000000000
--- a/addons/account/wizard/account_compare_account_balance_report.py
+++ /dev/null
@@ -1,135 +0,0 @@
-# -*- 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 time
-
-from osv import osv, fields
-from tools.translate import _
-
-class account_compare_account_balance_report(osv.osv_memory):
- """
- This wizard will provide the account balance comparision report by fiscal years.
- """
- _name = 'account.compare.account.balance.report'
- _description = 'Account Balance Report'
- _columns = {
- 'fiscalyear': fields.many2many('account.fiscalyear', 'account_fiscalyear_rel','account_id','fiscalyear_id','Fiscal year', help='Keep empty for all open fiscal year'),
- 'select_account': fields.many2one('account.account','Select Reference Account(for % comparision)',help='Keep empty for comparison to its parent'),
- 'account_choice': fields.selection([('all','All accounts'),
- ('bal_zero','With balance is not equal to 0'),
- ('moves','With movements')],'Show Accounts'),
- 'show_columns': fields.boolean('Show Debit/Credit Information'),
- 'landscape': fields.boolean('Show Report in Landscape Form'),
- 'format_perc': fields.boolean('Show Comparision in %'),
- 'compare_pattern': fields.selection([('bal_cash','Cash'),
- ('bal_perc','Percentage'),
- ('none','Don'+ "'" +'t Compare')],'Compare Selected Years In Terms Of'),
- 'period_manner': fields.selection([('actual','Financial Period'),('created','Creation Date')],'Entries Selection Based on'),
- 'periods': fields.many2many('account.period', 'period_account_balance_rel',
- 'report_id', 'period_id', 'Periods',
- help='Keep empty for all open fiscal year'),
- }
-
- _defaults={
- 'compare_pattern': 'none',
- 'account_choice': 'moves',
- 'period_manner': 'actual',
- }
-
- def check(self, cr, uid, ids, context=None):
- data={}
- if context is None:
- context = {}
- data = {
- 'ids':context['active_ids'],
- 'form': self.read(cr, uid, ids, ['fiscalyear', 'select_account', 'account_choice', 'periods', 'show_columns', 'landscape', 'format_perc','compare_pattern','period_manner'])[0],
- }
-
- data['form']['context'] = context
- if (len(data['form']['fiscalyear'])==0) or (len(data['form']['fiscalyear'])>1 and (data['form']['compare_pattern']!='none') and (data['form']['format_perc']==1) and (data['form']['show_columns']==1) and (data['form']['landscape']!=1)):
- raise osv.except_osv(_('Warning !'), _('You have to select at least 1 Fiscal Year. \nYou may have selected the compare options with more than 1 year with credit/debit columns and % option.This can lead contents to be printed out of the paper.Please try again.'))
-
-
- if ((len(data['form']['fiscalyear'])==3) and (data['form']['format_perc']!=1) and (data['form']['show_columns']!=1)):
- if data['form']['landscape']==1:
- return {
- 'type': 'ir.actions.report.xml',
- 'report_name': 'account.account.balance.landscape',
- 'datas': data,
- }
- else:
- return {
- 'type': 'ir.actions.report.xml',
- 'report_name': 'account.balance.account.balance',
- 'datas': data,
- }
- if data['form']['format_perc']==1:
- if len(data['form']['fiscalyear'])<=2:
- if data['form']['landscape']==1:
- return {
- 'type': 'ir.actions.report.xml',
- 'report_name': 'account.account.balance.landscape',
- 'datas': data,
- }
- else:
- return {
- 'type': 'ir.actions.report.xml',
- 'report_name': 'account.balance.account.balance',
- 'datas': data,
- }
- else:
- if len(data['form']['fiscalyear'])==3:
- if data['form']['landscape']==1:
- return {
- 'type': 'ir.actions.report.xml',
- 'report_name': 'account.account.balance.landscape',
- 'datas': data,
- }
- else:
- raise osv.except_osv(_('Warning !'), _('You might have done following mistakes. Please correct them and try again. \n 1. You have selected more than 3 years in any case. \n 2. You have not selected Percentage option, but you have selected more than 2 years. \n You can select maximum 3 years. Please check again. \n 3. You have selected Percentage option with more than 2 years, but you have not selected landscape format. You have to select Landscape option. Please Check it.'))
- else:
- raise osv.except_osv(_('Warning !'), _('You might have done following mistakes. Please correct them and try again. \n 1. You have selected more than 3 years in any case. \n 2. You have not selected Percentage option, but you have selected more than 2 years. \n You can select maximum 3 years. Please check again. \n 3. You have selected Percentage option with more than 2 years, but you have not selected landscape format. You have to select Landscape option. Please Check it.'))
- else:
- if len(data['form']['fiscalyear'])>2:
- if data['form']['landscape']==1:
- return {
- 'type': 'ir.actions.report.xml',
- 'report_name': 'account.account.balance.landscape',
- 'datas': data,
- }
- else:
- raise osv.except_osv(_('Warning !'), _('You might have done following mistakes. Please correct them and try again. \n 1. You have selected more than 3 years in any case. \n 2. You have not selected Percentage option, but you have selected more than 2 years. \n You can select maximum 3 years. Please check again. \n 3. You have selected Percentage option with more than 2 years, but you have not selected landscape format. You have to select Landscape option. Please Check it.'))
- else:
- if data['form']['landscape']==1:
- return {
- 'type': 'ir.actions.report.xml',
- 'report_name': 'account.account.balance.landscape',
- 'datas': data,
- }
- else:
- return {
- 'type': 'ir.actions.report.xml',
- 'report_name': 'account.balance.account.balance',
- 'datas': data,
- }
-account_compare_account_balance_report()
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
diff --git a/addons/account/wizard/account_compare_account_balance_report_view.xml b/addons/account/wizard/account_compare_account_balance_report_view.xml
deleted file mode 100644
index 22a9ff01cc7..00000000000
--- a/addons/account/wizard/account_compare_account_balance_report_view.xml
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-
-
- account.compare.account.balance.report.form
- account.compare.account.balance.report
- form
-
-
-
-
-
-
-
-
-
diff --git a/addons/account/wizard/account_invoice_refund.py b/addons/account/wizard/account_invoice_refund.py
index fb575509184..4e74774ce58 100644
--- a/addons/account/wizard/account_invoice_refund.py
+++ b/addons/account/wizard/account_invoice_refund.py
@@ -45,7 +45,7 @@ class account_invoice_refund(osv.osv_memory):
context = {}
journal = obj_journal.search(cr, uid, [('type', '=', 'sale_refund')])
if context.get('type', False):
- if context['type'] == 'in_invoice':
+ if context['type'] in ('in_invoice', 'in_refund'):
journal = obj_journal.search(cr, uid, [('type', '=', 'purchase_refund')])
return journal and journal[0] or False
@@ -55,6 +55,20 @@ class account_invoice_refund(osv.osv_memory):
'filter_refund': 'modify',
}
+ def fields_view_get(self, cr, uid, view_id=None, view_type=False, context=None, toolbar=False, submenu=False):
+ journal_obj = self.pool.get('account.journal')
+ res = super(account_invoice_refund,self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu)
+ type = context.get('journal_type', 'sale_refund')
+ if type in ('sale', 'sale_refund'):
+ type = 'sale_refund'
+ else:
+ type = 'purchase_refund'
+ for field in res['fields']:
+ if field == 'journal_id':
+ journal_select = journal_obj._name_search(cr, uid, '', [('type', '=', type)], context=context, limit=None, name_get_uid=1)
+ res['fields'][field]['selection'] = journal_select
+ return res
+
def compute_refund(self, cr, uid, ids, mode='refund', context=None):
"""
@param cr: the current row, from the database cursor,
diff --git a/addons/account/wizard/account_invoice_refund_view.xml b/addons/account/wizard/account_invoice_refund_view.xml
index e26eb4e12c9..c68c9162ce4 100644
--- a/addons/account/wizard/account_invoice_refund_view.xml
+++ b/addons/account/wizard/account_invoice_refund_view.xml
@@ -11,7 +11,7 @@
-
+
diff --git a/addons/account/wizard/account_reconcile.py b/addons/account/wizard/account_reconcile.py
index e18bd9f9555..c1d9854d014 100644
--- a/addons/account/wizard/account_reconcile.py
+++ b/addons/account/wizard/account_reconcile.py
@@ -85,7 +85,19 @@ class account_move_line_reconcile(osv.osv_memory):
ids = self.pool.get('account.period').find(cr, uid, dt=date, context=context)
if len(ids):
period_id = ids[0]
- context.update({'stop_reconcile': True})
+ #stop the reconciliation process by partner (manual reconciliation) only if there is nothing more to reconcile for this partner
+ if 'active_ids' in context and context['active_ids']:
+ tmp_ml_id = account_move_line_obj.browse(cr, uid, context['active_ids'], context)[0]
+ partner_id = tmp_ml_id.partner_id and tmp_ml_id.partner_id.id or False
+ debit_ml_ids = account_move_line_obj.search(cr, uid, [('partner_id', '=', partner_id), ('account_id.reconcile', '=', True), ('reconcile_id', '=', False), ('debit', '>', 0)], context=context)
+ credit_ml_ids = account_move_line_obj.search(cr, uid, [('partner_id', '=', partner_id), ('account_id.reconcile', '=', True), ('reconcile_id', '=', False), ('credit', '>', 0)], context=context)
+ for ml_id in context['active_ids']:
+ if ml_id in debit_ml_ids:
+ debit_ml_ids.remove(ml_id)
+ if ml_id in credit_ml_ids:
+ credit_ml_ids.remove(ml_id)
+ if not (len(debit_ml_ids) and len(credit_ml_ids)):
+ context.update({'stop_reconcile': True})
account_move_line_obj.reconcile(cr, uid, context['active_ids'], 'manual', account_id,
period_id, journal_id, context=context)
return {}
diff --git a/addons/account/wizard/account_reconcile_partner_process.py b/addons/account/wizard/account_reconcile_partner_process.py
index 05a1bbd48af..6b915dfe3c9 100644
--- a/addons/account/wizard/account_reconcile_partner_process.py
+++ b/addons/account/wizard/account_reconcile_partner_process.py
@@ -28,14 +28,18 @@ class account_partner_reconcile_process(osv.osv_memory):
_description = 'Reconcilation Process partner by partner'
def _get_to_reconcile(self, cr, uid, context=None):
- cr.execute(
- "SELECT l.partner_id " \
- "FROM account_move_line AS l LEFT JOIN res_partner p ON (p.id = l.partner_id) " \
- "WHERE l.reconcile_id IS NULL " \
- "AND (%s > to_char(p.last_reconciliation_date, 'YYYY-MM-DD') " \
- "OR p.last_reconciliation_date IS NULL ) " \
- "AND l.state <> 'draft' " \
- "GROUP BY l.partner_id ",(time.strftime('%Y-%m-%d'),)
+ cr.execute("""
+ SELECT p_id FROM (SELECT l.partner_id as p_id, SUM(l.debit) AS debit, SUM(l.credit) AS credit
+ FROM account_move_line AS l LEFT JOIN account_account a ON (l.account_id = a.id)
+ LEFT JOIN res_partner p ON (p.id = l.partner_id)
+ WHERE a.reconcile = 't'
+ AND l.reconcile_id IS NULL
+ AND (%s > to_char(p.last_reconciliation_date, 'YYYY-MM-DD') OR p.last_reconciliation_date IS NULL )
+ AND l.state <> 'draft'
+ GROUP BY l.partner_id) AS tmp
+ WHERE debit > 0
+ AND credit > 0
+ """,(time.strftime('%Y-%m-%d'),)
)
return len(map(lambda x: x[0], cr.fetchall())) - 1
@@ -57,7 +61,7 @@ class account_partner_reconcile_process(osv.osv_memory):
return partner[0]
def data_get(self, cr, uid, to_reconcile, today_reconciled, context=None):
- return {'progress': (100 / float(to_reconcile + today_reconciled)) * today_reconciled}
+ return {'progress': (100 / (float(to_reconcile + today_reconciled) or 1.0)) * today_reconciled}
def default_get(self, cr, uid, fields, context=None):
res = super(account_partner_reconcile_process, self).default_get(cr, uid, fields, context=context)
diff --git a/addons/account_analytic_plans/report/crossovered_analytic.rml b/addons/account_analytic_plans/report/crossovered_analytic.rml
index 73b7192e27f..1abde7093b8 100644
--- a/addons/account_analytic_plans/report/crossovered_analytic.rml
+++ b/addons/account_analytic_plans/report/crossovered_analytic.rml
@@ -197,7 +197,7 @@
Quantity
- Amount([[ company.currency_id.code]])
+ Amount
Percentage
@@ -245,7 +245,7 @@
Quantity
- Amount([[ company.currency_id.code]])
+ Amount
Percentage
diff --git a/addons/account_analytic_plans/test/acount_analytic_plans_report.yml b/addons/account_analytic_plans/test/acount_analytic_plans_report.yml
index debeba7daa0..0990b9ba5f9 100644
--- a/addons/account_analytic_plans/test/acount_analytic_plans_report.yml
+++ b/addons/account_analytic_plans/test/acount_analytic_plans_report.yml
@@ -1,5 +1,5 @@
-
- Print the Cross Overed Report in Normal mode
+ Print the Crossovered Analytic Report in Normal mode
-
!python {model: account.analytic.account}: |
import netsvc, tools, os, time
diff --git a/addons/account_budget/__openerp__.py b/addons/account_budget/__openerp__.py
index 5d6d8da0def..4fd24da70e9 100644
--- a/addons/account_budget/__openerp__.py
+++ b/addons/account_budget/__openerp__.py
@@ -26,7 +26,7 @@
'category': 'Generic Modules/Accounting',
'description': """This module allows accountants to manage analytic and crossovered budgets.
-Once the Master Budgets and the Budgets defined (in Financial
+Once the Master Budgets and the Budgets are defined (in Financial
Management/Budgets/), the Project Managers can set the planned amount on each
Analytic Account.
diff --git a/addons/account_budget/crossovered_budget.py b/addons/account_budget/crossovered_budget.py
index 3a5846c7d86..e0e1be5e2a2 100644
--- a/addons/account_budget/crossovered_budget.py
+++ b/addons/account_budget/crossovered_budget.py
@@ -20,7 +20,7 @@
##############################################################################
import datetime
-from osv import osv,fields
+from osv import osv, fields
from tools.translate import _
def strToDate(dt):
@@ -113,12 +113,14 @@ class crossovered_budget(osv.osv):
'date_from': fields.date('Start Date', required=True, states={'done':[('readonly',True)]}),
'date_to': fields.date('End Date', required=True, states={'done':[('readonly',True)]}),
'state' : fields.selection([('draft','Draft'),('confirm','Confirmed'),('validate','Validated'),('done','Done'),('cancel', 'Cancelled')], 'Status', select=True, required=True, readonly=True),
- 'crossovered_budget_line': fields.one2many('crossovered.budget.lines', 'crossovered_budget_id', 'Budget Lines', states={'done':[('readonly',True)]} ),
+ 'crossovered_budget_line': fields.one2many('crossovered.budget.lines', 'crossovered_budget_id', 'Budget Lines', states={'done':[('readonly',True)]}),
+ 'company_id': fields.many2one('res.company', 'Company', required=True),
}
_defaults = {
'state': 'draft',
'creating_user_id': lambda self,cr,uid,context: uid,
+ 'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'account.budget.post', context=c)
}
def budget_confirm(self, cr, uid, ids, *args):
@@ -244,7 +246,9 @@ class crossovered_budget_lines(osv.osv):
'practical_amount':fields.function(_prac, method=True, string='Practical Amount', type='float', digits=(16,2)),
'theoritical_amount':fields.function(_theo, method=True, string='Theoritical Amount', type='float', digits=(16,2)),
'percentage':fields.function(_perc, method=True, string='Percentage', type='float'),
+ 'company_id': fields.related('crossovered_budget_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True)
}
+
crossovered_budget_lines()
class account_analytic_account(osv.osv):
@@ -257,5 +261,4 @@ class account_analytic_account(osv.osv):
account_analytic_account()
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
diff --git a/addons/account_budget/crossovered_budget_view.xml b/addons/account_budget/crossovered_budget_view.xml
index b863979ad92..263dee3f686 100644
--- a/addons/account_budget/crossovered_budget_view.xml
+++ b/addons/account_budget/crossovered_budget_view.xml
@@ -21,7 +21,7 @@
-
+
@@ -69,7 +69,7 @@
@@ -166,6 +168,7 @@
+
@@ -238,6 +241,7 @@
+
diff --git a/addons/account_budget/report/analytic_account_budget_report.rml b/addons/account_budget/report/analytic_account_budget_report.rml
index 2cf00cb1bd5..e349b3d4920 100644
--- a/addons/account_budget/report/analytic_account_budget_report.rml
+++ b/addons/account_budget/report/analytic_account_budget_report.rml
@@ -128,13 +128,13 @@
Description
[[ formatLang(b['tot_theo']) ]] [[ company.currency_id.symbol ]]
diff --git a/addons/account_budget/security/account_budget_security.xml b/addons/account_budget/security/account_budget_security.xml
index 13ad6b34289..ec075205f68 100644
--- a/addons/account_budget/security/account_budget_security.xml
+++ b/addons/account_budget/security/account_budget_security.xml
@@ -1,10 +1,27 @@
-
+
+
+
-
- Budget post multi-company
-
-
- ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]
-
+
+ Budget post multi-company
+
+
+ ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]
+
-
+
+ Budget multi-company
+
+
+ ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]
+
+
+
+ Budget lines multi-company
+
+
+ ['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]
+
+
+
+
diff --git a/addons/account_budget/test/account_budget.yml b/addons/account_budget/test/account_budget.yml
index f77efa23b15..4a2d5023fc7 100644
--- a/addons/account_budget/test/account_budget.yml
+++ b/addons/account_budget/test/account_budget.yml
@@ -1,5 +1,5 @@
-
- In order to check account budget module in OpenERP I created a budget with few budget position
+ In order to check account budget module in OpenERP I created a budget with few budget positions
-
Creating a crossovered.budget record
-
@@ -58,7 +58,7 @@
- state == 'validate'
-
- I pressed the done button to done the Budget
+ I pressed the done button to set the Budget to "Done" state
-
Performing a workflow action done on module crossovered.budget
-
diff --git a/addons/account_budget/test/account_budget_report.yml b/addons/account_budget/test/account_budget_report.yml
index fa086e24a64..2115341c1a1 100644
--- a/addons/account_budget/test/account_budget_report.yml
+++ b/addons/account_budget/test/account_budget_report.yml
@@ -17,7 +17,7 @@
if tools.config['test_report_directory']:
file(os.path.join(tools.config['test_report_directory'], 'account_budget-budget_report.'+format), 'wb+').write(data)
-
- Print the Cross Overed Budget Report in Normal mode
+ Print the CrossOvered Budget Report in Normal mode
-
!python {model: crossovered.budget}: |
import netsvc, tools, os, time
diff --git a/addons/account_budget/test/account_budget_spread.yml b/addons/account_budget/test/account_budget_spread.yml
index 98d85222859..c996c647025 100644
--- a/addons/account_budget/test/account_budget_spread.yml
+++ b/addons/account_budget/test/account_budget_spread.yml
@@ -1,5 +1,5 @@
-
- In order to test Spread Wizard of account module I spread record with amount=1000
+ In order to test Spread Wizard of account_budget module I spread record with amount=1000
-
Creating a account.budget.spread record
-
@@ -9,7 +9,7 @@
-
- Performing an osv_memory action check_spread on module account.budget.spread
+ Performing an osv_memory action check_spread on model account.budget.spread
-
!python {model: account.budget.spread}: |
self.check_spread(cr, uid, [ref("account_budget_spread_0")], {"lang": 'en_US',
diff --git a/addons/account_coda/account_coda_view.xml b/addons/account_coda/account_coda_view.xml
index b53a7b4a132..26415fa8e98 100644
--- a/addons/account_coda/account_coda_view.xml
+++ b/addons/account_coda/account_coda_view.xml
@@ -9,7 +9,7 @@
[[ formatLang((reduce(lambda x,y: x+(y['debit'] - y['credit']), getLines(o), 0.00))) ]] [[ company.currency_id.symbol]]
diff --git a/addons/account_followup/test/account_followup.yml b/addons/account_followup/test/account_followup.yml
index 0a47ddad116..a81559011f3 100644
--- a/addons/account_followup/test/account_followup.yml
+++ b/addons/account_followup/test/account_followup.yml
@@ -101,11 +101,3 @@
"active_model": "ir.ui.menu", "active_ids": [ref("account_followup.account_followup_print_menu")],
"tz": False, "date": "2010-06-08", "followup_id": ref("account_followup_followup_testfollowups0"), "active_id": ref("account_followup.account_followup_print_menu"),
})
-
-
-
-
-
-
-
-
diff --git a/addons/account_followup/wizard/account_followup_print.py b/addons/account_followup/wizard/account_followup_print.py
index b89ad76d0ee..fe635a080c7 100644
--- a/addons/account_followup/wizard/account_followup_print.py
+++ b/addons/account_followup/wizard/account_followup_print.py
@@ -116,6 +116,7 @@ class account_followup_print_all(osv.osv_memory):
"AND (l.state<>'draft') "\
"AND (l.partner_id is NOT NULL) "\
"AND (a.active) "\
+ "AND (l.debit > 0) "\
"ORDER BY l.date")
move_lines = cr.fetchall()
old = None
@@ -294,4 +295,4 @@ class account_followup_print_all(osv.osv_memory):
account_followup_print_all()
-# 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_invoice_layout/report/report_account_invoice_layout.rml b/addons/account_invoice_layout/report/report_account_invoice_layout.rml
index 8f7d5f561e8..f92cd477f1a 100644
--- a/addons/account_invoice_layout/report/report_account_invoice_layout.rml
+++ b/addons/account_invoice_layout/report/report_account_invoice_layout.rml
@@ -260,7 +260,7 @@
Disc. (%)
- Price([[ o.currency_id.code ]])
+ Price
@@ -360,7 +360,7 @@
Disc. (%)
- Price([[ o.currency_id.code ]])
+ Price
@@ -477,7 +477,7 @@
- [[ format((o.payment_term and o.payment_term.note or '') or removeParentNode('blockTable')) ]]
+ [[ o.payment_term and o.payment_term.name + " :\n" + format(o.payment_term.note or '') or removeParentNode('blockTable') ]]
- [[ a['no_lot'] or '0.0' ]]
+ [[ a['no_lot'] or '0.0' ]]
- [[ a['adj_price'] or '0.0' ]]
-
+ [[ a['adj_price']) or '0.0' ]][[ company.currency_id.symbol ]]
- [[ a['buyer_cost'] or '0.0' ]]
+ [[ a['buyer_cost'] or '0.0' ]][[ company.currency_id.symbol ]]
- [[a['to_pay'] or '0.0' ]]
+ [[a['to_pay'] or '0.0' ]][[ company.currency_id.symbol ]]
@@ -100,28 +108,27 @@
.........
-
+
- Total:
+ Total:
- [[ '%.0f' % (sum_lots() or 0.0) ]]
+ [[ '%.0f' % (sum_lots() or 0.0) ]]
- [[ '%.2f' % (sum_adj_price() or 0.0) ]]
+ [[ '%.2f' % (sum_adj_price() or 0.0 )]][[ company.currency_id.symbol ]]
- [[ '%.2f' % (sum_buyer_obj_price() or 0.0) ]]
+ [[ '%.2f' % (sum_buyer_obj_price() or 0.0) ]][[ company.currency_id.symbol ]]
- [[ '%.2f' % (sum_buyer_price() or 0.0) ]]
+ [[ '%.2f' % (sum_buyer_price() or 0.0) ]][[ company.currency_id.symbol ]]
-
+
-
-
+
\ No newline at end of file
diff --git a/addons/auction/test/auction.yml b/addons/auction/test/auction.yml
index 6d07f5fc0a5..bbab6786e27 100644
--- a/addons/auction/test/auction.yml
+++ b/addons/auction/test/auction.yml
@@ -25,12 +25,12 @@
name: Vincent van Gogh
-
- I modifying a expenses journal record for analytic journal.
+ I am modifying an expenses journal record for analytic journal.
-
!record {model: account.journal, id: account.expenses_journal}:
analytic_journal_id: account.exp
-
- I modifying a sales journal record for analytic journal.
+ I am modifying a sales journal record for analytic journal.
-
!record {model: account.journal, id: account.sales_journal}:
analytic_journal_id: account.cose_journal_sale
@@ -49,7 +49,7 @@
name: Mr. Pinakin
-
- I'm creating new Buyer "Mr. Patel" with him email "info@myinfobid.com".
+ I'm creating new Buyer "Mr. Patel" with his email "info@myinfobid.com".
-
!record {model: res.partner, id: res_partner_mrpatel0}:
address:
@@ -62,7 +62,7 @@
name: Mr. Patel
-
- I'm creating new Buyer "Mr. Johnson" with him email "info@mrkjohnson.com".
+ I'm creating new Buyer "Mr. Johnson" with his email "info@mrkjohnson.com".
-
!record {model: res.partner, id: res_partner_mrkjohnson0}:
address:
@@ -76,7 +76,7 @@
name: Mr. Mark Johnson
-
- I'm creating new Buyer "Mr. Rahi" with him email "info@poalrahi.com".
+ I'm creating new Buyer "Mr. Rahi" with his email "info@poalrahi.com".
-
!record {model: res.partner, id: res_partner_poalrahi0}:
address:
@@ -90,7 +90,7 @@
-
- I create Account tax with 0.03 amount to give Buyer "3%" Commision.
+ I create an Account tax with 0.03 amount to give Buyer "3%" Commission.
-
!record {model: account.tax, id: account_tax_buyer0}:
amount: 0.029999999999999999
@@ -102,7 +102,7 @@
type: percent
type_tax_use: all
-
- I create Account tax with 0.04 amount to give seller "4%" commision.
+ I create another Account tax with 0.04 amount to give seller "4%" commission.
-
!record {model: account.tax, id: account_tax_sellercosts0}:
amount: 0.040000000000000001
@@ -116,7 +116,7 @@
-
Now I want to associate an object with the auction so for that I create an auction "Antique furniture exhibition" which
- start from 1 Aug to 31 Aug with Seller Commition 4%, buyer commition 3%.
+ start from 1 Aug to 31 Aug with Seller Commission 4%, buyer commission 3%.
-
!record {model: auction.dates, id: auction_dates_antiquefurnitureexhibition0}:
acc_expense: account.a_pay
@@ -165,7 +165,7 @@
state: draft
vnd_lim: 5000.0
-
- I create a bid for an object "wooden-chair" which is to be auctioned in Antique furniture exhibition bided by Mr.Patel.
+ I create a bid for an object "wooden-chair" which is to be auctioned in Antique furniture exhibition bid by Mr.Patel.
-
!record {model: auction.bid, id: auction_bid_bid0}:
auction_id: auction_dates_antiquefurnitureexhibition0
@@ -182,7 +182,7 @@
price: 3100.0
-
- I create another bid for an object "wooden-chair" bided by a Mr.poalrahi
+ I create another bid for an object "wooden-chair" bid by a Mr.poalrahi
-
!record {model: auction.bid, id: auction_bid_bid1}:
auction_id: auction_dates_antiquefurnitureexhibition0
@@ -199,7 +199,7 @@
price: 3200.0
-
- I create another bid for an object "wooden-chair" bided by a Mr.Johnson
+ I create another bid for an object "wooden-chair" bid by a Mr.Johnson
-
!record {model: auction.bid, id: auction_bid_bid2}:
auction_id: auction_dates_antiquefurnitureexhibition0
@@ -215,9 +215,9 @@
lot_id: auction.auction_lots_woodenchair0
price: 4000.0
-
- Mr. MarkJohnson bid are selected as Finallist Bid with 4000 Euro
+ Mr. MarkJohnson bid are selected as the Finalist Bid with 4000 Euro
-
- I check that buyer price and seller price gets bind with the value
+ I check that buyer price and seller price gets bound with the value
-
!python {model: auction.lots}: |
from tools.translate import _
@@ -254,13 +254,13 @@
number: 2010/003
objects: 1
-
- Then I click on the "Create Invoices" button.
+ I click on the "Create Invoices" button.
-
!python {model: auction.lots.make.invoice.buyer}: |
self.makeInvoices(cr, uid, [ref("auction_lots_make_invoice_buyer_0")], {"active_model": "auction.lots", "active_ids": [ref("auction_lots_woodenchair0")],
"active_id": ref("auction_lots_woodenchair0"), })
-
- I check that a "Buyer Invoice" field gets bind with the value.
+ I check that a "Buyer Invoice" field gets bound with the value.
-
!python {model: auction.lots}: |
from tools.translate import _
@@ -289,7 +289,7 @@
auc_id=self.browse(cr, uid, ref("auction_lots_woodenchair0"))
assert(auc_id.state == 'sold'), _('State not changed!')
-
- Then I click on the Taken Away button.
+ I click on the Taken Away button.
-
!python {model: auction.lots}: |
self.button_taken_away(cr, uid, [ref("auction_lots_woodenchair0")], {"lang":
@@ -307,7 +307,7 @@
!record {model: auction.lots.auction.move, id: auction_lots_auction_move_0}:
auction_id: auction.auction_date_2
-
- Then I click on the "Move to Auction date" button.
+ I click on the "Move to Auction date" button.
-
!python {model: auction.lots.auction.move}: |
self.auction_move_set(cr, uid, [ref("auction_lots_auction_move_0")], {"lang":
diff --git a/addons/auction/test/auction_report.yml b/addons/auction/test/auction_report.yml
index 0219af369b4..962c945f366 100644
--- a/addons/auction/test/auction_report.yml
+++ b/addons/auction/test/auction_report.yml
@@ -1,5 +1,5 @@
-
- In order to test the PDF reports defined on auction, we will print a auction artist
+ In order to test the PDF reports defined on Auction, we will print an Auction Artist Report
-
!python {model: auction.lots}: |
import netsvc, tools, os
@@ -8,7 +8,7 @@
file(os.path.join(tools.config['test_report_directory'], 'auction-auction_artist_report.'+format), 'wb+').write(data)
-
- In order to test the PDF reports defined on auction, we will print a auction Bid
+ In order to test the PDF reports defined on Auction, we will print an Auction Bid Report
-
!python {model: auction.bid}: |
import netsvc, tools, os
@@ -17,61 +17,61 @@
file(os.path.join(tools.config['test_report_directory'], 'auction-auction_bid_report.'+format), 'wb+').write(data)
-
- In order to test the PDF reports defined on auction, we will print a lots list Report
+ In order to test the PDF reports defined on Auction, we will print a Lots List Report
-
!python {model: auction.lots}: |
import netsvc, tools, os
(data, format) = netsvc.LocalService('report.lots.list').create(cr, uid, [ref('auction.auction_deposit_3_lot_1'),ref('auction.auction_deposit_3_lot_2')], {}, {})
if tools.config['test_report_directory']:
- file(os.path.join(tools.config['test_report_directory'], 'auction-auction_lots_list_report.'+format), 'wb+').write(data)
+ file(os.path.join(tools.config['test_report_directory'], 'auction-lots_list_report.'+format), 'wb+').write(data)
-
- In order to test the PDF reports defined on auction, we will print a lots inventory Report
+ In order to test the PDF reports defined on Auction, we will print a Lots Inventory Report
-
!python {model: auction.lots}: |
import netsvc, tools, os
(data, format) = netsvc.LocalService('report.lots.list.inventory').create(cr, uid, [ref('auction.auction_deposit_4_lot_1'),ref('auction.auction_deposit_4_lot_2')], {}, {})
if tools.config['test_report_directory']:
- file(os.path.join(tools.config['test_report_directory'], 'auction-auction_lots_inventory_report.'+format), 'wb+').write(data)
+ file(os.path.join(tools.config['test_report_directory'], 'auction-lots_inventory_report.'+format), 'wb+').write(data)
-
- In order to test the PDF reports defined on auction, we will print a deposit seller Report
+ In order to test the PDF reports defined on Auction, we will print a Deposit Seller Report
-
!python {model: auction.lots}: |
import netsvc, tools, os
(data, format) = netsvc.LocalService('report.deposit.seller').create(cr, uid, [ref('auction.auction_deposit_5_lot_1'),ref('auction.auction_deposit_5_lot_2')], {}, {})
if tools.config['test_report_directory']:
- file(os.path.join(tools.config['test_report_directory'], 'auction-auction_deposit_seller_report.'+format), 'wb+').write(data)
+ file(os.path.join(tools.config['test_report_directory'], 'auction-deposit_seller_report.'+format), 'wb+').write(data)
-
- In order to test the PDF reports defined on auction, we will print a catalog
+ In order to test the PDF reports defined on Auction, we will print a Catalogue List Report
-
!python {model: auction.dates}: |
import netsvc, tools, os
(data, format) = netsvc.LocalService('report.auction.cat_flagy').create(cr, uid, [ref('auction.auction_date_1'),ref('auction.auction_date_2')], {}, {})
if tools.config['test_report_directory']:
- file(os.path.join(tools.config['test_report_directory'], 'auction-auction_catalog_list.'+format), 'wb+').write(data)
+ file(os.path.join(tools.config['test_report_directory'], 'auction-catalog_list_report.'+format), 'wb+').write(data)
-
- In order to test the PDF reports defined on auction, we will print buyer form report
+ In order to test the PDF reports defined on Auction, we will print a Buyer Form Report
-
!python {model: auction.lots}: |
import netsvc, tools, os
(data, format) = netsvc.LocalService('report.buyer_form_report').create(cr, uid, [ref('auction.auction_deposit_6_lot_1'),ref('auction.auction_deposit_6_lot_2')], {}, {})
if tools.config['test_report_directory']:
- file(os.path.join(tools.config['test_report_directory'], 'auction-auction_buyer_form.'+format), 'wb+').write(data)
+ file(os.path.join(tools.config['test_report_directory'], 'auction-buyer_form_report.'+format), 'wb+').write(data)
-
- In order to test the PDF reports defined on auction, we will print bids phones report
+ In order to test the PDF reports defined on Auction, we will print a report of Bids Phones Details
-
!python {model: auction.lots}: |
import netsvc, tools, os
(data, format) = netsvc.LocalService('report.bids.phones.details').create(cr, uid, [ref('auction.auction_deposit_7_lot_1'),ref('auction.auction_deposit_7_lot_2')], {}, {})
if tools.config['test_report_directory']:
- file(os.path.join(tools.config['test_report_directory'], 'auction-auction_bids_phones_details.'+format), 'wb+').write(data)
+ file(os.path.join(tools.config['test_report_directory'], 'auction-bids_phones_details_report.'+format), 'wb+').write(data)
-
- In order to test the PDF reports defined on a auction, we will print a Auction Total
+ In order to test the PDF reports defined on Auction, we will print an Auction Total Report
-
!python {model: auction.lots}: |
import netsvc, tools, os
@@ -80,7 +80,7 @@
file(os.path.join(tools.config['test_report_directory'], 'auction-auction_total_report.'+format), 'wb+').write(data)
-
- In order to test the PDF reports defined on a auction, we will print a Auction Result
+ In order to test the PDF reports defined on Auction, we will print an Auction Result Report
-
!python {model: auction.lots}: |
import netsvc, tools, os
@@ -89,7 +89,7 @@
file(os.path.join(tools.config['test_report_directory'], 'auction-auction_result_report.'+format), 'wb+').write(data)
-
- In order to test the PDF reports defined on a auction, we will print a Auction Lot
+ In order to test the PDF reports defined on Auction, we will print an Auction Lot Report
-
!python {model: auction.lots}: |
import netsvc, tools, os
@@ -98,28 +98,44 @@
file(os.path.join(tools.config['test_report_directory'], 'auction-auction_lot_report.'+format), 'wb+').write(data)
-
- In order to test the PDF reports defined on a auction, we will print a Auction Buyer list report
+ In order to test the PDF reports defined on Auction, we will print an Auction Buyer List Report
-
!python {model: auction.lots}: |
import netsvc, tools, os
(data, format) = netsvc.LocalService('report.buyer.list').create(cr, uid, [ref('auction.auction_deposit_10_lot_1'),ref('auction.auction_deposit_10_lot_2')], {}, {})
if tools.config['test_report_directory']:
- file(os.path.join(tools.config['test_report_directory'], 'auction-auction_buyer_list_report.'+format), 'wb+').write(data)
+ file(os.path.join(tools.config['test_report_directory'], 'auction-buyer_list_report.'+format), 'wb+').write(data)
-
- In order to test the PDF reports defined on a auction, we will print a Auction Flagey Hussier report
+ In order to test the PDF reports defined on Auction, we will print an Auction Flagey Hussier Report
-
!python {model: auction.lots}: |
import netsvc, tools, os
(data, format) = netsvc.LocalService('report.flagey.huissier').create(cr, uid, [ref('auction.auction_deposit_3_lot_1'),ref('auction.auction_deposit_10_lot_2')], {}, {})
if tools.config['test_report_directory']:
- file(os.path.join(tools.config['test_report_directory'], 'auction-auction_flagey_hussier_report.'+format), 'wb+').write(data)
+ file(os.path.join(tools.config['test_report_directory'], 'auction-flagey_hussier_report.'+format), 'wb+').write(data)
-
- In order to test the PDF reports defined on a auction, we will print Auction Seller Form report
+ In order to test the PDF reports defined on Auction, we will print an Auction Seller Form Report
-
!python {model: auction.lots}: |
import netsvc, tools, os
(data, format) = netsvc.LocalService('report.seller_form_report').create(cr, uid, [ref('auction.auction_deposit_3_lot_1'),ref('auction.auction_deposit_10_lot_2')], {}, {})
if tools.config['test_report_directory']:
- file(os.path.join(tools.config['test_report_directory'], 'auction-auction_seller_form_report.'+format), 'wb+').write(data)
\ No newline at end of file
+ file(os.path.join(tools.config['test_report_directory'], 'auction-seller_form_report.'+format), 'wb+').write(data)
+-
+ In order to test the PDF reports defined on Auction, we will a print Buyer Result Report
+-
+ !python {model: auction.lots}: |
+ import netsvc, tools, os
+ (data, format) = netsvc.LocalService('report.auction.buyer.result').create(cr, uid, [ref('auction.auction_deposit_3_lot_1'),ref('auction.auction_deposit_10_lot_2')], {}, {})
+ if tools.config['test_report_directory']:
+ file(os.path.join(tools.config['test_report_directory'], 'auction-buyer_result_report.'+format), 'wb+').write(data)
+-
+ In order to test the PDF reports defined on Auction, we will print a Catalogue Report
+-
+ !python {model: auction.lots}: |
+ import netsvc, tools, os
+ (data, format) = netsvc.LocalService('report.auction.catelog').create(cr, uid, [ref('auction.auction_deposit_3_lot_1'),ref('auction.auction_deposit_10_lot_2')], {}, {})
+ if tools.config['test_report_directory']:
+ file(os.path.join(tools.config['test_report_directory'], 'auction-catelog_report.'+format), 'wb+').write(data)
\ No newline at end of file
diff --git a/addons/auction/test/auction_wizard.yml b/addons/auction/test/auction_wizard.yml
index f7308f8687c..bfe4f353ed5 100644
--- a/addons/auction/test/auction_wizard.yml
+++ b/addons/auction/test/auction_wizard.yml
@@ -81,7 +81,7 @@
"tz": False, "active_model": "auction.lots", "active_ids": [ref("auction_lots_painting0")],
"active_id": ref("auction_lots_painting0")})
-
- I check that the buyer field gets bind with the value.
+ I check that the buyer field gets bound with the value.
-
!python {model: auction.lots}: |
from tools.translate import _
@@ -89,7 +89,7 @@
assert(auc_id.ach_uid), _('Buyer not assigned!')
-
- I create statement lines for an object's payment by using the "Pay objects of the buyer" wizard
+ I create statement lines for the payment of an object using the "Pay objects of the buyer" wizard
-
I create a bank statement.
-
@@ -113,7 +113,7 @@
statement_id3: account_bank_statement_st0
total: 4000.0
-
- Then I click "Pay" button.
+ I click "Pay" button.
-
!python {model: auction.pay.buy}: |
self.pay_and_reconcile(cr, uid, [ref("auction_pay_buy_0")], {"lang": "en_US", "tz":
@@ -135,14 +135,14 @@
number: 2010/002
objects: 1
-
- Then I click on the "Create Invoices" button.
+ I click on the "Create Invoices" button.
-
!python {model: auction.lots.make.invoice}: |
self.makeInvoices(cr, uid, [ref("auction_lots_make_invoice_0")], {"lang": "en_US",
"active_model": "auction.lots", "active_ids": [ref("auction_lots_painting0")],
"tz": False, "active_id": ref("auction_lots_painting0"),})
-
- I check that a "Seller Invoice" field gets bind with the value.
+ I check that a "Seller Invoice" field gets bound with the value.
-
!python {model: auction.lots}: |
from tools.translate import _
@@ -157,14 +157,14 @@
number: 2010/003
objects: 1
-
- Then I click on the "Create Invoices" button.
+ I click on the "Create Invoices" button.
-
!python {model: auction.lots.make.invoice.buyer}: |
self.makeInvoices(cr, uid, [ref("auction_lots_make_invoice_buyer_0")], {"lang":
"en_US", "active_model": "auction.lots", "active_ids": [ref("auction_lots_painting0")],
"tz": False, "active_id": ref("auction_lots_painting0"), })
-
- I check that a "Buyer Invoice" field gets bind with the value.
+ I check that a "Buyer Invoice" field gets bound with the value.
-
!python {model: auction.lots}: |
from tools.translate import _
@@ -176,7 +176,7 @@
!record {model: auction.lots.auction.move, id: auction_lots_auction_move_0}:
auction_id: auction.auction_date_2
-
- Then I click on the "Move to Auction date" button.
+ I click on the "Move to Auction date" button.
-
!python {model: auction.lots.auction.move}: |
self.auction_move_set(cr, uid, [ref("auction_lots_auction_move_0")], {"lang":
diff --git a/addons/auction/wizard/auction_taken.py b/addons/auction/wizard/auction_taken.py
index 7db905cd576..ff79000d898 100644
--- a/addons/auction/wizard/auction_taken.py
+++ b/addons/auction/wizard/auction_taken.py
@@ -19,12 +19,6 @@
#
##############################################################################
from osv import fields, osv
-from tools.translate import _
-import netsvc
-import pooler
-import time
-import tools
-import wizard
class auction_taken(osv.osv_memory):
"""
diff --git a/addons/audittrail/__openerp__.py b/addons/audittrail/__openerp__.py
index e660b418aa3..c9164bfd839 100644
--- a/addons/audittrail/__openerp__.py
+++ b/addons/audittrail/__openerp__.py
@@ -25,7 +25,7 @@
'version': '1.0',
'category': 'Generic Modules/Others',
'description': """
- This module gives the administrator the right
+ This module gives the administrator the rights
to track every user operation on all the objects
of the system.
diff --git a/addons/audittrail/audittrail.py b/addons/audittrail/audittrail.py
index 4278e0a9179..dd843449c8c 100644
--- a/addons/audittrail/audittrail.py
+++ b/addons/audittrail/audittrail.py
@@ -35,15 +35,15 @@ class audittrail_rule(osv.osv):
_description = "Audittrail Rule"
_columns = {
"name": fields.char("Rule Name", size=32, required=True),
- "object_id": fields.many2one('ir.model', 'Object', required=True),
+ "object_id": fields.many2one('ir.model', 'Object', required=True, help="Select object for which you want to generate log."),
"user_id": fields.many2many('res.users', 'audittail_rules_users',
'user_id', 'rule_id', 'Users', help="if User is not added then it will applicable for all users"),
- "log_read": fields.boolean("Log Reads"),
- "log_write": fields.boolean("Log Writes"),
- "log_unlink": fields.boolean("Log Deletes"),
- "log_create": fields.boolean("Log Creates"),
- "log_action": fields.boolean("Log Action"),
- "log_workflow": fields.boolean("Log Workflow"),
+ "log_read": fields.boolean("Log Reads", help="Select this if you want to keep track of read/open on any record of the object of this rule"),
+ "log_write": fields.boolean("Log Writes", help="Select this if you want to keep track of modification on any record of the object of this rule"),
+ "log_unlink": fields.boolean("Log Deletes", help="Select this if you want to keep track of deletion on any record of the object of this rule"),
+ "log_create": fields.boolean("Log Creates",help="Select this if you want to keep track of creation on any record of the object of this rule"),
+ "log_action": fields.boolean("Log Action",help="Select this if you want to keep track of actions on the object of this rule"),
+ "log_workflow": fields.boolean("Log Workflow",help="Select this if you want to keep track of workflow on any record of the object of this rule"),
"state": fields.selection((("draft", "Draft"),
("subscribed", "Subscribed")),
"State", required=True),
diff --git a/addons/base_action_rule/base_action_rule_view.xml b/addons/base_action_rule/base_action_rule_view.xml
index 526fe55f4a3..755f6680d34 100644
--- a/addons/base_action_rule/base_action_rule_view.xml
+++ b/addons/base_action_rule/base_action_rule_view.xml
@@ -14,11 +14,13 @@
form
-
diff --git a/addons/crm/report/crm_lead_report.py b/addons/crm/report/crm_lead_report.py
index 2f10922a947..71d19b3d6f1 100644
--- a/addons/crm/report/crm_lead_report.py
+++ b/addons/crm/report/crm_lead_report.py
@@ -45,7 +45,6 @@ class crm_lead_report(osv.osv):
@param context: A standard dictionary for contextual values """
res = {}
- state_perc = 0.0
avg_ans = 0.0
for case in self.browse(cr, uid, ids, context):
@@ -156,7 +155,7 @@ class crm_lead_report(osv.osv):
(SELECT count(id) FROM mailgate_message WHERE model='crm.lead' AND res_id=c.id AND history=True) AS email,
date_trunc('day',c.create_date) as create_date,
extract('epoch' from (c.date_closed-c.create_date))/(3600*24) as delay_close,
- extract('epoch' from (c.date_deadline - c.date_closed))/(3600*24) as delay_expected,
+ abs(extract('epoch' from (c.date_deadline - c.date_closed))/(3600*24)) as delay_expected,
extract('epoch' from (c.date_open-c.create_date))/(3600*24) as delay_open
FROM
crm_lead c
diff --git a/addons/crm/report/crm_lead_report_view.xml b/addons/crm/report/crm_lead_report_view.xml
index 1939965c0dc..d35b8aea295 100644
--- a/addons/crm/report/crm_lead_report_view.xml
+++ b/addons/crm/report/crm_lead_report_view.xml
@@ -9,7 +9,7 @@
crm.lead.reporttree
-
+
@@ -23,12 +23,12 @@
+
-
@@ -71,41 +71,40 @@
-
-
-
-
-
+
+
+
+
-
+
-
+
+ domain="[('state','=','done')]"
+ help="Leads/Opportunities which are in done state"/>
+
+ help="My team" />
-
+
@@ -128,12 +127,15 @@
+
-
+
+
+
-
-
-
-
@@ -153,11 +151,11 @@
context="{'group_by':'company_id'}" />
+ domain="[]" context="{'group_by':'day'}" help="Day on which lead/opportunity is created"/>
+ domain="[]" context="{'group_by':'month'}" help="Month in which lead/opportunity is created"/>
+ domain="[]" context="{'group_by':'name'}" help="Year in which lead/opportunity is created"/>
@@ -206,7 +204,7 @@
form{'search_default_filter_lead': 1, 'search_default_lead':1, "search_default_user":1,"search_default_this_month":1,'group_by_no_leaf':1,'group_by':[]}tree,graph
- []
+ [('type', '=', 'lead')]Leads Analysis allows you to consult different informations relative to CRM. Check for treatments delays, number of responses given and emails send. You can sort out your leads analysis on different groups to get fine grained analysis.
@@ -230,7 +228,7 @@
form{"search_default_filter_opportunity":1, "search_default_opportunity": 1, "search_default_user":1,"search_default_this_month":1,'group_by_no_leaf':1,'group_by':[]}tree,graph
- []
+ [('type', '=', 'opportunity')]Opportunities Analysis menu gives you an instant access to your opportunities like expected revenue, planned cost, overpassed deadline or the number of exchanges by opportunity.
diff --git a/addons/crm/report/crm_phonecall_report.py b/addons/crm/report/crm_phonecall_report.py
index 00d13c7216c..259764e4170 100644
--- a/addons/crm/report/crm_phonecall_report.py
+++ b/addons/crm/report/crm_phonecall_report.py
@@ -119,9 +119,9 @@ class crm_phonecall_report(osv.osv):
create or replace view crm_phonecall_report as (
select
id,
- to_char(c.create_date, 'YYYY') as name,
- to_char(c.create_date, 'MM') as month,
- to_char(c.create_date, 'YYYY-MM-DD') as day,
+ to_char(c.date, 'YYYY') as name,
+ to_char(c.date, 'MM') as month,
+ to_char(c.date, 'YYYY-MM-DD') as day,
to_char(c.create_date, 'YYYY-MM-DD') as creation_date,
to_char(c.date_open, 'YYYY-MM-DD') as opening_date,
to_char(c.date_closed, 'YYYY-mm-dd') as date_closed,
diff --git a/addons/crm/report/crm_phonecall_report_view.xml b/addons/crm/report/crm_phonecall_report_view.xml
index 8024ca78bd5..8d8ee946ae0 100644
--- a/addons/crm/report/crm_phonecall_report_view.xml
+++ b/addons/crm/report/crm_phonecall_report_view.xml
@@ -9,7 +9,7 @@
crm.phonecall.reporttree
-
+
@@ -75,37 +75,41 @@
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
-
+ string="Todo"
+ domain="[('state','in',('draft','open'))]"
+ help="Phone calls which are in draft and open state"/>
+
+
+
+
+
+
+
@@ -128,29 +132,28 @@
domain="[]" context="{'group_by':'user_id'}" />
-
-
+
-
-
+
+ context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
+ domain="[]" context="{'group_by':'day'}" help="Date of call"/>
+ domain="[]" context="{'group_by':'month'}" help="Month of call"/>
+ domain="[]" context="{'group_by':'name'}" help="Year of call"/>
@@ -159,7 +162,7 @@
- Phone Calls
+ Phone Calls Analysiscrm.phonecall.reportformtree,graph
diff --git a/addons/crm/security/ir.model.access.csv b/addons/crm/security/ir.model.access.csv
index 7179a8ffdad..e68fe873b6c 100644
--- a/addons/crm/security/ir.model.access.csv
+++ b/addons/crm/security/ir.model.access.csv
@@ -10,7 +10,7 @@
"access_crm_phonecall_system","crm.phonecall.system","model_crm_phonecall","base.group_system",1,0,0,0
"access_crm_phonecall_manager","crm.phonecall.manager","model_crm_phonecall","base.group_sale_manager",1,0,0,0
"access_crm_case_categ","crm.case.categ","model_crm_case_categ","base.group_user",1,0,0,0
-"access_crm_meeting","crm.meeting","model_crm_meeting","base.group_sale_salesman",1,1,1,0
+"access_crm_meeting","crm.meeting","model_crm_meeting","base.group_sale_salesman",1,0,0,0
"access_crm_meeting_all","crm.meeting_allll","model_crm_meeting","base.group_user",1,0,0,0
"access_crm_lead","crm.lead","model_crm_lead","base.group_sale_salesman",1,1,1,1
"access_crm_lead.all","crm.lead.all","model_crm_lead","base.group_user",1,0,0,0
diff --git a/addons/crm/test/test_crm_lead.yml b/addons/crm/test/test_crm_lead.yml
index 337b52954b3..3c4a988cc79 100644
--- a/addons/crm/test/test_crm_lead.yml
+++ b/addons/crm/test/test_crm_lead.yml
@@ -87,16 +87,16 @@
#-
# |
-# yaml is also not working smpt server and send new email.
+# yaml is also not working with smtp server and send new email.
- |
I configure with smtp server.
- |
- And I communicate with lead through send New mail to Lead using it email address from user which are loged.
+ And I communicate with lead through send New mail to Lead using its email address from the user who is logged in.
- |
I check that communication history generated when send email to lead.
- |
- Then, I add a cc which receive copy of future communication between partner and users by mail.
+ Then, I add a cc which receive copy of future communication between partner and users by mail.
- |
I Reply to last Email to lead with some document attached.and check that communication history generated or not.
diff --git a/addons/crm/test/test_crm_meeting.yml b/addons/crm/test/test_crm_meeting.yml
index 07a05caa09a..6dcf56cfe66 100644
--- a/addons/crm/test/test_crm_meeting.yml
+++ b/addons/crm/test/test_crm_meeting.yml
@@ -39,7 +39,7 @@
self.write(cr, uid, [ref('crm_meeting_regardingpresentation0')], {'alarm_id': ref("res_alarm_minituesbefore0")})
- |
In order to check recurrence on meetings I will set Recurrency to Custom
- and I set the fields so that the meeting will occure weekly on Monday and Friday 10 times
+ and I set the fields so that the meeting will occur weekly on Monday and Friday 10 times
-
!python {model: crm.meeting}: |
self.write(cr, uid, [ref("crm_meeting_regardingpresentation0")], {'fr': 1, 'mo': 1, 'th': 1, 'tu': 1, 'we':1, 'count':10, 'interval': 1, 'freq': 'weekly', 'rrule_type': 'custom'})
@@ -59,14 +59,14 @@
assert len(ids) == 10
- |
- Now If I want to edit meetings information for all occurence I click on "Edit All" button.
+ Now If I want to edit meetings information for all occurrence I click on "Edit All" button.
-
!python {model: crm.meeting}: |
self.open_meeting(cr, uid, [ref('crm_meeting_regardingpresentation0')])
- |
I can see that new meeting form is opened with same value
I change some data for meeting and save it
- I can see from meeting's calendar view that all meeting occurences are changed accordingly
+ I can see from meeting's calendar view that all meeting occurrences are changed accordingly
-
!record {model: crm.meeting, id: crm.crm_meeting_regardingpresentation0}:
alarm_id: base_calendar.alarm9
diff --git a/addons/crm/test/test_crm_opportunity.yml b/addons/crm/test/test_crm_opportunity.yml
index cf62d05e0b6..e293c8f1797 100644
--- a/addons/crm/test/test_crm_opportunity.yml
+++ b/addons/crm/test/test_crm_opportunity.yml
@@ -32,7 +32,7 @@
- |
I can see that Meeting's calendar view is shown.
- then I click on the date on which I want schedule meeting.
+ then I click on the date on which I want to schedule meeting.
I fill proper data for that meeting and save it
-
!record {model: crm.meeting, id: crm_meeting_abcfuelcounits0}:
diff --git a/addons/crm/wizard/crm_add_note.py b/addons/crm/wizard/crm_add_note.py
index 9a8d4f2d4f3..6bdf472cd97 100644
--- a/addons/crm/wizard/crm_add_note.py
+++ b/addons/crm/wizard/crm_add_note.py
@@ -9,7 +9,7 @@ AVAILABLE_STATES = crm.AVAILABLE_STATES + [('unchanged', 'Unchanged')]
class crm_add_note(osv.osv_memory):
"""Adds a new note to the case."""
_name = 'crm.add.note'
- _description = "Add New Note"
+ _description = "Add Internal Note"
_columns = {
'body': fields.text('Note Body', required=True),
diff --git a/addons/crm/wizard/crm_lead_to_opportunity.py b/addons/crm/wizard/crm_lead_to_opportunity.py
index 79c833b278c..502dddcdcaa 100644
--- a/addons/crm/wizard/crm_lead_to_opportunity.py
+++ b/addons/crm/wizard/crm_lead_to_opportunity.py
@@ -19,7 +19,6 @@
#
##############################################################################
-from mx.DateTime import now
from osv import osv, fields
from tools.translate import _
@@ -70,8 +69,6 @@ class crm_lead2opportunity(osv.osv_memory):
id3 = data_obj.browse(cr, uid, id3, context=context).res_id
lead = lead_obj.browse(cr, uid, record_id, context=context)
- model_ids = model_obj.search(cr, uid, [('model', '=', 'crm.lead')])
-
for this in self.browse(cr, uid, ids, context=context):
vals ={
@@ -105,8 +102,8 @@ class crm_lead2opportunity(osv.osv_memory):
return value
_columns = {
- 'name' : fields.char('Opportunity Summary', size=64, required=True, select=1),
- 'probability': fields.float('Success Probability'),
+ 'name' : fields.char('Opportunity', size=64, required=True, select=1),
+ 'probability': fields.float('Success Rate (%)'),
'planned_revenue': fields.float('Expected Revenue'),
'partner_id': fields.many2one('res.partner', 'Partner'),
}
@@ -144,7 +141,6 @@ Leads Could not convert into Opportunity"))
@return : default values of fields.
"""
lead_obj = self.pool.get('crm.lead')
- rec_ids = context and context.get('active_ids', [])
data = context and context.get('active_ids', []) or []
res = super(crm_lead2opportunity, self).default_get(cr, uid, fields, context=context)
for lead in lead_obj.browse(cr, uid, data, context=context):
@@ -181,7 +177,6 @@ class crm_lead2opportunity_partner(osv.osv_memory):
lead_obj = self.pool.get('crm.lead')
partner_obj = self.pool.get('res.partner')
contact_obj = self.pool.get('res.partner.address')
- rec_ids = context and context.get('active_ids', [])
partner_id = False
data = context and context.get('active_ids', []) or []
@@ -219,7 +214,6 @@ class crm_lead2opportunity_partner(osv.osv_memory):
partner_ids = self._create_partner(cr, uid, ids, context)
mod_obj = self.pool.get('ir.model.data')
result = mod_obj._get_id(cr, uid, 'base', 'view_res_partner_filter')
- res = mod_obj.read(cr, uid, result, ['res_id'])
value = {}
data_obj = self.pool.get('ir.model.data')
data_id = data_obj._get_id(cr, uid, 'crm', 'view_crm_lead2opportunity_action')
diff --git a/addons/crm/wizard/crm_lead_to_partner.py b/addons/crm/wizard/crm_lead_to_partner.py
index 8592a934647..aeb5b2db673 100644
--- a/addons/crm/wizard/crm_lead_to_partner.py
+++ b/addons/crm/wizard/crm_lead_to_partner.py
@@ -143,13 +143,13 @@ class crm_lead2partner(osv.osv_memory):
for lead in lead_obj.browse(cr, uid, rec_ids):
if data.action == 'create':
partner_id = partner_obj.create(cr, uid, {
- 'name': lead.partner_name or lead.name,
+ 'name': lead.partner_name or lead.contact_name or lead.name,
'user_id': lead.user_id.id,
'comment': lead.description,
})
contact_id = contact_obj.create(cr, uid, {
'partner_id': partner_id,
- 'name': lead.name,
+ 'name': lead.contact_name,
'phone': lead.phone,
'mobile': lead.mobile,
'email': lead.email_from,
diff --git a/addons/crm/wizard/crm_merge_opportunities_view.xml b/addons/crm/wizard/crm_merge_opportunities_view.xml
index b6af1f27e8e..cf1a7ee09a4 100644
--- a/addons/crm/wizard/crm_merge_opportunities_view.xml
+++ b/addons/crm/wizard/crm_merge_opportunities_view.xml
@@ -34,5 +34,10 @@
new
+
+
\ No newline at end of file
diff --git a/addons/crm/wizard/crm_opportunity_to_phonecall_view.xml b/addons/crm/wizard/crm_opportunity_to_phonecall_view.xml
index 4d0cf3129f6..3c27eef3d10 100644
--- a/addons/crm/wizard/crm_opportunity_to_phonecall_view.xml
+++ b/addons/crm/wizard/crm_opportunity_to_phonecall_view.xml
@@ -16,7 +16,7 @@
-
+
diff --git a/addons/crm/wizard/crm_send_email.py b/addons/crm/wizard/crm_send_email.py
index aadd607c154..13dae7b35a1 100644
--- a/addons/crm/wizard/crm_send_email.py
+++ b/addons/crm/wizard/crm_send_email.py
@@ -131,8 +131,8 @@ class crm_send_new_email(osv.osv_memory):
x_headers=x_headers
)
- if not flag:
- raise osv.except_osv(_('Error!'), _('Unable to send mail. Please check SMTP is configured properly.'))
+# if not flag:
+# raise osv.except_osv(_('Error!'), _('Unable to send mail. Please check SMTP is configured properly.'))
msg_dict = {'new': 'Send', 'reply': 'Reply', 'forward': 'Forward'}
case_pool.history(cr, uid, [case], _(msg_dict[context.get('mail', 'new')]), history=True, \
diff --git a/addons/crm/wizard/crm_send_email_view.xml b/addons/crm/wizard/crm_send_email_view.xml
index 77202a19f6c..91a934da0e0 100644
--- a/addons/crm/wizard/crm_send_email_view.xml
+++ b/addons/crm/wizard/crm_send_email_view.xml
@@ -81,7 +81,7 @@
-
+
diff --git a/addons/crm_claim/crm_claim.py b/addons/crm_claim/crm_claim.py
index 81a98a7e326..de77c842aa6 100644
--- a/addons/crm_claim/crm_claim.py
+++ b/addons/crm_claim/crm_claim.py
@@ -46,10 +46,8 @@ class crm_claim(crm.crm_case, osv.osv):
'ref' : fields.reference('Reference', selection=crm._links_get, size=128),
'ref2' : fields.reference('Reference 2', selection=crm._links_get, size=128),
'canal_id': fields.many2one('res.partner.canal', 'Channel', \
- help="The channels represent the different communication"\
- "modes available with the customer." \
- " With each commercial opportunity, you can indicate the"\
- "canall which is this opportunity source."),
+ help="The channels represent the different communication \
+ modes available with the customer."),
'planned_revenue': fields.float('Planned Revenue'),
'planned_cost': fields.float('Planned Costs'),
'categ_id': fields.many2one('crm.case.categ', 'Category', \
diff --git a/addons/crm_claim/crm_claim_view.xml b/addons/crm_claim/crm_claim_view.xml
index 44b1eb34fd8..a341915bc39 100644
--- a/addons/crm_claim/crm_claim_view.xml
+++ b/addons/crm_claim/crm_claim_view.xml
@@ -35,21 +35,6 @@
-
-
-
- Claim Resource Type
- crm.case.resource.type
- form
-
- [('object_id.model', '=', 'crm.claim')]
- {'object_id':'crm.claim'}
-
-
-
-
@@ -57,7 +42,7 @@
crm.claimtree
-
+
@@ -168,7 +153,7 @@
-
+
-
+
@@ -205,7 +190,7 @@
-
@@ -269,7 +254,7 @@
@@ -339,6 +325,7 @@
context="{'default_partner_address_id': active_id}"
id="act_claim_partner_address"
name="Report a Claim"
+ view_mode="form,tree"
res_model="crm.claim"
src_model="res.partner.address"/>
diff --git a/addons/crm_claim/i18n/en_US.po b/addons/crm_claim/i18n/en_US.po
index 27818261434..b67bd61d7f9 100644
--- a/addons/crm_claim/i18n/en_US.po
+++ b/addons/crm_claim/i18n/en_US.po
@@ -87,8 +87,8 @@ msgstr "Day"
#. module: crm_claim
#: help:crm.claim,canal_id:0
-msgid "The channels represent the different communicationmodes available with the customer. With each commercial opportunity, you can indicate thecanall which is this opportunity source."
-msgstr "The channels represent the different communicationmodes available with the customer. With each commercial opportunity, you can indicate thecanall which is this opportunity source."
+msgid "The channels represent the different communication modes available with the customer."
+msgstr "The channels represent the different communication modes available with the customer."
#. module: crm_claim
#: help:crm.claim,section_id:0
diff --git a/addons/crm_claim/report/crm_claim_report.py b/addons/crm_claim/report/crm_claim_report.py
index fed4026aa02..e0dc7244f14 100644
--- a/addons/crm_claim/report/crm_claim_report.py
+++ b/addons/crm_claim/report/crm_claim_report.py
@@ -74,6 +74,8 @@ class crm_claim_report(osv.osv):
'type_id': fields.many2one('crm.case.resource.type', 'Claim Type',\
domain="[('section_id','=',section_id),\
('object_id.model', '=', 'crm.claim')]"),
+ 'date_closed': fields.date('Closed', readonly=True),
+ 'delay_expected': fields.float('Overpassed Deadline',digits=(16,2),readonly=True, group_operator="avg"),
}
def init(self, cr):
@@ -87,9 +89,10 @@ class crm_claim_report(osv.osv):
create or replace view crm_claim_report as (
select
min(c.id) as id,
- to_char(c.create_date, 'YYYY') as name,
- to_char(c.create_date, 'MM') as month,
- to_char(c.create_date, 'YYYY-MM-DD') as day,
+ to_char(c.date, 'YYYY') as name,
+ to_char(c.date, 'MM') as month,
+ to_char(c.date, 'YYYY-MM-DD') as day,
+ to_char(c.date_closed, 'YYYY-MM-DD') as date_closed,
c.state,
c.user_id,
c.stage_id,
@@ -101,13 +104,14 @@ class crm_claim_report(osv.osv):
c.priority as priority,
c.type_id as type_id,
date_trunc('day',c.create_date) as create_date,
- avg(extract('epoch' from (c.date_closed-c.create_date)))/(3600*24) as delay_close
+ avg(extract('epoch' from (c.date_closed-c.create_date)))/(3600*24) as delay_close,
+ extract('epoch' from (c.date_deadline - c.date_closed))/(3600*24) as delay_expected
from
crm_claim c
- group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'), \
+ group by to_char(c.date, 'YYYY'), to_char(c.date, 'MM'),to_char(c.date, 'YYYY-MM-DD'),\
c.state, c.user_id,c.section_id, c.stage_id,\
- c.categ_id,c.partner_id,c.company_id,c.create_date,to_char(c.create_date, 'YYYY-MM-DD')
- ,c.priority,c.type_id
+ c.categ_id,c.partner_id,c.company_id,c.create_date,
+ c.priority,c.type_id,c.date_deadline,c.date_closed
)""")
crm_claim_report()
diff --git a/addons/crm_claim/report/crm_claim_report_view.xml b/addons/crm_claim/report/crm_claim_report_view.xml
index edb3dc2b6db..db5973c1867 100644
--- a/addons/crm_claim/report/crm_claim_report_view.xml
+++ b/addons/crm_claim/report/crm_claim_report_view.xml
@@ -19,6 +19,7 @@
+
@@ -42,6 +43,7 @@
+
@@ -75,14 +77,17 @@
-
+
-
+
-
+
-
+ help="My team" />
-
+
-
+
@@ -139,42 +143,41 @@
-
-
-
-
-
+
-
-
-
+
-
-
-
+
+
+
+
+ domain="[]" context="{'group_by':'day'}"
+ help="Date of claim"/>
+ domain="[]" context="{'group_by':'month'}"
+ help="Month of claim"/>
+ domain="[]" context="{'group_by':'name'}"
+ help="Year of claim"/>
-
@@ -182,7 +185,7 @@
- Claims
+ Claims Analysiscrm.claim.reportformtree,graph
diff --git a/addons/crm_fundraising/crm_fundraising.py b/addons/crm_fundraising/crm_fundraising.py
index df7bc4a0789..d815e645c10 100644
--- a/addons/crm_fundraising/crm_fundraising.py
+++ b/addons/crm_fundraising/crm_fundraising.py
@@ -19,7 +19,7 @@
#
##############################################################################
-from osv import fields, osv, orm
+from osv import fields, osv
from crm import crm
class crm_fundraising(crm.crm_case, osv.osv):
@@ -71,10 +71,8 @@ class crm_fundraising(crm.crm_case, osv.osv):
'ref': fields.reference('Reference', selection=crm._links_get, size=128),
'ref2': fields.reference('Reference 2', selection=crm._links_get, size=128),
'canal_id': fields.many2one('res.partner.canal', 'Channel', \
- help="The channels represent the different communication "\
- "modes available with the customer." \
- " With each commercial opportunity, you can indicate\
- the canall which is this opportunity source."),
+ help="The channels represent the different communication \
+ modes available with the customer."),
'state': fields.selection(crm.AVAILABLE_STATES, 'State', size=16, readonly=True,
help='The state is set to \'Draft\', when a case is created.\
\nIf the case is in progress the state is set to \'Open\'.\
diff --git a/addons/crm_fundraising/crm_fundraising_view.xml b/addons/crm_fundraising/crm_fundraising_view.xml
index 84af1b141c9..2021245c1f5 100644
--- a/addons/crm_fundraising/crm_fundraising_view.xml
+++ b/addons/crm_fundraising/crm_fundraising_view.xml
@@ -37,24 +37,6 @@
id="menu_crm_fundraising_stage_act"
parent="menu_config_fundrising" />
-
-
-
-
- Fundraising Resource Type
- crm.case.resource.type
- form
-
- [('object_id.model', '=', 'crm.fundraising')]
- {'object_id':'crm.fundraising'}
-
-
-
-
-
@@ -63,7 +45,7 @@
tree
+ colors="blue:state=='pending';grey:state in ('cancel', 'done')">
@@ -159,7 +141,7 @@
-
+
-
-
@@ -264,10 +264,10 @@
domain="[]" help="Sales Team"
context="{'group_by':'section_id'}" />
-
+ crm.helpdesk.reporttree
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
+
+
+
+
+
@@ -71,13 +76,15 @@
-
-
-
+
+
+
-
-
-
+ help="My team" />
-
-
+
-
-
+
+
+
@@ -123,29 +127,34 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
+ domain="[]" context="{'group_by':'month'}" help="Month of helpdesk requests"/>
+ domain="[]" context="{'group_by':'name'}" help="Year of helpdesk requests" />
@@ -154,10 +163,11 @@
- Helpdesk
+ Helpdesk Analysiscrm.helpdesk.reportformtree,graph
+ {"search_default_User":1,"search_default_This Month":1,'group_by_no_leaf':1,'group_by':[]}Helpdesk allows you to consult different informations relative to support demands. Check for treatments delays, number of responses given and emails send and costs. You can sort out your analysis on different groups to get fine grained analysis.
diff --git a/addons/document/document_view.xml b/addons/document/document_view.xml
index f6e21f338e7..69c1c5e2cc3 100644
--- a/addons/document/document_view.xml
+++ b/addons/document/document_view.xml
@@ -44,7 +44,7 @@
-
+
@@ -80,7 +80,7 @@
-
@@ -93,7 +93,7 @@
-
+
@@ -168,7 +168,7 @@
-
+
@@ -282,10 +282,9 @@
ir.attachmentsearch
-
-
+
@@ -293,7 +292,7 @@
+ help="Filter on my documents" />
@@ -332,7 +331,6 @@
Documentsir.actions.act_windowir.attachment
- DocumentformDocuments give your access to all attached documents; it's a repository of all attached documents (mails, documents attached to a project, etc.)
diff --git a/addons/document_email/__openerp__.py b/addons/document_email/__openerp__.py
index 9ac6dc2fd84..0348665ffa0 100644
--- a/addons/document_email/__openerp__.py
+++ b/addons/document_email/__openerp__.py
@@ -28,7 +28,7 @@
"author" : "Tiny",
"description": """Email Integrated Document
* Email based Document submission
- * user based document subission
+ * user based document submission
""",
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
diff --git a/addons/document_ftp/__openerp__.py b/addons/document_ftp/__openerp__.py
index 09c1ca6a66b..798ecba72c3 100644
--- a/addons/document_ftp/__openerp__.py
+++ b/addons/document_ftp/__openerp__.py
@@ -27,7 +27,7 @@
'description': """This is a support FTP Interface with document management system.
With this module you would not only be able to access documents through OpenERP
but you would also be able to connect with them through the file system using the
- a FTP client.
+ FTP client.
""",
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
diff --git a/addons/document_ftp/test/document_ftp_test.yml b/addons/document_ftp/test/document_ftp_test.yml
index f7c4abb0cdf..b3ff2a89250 100644
--- a/addons/document_ftp/test/document_ftp_test.yml
+++ b/addons/document_ftp/test/document_ftp_test.yml
@@ -1,7 +1,7 @@
- |
- In order to test the document_ftp module in OpenERP, I will try different operation on the FTP interface, and check their impacts on OpenERP's documents and vice-versa.
+ In order to test the document_ftp module in OpenERP, I will try different operations on the FTP interface and check their impacts on OpenERP's documents and vice-versa.
-
- In order to test behaviour of resource Directory I will make one resource Directory "Labels" in OpenERP having type "Other Resources" and Directory mapped to object "Partner"
+ In order to test the behaviour of resource Directory, I will make one resource Directory "Labels" in OpenERP having type "Other Resources" and Directory mapped to object "Partner"
-
!record {model: 'document.directory', id: dir_label}:
name : "Labels"
@@ -25,20 +25,20 @@
storage_id : document.storage_default
type : directory
-
- I am create a one Document name "Document" and select "File" as its Directory,
+ I am create one Document name "Document" and select "File" as its Directory,
-
- When I am creating the record then "Resource Title" is filled automatic with "Document".
+ When I am creating the record, "Resource Title" is filled automatic with "Document".
-
!record {model: 'ir.attachment', id: document_1}:
name : "Document"
parent_id : directory_file
-
- In order to connect FTP server and set "File" path.
- I create one directory "New" in "File" directory from FTP and check its effect in OpenERP
+ In order to connect FTP server and set "File" path,
+ I create one directory "New" in "File" directory from FTP and check its effect in OpenERP.
-
Also Rename the directory name "New" to "New Directory".
-
- Remove directory "New Directory" and remove file "Document".
+ Remove directory "New Directory" and remove file "Document".
-
!python {model: ir.attachment}: |
from ftplib import FTP
@@ -64,10 +64,10 @@
In order to check directory created from FTP is working perfectly
-
Now I will test the same for Resource directory which is mapped with OpenERP object.
- When you open this directory from FTP clients, it displays each records of mapped resource object as directory.
+ When you open this directory from FTP clients, it displays each record of mapped resource object as directory.
-
Now I test FTP client and Open the "Labels" Directory to check Resource Directory in FTP.
- I can see that all Label of OpenERP are shown as children of "Labels" in FTP client as Directories
+ I can see that all Labels of OpenERP are shown as children of "Labels" in FTP client as Directories.
-
!python {model: ir.attachment}: |
from ftplib import FTP
diff --git a/addons/document_ftp/test/document_ftp_test2.yml b/addons/document_ftp/test/document_ftp_test2.yml
index 5a4df87fbe4..32434962ba2 100644
--- a/addons/document_ftp/test/document_ftp_test2.yml
+++ b/addons/document_ftp/test/document_ftp_test2.yml
@@ -48,7 +48,7 @@
ftp = te.get_ftp_folder(cr, uid, self, 'Documents')
assert te.get_ftp_fulldata(ftp, "test.txt") == 'abcd'
-
- I append the string 'defgh' into "test.txt"
+ I append the string 'defgh' to "test.txt"
-
!python {model: ir.attachment}: |
from document_ftp import test_easyftp as te
diff --git a/addons/document_ftp/test/document_ftp_test3.yml b/addons/document_ftp/test/document_ftp_test3.yml
index 2161c1421da..dbdab370b97 100644
--- a/addons/document_ftp/test/document_ftp_test3.yml
+++ b/addons/document_ftp/test/document_ftp_test3.yml
@@ -5,10 +5,10 @@
from document_ftp import test_easyftp as te
ftp = te.get_plain_ftp(timeout=1.0)
-
- I create in the server a folder called 'Äïêéìáóôéêüò ÖÜêåëëïò'
+ I create a folder called '������������ ��������' in the server.
-
!record {model: document.directory, id: dir_itests }:
- name: 'Äïêéìáóôéêüò ÖÜêåëëïò'
+ name: '������������ ��������'
parent_id: document.dir_root
-
And then I create another folder, under it, through FTP
@@ -16,67 +16,67 @@
!python {model: ir.attachment}: |
cr.commit()
from document_ftp import test_easyftp as te
- ftp = te.get_ftp_folder(cr, uid, self, 'Documents/Äïêéìáóôéêüò ÖÜêåëëïò')
- ftp.mkd("ÖÜêåëëïò áðü êÜôù")
+ ftp = te.get_ftp_folder(cr, uid, self, 'Documents/������������ ��������')
+ ftp.mkd("�������� ��� ����")
-
I check that this folder exists at the server
-
- !assert {model: document.directory, id: , search: "[('name','=','ÖÜêåëëïò áðü êÜôù')]" }:
+ !assert {model: document.directory, id: , search: "[('name','=','�������� ��� ����')]" }:
- parent_id != False
-
- I login with FTP and check that 'Äïêéìáóôéêüò ÖÜêåëëïò' is there
+ I login with FTP and check that '������������ ��������' is there
-
!python {model: ir.attachment}: |
from document_ftp import test_easyftp as te
- ftp = te.get_ftp_folder(cr, uid, self, 'Documents/Äïêéìáóôéêüò ÖÜêåëëïò/ÖÜêåëëïò áðü êÜôù')
+ ftp = te.get_ftp_folder(cr, uid, self, 'Documents/������������ ��������/�������� ��� ����')
-
- I create a file named 'ÄïêéìÞ' into that folder
+ I create a file named '������' into that folder
-
!python {model: ir.attachment}: |
from document_ftp import test_easyftp as te
from cStringIO import StringIO
- ftp = te.get_ftp_folder(cr, uid, self, 'Documents/Äïêéìáóôéêüò ÖÜêåëëïò/ÖÜêåëëïò áðü êÜôù')
- fdata = StringIO('êåßìåíï ìå utf-8')
- ftp.storbinary('STOR ÄïêéìÞ.txt', fdata)
+ ftp = te.get_ftp_folder(cr, uid, self, 'Documents/������������ ��������/�������� ��� ����')
+ fdata = StringIO('������� �� utf-8')
+ ftp.storbinary('STOR ������.txt', fdata)
-
- I remove the 'ÄïêéìÞ.txt' file
+ I remove the '������.txt' file
-
!python {model: ir.attachment}: |
from document_ftp import test_easyftp as te
from cStringIO import StringIO
- ftp = te.get_ftp_folder(cr, uid, self, 'Documents/Äïêéìáóôéêüò ÖÜêåëëïò/ÖÜêåëëïò áðü êÜôù')
- ftp.delete('ÄïêéìÞ.txt')
+ ftp = te.get_ftp_folder(cr, uid, self, 'Documents/������������ ��������/�������� ��� ����')
+ ftp.delete('������.txt')
-
- I rename 'ÖÜêåëëïò áðü êÜôù' into 'Üëëïò'
+ I rename '�������� ��� ����' into '�����'
-
!python {model: ir.attachment}: |
from document_ftp import test_easyftp as te
- ftp = te.get_ftp_folder(cr, uid, self, 'Documents/Äïêéìáóôéêüò ÖÜêåëëïò')
- ftp.rename("ÖÜêåëëïò áðü êÜôù", "Üëëïò")
+ ftp = te.get_ftp_folder(cr, uid, self, 'Documents/������������ ��������')
+ ftp.rename("�������� ��� ����", "�����")
-
- I place a file 'file Ö3' in 'Üëëïò'
+ I place a file 'file �3' in '�����'
-
!python {model: ir.attachment}: |
from document_ftp import test_easyftp as te
from cStringIO import StringIO
- ftp = te.get_ftp_folder(cr, uid, self, 'Documents/Äïêéìáóôéêüò ÖÜêåëëïò/Üëëïò')
- fdata = StringIO('êé Üëëï êåßìåíï')
- ftp.storbinary('STOR file Ö3.txt', fdata)
+ ftp = te.get_ftp_folder(cr, uid, self, 'Documents/������������ ��������/�����')
+ fdata = StringIO('�� ���� �������')
+ ftp.storbinary('STOR file �3.txt', fdata)
-
I rename the file into file+range(1..200) (large filename)
-
!python {model: ir.attachment}: |
from document_ftp import test_easyftp as te
from cStringIO import StringIO
- ftp = te.get_ftp_folder(cr, uid, self, 'Documents/Äïêéìáóôéêüò ÖÜêåëëïò/Üëëïò')
+ ftp = te.get_ftp_folder(cr, uid, self, 'Documents/������������ ��������/�����')
vuvuzela = 'b'+''.join('z' * 200)+'!'
- ftp.rename("file Ö3.txt", vuvuzela)
+ ftp.rename("file �3.txt", vuvuzela)
-
I delete the file with the large name
-
!python {model: ir.attachment}: |
from document_ftp import test_easyftp as te
from cStringIO import StringIO
- ftp = te.get_ftp_folder(cr, uid, self, 'Documents/Äïêéìáóôéêüò ÖÜêåëëïò/Üëëïò')
+ ftp = te.get_ftp_folder(cr, uid, self, 'Documents/������������ ��������/�����')
vuvuzela = 'b'+''.join('z' * 200)+'!'
ftp.delete(vuvuzela)
diff --git a/addons/document_ftp/test_easyftp.py b/addons/document_ftp/test_easyftp.py
index 8d75578718d..c5526371065 100644
--- a/addons/document_ftp/test_easyftp.py
+++ b/addons/document_ftp/test_easyftp.py
@@ -25,20 +25,19 @@
"""
from ftplib import FTP
-from tools.misc import detect_ip_addr
from tools import config
def get_plain_ftp(timeout=10.0):
ftp = FTP()
host = config.get('ftp_server_host', '127.0.0.1')
- port = config.get('ftp_server_port','8021')
- ftp.connect(host,port, timeout=timeout)
+ port = config.get('ftp_server_port', '8021')
+ ftp.connect(host, port, timeout=timeout)
return ftp
def get_ftp_login(cr, uid, ormobj):
ftp = get_plain_ftp()
user = ormobj.pool.get('res.users').read(cr, uid, uid)
- ftp.login(user.get('login',''),user.get('password',''))
+ ftp.login(user.get('login',''), user.get('password',''))
ftp.cwd("/" + cr.dbname)
return ftp
diff --git a/addons/document_ftp/wizard/ftp_browse_view.xml b/addons/document_ftp/wizard/ftp_browse_view.xml
index 44cedccfc3e..7a52c1fd291 100644
--- a/addons/document_ftp/wizard/ftp_browse_view.xml
+++ b/addons/document_ftp/wizard/ftp_browse_view.xml
@@ -4,7 +4,7 @@
Document FTP Browsedocument.ftp.browse
- form
+ form
-
diff --git a/addons/event/test/test_event.yml b/addons/event/test/test_event.yml
index 3440ef5d28d..da657640e93 100644
--- a/addons/event/test/test_event.yml
+++ b/addons/event/test/test_event.yml
@@ -15,7 +15,7 @@
!record {model: event.type, id: event_type_conference0}:
name: Conferences
- |
- I'm creating one Event "Conference on OpenERP Business" which will be started beetween 1 and 10 in this month.
+ I'm creating one Event "Conference on OpenERP Business" which will last from 1st of this month to 10th of this month.
-
!record {model: event.event, id: event_event_conference0}:
date_begin: 2010-08-01
@@ -30,9 +30,9 @@
!assert {model: event.event, id: event_event_conference0}:
- state == 'draft', "Event should be in draft by default when first time created"
- |
- Need Minimun 10 Registrations to confirm/start this Conference Event and does not allowed more than 100 Registrations.
+ Need Minimum 10 Registrations to confirm/start this Conference Event and does not allowed more than 100 Registrations.
- |
- So I set Minimun and Maximun Registrations limit.
+ So I set Minimum and Maximum Registrations limit.
-
!python {model: event.event}: |
self.write(cr, uid, [ref('event_event_conference0')], {'register_max': 100, 'register_min': 10})
@@ -49,7 +49,7 @@
- |
"Mark Johnson" want to subscribe/join into "Conference on OpenERP Business" with 10 tickets.
- |
- I'm creating new partner "Mark Johnson" with him email "info@mycustomer.com".
+ I'm creating new partner "Mark Johnson" with his email "info@mycustomer.com".
-
!record {model: res.partner, id: res_partner_markjohnson0}:
address:
@@ -79,24 +79,24 @@
unit_price: 68.0
nb_register: 10
- |
- I'm doing to Open that Registration.
+ I'm going to Open that Registration.
-
!python {model: event.registration}: |
self.check_confirm(cr, uid, [ref("event_registration_registrationjacot0")])
- |
- Check that Registration is in "Open" or not."
+ Check that Registration is in "Open" state or not.
-
!assert {model: event.registration, id: event_registration_registrationjacot0}:
- state == 'open', "Registration should be open here."
- |
- I'm again try to confirm that conference event.
+ I'm again trying to confirm that conference event.
-
!python {model: event.event}: |
self.button_confirm(cr, uid, [ref("event_event_conference0")])
- |
- Now Minimun requirement of Registration is fullfil. so Check that Event is "confirmed" or not.
+ Now Minimum requirement of Registration is fulfil. so Check that Event is "confirmed" or not.
-
!assert {model: event.event, id: event_event_conference0}:
- state == 'confirm', "Event should be confirmed here."
@@ -133,18 +133,18 @@
nb_register: 100
- |
- I'm doing to open "Mark Johnson" registration.
+ I'm going to open "Mark Johnson" registration.
-
!python {model: event.registration}: |
self.check_confirm(cr, uid, [ref("event_registration_registrationzen0")])
- |
- But conference event do not allowed more than 100 Registrations. so Check that registration is not "open".
+ But conference event does not allow more than 100 Registrations. so Check that registration is not in "open" state.
-
!assert {model: event.registration, id: event_registration_registrationzen0}:
- state == 'draft', "Registration should be in draft by default."
- |
- Now I'm modify number of tickets of "Mark Johnson"'s registration with 90 tickets.
+ Now I'm modifying number of tickets of "Mark Johnson"'s registration with 90 tickets.
-
!python {model: event.registration}: |
self.write(cr, uid, [ref("event_registration_registrationzen0")], {'nb_register': 90})
@@ -165,7 +165,7 @@
!python {model: event.event}: |
self.button_done(cr, uid, [ref("event_event_conference0")])
- |
- Check that conference "close" or not.
+ Check that conference is in "close" state or not.
-
!assert {model: event.event, id: event_event_conference0}:
- state == 'done', "Registration should be Closed here."
diff --git a/addons/hr/__openerp__.py b/addons/hr/__openerp__.py
index 70c91fbe362..0aa26987aa5 100755
--- a/addons/hr/__openerp__.py
+++ b/addons/hr/__openerp__.py
@@ -44,6 +44,7 @@
'hr_installer.xml',
'hr_data.xml',
'board_hr_view.xml',
+ 'board_hr_manager_view.xml',
],
'demo_xml': [
'hr_demo.xml',
@@ -54,4 +55,4 @@
'active': False,
'certificate': '0086710558965',
}
-# 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/hr/board_hr_manager_view.xml b/addons/hr/board_hr_manager_view.xml
new file mode 100644
index 00000000000..3cfaf165840
--- /dev/null
+++ b/addons/hr/board_hr_manager_view.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+ board.hr.manager.form
+ board.board
+ form
+
+
@@ -84,7 +85,7 @@
-
+
@@ -125,7 +126,7 @@
hr_evaluation.plan.phasetree
-
+
@@ -184,7 +185,7 @@
-
@@ -204,7 +205,7 @@
-
+
@@ -230,40 +231,40 @@
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
- Evaluation
+ Evaluationshr_evaluation.evaluationformtree,form,graph
- Each employee can be assigned to an evaluation plan. These plans define the frequency and the way you manage your periodic personnal evalautions. You will be able to define steps and attach interview forms to each step. OpenERP manages all kind of evaluations: bottom-up, top-down, self evaluation and final evaluation by the manager.
+ Each employee can be assigned to an evaluation plan. These plans define the frequency and the way you manage your periodic personnal evaluation. You will be able to define steps and attach interview forms to each step. OpenERP manages all kind of evaluations: bottom-up, top-down, self evaluation and final evaluation by the manager.
-
@@ -299,7 +300,7 @@
tree
-
+
@@ -327,26 +328,57 @@
-
+
+
+
+ Interview Request
+ hr.evaluation.interview
+ calendar
+
+
+
+
+
+
+
Interview Requestshr.evaluation.interviewform
- tree,form
+ [('is_evaluation' ,'=', True)]{"search_default_todo":1,"search_default_user_id":uid}Interview Requests are generated automatically by OpenERP according to employees evaluation plan. Each user receives automatic emails and requests to perform evaluation of their collegues periodically.
+
+
+ tree
+
+
+
+
+
+ form
+
+
+
+
+
+ calendar
+
+
+
+
+
+
+
@@ -44,15 +47,13 @@
-
-
-
+
+
+
-
-
@@ -62,24 +63,25 @@
-
-
-
+
+
+
+
-
-
-
-
-
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/hr_evaluation/security/ir.model.access.csv b/addons/hr_evaluation/security/ir.model.access.csv
index 181e412ce69..7c57d67d1cd 100644
--- a/addons/hr_evaluation/security/ir.model.access.csv
+++ b/addons/hr_evaluation/security/ir.model.access.csv
@@ -2,9 +2,9 @@
"access_hr_evaluation_evaluation_user","hr_evaluation.evaluation.user","model_hr_evaluation_evaluation","base.group_hr_user",1,1,1,1
"access_hr_evaluation_evaluation_manager","hr_evaluation.evaluation.manager","model_hr_evaluation_evaluation","base.group_hr_manager",1,1,1,1
"access_hr_evaluation_plan_user","hr_evaluation.plan.user","model_hr_evaluation_evaluation","base.group_hr_user",1,0,0,0
-"access_hr_evaluation_plan_manager","hr_evaluation.plan.manager","model_hr_evaluation_plan","base.group_hr_manager",1,0,0,0
+"access_hr_evaluation_plan_manager","hr_evaluation.plan.manager","model_hr_evaluation_plan","base.group_hr_manager",1,1,1,1
"access_hr_evaluation_plan_phase_user","hr_evaluation.plan.phase.user","model_hr_evaluation_plan_phase","base.group_hr_user",1,0,0,0
-"access_hr_evaluation_plan_phase_manager","hr_evaluation.plan.phase.manager","model_hr_evaluation_plan_phase","base.group_hr_manager",1,0,0,0
+"access_hr_evaluation_plan_phase_manager","hr_evaluation.plan.phase.manager","model_hr_evaluation_plan_phase","base.group_hr_manager",1,1,1,1
"access_hr_evaluation_interview_user","hr.evaluation.interview.user","model_hr_evaluation_interview","base.group_hr_user",1,1,1,1
"access_hr_evaluation_interview_manager","hr.evaluation.interview.manager","model_hr_evaluation_interview","base.group_hr_manager",1,1,1,1
"access_hr_evaluation_report","hr.evaluation.report","model_hr_evaluation_report","base.group_hr_manager",1,1,1,1
@@ -12,6 +12,10 @@
"access_hr_evaluation_plan_phase_system","hr_evaluation.plan.phase.system","model_hr_evaluation_plan_phase","base.group_system",1,1,1,1
"access_hr_evaluation_evaluation_system","hr_evaluation.evaluation.system","model_hr_evaluation_evaluation","base.group_system",1,0,0,0
"access_hr_evaluation_interview_system","hr.evaluation.interview.system","model_hr_evaluation_interview","base.group_system",1,0,0,0
+"access_hr_evaluation_evaluation_employee","hr_evaluation.evaluation.employee","model_hr_evaluation_evaluation","base.group_user",1,0,0,0
+"access_hr_evaluation_interview_employee","hr.evaluation.interview.employee","model_hr_evaluation_interview","base.group_user",1,0,0,0
+"access_hr_evaluation_user","hr_evaluation.user","model_hr_evaluation_plan","base.group_hr_user",1,1,1,1
+"access_hr_evaluation_employee","hr_evaluation.employee","model_hr_evaluation_plan","base.group_user",1,0,0,0
"access_survey_type_hr_manager","survey.type","survey.model_survey_type","base.group_hr_manager",1,1,1,1
"access_survey_hr_manager","survey.hr.manager","survey.model_survey","base.group_hr_manager",1,1,1,1
"access_survey_history_manager","survey.history","survey.model_survey_history","base.group_hr_manager",1,1,1,1
@@ -28,4 +32,11 @@
"access_survey_answer_hr_user","survey.answer.hr.user","survey.model_survey_answer","base.group_hr_user",1,1,1,0
"access_survey_response_answer_hr_user","survey.response.answer.hr.user","survey.model_survey_response_answer","base.group_hr_user",1,1,1,0
"access_survey_type_hr_user","survey.type.hr.user","survey.model_survey_type","base.group_hr_user",1,1,1,0
-"access_survey_question_hr_user","survey.question.hr.user","survey.model_survey_question","base.group_hr_user",1,1,1,0
\ No newline at end of file
+"access_survey_question_hr_user","survey.question.hr.user","survey.model_survey_question","base.group_hr_user",1,1,1,0
+"access_survey_page_hr_user","survey.page.hr.user","survey.model_survey_page","base.group_hr_user",1,1,1,1
+"access_survey_response_hr_user","survey.response.hr.user","survey.model_survey_response","base.group_hr_user",1,1,1,0
+"access_survey_history_hr_user","survey.history.hr.user","survey.model_survey_history","base.group_hr_user",1,1,1,0
+"access_survey_request_hr_user","survey.request.hr.user","survey.model_survey_request","base.group_hr_user",1,1,1,0
+"access_survey_question_column_heading_hr_user","survey.question.column.heading.hr.user","survey.model_survey_question_column_heading","base.group_hr_user",1,0,0,0
+"access_survey_response_line_hr_user","survey.response.line.hr.user","survey.model_survey_response_line","base.group_hr_user",1,1,1,0
+"access_survey_tbl_column_heading_hr_user","survey.tbl.column.heading.hr.user","survey.model_survey_tbl_column_heading","base.group_hr_user",1,1,1,0
diff --git a/addons/hr_evaluation/test/test_hr_evaluation.yml b/addons/hr_evaluation/test/test_hr_evaluation.yml
index 1d2acbcbd49..7797ce417d2 100644
--- a/addons/hr_evaluation/test/test_hr_evaluation.yml
+++ b/addons/hr_evaluation/test/test_hr_evaluation.yml
@@ -125,7 +125,7 @@
self.button_plan_in_progress(cr, uid, [ref('hr_evaluation_evaluation_0')])
-
- I close this servey request by giving answer of survey question.
+ I close this survey request by giving answer of survey question.
-
!python {model: hr.evaluation.interview}: |
self.survey_req_done(cr, uid, [ref('hr_evaluation_interview_0')])
diff --git a/addons/hr_evaluation/wizard/hr_evaluation_mail.py b/addons/hr_evaluation/wizard/hr_evaluation_mail.py
index 75aecf6a9f1..576c782bfd8 100644
--- a/addons/hr_evaluation/wizard/hr_evaluation_mail.py
+++ b/addons/hr_evaluation/wizard/hr_evaluation_mail.py
@@ -25,7 +25,7 @@ class hr_evaluation_reminder(osv.osv_memory):
_name = "hr.evaluation.reminder"
_description = "Sends Reminders to employess to fill the evaluations"
_columns = {
- 'evaluation_id': fields.many2one('hr_evaluation.evaluation', 'Evaluations', required=True)
+ 'evaluation_id': fields.many2one('hr.evaluation.interview', 'Interview', required=True)
}
def send_mail(self, cr, uid, ids, context=None):
diff --git a/addons/hr_expense/__openerp__.py b/addons/hr_expense/__openerp__.py
index fe06b0110c2..c9df8587153 100644
--- a/addons/hr_expense/__openerp__.py
+++ b/addons/hr_expense/__openerp__.py
@@ -51,6 +51,7 @@
'process/hr_expense_process.xml',
'report/hr_expense_report_view.xml',
'board_hr_expense_view.xml',
+ 'board_hr_expense_manager_view.xml'
],
'demo_xml': [
'hr_expense_demo.xml',
diff --git a/addons/hr_expense/board_hr_expense_manager_view.xml b/addons/hr_expense/board_hr_expense_manager_view.xml
new file mode 100644
index 00000000000..9063ac32458
--- /dev/null
+++ b/addons/hr_expense/board_hr_expense_manager_view.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+ All Employee Expenses
+ hr.expense.expense
+ form
+ [('state','in',('confirm', 'accepted'))]
+
+
+
+
+ board.hr.manager.expense.form
+ board.board
+
+ form
+
+
+
+
+
+
+
+
+
diff --git a/addons/hr_expense/board_hr_expense_view.xml b/addons/hr_expense/board_hr_expense_view.xml
index 4b06cd758b1..69dbad767d9 100644
--- a/addons/hr_expense/board_hr_expense_view.xml
+++ b/addons/hr_expense/board_hr_expense_view.xml
@@ -13,7 +13,7 @@
My Expenseshr.expense.expenseform
- [('state','in',('draft', 'confirm')),('user_id','=',uid)]
+ [('state','in',('confirm', 'accepted')),('user_id','=',uid)]
diff --git a/addons/hr_expense/hr_expense.py b/addons/hr_expense/hr_expense.py
index 96fdcb5250a..4060a8ec566 100644
--- a/addons/hr_expense/hr_expense.py
+++ b/addons/hr_expense/hr_expense.py
@@ -61,12 +61,12 @@ class hr_expense_expense(osv.osv):
_name = "hr.expense.expense"
_description = "Expense"
_columns = {
- 'name': fields.char('Expense Sheet', size=128, required=True),
+ 'name': fields.char('Description', size=128, required=True),
'id': fields.integer('Sheet ID', readonly=True),
'ref': fields.char('Reference', size=32),
'date': fields.date('Date'),
'journal_id': fields.many2one('account.journal', 'Force Journal', help = "The journal used when the expense is invoiced"),
- 'employee_id': fields.many2one('hr.employee', "Employee's Name", required=True),
+ 'employee_id': fields.many2one('hr.employee', "Employee", required=True),
'user_id': fields.many2one('res.users', 'User', required=True),
'date_confirm': fields.date('Confirmation Date', help = "Date of the confirmation of the sheet expense. It's filled when the button Confirm is pressed."),
'date_valid': fields.date('Validation Date', help = "Date of the acceptation of the sheet expense. It's filled when the button Accept is pressed."),
@@ -81,11 +81,11 @@ class hr_expense_expense(osv.osv):
'company_id': fields.many2one('res.company', 'Company', required=True),
'state': fields.selection([
('draft', 'Draft'),
- ('confirm', 'Waiting confirmation'),
- ('accepted', 'Accepted'),
+ ('confirm', 'Waiting Approval'),
+ ('accepted', 'Approved'),
('invoiced', 'Invoiced'),
('paid', 'Reimbursed'),
- ('cancelled', 'Cancelled')],
+ ('cancelled', 'Refused')],
'State', readonly=True, help='When the expense request is created the state is \'Draft\'.\n It is confirmed by the user and request is sent to admin, the state is \'Waiting Confirmation\'.\
\nIf the admin accepts it, the state is \'Accepted\'.\n If an invoice is made for the expense request, the state is \'Invoiced\'.\n If the expense is paid to user, the state is \'Reimbursed\'.'),
}
diff --git a/addons/hr_expense/hr_expense_demo.xml b/addons/hr_expense/hr_expense_demo.xml
index da348b02ab4..c3fa9e90c67 100644
--- a/addons/hr_expense/hr_expense_demo.xml
+++ b/addons/hr_expense/hr_expense_demo.xml
@@ -104,6 +104,17 @@
-
+
+ Employee Expense
+
+ [('employee_id.user_id','=',user.id)]
+
+
+
+ Manager Expense
+
+ ['|',('employee_id.user_id','=',user.id),('employee_id.parent_id.user_id','=',user.id )]
+
+
diff --git a/addons/hr_expense/hr_expense_view.xml b/addons/hr_expense/hr_expense_view.xml
index 4d25c01e773..79c0d5513f0 100644
--- a/addons/hr_expense/hr_expense_view.xml
+++ b/addons/hr_expense/hr_expense_view.xml
@@ -27,12 +27,12 @@
tree
-
+
+
-
@@ -77,7 +77,7 @@
-
+
@@ -98,10 +98,10 @@
-
+
+
-
-
+
@@ -134,14 +134,16 @@
-
-
+
-
+
@@ -149,8 +151,9 @@
+
+
-
@@ -162,7 +165,7 @@
Expenseshr.expense.expenseform
- {"search_default_user_id":uid}
+ {"search_default_user_id":uid,'search_default_this':1}The OpenERP expenses management module allows you to track the full flow. Every month, the employees record their expenses. At the end of the month, their managers validates the expenses sheets which creates costs on projects/analytic accounts. The accountant validates the proposed entries and the employee can be reimbursed. You can also reinvoice the customer at the end of the flow.
diff --git a/addons/hr_expense/report/expense.rml b/addons/hr_expense/report/expense.rml
index 4ae45ad0aa2..fa9e78c68cd 100644
--- a/addons/hr_expense/report/expense.rml
+++ b/addons/hr_expense/report/expense.rml
@@ -181,7 +181,7 @@
+
+
-
diff --git a/addons/lunch/test/test_lunch.yml b/addons/lunch/test/test_lunch.yml
index 6af4113f153..3183764d927 100644
--- a/addons/lunch/test/test_lunch.yml
+++ b/addons/lunch/test/test_lunch.yml
@@ -1,23 +1,23 @@
- |
- In order to test the Lunch module in OpenERP,
+ In order to test the Lunch module in OpenERP,
I will create one lunch order and then check the effect on cashboxes and cashmoves
-
+
- |
Given that I have a category of lunch products "Burger".
--
+-
!record {model: lunch.category, id: lunch_category_burger0}:
name: Burger
- |
Given that I have a product "Club1" in this category with a price of "2.75".
--
+-
!record {model: lunch.product, id: lunch_product_club1}:
category_id: lunch_category_burger0
name: Club1
- price: 2.75
+ price: 2.75
- |
Given that I have a cashbox "Employee Cashbox"
--
+-
!record {model: lunch.cashbox, id: lunch_cashbox_cashbox0}:
manager: base.user_root
name: Employee Cashbox
@@ -25,87 +25,87 @@
I create a lunch order "LU001" for the "Club1" product
- |
When I select the product "club1", the price of 2.75 is automatically proposed
--
+-
!record {model: lunch.order, id: lunch_order_0}:
date: '2010-04-19'
product: 'lunch_product_club1'
price: 2.75
user_id: base.user_root
-
+
- |
I check that lunch order is on draft state after having created it.
-
!assert {model: lunch.order, id: lunch_order_0}:
- - state == 'draft'
+ - state == 'draft'
- |
I confirm the order "LU001" using the "Confirm Order" wizard.
--
+-
!record {model: lunch.order.confirm, id: lunch_order_confirm_0}:
confirm_cashbox: 'lunch_cashbox_cashbox0'
-
- I click on "Confirm Order" button of this wizard.
+ I click on "Confirm Order" button of this wizard.
-
!python {model: lunch.order.confirm}: |
- self.confirm(cr, uid, [ref('lunch_order_confirm_0')], {'active_ids': [ref('lunch_order_0')]})
-
+ self.confirm(cr, uid, [ref('lunch_order_confirm_0')], {'active_ids': [ref('lunch_order_0')]})
+
- |
I check that the Cash Moves have been generated with the right box
name
-
- !assert {model: lunch.order, id: lunch_order_0}:
+ !assert {model: lunch.order, id: lunch_order_0}:
- cashmove.id != False
-
+
- |
I check that the Total on the "Employee Cashbox" is -2.75
-
+
-
!assert {model: lunch.cashbox, id: lunch_cashbox_cashbox0}:
- sum_remain == -2.75
-
+
- |
I create a new lunch order "LU002" for the "Club1" product, at another date.
--
+-
!record {model: lunch.order, id: lunch_order_1}:
date: '2010-04-22'
product: 'lunch_product_club1'
price: 2.75
user_id: base.user_root
-
+
- |
I confirm this order.open wizard and select "Employee Cashbox".
--
+-
!record {model: lunch.order.confirm, id: lunch_order_confirm_1}:
confirm_cashbox: 'lunch_cashbox_cashbox0'
- |
- Now I click on "Confirm Order" button of this wizard.
+ Now I click on "Confirm Order" button of this wizard.
-
!python {model: lunch.order.confirm}: |
self.confirm(cr, uid, [ref('lunch_order_confirm_1')], {'active_ids': [ref('lunch_order_1')]})
-
+
- |
I check that the Total on the "Employee Cashbox" is -5.50
-
!assert {model: lunch.cashbox, id: lunch_cashbox_cashbox0}:
- - sum_remain == -5.50
+ - sum_remain == -5.50
- |
I cancel the order "LU002"
--
+-
!record {model: lunch.order.cancel, id: lunch_order_cancel_0}:
{}
- |
- I click on "Yes" button of this wizard for cancel order.
-
+ I click on "Yes" button of this wizard for cancel order.
+
-
!python {model: lunch.order.cancel}: |
self.cancel(cr, uid, [ref('lunch_order_cancel_0')], {'active_ids': [ref('lunch_order_1')]})
-
+
- |
I test that the Cash Moves record have been removed for the order LU002.
-
- !assert {model: lunch.order, id: lunch_order_1}:
+ !assert {model: lunch.order, id: lunch_order_1}:
- cashmove.id == False
-
+
- |
I check that the Total on the "Employee Cashbox" is -2.75
-
@@ -113,7 +113,7 @@
- sum_remain == -2.75
- |
I reset the "Employee Cashbox" to zero using the "Set CashBox to Zero" wizard.
--
+-
!record {model: lunch.cashbox.clean, id: lunch_cashbox_clean_0}:
{}
-
@@ -121,10 +121,10 @@
-
!python {model: lunch.cashbox.clean, id: lunch_cashbox_clean_0}: |
self.set_to_zero(cr, uid, [ref('lunch_cashbox_clean_0')], {'active_ids': [ref('lunch_cashbox_cashbox0')]})
-
+
- |
- I check that the Total on the "Employee Cashbox" is 0.0
+ I check that the Total on the "Employee Cashbox" is -5.50
-
!assert {model: lunch.cashbox, id: lunch_cashbox_cashbox0}:
- sum_remain == 0.00
-
+
diff --git a/addons/mrp/installer.py b/addons/mrp/installer.py
index eeb00ece494..407d401e463 100644
--- a/addons/mrp/installer.py
+++ b/addons/mrp/installer.py
@@ -28,7 +28,7 @@ class mrp_installer(osv.osv_memory):
# Manufacturing Resource Planning
'stock_location': fields.boolean('Advanced Routes',
help="Manages product routes and paths within and between "
- "locations (e.g. warehouses)"),
+ "locations (e.g. warehouses)."),
'mrp_jit': fields.boolean('Just In Time Scheduling',
help="Enables Just In Time computation of procurement orders."
"\n\nWhile it's more resource intensive than the default "
@@ -37,7 +37,7 @@ class mrp_installer(osv.osv_memory):
"procurement scheduler manually."),
'mrp_operations': fields.boolean('Manufacturing Operations',
help="Enhances production orders with readiness states as well "
- "as the date of start and end of execution of the order."),
+ "as the start date and end date of execution of the order."),
'mrp_subproduct': fields.boolean('MRP Subproducts',
help="Enables multiple product output from a single production "
"order: without this, a production order can have only one "
diff --git a/addons/mrp_repair/mrp_repair.py b/addons/mrp_repair/mrp_repair.py
index 7fa3d29ebc9..13cc91b8338 100644
--- a/addons/mrp_repair/mrp_repair.py
+++ b/addons/mrp_repair/mrp_repair.py
@@ -272,7 +272,6 @@ class mrp_repair(osv.osv):
@param product_id: Product id from current record.
@return: Dictionary of values.
"""
- prodlot_obj = self.pool.get('stock.production.lot')
move_obj = self.pool.get('stock.move')
data = {}
data['value'] = {
@@ -429,7 +428,7 @@ class mrp_repair(osv.osv):
raise osv.except_osv(_('Warning !'), _('No product defined on Fees!'))
if fee.product_id.property_account_income:
- account_id = fee.product_id.property_account_income
+ account_id = fee.product_id.property_account_income.id
elif fee.product_id.categ_id.property_account_income_categ:
account_id = fee.product_id.categ_id.property_account_income_categ.id
else:
@@ -503,7 +502,7 @@ class mrp_repair(osv.osv):
return True
def wkf_repair_done(self, cr, uid, ids, *args):
- res = self.action_repair_done(cr, uid, ids)
+ self.action_repair_done(cr, uid, ids)
return True
def action_repair_done(self, cr, uid, ids, context=None):
diff --git a/addons/mrp_repair/report/order.py b/addons/mrp_repair/report/order.py
index 3257ba3df7a..3d6f9200dd8 100644
--- a/addons/mrp_repair/report/order.py
+++ b/addons/mrp_repair/report/order.py
@@ -21,8 +21,6 @@
import time
from report import report_sxw
-from osv import osv
-import pooler
class order(report_sxw.rml_parse):
def __init__(self, cr, uid, name, context):
diff --git a/addons/point_of_sale/report/account_statement.rml b/addons/point_of_sale/report/account_statement.rml
index 180e9d6a97b..e4c3b99b6ee 100644
--- a/addons/point_of_sale/report/account_statement.rml
+++ b/addons/point_of_sale/report/account_statement.rml
@@ -1,6 +1,6 @@
-
+
@@ -10,111 +10,105 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
+
-
-
+
-
-
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
@@ -124,8 +118,8 @@
-
-
+
+
@@ -139,34 +133,27 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
- [[ repeatIn(objects,'statement') ]]
-
+
+
+
+
+
+
+ Statement
+
+
+
+
+
+
+
+ [[o.state=='cancel' and o.statement_ids and '-' or '']][['%.f' % line.qty ]]
+
+
+ [[o.state=='cancel' and o.statement_ids and '-' or '']][[ '%.2f' % net(line.id) ]] [[company.currency_id.symbol]] [[ line and line.discount == 0.0 and removeParentNode('font') ]] ([[ '%.2f' % line.discount ]]%) [[company.currency_id.symbol]]
+
+
+
+
+
+
+ Taxes :
+
+
+ [[o.state=='cancel' and o.statement_ids and '-' or '']][['%.2f' % o.amount_tax]] [[company.currency_id.symbol]]
+
+
+
+
+
+
+ Total :
+
+
+ [[o.state=='cancel' and o.statement_ids and '-' or '']][['%.2f' % o.amount_total]] [[company.currency_id.symbol]]
+
- [[o.state=='cancel' and o.statement_ids and '-' or '']][['%.f' % line.qty ]]
-
-
-
- [[o.state=='cancel' and o.statement_ids and '-' or '']][[ '%.2f' % net(line.id) ]] [[ line and line.discount == 0.0 and removeParentNode('font') ]] ([[ '%.2f' % line.discount ]]%)
-
-
-
-
-
-
- Taxes :
-
-
- [[o.state=='cancel' and o.statement_ids and '-' or '']][['%.2f' % o.amount_tax ]]
-
-
-
-
-
-
-
-
- Total :
-
-
- [[o.state=='cancel' and o.statement_ids and '-' or '']][['%.2f' % o.amount_total ]]
-
+
+
+
+
-
+
\ No newline at end of file
diff --git a/addons/point_of_sale/wizard/pos_return.py b/addons/point_of_sale/wizard/pos_return.py
index 79b6da85592..151b724c4ba 100644
--- a/addons/point_of_sale/wizard/pos_return.py
+++ b/addons/point_of_sale/wizard/pos_return.py
@@ -239,7 +239,6 @@ class add_product(osv.osv_memory):
data = data and data[0] or False
if active_id:
order_obj = self.pool.get('pos.order')
- lines_obj = self.pool.get('pos.order.line')
picking_obj = self.pool.get('stock.picking')
stock_move_obj = self.pool.get('stock.move')
property_obj= self.pool.get("ir.property")
diff --git a/addons/process/process_view.xml b/addons/process/process_view.xml
index b743c82f84f..f33af42c533 100644
--- a/addons/process/process_view.xml
+++ b/addons/process/process_view.xml
@@ -35,7 +35,7 @@
-
+
@@ -74,14 +74,14 @@
-
+
-
+
@@ -114,7 +114,7 @@
-
+
@@ -160,7 +160,7 @@
-
+
@@ -199,7 +199,7 @@
-
+
@@ -220,8 +220,8 @@
-
-
+
+
@@ -261,9 +261,8 @@
form
-
+
-
@@ -308,11 +307,13 @@
+
diff --git a/addons/product/report/product_pricelist.py b/addons/product/report/product_pricelist.py
index ce6cdb2d864..613de646fe0 100644
--- a/addons/product/report/product_pricelist.py
+++ b/addons/product/report/product_pricelist.py
@@ -87,9 +87,12 @@ class product_pricelist(report_sxw.rml_parse):
pro_ids.append(product.id)
if product.categ_id.id not in cat_ids:
cat_ids.append(product.categ_id.id)
- cats = pool.get('product.category').read(self.cr, self.uid, cat_ids, ['name'])
+
+ cats = pool.get('product.category').name_get(self.cr, self.uid, cat_ids)
+ if not cats:
+ return res
for cat in cats:
- product_ids=pool.get('product.product').search(self.cr, self.uid, [('id','in',pro_ids),('categ_id','=',cat['id'])])
+ product_ids=pool.get('product.product').search(self.cr, self.uid, [('id','in',pro_ids),('categ_id','=',cat[0])])
products = []
for product in pool.get('product.product').read(self.cr, self.uid, product_ids, ['name','code']):
val = {
@@ -105,7 +108,7 @@ class product_pricelist(report_sxw.rml_parse):
val['qty'+str(i)]=self._get_price(self.pricelist, product['id'], qty)
i += 1
products.append(val)
- res.append({'name':cat['name'],'products': products})
+ res.append({'name':cat[1],'products': products})
return res
def _get_price(self,pricelist_id, product_id,qty):
diff --git a/addons/product/report/product_pricelist.rml b/addons/product/report/product_pricelist.rml
index fe3fad5ed62..5d3a39e9144 100644
--- a/addons/product/report/product_pricelist.rml
+++ b/addons/product/report/product_pricelist.rml
@@ -191,7 +191,7 @@
[[repeatIn(get_categories(objects,data['form']), 'c')]]
-
+
[[ c['name'] ]]
diff --git a/addons/product/security/ir.model.access.csv b/addons/product/security/ir.model.access.csv
index 1e1572a3c0a..7b8da0dd675 100644
--- a/addons/product/security/ir.model.access.csv
+++ b/addons/product/security/ir.model.access.csv
@@ -40,3 +40,4 @@
"access_product_ul_system","product.ul system","model_product_ul","base.group_system",1,1,1,1
"access_product_product_system","product.product system","model_product_product","base.group_system",1,0,0,0
"access_product_category_system","product.category.system","model_product_category","base.group_system",1,1,1,1
+"access_product_product_employee","product.product employee","model_product_product","base.group_user",1,0,0,0
diff --git a/addons/product/wizard/product_price.py b/addons/product/wizard/product_price.py
index 4681f28d71b..853935acf6e 100644
--- a/addons/product/wizard/product_price.py
+++ b/addons/product/wizard/product_price.py
@@ -51,7 +51,6 @@ class product_price_list(osv.osv_memory):
datas = {'ids': context.get('active_ids', [])}
res = self.read(cr, uid, ids, ['price_list','qty1', 'qty2','qty3','qty4','qty5'], context)
res = res and res[0] or {}
- price_dict = self.pool.get('product.pricelist').price_get(cr, uid, [res['price_list']], 1, 1.0)
datas['form'] = res
return {
'type': 'ir.actions.report.xml',
diff --git a/addons/profile_tools/installer.py b/addons/profile_tools/installer.py
index 1e2ff655353..06be50a903f 100644
--- a/addons/profile_tools/installer.py
+++ b/addons/profile_tools/installer.py
@@ -25,9 +25,9 @@ class misc_tools_installer(osv.osv_memory):
_inherit = 'res.config.installer'
_columns = {
- 'lunch':fields.boolean('Lunch',help='Helps to manage Lunch Orders'),
- 'subscription':fields.boolean('Recurring Documents',help='Helps to add subscription on documents'),
- 'survey':fields.boolean('Survey',help='Manages Custom Surveys'),
+ 'lunch':fields.boolean('Lunch',help='Helps to manage Lunch Orders.'),
+ 'subscription':fields.boolean('Recurring Documents',help='Helps to add subscription on documents.'),
+ 'survey':fields.boolean('Survey',help='Manages Custom Surveys.'),
'idea':fields.boolean('Idea',help='Manages ideas and votes'),
'audittrail':fields.boolean('Audit Trail',help="Lets you to track user's operations on specific Objects."),
}
diff --git a/addons/project/installer.py b/addons/project/installer.py
index ef2c2b5e8c8..4662ebeda5d 100644
--- a/addons/project/installer.py
+++ b/addons/project/installer.py
@@ -31,32 +31,29 @@ class project_installer(osv.osv_memory):
'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',
- help=""),
'hr_timesheet_sheet': fields.boolean('Timesheets',
help="Tracks and helps employees encode and validate timesheets "
- "and attendance."),
+ "and attendances."),
'hr_timesheet_invoice': fields.boolean('Invoice Based on Hours',
- help="Helps generate invoice based on human resources "
+ help="Helps generate invoices based on human resources "
"costs and general expenses."),
'account_budget': fields.boolean('Budgets',
help="Helps accountants manage analytic and crossover budgets."),
'project_messages': fields.boolean('Project Messages',
help="Lets employees send messages to other members of the "
"projects they're working on."),
- 'project_crm': fields.boolean('Issues Tracker',
+ 'project_issue': fields.boolean('Issues Tracker',
help="Automatically synchronizes project tasks and crm cases."),
# Methodologies
'project_scrum': fields.boolean('SCRUM',
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 "
- "project management."),
+ help="GTD is a methodology to efficiently organise yourself and your tasks. This module fully integrates GTD principle with OpenERP's project management."),
}
_defaults={
- 'project_crm': True,
+ 'project_issue': True,
}
project_installer()
diff --git a/addons/project/project.py b/addons/project/project.py
index 6959a19fd03..da3fef05f66 100644
--- a/addons/project/project.py
+++ b/addons/project/project.py
@@ -28,7 +28,6 @@ from itertools import groupby
from tools.misc import flatten
from tools.translate import _
from osv import fields, osv
-from tools import email_send as email
class project_task_type(osv.osv):
@@ -245,13 +244,12 @@ class project(osv.osv):
if context is None:
context = {}
- task_obj = self.pool.get('project.task')
proj = self.browse(cr, uid, id, context=context)
default = default or {}
context['active_test'] = False
default['state'] = 'open'
if not default.get('name', False):
- default['name'] = proj.name+_(' (copy)')
+ default['name'] = proj.name + _(' (copy)')
res = super(project, self).copy(cr, uid, id, default, context)
return res
@@ -261,7 +259,6 @@ class project(osv.osv):
context = {}
project_obj = self.pool.get('project.project')
data_obj = self.pool.get('ir.model.data')
- task_obj = self.pool.get('project.task')
result = []
for proj in self.browse(cr, uid, ids, context=context):
parent_id = context.get('parent_id', False)
@@ -279,8 +276,7 @@ class project(osv.osv):
'date':new_date_end,
'parent_id':parent_id}, context=context)
result.append(new_id)
- cr.execute('select id from project_task where project_id=%s', (proj.id,))
- res = cr.fetchall()
+
child_ids = self.search(cr, uid, [('parent_id','=', proj.analytic_account_id.id)], context=context)
parent_id = self.read(cr, uid, new_id, ['analytic_account_id'])['analytic_account_id'][0]
if child_ids:
@@ -320,7 +316,7 @@ class project(osv.osv):
if child_ids:
self.setActive(cr, uid, child_ids, value, context=None)
return True
-
+
project()
class users(osv.osv):
@@ -393,6 +389,8 @@ class task(osv.osv):
if not default.get('remaining_hours', False):
default['remaining_hours'] = float(self.read(cr, uid, id, ['planned_hours'])['planned_hours'])
default['active'] = True
+ if not default.get('name', False):
+ default['name'] = self.browse(cr, uid, id, context=context).name + _(' (copy)')
return super(task, self).copy_data(cr, uid, id, default, context)
def _check_dates(self, cr, uid, ids, context=None):
@@ -401,7 +399,7 @@ class task(osv.osv):
if task['date_start'] > task['date_end']:
return False
return True
-
+
def _is_template(self, cr, uid, ids, field_name, arg, context=None):
res = {}
for task in self.browse(cr, uid, ids, context=context):
@@ -415,7 +413,7 @@ class task(osv.osv):
'active': fields.function(_is_template, method=True, store=True, string='Not a Template Task', type='boolean', help="This field is computed automatically and have the same behavior than the boolean 'active' field: if the task is linked to a template or unactivated project, it will be hidden unless specifically asked."),
'name': fields.char('Task Summary', size=128, required=True),
'description': fields.text('Description'),
- 'priority' : fields.selection([('4','Very Low'), ('3','Low'), ('2','Medium'), ('1','Urgent'), ('0','Very urgent')], 'Importance'),
+ 'priority' : fields.selection([('4','Very Low'), ('3','Low'), ('2','Medium'), ('1','Urgent'), ('0','Very urgent')], 'Priority'),
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of tasks."),
'type_id': 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,
@@ -425,8 +423,7 @@ class task(osv.osv):
'date_start': fields.datetime('Starting Date'),
'date_end': fields.datetime('Ending Date'),
'date_deadline': fields.date('Deadline'),
- 'project_id': fields.many2one('project.project', 'Project', ondelete='cascade',
- help="If you have [?] in the project name, it means there are no analytic account linked to this project."),
+ 'project_id': fields.many2one('project.project', 'Project', ondelete='cascade'),
'parent_ids': fields.many2many('project.task', 'project_task_parent_rel', 'task_id', 'parent_id', 'Parent Tasks'),
'child_ids': fields.many2many('project.task', 'project_task_parent_rel', 'parent_id', 'task_id', 'Delegated Tasks'),
'notes': fields.text('Notes'),
@@ -457,15 +454,15 @@ class task(osv.osv):
}
_order = "sequence, priority, date_start, id"
-
+
def _check_recursion(self, cr, uid, ids):
obj_task = self.browse(cr, uid, ids[0])
parent_ids = [x.id for x in obj_task.parent_ids]
children_ids = [x.id for x in obj_task.child_ids]
-
+
if (obj_task.id in children_ids) or (obj_task.id in parent_ids):
return False
-
+
while(ids):
cr.execute('SELECT DISTINCT task_id '\
'FROM project_task_parent_rel '\
@@ -518,6 +515,26 @@ class task(osv.osv):
res['fields'][f]['string'] = res['fields'][f]['string'].replace('Hours',tm)
return res
+ def action_close(self, cr, uid, ids, context=None):
+ # This action open wizard to send email to partner or project manager after close task.
+ project_id = len(ids) and ids[0] or False
+ if not project_id: return False
+ task = self.browse(cr, uid, project_id, context=context)
+ project = task.project_id
+ res = self.do_close(cr, uid, [project_id], context=context)
+ if project.warn_manager or project.warn_customer:
+ return {
+ 'name': _('Send Email after close task'),
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'res_model': 'project.task.close',
+ 'type': 'ir.actions.act_window',
+ 'target': 'new',
+ 'nodestroy': True,
+ 'context': {'active_id': task.id}
+ }
+ return res
+
def do_close(self, cr, uid, ids, context=None):
"""
Close Task
@@ -539,7 +556,7 @@ class task(osv.osv):
'ref_doc1': 'project.task,%d'% (task.id,),
'ref_doc2': 'project.project,%d'% (project.id,),
})
-
+
for parent_id in task.parent_ids:
if parent_id.state in ('pending','draft'):
reopen = True
diff --git a/addons/project/project_installer.xml b/addons/project/project_installer.xml
index e12fa4d3815..2c22a4b6743 100644
--- a/addons/project/project_installer.xml
+++ b/addons/project/project_installer.xml
@@ -24,9 +24,8 @@
Configure
-
+
-
diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml
index 421729ccda5..e1b64ccbf1b 100644
--- a/addons/project/project_view.xml
+++ b/addons/project/project_view.xml
@@ -21,8 +21,8 @@
-
-
+
+
@@ -43,12 +43,13 @@
+
-
+
@@ -300,8 +307,11 @@
+
+
+
-
-
+
@@ -369,8 +378,8 @@
-
-
+
+
-
+
@@ -397,9 +406,10 @@
+
+
-
@@ -414,10 +424,7 @@
{"search_default_project_id":project_id, "search_default_user_id":uid, "search_default_current": 1}
- In OpenERP, a project is made of a set of activities (or tasks) for completion.A list view allows the manager to quickly check for task status and make it evolve, delegate task, etc. A search tool allows a multi-criteria sort of activities.
-
-Issues like bugs in a system, client complain, materials breakdown are collected here.A list view allows the manager to quickly check for them, assign them, make their status evolved.
-
+ In OpenERP, a project is made of a set of activities (or tasks) for completion. A list view allows the manager to quickly check for task status and make it evolve, delegate task, etc. A search tool allows a multi-criteria sort of activities.
@@ -486,10 +493,10 @@ Issues like bugs in a system, client complain, materials breakdown are collected
-
+
-
-
+
+
diff --git a/addons/project/report/project_report.py b/addons/project/report/project_report.py
index b9c22faee8b..e411248db4b 100644
--- a/addons/project/report/project_report.py
+++ b/addons/project/report/project_report.py
@@ -49,7 +49,7 @@ class report_project_task_user(osv.osv):
'delay_endings_days': fields.float('Overpassed Deadline', digits=(16,2), readonly=True),
'nbr': fields.integer('# of tasks', readonly=True),
'priority' : fields.selection([('4','Very Low'), ('3','Low'), ('2','Medium'), ('1','Urgent'),
-('0','Very urgent')], 'Importance', readonly=True),
+('0','Very urgent')], 'Priority', readonly=True),
'month':fields.selection([('01','January'), ('02','February'), ('03','March'), ('04','April'), ('05','May'), ('06','June'), ('07','July'), ('08','August'), ('09','September'), ('10','October'), ('11','November'), ('12','December')], 'Month', readonly=True),
'state': fields.selection([('draft', 'Draft'), ('open', 'In Progress'), ('pending', 'Pending'), ('cancelled', 'Cancelled'), ('done', 'Done')],'State', readonly=True),
'company_id': fields.many2one('res.company', 'Company', readonly=True, groups="base.group_multi_company"),
diff --git a/addons/project/report/project_report_view.xml b/addons/project/report/project_report_view.xml
index f269399877c..1ae5adc489a 100644
--- a/addons/project/report/project_report_view.xml
+++ b/addons/project/report/project_report_view.xml
@@ -58,18 +58,18 @@
-
-
+
+ domain="[('date_start','<=', time.strftime('%%Y-%%m-%%d')),('date_start','>=',time.strftime('%%Y-%%m-01'))]"
+ help="Current Month"/>
+ domain="[('date_start','<=', (datetime.date (int(time.strftime('%%Y')), datetime.date.today().month, 1) - datetime.timedelta (days = 1)).strftime('%%Y-%%m-%%d')),('date_start','>',(datetime.date (int(time.strftime('%%Y')), datetime.date.today().month-1, 1)).strftime('%%Y-%%m-%%d'))]"
+ help="Previous Month"/>
-
-
-
+
+
+
-
-
-
+
+
+
diff --git a/addons/project/security/project_security.xml b/addons/project/security/project_security.xml
index f968ffc51a3..97453dcb33b 100644
--- a/addons/project/security/project_security.xml
+++ b/addons/project/security/project_security.xml
@@ -6,6 +6,10 @@
Project / Financial Manager
+
+ Project / Financial User
+
+
Project / Manager
@@ -43,5 +47,12 @@
['|','|','|',('user_id','=',False),('user_id','=',user.id),('project_id.members','in', [user.id]),('project_id.user_id','=',user.id)]
+
+ Projects According to User
+
+
+ [('user_id','=',user.id)]
+
+
diff --git a/addons/project/test/test_project_delegation.yml b/addons/project/test/test_project_delegation.yml
index f86f488dee7..722f58e65c2 100644
--- a/addons/project/test/test_project_delegation.yml
+++ b/addons/project/test/test_project_delegation.yml
@@ -1,11 +1,11 @@
-
This scenario tests the delegation process. Closing all the delegated tasks(task delegation at multiple levels) transits the parent task from pending to open state.
-
- Creating a project OpenERP Documentaion
+ Creating a project OpenERP Documentation
-
- !record {model: project.project, id: project_project_openerpdocumentaion0}:
+ !record {model: project.project, id: project_project_openerpdocumentation0}:
company_id: base.main_company
- name: OpenERP Documentaion
+ name: OpenERP Documentation
-
Creating a task 'Develop book for Technical and Functional reference'
@@ -13,7 +13,7 @@
!record {model: project.task, id: project_task_documentation_book}:
name: Develop book for Technical and Functional reference
planned_hours: 20.0
- project_id: project_project_openerpdocumentaion0
+ project_id: project_project_openerpdocumentation0
remaining_hours: 20.0
state: draft
@@ -31,7 +31,7 @@
!record {model: project.task, id: project_task_publish_book}:
name: Publish the References
planned_hours: 10.0
- project_id: project_project_openerpdocumentaion0
+ project_id: project_project_openerpdocumentation0
remaining_hours: 10.0
state: draft
@@ -77,7 +77,7 @@
!record {model: project.task, id: project_task_delegate_openerp_tutorial}:
name: Prepare a book that gives functional overview of OpenERP
planned_hours: 30.0
- project_id: project.project_project_openerpdocumentaion0
+ project_id: project.project_project_openerpdocumentation0
remaining_hours: 30.0
state: draft
@@ -95,7 +95,7 @@
!record {model: project.task, id: project_task_delegate_developer_book}:
name: Prepare a technical reference for creating your modules
planned_hours: 30.0
- project_id: project_project_openerpdocumentaion0
+ project_id: project_project_openerpdocumentation0
remaining_hours: 30.0
state: draft
@@ -123,7 +123,7 @@
!record {model: project.task, id: project_task_delegate_module_develop}:
name: Prepare documentation for Module Development
planned_hours: 30.0
- project_id: project.project_project_openerpdocumentaion0
+ project_id: project.project_project_openerpdocumentation0
remaining_hours: 30.0
state: draft
@@ -134,7 +134,7 @@
!record {model: project.task, id: project_task_delegate_business_process_develop}:
name: Prepare documentation for Business Process Development
planned_hours: 30.0
- project_id: project_project_openerpdocumentaion0
+ project_id: project_project_openerpdocumentation0
remaining_hours: 30.0
state: draft
diff --git a/addons/project/wizard/project_task_close.py b/addons/project/wizard/project_task_close.py
index 99b6caef308..7091f466e2c 100644
--- a/addons/project/wizard/project_task_close.py
+++ b/addons/project/wizard/project_task_close.py
@@ -19,11 +19,9 @@
#
##############################################################################
-import time
-
from osv import fields, osv
+import tools
from tools.translate import _
-from tools import email_send as email
class project_task_close(osv.osv_memory):
"""
@@ -47,7 +45,6 @@ class project_task_close(osv.osv_memory):
context = {}
record_id = context and context.get('active_id', False) or False
task_pool = self.pool.get('project.task')
- project_pool = self.pool.get('project.project')
res = super(project_task_close, self).default_get(cr, uid, fields, context=context)
task = task_pool.browse(cr, uid, record_id, context=context)
@@ -56,24 +53,18 @@ class project_task_close(osv.osv_memory):
partner = task.partner_id or task.project_id.partner_id
if 'description' in fields:
- res.update({'description': task.description})
+ res.update({'description': task.description or False})
if 'manager_warn' in fields:
- res.update({'manager_warn': project.warn_manager})
+ res.update({'manager_warn': project.warn_manager or False})
if 'partner_warn' in fields:
- res.update({'partner_warn': project.warn_customer})
+ res.update({'partner_warn': project.warn_customer or False})
if 'manager_email' in fields:
res.update({'manager_email': manager and manager.user_email or False})
if partner and len(partner.address) and 'partner_email' in fields:
res.update({'partner_email': partner.address[0].email})
return res
- def done(self, cr, uid, ids, context=None):
- task_pool = self.pool.get('project.task')
- task_id = context.get('active_id', False)
- res = task_pool.do_close(cr, uid, [task_id], context=context)
- return res
-
- def confirm(self, cr, uid, ids, context=None):
+ def send(self, cr, uid, ids, context=None):
if context is None:
context = {}
@@ -83,42 +74,41 @@ class project_task_close(osv.osv_memory):
return {}
task = task_pool.browse(cr, uid, task_id, context=context)
for data in self.browse(cr, uid, ids, context=context):
- res = task_pool.do_close(cr, uid, [task.id], context=context)
- if res:
- # Send Warn Message by Email to Manager and Customer
- if data.manager_warn and not data.manager_email:
- raise osv.except_osv(_('Error'), _("Please specify the email address of Project Manager."))
+ # Send Warn Message by Email to Manager and Customer
+ if data.manager_warn and not data.manager_email:
+ raise osv.except_osv(_('Error'), _("Please specify the email address of Project Manager."))
- elif data.partner_warn and not data.partner_email:
- raise osv.except_osv(_('Error'), _("Please specify the email address of Customer."))
+ elif data.partner_warn and not data.partner_email:
+ raise osv.except_osv(_('Error'), _("Please specify the email address of Customer."))
- elif data.manager_warn or data.partner_warn:
- 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:
- from_adr = task.user_id.address_id.email
- signature = task.user_id.signature
- else:
- raise osv.except_osv(_('Error'), _("Couldn't send mail because your email address is not configured!"))
- val = {
- 'name': task.name,
- 'user_id': task.user_id.name,
- 'task_id': "%d/%d" % (project.id, task.id),
- 'date_start': task.date_start,
- 'date_end': task.date_end,
- 'state': task.state
- }
+ elif data.manager_warn or data.partner_warn:
+ 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:
+ from_adr = task.user_id.address_id.email
+ signature = task.user_id.signature
+ else:
+ raise osv.except_osv(_('Error'), _("Couldn't send mail because your email address is not configured!"))
+ val = {
+ 'name': task.name,
+ 'user_id': task.user_id.name,
+ 'task_id': "%d/%d" % (project.id, task.id),
+ 'date_start': task.date_start,
+ 'date_end': task.date_end,
+ 'state': task.state
+ }
- header = (project.warn_header or '') % val
- footer = (project.warn_footer or '') % val
- body = u'%s\n%s\n%s\n\n-- \n%s' % (header, description, footer, signature)
- if data.manager_warn and data.manager_email:
- to_adr.append(data.manager_email)
- if data.partner_warn and data.partner_email:
- to_adr.append(data.partner_email)
- mail_id = email(from_adr, to_adr, subject, tools.ustr(body), email_bcc=[from_adr])
- if not mail_id:
- raise osv.except_osv(_('Error'), _("Couldn't send mail! Check the email ids and smtp configuration settings"))
+ to_adr = []
+ header = (project.warn_header or '') % val
+ footer = (project.warn_footer or '') % val
+ body = u'%s\n%s\n%s\n\n-- \n%s' % (header, task.description, footer, signature)
+ if data.manager_warn and data.manager_email:
+ to_adr.append(data.manager_email)
+ if data.partner_warn and data.partner_email:
+ to_adr.append(data.partner_email)
+ mail_id = tools.email_send(from_adr, to_adr, subject, tools.ustr(body), email_bcc=[from_adr])
+ if not mail_id:
+ raise osv.except_osv(_('Error'), _("Couldn't send mail! Check the email ids and smtp configuration settings"))
return {}
project_task_close()
diff --git a/addons/project/wizard/project_task_close_view.xml b/addons/project/wizard/project_task_close_view.xml
index 9692fe9a733..6c064784827 100644
--- a/addons/project/wizard/project_task_close_view.xml
+++ b/addons/project/wizard/project_task_close_view.xml
@@ -3,34 +3,32 @@
- Done Task
+ Send Emailproject.task.closeform
-
-
+
-
+
-
+
-
-
-
+
+
- Done Task
+ Send Emailir.actions.act_windowproject.task.closeform
diff --git a/addons/project/wizard/project_task_delegate.py b/addons/project/wizard/project_task_delegate.py
index 2ce74ceefc8..ac160fb6c94 100644
--- a/addons/project/wizard/project_task_delegate.py
+++ b/addons/project/wizard/project_task_delegate.py
@@ -30,7 +30,7 @@ class project_task_delegate(osv.osv_memory):
_columns = {
'name': fields.char('Delegated Title', size=64, required=True, help="New title of the task delegated to the user"),
- 'prefix': fields.char('Your Task Title', size=64, required=True, help="New title of your own task to validate the work done"),
+ 'prefix': fields.char('Your Task Title', size=64, required=True, help="Title for your validation task"),
'user_id': fields.many2one('res.users', 'Assign To', required=True, help="User you want to delegate this task to"),
'new_task_description': fields.text('New Task Description', help="Reinclude the description of the task in the task of the user"),
'planned_hours': fields.float('Planned Hours', help="Estimated time to close this task by the delegated user"),
@@ -48,10 +48,7 @@ class project_task_delegate(osv.osv_memory):
record_id = context and context.get('active_id', False) or False
task_pool = self.pool.get('project.task')
task = task_pool.browse(cr, uid, record_id, context=context)
- project = task.project_id
- manager = project.user_id or False
- partner = task.partner_id or task.project_id.partner_id
-
+
if 'name' in fields:
if task.name.startswith(_('CHECK: ')):
newname = str(task.name).replace(_('CHECK: '), '')
diff --git a/addons/project/wizard/project_task_delegate_view.xml b/addons/project/wizard/project_task_delegate_view.xml
index 7bedecd8f53..dc299826419 100644
--- a/addons/project/wizard/project_task_delegate_view.xml
+++ b/addons/project/wizard/project_task_delegate_view.xml
@@ -15,17 +15,17 @@
-
+
-
+
-
+
-
+
diff --git a/addons/project/wizard/project_task_reevaluate_view.xml b/addons/project/wizard/project_task_reevaluate_view.xml
index 5e0e7c89069..db7bda3afe7 100644
--- a/addons/project/wizard/project_task_reevaluate_view.xml
+++ b/addons/project/wizard/project_task_reevaluate_view.xml
@@ -1,7 +1,7 @@
-
+
Re-evaluate Taskproject.task.reevaluate
@@ -14,7 +14,7 @@
-
+
diff --git a/addons/project_gtd/project_gtd.py b/addons/project_gtd/project_gtd.py
index 46031048ae9..47c7c02cba8 100644
--- a/addons/project_gtd/project_gtd.py
+++ b/addons/project_gtd/project_gtd.py
@@ -22,16 +22,9 @@
import sys
from osv import fields, osv
-import ir
import tools
from tools.translate import _
-try:
- from lxml import etree
-except ImportError:
- sys.stderr.write("ERROR: Import lxml module\n")
- sys.stderr.write("ERROR: Try to install the python-lxml package\n")
-
class project_gtd_context(osv.osv):
_name = "project.gtd.context"
_description = "Context"
@@ -114,7 +107,7 @@ class project_task(osv.osv):
if res['type'] == 'search':
tt = timebox_obj.browse(cr, uid, timebox_obj.search(cr,uid,[]))
search_extended ='''''' % (len(tt)+7,_('Getting Things Done'))
- search_extended += '''''' % (_('Inbox'),)
+ search_extended += '''''' % (_('Inbox'),)
search_extended += ''''''
for time in tt:
if time.icon:
diff --git a/addons/project_gtd/project_gtd_view.xml b/addons/project_gtd/project_gtd_view.xml
index 5672fdafa7c..99e87fcb325 100644
--- a/addons/project_gtd/project_gtd_view.xml
+++ b/addons/project_gtd/project_gtd_view.xml
@@ -19,7 +19,7 @@
form
-
+
@@ -53,7 +53,7 @@
-
+
diff --git a/addons/project_issue/project_issue.py b/addons/project_issue/project_issue.py
index 5c5a8907dc9..19db547983b 100644
--- a/addons/project_issue/project_issue.py
+++ b/addons/project_issue/project_issue.py
@@ -19,21 +19,15 @@
#
##############################################################################
-import base64
-import os
-import re
-import time
-from datetime import datetime, timedelta
-import binascii
-import collections
-
-import tools
from crm import crm
-from osv import fields,osv,orm
-from osv.orm import except_orm
+from datetime import datetime
+from osv import fields,osv
from tools.translate import _
+import binascii
+import time
import tools
+
class project_issue(crm.crm_case, osv.osv):
_name = "project.issue"
_description = "Project Issue"
@@ -70,7 +64,7 @@ class project_issue(crm.crm_case, osv.osv):
message = _('Issue ') + " '" + name + "' "+ _("is Closed.")
self.log(cr, uid, id, message)
return res
-
+
def _compute_day(self, cr, uid, ids, fields, args, context=None):
if context is None:
context = {}
@@ -152,7 +146,7 @@ class project_issue(crm.crm_case, osv.osv):
domain="[('partner_id','=',partner_id)]"),
'company_id': fields.many2one('res.company', 'Company'),
'description': fields.text('Description'),
- 'state': fields.selection([('draft', 'Draft'), ('open', 'Todo'), ('cancel', 'Cancelled'), ('done', 'Closed'),('pending', 'Pending'), ], 'State', size=16, readonly=True,
+ 'state': fields.selection([('draft', 'Draft'), ('open', 'To Do'), ('cancel', 'Cancelled'), ('done', 'Closed'),('pending', 'Pending'), ], 'State', size=16, readonly=True,
help='The state is set to \'Draft\', when a case is created.\
\nIf the case is in progress the state is set to \'Open\'.\
\nWhen the case is over, the state is set to \'Done\'.\
@@ -409,7 +403,7 @@ class project(osv.osv):
'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.', states={'close':[('readonly',True)], 'cancelled':[('readonly',True)]}),
'reply_to' : fields.char('Reply-To Email Address', size=256)
}
-
+
def _check_escalation(self, cr, uid, ids):
project_obj = self.browse(cr, uid, ids[0])
if project_obj.project_escalation_id:
diff --git a/addons/project_issue/project_issue_data.xml b/addons/project_issue/project_issue_data.xml
index 1c7f5c73c77..b5fa80b96bd 100644
--- a/addons/project_issue/project_issue_data.xml
+++ b/addons/project_issue/project_issue_data.xml
@@ -22,19 +22,16 @@
Version 4.2
- Version 5.0
- Version 6.0
-
diff --git a/addons/project_issue/project_issue_menu.xml b/addons/project_issue/project_issue_menu.xml
index 9c074ed2fd3..df76e808bff 100644
--- a/addons/project_issue/project_issue_menu.xml
+++ b/addons/project_issue/project_issue_menu.xml
@@ -12,10 +12,10 @@
formtree,calendar
-
+ {"search_default_user_id": uid, "search_default_current":1, "search_default_project_id":project_id}
- Issues like bugs in a system, client complain, materials breakdown are collected here.A list view allows the manager to quickly check for them, assign them, make their status evolved.
+ Issues like bugs in a system, client complain, materials breakdown are collected here. A list view allows the manager to quickly check for them, assign them, make their status evolved.
@@ -40,7 +40,7 @@
-
+
@@ -75,10 +75,10 @@
-
+
-
+
-
+
@@ -117,7 +117,7 @@
-
@@ -157,13 +157,13 @@
project.issuetree
-
+
-
+
@@ -174,11 +174,12 @@
-
+
+
@@ -190,8 +191,8 @@
-
-
+
+
@@ -204,25 +205,31 @@
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+ domain="[]" context="{'group_by':'create_date'}" help="Creation Month"/>
@@ -254,7 +261,7 @@
-
+
@@ -316,6 +323,6 @@
-
+
diff --git a/addons/project_issue/report/project_issue_report.py b/addons/project_issue/report/project_issue_report.py
index bf8085ba932..97a340851ef 100644
--- a/addons/project_issue/report/project_issue_report.py
+++ b/addons/project_issue/report/project_issue_report.py
@@ -44,7 +44,6 @@ class project_issue_report(osv.osv):
@param context: A standard dictionary for contextual values """
res = {}
- avg_ans = 0.0
for report in self.browse(cr, uid, ids, context):
res[report.id]= {
@@ -87,7 +86,7 @@ class project_issue_report(osv.osv):
'company_id' : fields.many2one('res.company', 'Company'),
'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'),
'project_id':fields.many2one('project.project', 'Project',readonly=True),
- 'type_id': fields.many2one('crm.case.resource.type', 'Version', domain="[('object_id.model', '=', 'project.issue')]"),
+ 'type_id': fields.many2one('crm.case.resource.type', 'Version'),
'assigned_to' : fields.many2one('res.users', 'Assigned to',readonly=True),
'partner_id': fields.many2one('res.partner','Partner',domain="[('object_id.model', '=', 'project.issue')]"),
'canal_id': fields.many2one('res.partner.canal', 'Channel',readonly=True),
diff --git a/addons/project_issue/report/project_issue_report_view.xml b/addons/project_issue/report/project_issue_report_view.xml
index 9ceded378ba..d1b421d59ca 100644
--- a/addons/project_issue/report/project_issue_report_view.xml
+++ b/addons/project_issue/report/project_issue_report_view.xml
@@ -54,14 +54,16 @@
-
+
-
-
-
+
+
@@ -83,7 +86,7 @@
+ help="My Sale Team" />
@@ -96,7 +99,7 @@
-
+
@@ -108,45 +111,42 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
-
+
+
-
-
-
-
+ domain="[]" context="{'group_by':'day'}" help="Current Day"/>
+ domain="[]" context="{'group_by':'month'}" help="Current Month"/>
+ domain="[]" context="{'group_by':'name'}" help="Current Year"/>
-
diff --git a/addons/project_long_term/project_long_term.py b/addons/project_long_term/project_long_term.py
index 79baff679cc..a535015d067 100644
--- a/addons/project_long_term/project_long_term.py
+++ b/addons/project_long_term/project_long_term.py
@@ -19,11 +19,11 @@
#
##############################################################################
-import time
-from datetime import date, datetime, timedelta
-
+from datetime import datetime
from tools.translate import _
from osv import fields, osv
+from resource.faces import task as Task
+import operator
class project_phase(osv.osv):
_name = "project.phase"
@@ -181,38 +181,55 @@ class project_phase(osv.osv):
uom_obj = self.pool.get('product.uom')
if context is None:
context = {}
+ res = super(project_phase, self).write(cr, uid, ids, vals, context=context)
if context.get('scheduler',False):
- return super(project_phase, self).write(cr, uid, ids, vals, context=context)
+ return res
# Consider calendar and efficiency if the phase is performed by a resource
# otherwise consider the project's working calendar
+
+ #TOCHECK : why need this ?
if isinstance(ids, (int, long)):
ids = [ids]
- phase = self.browse(cr, uid, ids[0], context=context)
- calendar_id = phase.project_id.resource_calendar_id and phase.project_id.resource_calendar_id.id or False
- resource_id = resource_obj.search(cr, uid, [('user_id', '=', phase.responsible_id.id)],context=context)
- if resource_id:
+ default_uom_id = self._get_default_uom_id(cr, uid)
+ for phase in self.browse(cr, uid, ids, context=context):
+ calendar_id = phase.project_id.resource_calendar_id and phase.project_id.resource_calendar_id.id or False
+ resource_id = resource_obj.search(cr, uid, [('user_id', '=', phase.responsible_id.id)],context=context)
+ if resource_id:
cal_id = resource_obj.browse(cr, uid, resource_id[0], context=context).calendar_id.id
if cal_id:
calendar_id = cal_id
- default_uom_id = self._get_default_uom_id(cr, uid)
- avg_hours = uom_obj._compute_qty(cr, uid, phase.product_uom.id, phase.duration, default_uom_id)
- # Change the date_start and date_end
- # for previous and next phases respectively based on valid condition
- if vals.get('date_start', False) and vals['date_start'] < phase.date_start:
+
+ avg_hours = uom_obj._compute_qty(cr, uid, phase.product_uom.id, phase.duration, default_uom_id)
+ # Change the date_start and date_end
+ # for previous and next phases respectively based on valid condition
+ if vals.get('date_start', False) and vals['date_start'] < phase.date_start:
dt_start = datetime.strptime(vals['date_start'], '%Y-%m-%d')
work_times = resource_calendar_obj.interval_get(cr, uid, calendar_id, dt_start, avg_hours or 0.0, resource_id and resource_id[0] or False)
if work_times:
vals['date_end'] = work_times[-1][1].strftime('%Y-%m-%d')
for prv_phase in phase.previous_phase_ids:
+ if prv_phase.id == phase.id:
+ continue
self._check_date_start(cr, uid, prv_phase, dt_start, context=context)
- if vals.get('date_end', False) and vals['date_end'] > phase.date_end:
+
+ if vals.get('date_end', False) and vals['date_end'] > phase.date_end:
dt_end = datetime.strptime(vals['date_end'], '%Y-%m-%d')
work_times = resource_calendar_obj.interval_min_get(cr, uid, calendar_id, dt_end, avg_hours or 0.0, resource_id and resource_id[0] or False)
if work_times:
vals['date_start'] = work_times[0][0].strftime('%Y-%m-%d')
for next_phase in phase.next_phase_ids:
+ if next_phase.id == phase.id:
+ continue
self._check_date_end(cr, uid, next_phase, dt_end, context=context)
- return super(project_phase, self).write(cr, uid, ids, vals, context=context)
+
+ return res
+
+ def copy(self, cr, uid, id, default=None, context=None):
+ if default is None:
+ default = {}
+ if not default.get('name', False):
+ default['name'] = self.browse(cr, uid, id, context=context).name + _(' (copy)')
+ return super(project_phase, self).copy(cr, uid, id, default, context)
def set_draft(self, cr, uid, ids, *args):
self.write(cr, uid, ids, {'state': 'draft'})
@@ -234,6 +251,118 @@ class project_phase(osv.osv):
self.write(cr, uid, ids, {'state': 'done'})
return True
+ def generate_resources(self, cr, uid, ids, context=None):
+ """
+ Return a list of Resource Class objects for the resources allocated to the phase.
+ """
+ res = {}
+ if context is None:
+ context = {}
+ resource_pool = self.pool.get('resource.resource')
+ for phase in self.browse(cr, uid, ids, context=context):
+ user_ids = map(lambda x:x.resource_id.user_id.id, phase.resource_ids)
+ project = phase.project_id
+ calendar_id = project.resource_calendar_id and project.resource_calendar_id.id or False
+ resource_objs = resource_pool.generate_resources(cr, uid, user_ids, calendar_id, context=context)
+ res[phase.id] = resource_objs
+ return res
+
+ def generate_schedule(self, cr, uid, ids, start_date, calendar_id=False, context=None):
+ """
+ Schedule phase with the start date till all the next phases are completed.
+ @param: start_dsate : start date for the phase
+ @param: calendar_id : working calendar of the project
+ """
+ if context is None:
+ context = {}
+ resource_pool = self.pool.get('resource.resource')
+ uom_pool = self.pool.get('product.uom')
+ phase_resource = False
+ if context is None:
+ context = {}
+ default_uom_id = self._get_default_uom_id(cr, uid)
+ for phase in self.browse(cr, uid, ids, context=context):
+ if not phase.responsible_id:
+ raise osv.except_osv(_('No responsible person assigned !'),_("You must assign a responsible person for phase '%s' !") % (phase.name,))
+
+ phase_resource_obj = resource_pool.generate_resources(cr, uid, [phase.responsible_id.id], calendar_id, context=context)
+ avg_hours = uom_pool._compute_qty(cr, uid, phase.product_uom.id, phase.duration, default_uom_id)
+ duration = str(avg_hours) + 'H'
+ # Create a new project for each phase
+ def Project():
+ start = start_date
+ minimum_time_unit = 1
+ resource = phase_resource_obj
+ # If project has working calendar then that
+ # else the default one would be considered
+ if calendar_id:
+ working_days = resource_pool.compute_working_calendar(cr, uid, calendar_id, context=context)
+ vacation = tuple(resource_pool.compute_vacation(cr, uid, calendar_id))
+
+ def phase():
+ effort = duration
+
+ project = Task.BalancedProject(Project)
+ s_date = project.phase.start.to_datetime()
+ e_date = project.phase.end.to_datetime()
+ # Recalculate date_start and date_end
+ # according to constraints on date start and date end on phase
+ if phase.constraint_date_start and str(s_date) < phase.constraint_date_start:
+ start_date = datetime.strptime(phase.constraint_date_start, '%Y-%m-%d')
+ else:
+ start_date = s_date
+ if phase.constraint_date_end and str(e_date) > phase.constraint_date_end:
+ end_date= datetime.strptime(phase.constraint_date_end, '%Y-%m-%d')
+ date_start = phase.constraint_date_end
+ else:
+ end_date = e_date
+ date_start = end_date
+ # Write the calculated dates back
+ ctx = context.copy()
+ ctx.update({'scheduler': True})
+ self.write(cr, uid, [phase.id], {
+ 'date_start': start_date.strftime('%Y-%m-%d'),
+ 'date_end': end_date.strftime('%Y-%m-%d')
+ }, context=ctx)
+
+ # Recursive call till all the next phases scheduled
+ for phase in phase.next_phase_ids:
+ if phase.state in ['draft', 'open', 'pending']:
+ id_cal = phase.project_id.resource_calendar_id and phase.project_id.resource_calendar_id.id or False
+ self.generate_schedule(cr, uid, [phase.id], date_start, id_cal, context=context)
+ else:
+ continue
+ return True
+
+ def schedule_tasks(self, cr, uid, ids, context=None):
+ """
+ Schedule the tasks according to resource available and priority.
+ """
+ task_pool = self.pool.get('project.task')
+ resource_pool = self.pool.get('resource.resource')
+ if context is None:
+ context = {}
+ resources_list = self.generate_resources(cr, uid, ids, context=context)
+ return_msg = {}
+ for phase in self.browse(cr, uid, ids, context=context):
+ start_date = phase.date_start
+ if not start_date and phase.project_id.date_start:
+ start_date = phase.project_id.date_start
+ if not start_date:
+ start_date = datetime.now().strftime("%Y-%m-%d")
+ resources = resources_list.get(phase.id, [])
+ calendar_id = phase.project_id.resource_calendar_id.id
+ task_ids = map(lambda x : x.id, (filter(lambda x : x.state in ['open', 'draft', 'pending'] , phase.task_ids)))
+ if task_ids:
+ task_pool.generate_schedule(cr, uid, task_ids, resources, calendar_id, start_date, context=context)
+
+ if not task_ids:
+ warning_msg = _("No tasks to compute for Phase '%s'.") % (phase.name)
+ if "warning" not in return_msg:
+ return_msg["warning"] = warning_msg
+ else:
+ return_msg["warning"] = return_msg["warning"] + "\n" + warning_msg
+ return return_msg
project_phase()
class project_resource_allocation(osv.osv):
@@ -259,14 +388,172 @@ class project(osv.osv):
'phase_ids': fields.one2many('project.phase', 'project_id', "Project Phases"),
'resource_calendar_id': fields.many2one('resource.calendar', 'Working Time', help="Timetable working hours to adjust the gantt diagram report", states={'close':[('readonly',True)]} ),
}
+ def generate_members(self, cr, uid, ids, context=None):
+ """
+ Return a list of Resource Class objects for the resources allocated to the phase.
+ """
+ res = {}
+ resource_pool = self.pool.get('resource.resource')
+ if context is None:
+ context = {}
+ for project in self.browse(cr, uid, ids, context=context):
+ user_ids = map(lambda x:x.id, project.members)
+ calendar_id = project.resource_calendar_id and project.resource_calendar_id.id or False
+ resource_objs = resource_pool.generate_resources(cr, uid, user_ids, calendar_id, context=context)
+ res[project.id] = resource_objs
+ return res
+
+ def schedule_phases(self, cr, uid, ids, context=None):
+ """
+ Schedule the phases.
+ """
+ if context is None:
+ context = {}
+ if type(ids) in (long, int,):
+ ids = [ids]
+ phase_pool = self.pool.get('project.phase')
+ for project in self.browse(cr, uid, ids, context=context):
+ phase_ids = phase_pool.search(cr, uid, [('project_id', '=', project.id),
+ ('state', 'in', ['draft', 'open', 'pending']),
+ ('previous_phase_ids', '=', False)
+ ])
+ start_date = project.date_start
+ if not start_date:
+ start_date = datetime.now().strftime("%Y-%m-%d")
+ start_dt = datetime.strftime((datetime.strptime(start_date, "%Y-%m-%d")), "%Y-%m-%d %H:%M")
+ calendar_id = project.resource_calendar_id and project.resource_calendar_id.id or False
+ phase_pool.generate_schedule(cr, uid, phase_ids, start_dt, calendar_id, context=context)
+ return True
+
+ def schedule_tasks(self, cr, uid, ids, context=None):
+ """
+ Schedule the tasks according to resource available and priority.
+ """
+ if type(ids) in (long, int,):
+ ids = [ids]
+ user_pool = self.pool.get('res.users')
+ task_pool = self.pool.get('project.task')
+ resource_pool = self.pool.get('resource.resource')
+ if context is None:
+ context = {}
+
+ resources_list = self.generate_members(cr, uid, ids, context=context)
+ return_msg = {}
+ for project in self.browse(cr, uid, ids, context=context):
+ start_date = project.date_start
+ if not start_date:
+ start_date = datetime.now().strftime("%Y-%m-%d")
+ resources = resources_list.get(project.id, [])
+ calendar_id = project.resource_calendar_id.id
+ task_ids = task_pool.search(cr, uid, [('project_id', '=', project.id),
+ ('state', 'in', ['draft', 'open', 'pending'])
+ ])
+
+
+ if task_ids:
+ task_pool.generate_schedule(cr, uid, task_ids, resources, calendar_id, start_date, context=context)
+ else:
+ warning_msg = _("No tasks to compute for Project '%s'.") % (project.name)
+ if "warning" not in return_msg:
+ return_msg["warning"] = warning_msg
+ else:
+ return_msg["warning"] = return_msg["warning"] + "\n" + warning_msg
+
+ return return_msg
project()
-class task(osv.osv):
+class resource_resource(osv.osv):
+ _inherit = "resource.resource"
+ def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
+ if context is None:
+ context = {}
+ if context.get('project_id',False):
+ project_pool = self.pool.get('project.project')
+ project_rec = project_pool.browse(cr, uid, context['project_id'])
+ user_ids = [user_id.id for user_id in project_rec.members]
+ args.append(('user_id','in',user_ids))
+ return super(resource_resource, self).search(cr, uid, args, offset, limit, order, context, count)
+
+resource_resource()
+
+class project_task(osv.osv):
_inherit = "project.task"
_columns = {
'phase_id': fields.many2one('project.phase', 'Project Phase'),
}
+
+ def generate_schedule(self, cr, uid, ids, resources, calendar_id, start_date, context=None):
+ """
+ Schedule the tasks according to resource available and priority.
+ """
+ if not ids:
+ return False
+ if context is None:
+ context = {}
+ user_pool = self.pool.get('res.users')
+ project_pool = self.pool.get('project.project')
+ priority_dict = {'0': 1000, '1': 800, '2': 500, '3': 300, '4': 100}
+ # Create dynamic no of tasks with the resource specified
+ def create_tasks(task_number, eff, priorty=500, obj=False):
+ def task():
+ """
+ task is a dynamic method!
+ """
+ effort = eff
+ if obj:
+ resource = obj
+ priority = priorty
+ task.__doc__ = "TaskNO%d" %task_number
+ task.__name__ = "task%d" %task_number
+ return task
-task()
+ # Create a 'Faces' project with all the tasks and resources
+ def Project():
+ title = "Project"
+ start = datetime.strftime(datetime.strptime(start_date, "%Y-%m-%d"), "%Y-%m-%d %H:%M")
+ try:
+ resource = reduce(operator.or_, resources)
+ except:
+ raise osv.except_osv(_('Error'), _('Should have Resources Allocation or Project Members!'))
+ minimum_time_unit = 1
+ if calendar_id: # If project has working calendar
+ working_days = resource_pool.compute_working_calendar(cr, uid, calendar_id, context=context)
+ vacation = tuple(resource_pool.compute_vacation(cr, uid, calendar_id, context=context))
+ # Dynamic creation of tasks
+ task_number = 0
+ for openobect_task in self.browse(cr, uid, ids, context=context):
+ hours = str(openobect_task.planned_hours )+ 'H'
+ if openobect_task.priority in priority_dict.keys():
+ priorty = priority_dict[openobect_task.priority]
+ real_resource = False
+ if openobect_task.user_id:
+ for task_resource in resources:
+ if task_resource.__name__ == task_resource:
+ real_resource = task_resource
+ break
+
+ task = create_tasks(task_number, hours, priorty, real_resource)
+ task_number += 1
+
+
+ face_projects = Task.BalancedProject(Project)
+ loop_no = 0
+ # Write back the computed dates
+ for face_project in face_projects:
+ s_date = face_project.start.to_datetime()
+ e_date = face_project.end.to_datetime()
+ if loop_no > 0:
+ ctx = context.copy()
+ ctx.update({'scheduler': True})
+ user_id = user_pool.search(cr, uid, [('name', '=', face_project.booked_resource[0].__name__)])
+ self.write(cr, uid, [ids[loop_no-1]], {
+ 'date_start': s_date.strftime('%Y-%m-%d %H:%M:%S'),
+ 'date_end': e_date.strftime('%Y-%m-%d %H:%M:%S'),
+ 'user_id': user_id[0]
+ }, context=ctx)
+
+ loop_no += 1
+ return True
+project_task()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/project_long_term/project_long_term_demo.xml b/addons/project_long_term/project_long_term_demo.xml
index 7718048dc05..30acac99377 100644
--- a/addons/project_long_term/project_long_term_demo.xml
+++ b/addons/project_long_term/project_long_term_demo.xml
@@ -1,741 +1,393 @@
-
-
-
-
-
- en_US
- Demo User1
-
- Mr Demo
-
-
-
-
-
- demo1
- demo1
-
-
-
-
-
- en_US
- Manager1
+
+
+
+
+ Phoung
-
-
-
-
-
- manager1
- manager1
-
+ phu
+ phu
-
-
-
- en_US
- Manager2
+
+ Anthony
-
-
-
-
-
- manager2
- manager2
-
+ al
+ al
-
-
-
- en_US
- user1
+
+ Qwintin
-
-
-
-
-
- user1
- USER1
-
+ qdp
+ qdp
-
-
-
- en_US
- user2
+
+ Francois
-
-
-
-
-
- user2
- user2
-
+ fpi
+ fpi
-
-
-
- en_US
- user_finance
+
+ Julien
+
+ jth
+ jth
+
+
+ Alien
+
+ apr
+ apr
+
+
+ Fabian
-
-
-
-
-
- user_finance
- user_finance
-
+ fbs
+ fbs
-
-
- en_US
- user_design1
-
-
-
-
-
-
- user_design1
- user_design1
-
-
-
-
-
- en_US
- user_design2
-
-
-
-
-
-
- user_design2
- user_design2
-
-
-
-
-
- en_US
- user_developer1
-
-
-
-
-
-
- user_developer1
- user_developer1
-
-
-
-
-
- en_US
- user_developer2
-
-
-
-
-
-
- user_developer2
- user_developer1
-
-
-
-
-
- en_US
- user_tester1
-
-
-
-
-
-
- user_tester1
- user_tester1
-
-
-
-
-
- en_US
- user_tester2
-
-
-
-
-
-
- user_tester2
- user_tester2
-
-
-
-
-
- en_US
- user_analyst
-
-
-
-
-
-
- user_analyst
- user_analyst
-
-
-
-
-
-
-
-
+
+
+ Analyst
-
-
- user
-
-
-
- Programmer
-
-
+
+
+ Project Manager
- user
-
-
-
+
+
+ Technical Leader
+
+
+
+
+
+ Developer
+
+
+
+
+
+ Designer
+
+
+
+
+ Tester
-
-
- user
-
-
-
- Web Designer
-
-
+
+
+ Project Finacial Manager
- user
+
+
-
-
-
-
-
-
-
-
-
+
+ opennormal
- Develop an OpenERP Website.
-
-
-
-
-
- OpenERP Website Development
+ Integrate an Sale and Warehouse Management.
+
+
+ Integrate an Sale and Warehouse Management.
-
+
- Information Gathering and Understanding
+ Collect Requirement and Make SRS
-
-
-
- draft
-
-
-
-
-
+
+ 30
+
+
-
-
- Planning
+
+
+ Design Model
-
-
-
- draft
-
-
-
-
-
+
+ 20
+
+
-
-
- Web Design
+
+
+ Planning and compute Risk analysis, Time chart
-
-
-
- draft
-
-
-
-
-
+
+ 20
+
+
-
-
- Development, Integration and Testing
+
+
+ Development and Integration
-
-
-
- draft
-
-
-
-
-
+
+ 90
+
+
-
-
- Website Deployment
+
+
+ Review and Testing
-
-
-
- draft
-
-
-
-
-
+
+ 30
+
+
+
+
+
+
+ Deployement and Training
+
+
+ 10
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
+
-
-
-
-
-
+
+
+
+
-
-
+
+
-
- open
-
-
+ 2
-
-
-
-
+ Prepare Requirements Document
-
-
-
-
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
- Define Website Goals, Purposes and Target Audience
-
-
-
-
+
+ Make SRS
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
- Use Cases
-
-
-
-
+
+ Design Use Cases
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
+ Budget Planning
-
-
-
-
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
+ Quality Planning
-
-
-
-
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
+ Risk Management Planning
-
-
-
-
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
+ Create Project Schedules
-
-
-
-
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
+ Dataflow Design
-
-
-
-
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
+ User Interface Design
-
-
-
-
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
- Task Level WBS
-
-
-
-
+
+ Develop Module in Sale Management
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
- Modular Programming
-
-
-
-
+
+ Develop module in Warehouse
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
+ Integrate Modules
-
-
-
-
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
+ Unit Testing
-
-
-
-
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
+ Regression Test
-
-
-
-
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
+ Documentation
-
-
-
-
+
-
+
-
- open
-
-
+ 2
-
-
-
-
+ Performance Tuning
-
-
-
-
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
- Deploy Website
-
-
-
-
+
+ Deploy and Review on Customer System
+
-
-
+
-
- open
-
-
+ 2
-
-
-
-
- Presentation
-
-
-
-
+
+ Training and Presentation
+
+
+
+
+
+
diff --git a/addons/project_long_term/project_long_term_view.xml b/addons/project_long_term/project_long_term_view.xml
index ee763b759b6..a3ff3b39669 100644
--- a/addons/project_long_term/project_long_term_view.xml
+++ b/addons/project_long_term/project_long_term_view.xml
@@ -30,7 +30,7 @@
-
+
@@ -60,8 +60,9 @@
-
+
+
@@ -89,16 +90,21 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -115,9 +121,9 @@
-
-
+
+
@@ -184,7 +190,7 @@
tree
-
+
@@ -228,23 +234,26 @@
-
+
-
+
-
-
-
+
-
+
+
+
+
+
+
@@ -257,7 +266,7 @@
tree,form,gantt,calendar{'search_default_responsible_id':uid}
- You can subdivide your larger projects into several phases. For each phase, you can define your resources allocation (humans or engine), describe de differend task and link your phase with previous and next one, add constraints date and scheduling. A gantt view of your project phase is also available from this menu. Gantt view is a graphically draw of the project plan; it includes any task dependencies by visually adjusting task durations and priorities, and by linking tasks to each other.
+ You can subdivide your larger projects into several phases. For each phase, you can define your resources allocation (humans or engine), describe de differend task and link your phase with previous and next one, add constraints date and scheduling. A gantt view of your project phase is also available from this menu. Gantt view is a graphically draw of the project plan; it includes any task dependencies by visually adjusting task durations and priorities, and by linking tasks to each other.
@@ -297,10 +306,10 @@
res_model="project.task"
src_model="project.phase"
view_mode="tree,form"
- domain="[('phase_id','=',active_id)]"/>
+ context="{'search_default_phase_id': [active_id]}"/>
diff --git a/addons/project_long_term/security/ir.model.access.csv b/addons/project_long_term/security/ir.model.access.csv
index 3653cd375f1..7af7984d7e6 100644
--- a/addons/project_long_term/security/ir.model.access.csv
+++ b/addons/project_long_term/security/ir.model.access.csv
@@ -1,9 +1,10 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
-"access_project_phase","project.phase","model_project_phase",project.group_project_user,1,1,1,0
-"access_project_resource_allocation","project.resource.allocation","model_project_resource_allocation",project.group_project_user,1,1,1,0
-"access_project_phase_manager","project.phase manager","model_project_phase",project.group_project_manager,1,0,0,0
-"access_project_resource_allocation_manager","project.resource.allocation manager","model_project_resource_allocation",project.group_project_manager,1,0,0,0
-"access_project_resource_allocation_system","project.resource.allocation system","model_project_resource_allocation",base.group_system,1,0,0,0
-"access_project_phase_system","project.phase system","model_project_phase",base.group_system,1,0,0,0
-"access_resource_resource_user","resource.resource user","resource.model_resource_resource",project.group_project_user,1,1,1,1
+"access_project_phase","project.phase","model_project_phase","project.group_project_user",1,1,1,0
+"access_project_resource_allocation","project.resource.allocation","model_project_resource_allocation","project.group_project_user",1,1,1,0
+"access_project_phase_manager","project.phase manager","model_project_phase","project.group_project_manager",1,0,0,0
+"access_project_resource_allocation_manager","project.resource.allocation manager","model_project_resource_allocation","project.group_project_manager",1,0,0,0
+"access_project_resource_allocation_system","project.resource.allocation system","model_project_resource_allocation","base.group_system",1,0,0,0
+"access_project_phase_system","project.phase system","model_project_phase","base.group_system",1,0,0,0
+"access_resource_resource_user","resource.resource user","resource.model_resource_resource","project.group_project_user",1,0,1,1
"access_resource_calendar_leaves_user","resource.calendar.leaves user","resource.model_resource_calendar_leaves","project.group_project_user",1,1,1,1
+"access_resource_resource_manager","resource.resource manager","resource.model_resource_resource","project.group_project_manager",1,1,1,1
diff --git a/addons/project_long_term/test/schedule_phase_tasks.yml b/addons/project_long_term/test/schedule_phase_tasks.yml
index 323d9cbc8f2..150d80af822 100644
--- a/addons/project_long_term/test/schedule_phase_tasks.yml
+++ b/addons/project_long_term/test/schedule_phase_tasks.yml
@@ -2,32 +2,31 @@
Create project 'Develop an outlook-openerp synchronization plugin'
-
!record {model: project.project, id: project_project_project0}:
- company_id: base.main_company
- name: Project123
+ name: Develop an outlook-openerp synchronization plugin
members:
- - project_long_term.res_users_manager0
- - project_long_term.res_users_user0
- - project_long_term.res_users_userfinance0
- - project_long_term.res_users_userdesign0
- - project_long_term.res_users_userdeveloper0
- - project_long_term.res_users_usertester0
- - project_long_term.res_users_useranalyst0
+ - project_long_term.res_users_project_manager
+ - project_long_term.res_users_technical_leader
+ - project_long_term.res_users_developer
+ - project_long_term.res_users_designer
+ - project_long_term.res_users_tester
+ - project_long_term.res_users_analyst
+ - project_long_term.res_users_finacial_manager
-
Create phase 'Develop GUI' in Outlook
-
!record {model: project.phase, id: project_phase_phase0}:
date_start: '2010-06-02'
duration: 200.0
- name: phase123
+ name: Develop GUI in Outlook
product_uom: product.uom_day
project_id: project_project_project0
state: draft
resource_ids:
- - resource_id: project_long_term.resource_resource_analyst0
+ - resource_id: project_long_term.resource_analyst
useability: 80.0
- - resource_id: project_long_term.resource_resource_programmer0
+ - resource_id: project_long_term.resource_developer
useability: 30.0
- - resource_id: project_long_term.resource_resource_webdesigner0
+ - resource_id: project_long_term.resource_designer
useability: 30.0
@@ -35,66 +34,60 @@
Create the phase task 'Develop GUI for Server Configuration'
-
!record {model: project.task, id: project_task_t0}:
- name: t1
+ name: Develop GUI for Server Configuration
planned_hours: 20.0
remaining_hours: 20.0
state: draft
phase_id: project_phase_phase0
project_id: project_project_project0
- user_id: project_long_term.res_users_userdeveloper0
+ user_id: project_long_term.res_users_developer
-
Create the phase task 'Develop GUI for Modules Configuration'
-
!record {model: project.task, id: project_task_t1}:
- name: t2
+ name: Develop GUI for Modules Configuration
planned_hours: 25.0
remaining_hours: 25.0
state: draft
phase_id: project_phase_phase0
project_id: project_project_project0
- user_id: project_long_term.res_users_userdeveloper0
+ user_id: project_long_term.res_users_developer
-
Create the phase task 'Develop GUI for OpenERP Synchronisation'
-
!record {model: project.task, id: project_task_t2}:
- name: t3
+ name: Develop GUI for OpenERP Synchronisation
planned_hours: 30.0
remaining_hours: 30.0
state: draft
phase_id: project_phase_phase0
project_id: project_project_project0
- user_id: project_long_term.res_users_userdeveloper0
+ user_id: project_long_term.res_users_developer
-
- Create the phase task 'Develop required Menus'
+ Create the phase task 'Design required GUI/Menus'
-
!record {model: project.task, id: project_task_3}:
- name: t4
+ name: Design required GUI/Menus
planned_hours: 25.0
remaining_hours: 25.0
state: draft
phase_id: project_phase_phase0
project_id: project_project_project0
- user_id: project_long_term.res_users_userdesign0
+ user_id: project_long_term.res_users_designer
-
Schedule phase tasks
-
- !python {model: project.schedule.tasks}: |
- res = self.compute_date(cr, uid, {"lang": "en_US", "tz": False,
- "active_id": ref("project_phase_phase0"),
- # rest may be obsolete:
- # "active_model": "project.phase", "active_ids": [ref("project_phase_phase0")],
- # "record_id": 138, "project_id": ref("project_project_project0"),
- })
- print res
+ !python {model: project.phase}: |
+ res = self.schedule_tasks(cr, uid, [ref("project_phase_phase0")])
-
Check if tasks scheduled, check that either of task's start_date, end_date and user_id is not null
-
!python {model: project.phase}: |
- phase=self.browse(cr, uid, [ref("project_phase_phase0")])[0]
+ phase = self.browse(cr, uid, [ref("project_phase_phase0")])[0]
for task in phase.task_ids:
if (not task.user_id) or (not task.date_start) or (not task.date_end):
raise AssertionError("Phase Tasks not scheduled: %d uid=%r start=%r end=%r" % \
- (task.id, task.user_id, task.date_start, task.date_end))
\ No newline at end of file
+ (task.id, task.user_id, task.date_start, task.date_end))
diff --git a/addons/project_long_term/test/schedule_project_phases.yml b/addons/project_long_term/test/schedule_project_phases.yml
index 66bca5ff97d..e06feaaa4ca 100644
--- a/addons/project_long_term/test/schedule_project_phases.yml
+++ b/addons/project_long_term/test/schedule_project_phases.yml
@@ -2,7 +2,6 @@
Create a project 'World Bank's Project'
-
!record {model: project.project, id: project_project_worldbanksproject0}:
- company_id: base.main_company
name: "World Bank's Project"
priority: 4
@@ -15,7 +14,6 @@
name: "Defining Client's Basic Idea of Project"
product_uom: product.uom_day
project_id: project_project_worldbanksproject0
- state: draft
-
@@ -27,7 +25,6 @@
name: Establishing Project Feasibility
product_uom: product.uom_day
project_id: project_project_worldbanksproject0
- state: draft
-
Create project phase 'Preparation of Engineering Designs'
@@ -38,7 +35,6 @@
name: Preparation of Engineering Designs
product_uom: product.uom_hour
project_id: project_project_worldbanksproject0
- state: draft
-
@@ -50,7 +46,6 @@
name: Procurement of Works and Goods
product_uom: product.uom_hour
project_id: project_project_worldbanksproject0
- state: draft
-
@@ -62,7 +57,6 @@
name: Project Construction
product_uom: product.uom_hour
project_id: project_project_worldbanksproject0
- state: draft
-
@@ -74,7 +68,6 @@
name: Project Completion
product_uom: product.uom_hour
project_id: project_project_worldbanksproject0
- state: draft
-
Set previous phase for phase 'Establishing Project Feasibility'
@@ -125,11 +118,8 @@
-
Schedule project phases
-
- !python {model: project.compute.phases}: |
- self.check_selection(cr, uid, [ref("project_compute_phases_0")], {"lang": "en_US",
- "project_id": False, "tz": False, "active_model": "ir.ui.menu", "department_id":
- False, "section_id": False, "record_id": 279, "active_ids": [ref("project_long_term.menu_compute_phase")],
- "active_id": ref("project_long_term.menu_compute_phase"), })
+ !python {model: project.project}: |
+ self.schedule_phases(cr, uid, ref("project_project_worldbanksproject0"))
-
Check if phases scheduled, check that either of phase's start_date, end_date and user_id is not null
@@ -140,4 +130,4 @@
if (not phase.responsible_id) or (not phase.date_start) or (not phase.date_end):
raise AssertionError("Tasks not scheduled")
-
\ No newline at end of file
+
diff --git a/addons/project_long_term/test/schedule_project_tasks.yml b/addons/project_long_term/test/schedule_project_tasks.yml
index b1cd70487f7..dfc4cf1fc5e 100644
--- a/addons/project_long_term/test/schedule_project_tasks.yml
+++ b/addons/project_long_term/test/schedule_project_tasks.yml
@@ -2,103 +2,93 @@
Create project 'Develop a thunderbird-openerp synchronization plugin'
-
!record {model: project.project, id: project_project_project1}:
- company_id: base.main_company
- name: Project2
+ name: Develop a thunderbird-openerp synchronization plugin
members:
- - project_long_term.res_users_manager0
- - project_long_term.res_users_user0
- - project_long_term.res_users_userfinance0
- - project_long_term.res_users_userdesign0
- - project_long_term.res_users_userdeveloper0
- - project_long_term.res_users_usertester0
- - project_long_term.res_users_useranalyst0
+ - project_long_term.res_users_project_manager
+ - project_long_term.res_users_technical_leader
+ - project_long_term.res_users_developer
+ - project_long_term.res_users_designer
+ - project_long_term.res_users_tester
+ - project_long_term.res_users_analyst
+ - project_long_term.res_users_finacial_manager
-
- Create phase 'Develop GUI' in Thunderbird
+ Create phase 'Develop GUI' in thunderbird
-
!record {model: project.phase, id: project_phase_phase1}:
date_start: '2010-06-02'
- duration: 100.0
- name: phase22
+ duration: 200.0
+ name: Develop GUI in thunderbird
product_uom: product.uom_day
project_id: project_project_project1
state: draft
resource_ids:
- - resource_id: project_long_term.resource_resource_analyst0
+ - resource_id: project_long_term.resource_analyst
useability: 80.0
- - resource_id: project_long_term.resource_resource_programmer0
+ - resource_id: project_long_term.resource_developer
useability: 30.0
- - resource_id: project_long_term.resource_resource_webdesigner0
+ - resource_id: project_long_term.resource_designer
useability: 30.0
-
Create the phase task 'Develop GUI for Server Configuration'
-
- !record {model: project.task, id: project_task_t00}:
- name: t1
+ !record {model: project.task, id: project_task_t10}:
+ name: Develop GUI for Server Configuration
planned_hours: 20.0
remaining_hours: 20.0
state: draft
phase_id: project_phase_phase1
project_id: project_project_project1
- user_id: project_long_term.res_users_userdeveloper0
+ user_id: project_long_term.res_users_developer
-
Create the phase task 'Develop GUI for Modules Configuration'
-
!record {model: project.task, id: project_task_t11}:
- name: t2
+ name: Develop GUI for Modules Configuration
planned_hours: 25.0
remaining_hours: 25.0
state: draft
phase_id: project_phase_phase1
project_id: project_project_project1
- user_id: project_long_term.res_users_userdeveloper0
+ user_id: project_long_term.res_users_developer
-
Create the phase task 'Develop GUI for OpenERP Synchronisation'
-
- !record {model: project.task, id: project_task_t22}:
- name: t3
+ !record {model: project.task, id: project_task_t12}:
+ name: Develop GUI for OpenERP Synchronisation
planned_hours: 30.0
remaining_hours: 30.0
state: draft
phase_id: project_phase_phase1
project_id: project_project_project1
-
-
+ user_id: project_long_term.res_users_developer
-
- Create the phase task 'Develop required Menus'
+ Create the phase task 'Design required GUI/Menus'
-
- !record {model: project.task, id: project_task_t33}:
- name: t4
+ !record {model: project.task, id: project_task_13}:
+ name: Design required GUI/Menus
planned_hours: 25.0
remaining_hours: 25.0
state: draft
phase_id: project_phase_phase1
project_id: project_project_project1
-
--
- Get the project to schedule the tasks
--
- !record {model: project.compute.tasks, id: project_compute_tasks_0}:
- project_id: project_project_project1
+ user_id: project_long_term.res_users_designer
-
Schedule tasks
-
- !python {model: project.compute.tasks}: |
- self.compute_date(cr, uid, [ref("project_compute_tasks_0")], {"lang": "en_US", "tz": False,
- "active_id": ref("project_long_term.menu_compute_tasks"),
- "active_model": "ir.ui.menu", "active_ids": [ref("project_long_term.menu_compute_tasks")],
- })
+ !python {model: project.project}: |
+ self.schedule_tasks(cr, uid, ref("project_project_project1"))
-
Check if tasks scheduled, check that either of task's start_date, end_date and user_id is not null
-
!python {model: project.project}: |
- prj=self.browse(cr, uid, [ref("project_project_project1")])[0]
+ prj = self.browse(cr, uid, [ref("project_project_project1")])[0]
for task in prj.tasks:
if (not task.user_id) or (not task.date_start) or (not task.date_end):
raise AssertionError("Project Tasks not scheduled")
diff --git a/addons/project_long_term/wizard/__init__.py b/addons/project_long_term/wizard/__init__.py
index 5056cad3b77..c1e6d838111 100644
--- a/addons/project_long_term/wizard/__init__.py
+++ b/addons/project_long_term/wizard/__init__.py
@@ -22,6 +22,5 @@
import project_compute_phases
import project_compute_tasks
import project_schedule_tasks
-import working_calendar
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/project_long_term/wizard/project_compute_phases.py b/addons/project_long_term/wizard/project_compute_phases.py
index 75631fb3d18..ade1da5c9d9 100644
--- a/addons/project_long_term/wizard/project_compute_phases.py
+++ b/addons/project_long_term/wizard/project_compute_phases.py
@@ -18,18 +18,10 @@
# along with this program. If not, see .
#
##############################################################################
-
-import datetime
-from resource.faces import *
-from new import classobj
-
from tools.translate import _
from osv import fields, osv
-import working_calendar as wkcal
-
class project_compute_phases(osv.osv_memory):
-
_name = 'project.compute.phases'
_description = 'Project Compute Phases'
_columns = {
@@ -45,121 +37,26 @@ class project_compute_phases(osv.osv_memory):
}
def check_selection(self, cr, uid, ids, context=None):
- data_select = self.read(cr, uid, ids, ['target_project'])[0]
return self.compute_date(cr, uid, ids, context=context)
- def _phase_schedule(self, cr, uid, phase, start_date, calendar_id=False, context=None):
- if context is None:
- context = {}
- """Schedule phase with the start date till all the next phases are completed.
-
- Arguements: start_dsate -- start date for the phase
- calendar_id -- working calendar of the project
-
- """
- phase_obj = self.pool.get('project.phase')
- resource_obj = self.pool.get('resource.resource')
- uom_obj = self.pool.get('product.uom')
- phase_resource_obj = False
- if context is None:
- context = {}
- if phase:
- leaves = []
- time_efficiency = 1.0
- resource_id = resource_obj.search(cr, uid, [('user_id', '=', phase.responsible_id.id)])
-
- if resource_id:
- # Create a new resource object with
- # all the attributes of the Resource Class
- resource = resource_obj.browse(cr, uid, resource_id, context=context)[0]
- time_efficiency = resource.time_efficiency
- leaves = wkcal.compute_leaves(cr, uid, calendar_id , resource.id, resource.calendar_id.id)
- if not phase.responsible_id:
- raise osv.except_osv(_('No responsible person assigned !'),_("You must assign a responsible person for phase '%s' !") % (phase.name,))
- phase_resource_obj = classobj((phase.responsible_id.name.encode('utf8')), (Resource,),{
- '__doc__': phase.responsible_id.name,
- '__name__': phase.responsible_id.name,
- 'vacation': tuple(leaves),
- 'efficiency': time_efficiency
- })
- default_uom_id = phase_obj._get_default_uom_id(cr, uid)
- avg_hours = uom_obj._compute_qty(cr, uid, phase.product_uom.id, phase.duration, default_uom_id)
- duration = str(avg_hours) + 'H'
- # Create a new project for each phase
- def Project():
- start = start_date
- minimum_time_unit = 1
- resource = phase_resource_obj
- # If project has working calendar then that
- # else the default one would be considered
- if calendar_id:
- working_days = wkcal.compute_working_calendar(cr, uid, calendar_id, context=context)
- vacation = tuple(wkcal.compute_leaves(cr, uid, calendar_id))
-
- def phase():
- effort = duration
-
- project = BalancedProject(Project)
- s_date = project.phase.start.to_datetime()
- e_date = project.phase.end.to_datetime()
- # Recalculate date_start and date_end
- # according to constraints on date start and date end on phase
- if phase.constraint_date_start and str(s_date) < phase.constraint_date_start:
- start_date = datetime.datetime.strptime(phase.constraint_date_start, '%Y-%m-%d')
- else:
- start_date = s_date
- if phase.constraint_date_end and str(e_date) > phase.constraint_date_end:
- end_date= datetime.datetime.strptime(phase.constraint_date_end, '%Y-%m-%d')
- date_start = phase.constraint_date_end
- else:
- end_date = e_date
- date_start = end_date
- # Write the calculated dates back
- ctx = context.copy()
- ctx.update({'scheduler': True})
- phase_obj.write(cr, uid, [phase.id], {
- 'date_start': start_date.strftime('%Y-%m-%d'),
- 'date_end': end_date.strftime('%Y-%m-%d')
- }, context=ctx)
-
- # Recursive call till all the next phases scheduled
- for phase in phase.next_phase_ids:
- if phase.state in ['draft', 'open', 'pending']:
- id_cal = phase.project_id.resource_calendar_id and phase.project_id.resource_calendar_id.id or False
- self._phase_schedule(cr, uid, phase, date_start, id_cal, context=context)
- else:
- continue
-
+
def compute_date(self, cr, uid, ids, context=None):
"""
Compute the phases for scheduling.
"""
-
if context is None:
context = {}
- phase_obj = self.pool.get('project.phase')
+ project_pool = self.pool.get('project.project')
data = self.read(cr, uid, ids, [], context=context)[0]
if not data['project_id'] and data['target_project'] == 'one':
raise osv.except_osv(_('Error!'), _('Please Specify Project to be schedule'))
+
if data['project_id']: # If project mentioned find its phases
- project_id = data['project_id']
- phase_ids = phase_obj.search(cr, uid, [('project_id', '=', project_id),
- ('state', 'in', ['draft', 'open', 'pending']),
- ('previous_phase_ids', '=', False)
- ])
+ project_ids = [data['project_id']]
else: # Else take all the draft,open,pending states phases
- phase_ids = phase_obj.search(cr, uid,[('state', 'in', ['draft', 'open', 'pending']),
- ('previous_phase_ids', '=', False)
- ], context=context)
- phase_ids.sort()
- phases = phase_obj.browse(cr, uid, phase_ids, context=context)
- for phase in phases:
- start_date = phase.project_id.date_start
- if not phase.project_id.date_start:
- start_date = datetime.datetime.now().strftime("%Y-%m-%d")
- start_dt = datetime.datetime.strftime((datetime.datetime.strptime(start_date, "%Y-%m-%d")), "%Y-%m-%d %H:%M")
- calendar_id = phase.project_id.resource_calendar_id and phase.project_id.resource_calendar_id.id or False
- self._phase_schedule(cr, uid, phase, start_dt, calendar_id, context=context)
+ project_ids = project_pool.search(cr, uid, [], context=context)
+
+ project_pool.schedule_phases(cr, uid, project_ids, context=context)
return self._open_phases_list(cr, uid, data, context=context)
def _open_phases_list(self, cr, uid, data, context=None):
@@ -173,10 +70,7 @@ class project_compute_phases(osv.osv_memory):
result = mod_obj._get_id(cr, uid, 'project_long_term', 'act_project_phase_list')
id = mod_obj.read(cr, uid, [result], ['res_id'])[0]['res_id']
result = act_obj.read(cr, uid, [id], context=context)[0]
- result['domain'] = [('state', 'not in', ['cancelled','done'])]
- if data['project_id']:
- result['domain'] = [('project_id', '=', data['project_id']),
- ('state', 'not in', ['cancelled','done'])]
+ result['context'] = {"search_default_project_id":data['project_id'], "search_default_responsible_id":uid, "search_default_current": 1}
return result
project_compute_phases()
diff --git a/addons/project_long_term/wizard/project_compute_phases_view.xml b/addons/project_long_term/wizard/project_compute_phases_view.xml
index 8818684e8fa..9d5754af09c 100644
--- a/addons/project_long_term/wizard/project_compute_phases_view.xml
+++ b/addons/project_long_term/wizard/project_compute_phases_view.xml
@@ -16,7 +16,7 @@
-
+
diff --git a/addons/project_long_term/wizard/project_compute_tasks.py b/addons/project_long_term/wizard/project_compute_tasks.py
index 8e98f26b353..0d5fa22e6a8 100644
--- a/addons/project_long_term/wizard/project_compute_tasks.py
+++ b/addons/project_long_term/wizard/project_compute_tasks.py
@@ -19,16 +19,8 @@
#
##############################################################################
-import datetime
-from resource.faces import *
-from new import classobj
-import operator
-
-from tools.translate import _
from osv import osv, fields
-import working_calendar as wkcal
-
class project_compute_tasks(osv.osv_memory):
_name = 'project.compute.tasks'
_description = 'Project Compute Tasks'
@@ -40,108 +32,32 @@ class project_compute_tasks(osv.osv_memory):
"""
Schedule the tasks according to resource available and priority.
"""
- project_obj = self.pool.get('project.project')
+ project_pool = self.pool.get('project.project')
task_pool = self.pool.get('project.task')
- resource_obj = self.pool.get('resource.resource')
- user_obj = self.pool.get('res.users')
-
if context is None:
context = {}
-
+ context['compute_by'] = 'project'
data = self.read(cr, uid, ids, [])[0]
project_id = data['project_id']
- project = project_obj.browse(cr, uid, project_id, context=context)
- task_ids = task_pool.search(cr, uid, [('project_id', '=', project_id),
- ('state', 'in', ['draft', 'open', 'pending'])
- ])
- if task_ids:
- task_ids.sort()
- tasks = task_pool.browse(cr, uid, task_ids, context=context)
- calendar_id = project.resource_calendar_id and project.resource_calendar_id.id or False
- start_date = project.date_start
- if not project.date_start:
- start_date = datetime.datetime.now().strftime("%Y-%m-%d")
- date_start = datetime.datetime.strftime(datetime.datetime.strptime(start_date, "%Y-%m-%d"), "%Y-%m-%d %H:%M")
- # Create Resource Class objects which are the Project Members
- resources = []
- for user in project.members:
- leaves = []
- time_efficiency = 1.0
- resource_id = resource_obj.search(cr, uid, [('user_id', '=', user.id)], context=context)
- if resource_id:
-# resource = resource_obj.browse(cr, uid, resource_id, context=context)[0]
- resource = resource_obj.read(cr, uid, resource_id, ['calendar_id', 'time_efficiency'], context=context)[0]
- if resource.get('calendar_id', False):
- leaves = wkcal.compute_leaves(cr, uid, calendar_id , resource_id[0], resource['calendar_id'] and resource['calendar_id'][0] or False)
- time_efficiency = resource.get('time_efficiency')
- resources.append(classobj((user.name.encode('utf8')), (Resource,), {
- '__doc__': user.name,
- '__name__': user.name,
- 'vacation': tuple(leaves),
- 'efficiency': time_efficiency
- }))
- priority_dict = {'0': 1000, '1': 800, '2': 500, '3': 300,'4': 100}
- # Create dynamic no of tasks with the resource specified
- def create_tasks(j, eff, priorty=500, obj=None):
- def task():
- """
- task is a dynamic method!
- """
- effort = eff
- if obj:
- resource = obj
- priority = priorty
- task.__doc__ = "TaskNO%d" %j
- task.__name__ = "task%d" %j
- return task
+ project_pool.schedule_tasks(cr, uid, [project_id], context=context)
+ return self._open_task_list(cr, uid, data, context=context)
- # Create a 'Faces' project with all the tasks and resources
- def Project():
- title = project.name
- start = date_start
- try:
- resource = reduce(operator.or_, resources)
- except:
- raise osv.except_osv(_('Error'), _('Project must have members assigned !'))
- minimum_time_unit = 1
- if calendar_id: # If project has calendar
- working_days = wkcal.compute_working_calendar(cr, uid, calendar_id)
- vacation = tuple(wkcal.compute_leaves(cr, uid, calendar_id))
- # Dynamic Creation of tasks
- i = 0
- for each_task in tasks:
- hours = str(each_task.planned_hours )+ 'H'
- if each_task.priority in priority_dict.keys():
- priorty = priority_dict[each_task.priority]
- rcre = False
- if each_task.user_id:
- for resrce in resources:
- if resrce.__name__ == each_task.user_id.name: # check me!!
- rcre = resrce
- break
- task = create_tasks(i, hours, priorty, rcre)
- i += 1
-
- project = BalancedProject(Project)
- loop_no = 0
- # Write back the computed dates
- for t in project:
- s_date = t.start.to_datetime()
- e_date = t.end.to_datetime()
- if loop_no == 0:
- project_obj.write(cr, uid, [project_id], {'date': e_date}, context=context)
- else:
- ctx = context.copy()
- ctx.update({'scheduler': True})
- user_id = user_obj.search(cr, uid, [('name', '=', t.booked_resource[0].__name__)])
- task_pool.write(cr, uid, [tasks[loop_no-1].id], {
- 'date_start': s_date.strftime('%Y-%m-%d %H:%M:%S'),
- 'date_end': e_date.strftime('%Y-%m-%d %H:%M:%S'),
- 'user_id': user_id[0]
- }, context=ctx)
-
- loop_no +=1
- return {}
+ def _open_task_list(self, cr, uid, data, context=None):
+ """
+ Return the scheduled task list.
+ """
+ if context is None:
+ context = {}
+ mod_obj = self.pool.get('ir.model.data')
+ act_obj = self.pool.get('ir.actions.act_window')
+ result = mod_obj._get_id(cr, uid, 'project', 'action_view_task')
+ id = mod_obj.read(cr, uid, [result], ['res_id'])[0]['res_id']
+ result = {}
+ if not id:
+ return result
+ result = act_obj.read(cr, uid, [id], context=context)[0]
+ result['context'] = {"search_default_project_id":data['project_id'], "search_default_user_id":uid, "search_default_current": 1}
+ return result
project_compute_tasks()
diff --git a/addons/project_long_term/wizard/project_compute_tasks_view.xml b/addons/project_long_term/wizard/project_compute_tasks_view.xml
index e0cd30d5622..e6540fafff9 100644
--- a/addons/project_long_term/wizard/project_compute_tasks_view.xml
+++ b/addons/project_long_term/wizard/project_compute_tasks_view.xml
@@ -9,13 +9,13 @@
-
+
-
+
diff --git a/addons/project_long_term/wizard/project_schedule_tasks.py b/addons/project_long_term/wizard/project_schedule_tasks.py
index c64e800c9c6..48039112e86 100644
--- a/addons/project_long_term/wizard/project_schedule_tasks.py
+++ b/addons/project_long_term/wizard/project_schedule_tasks.py
@@ -19,18 +19,9 @@
#
##############################################################################
-import datetime
-from resource.faces import *
-from new import classobj
-import operator
-
-from tools.translate import _
-from osv import osv, fields
-
-import working_calendar as wkcal
+from osv import fields, osv
class project_schedule_task(osv.osv_memory):
-
_name = "project.schedule.tasks"
_description = 'project.schedule.tasks'
_columns = {
@@ -46,126 +37,17 @@ class project_schedule_task(osv.osv_memory):
res = super(project_schedule_task, self).default_get(cr, uid, fields_list, context)
self.compute_date(cr, uid, context=context)
return res
-
- def create_resources(self, cr, uid, phase, context=None):
- """
- Return a list of Resource Class objects for the resources allocated to the phase.
- """
- resource_objs = []
-
- if context is None:
- context = {}
-
- for resource in phase.resource_ids:
- res = resource.resource_id
- leaves = []
- resource_eff = res.time_efficiency
- resource_cal = res.calendar_id.id
- if resource_cal:
- cal_id = phase.project_id.resource_calendar_id and phase.project_id.resource_calendar_id.id or False
- leaves = wkcal.compute_leaves(cr, uid, cal_id, res.id, resource_cal, context=context)
- resource_objs.append(classobj(res.user_id.name.encode('utf8'), (Resource,),{
- '__doc__': res.user_id.name,
- '__name__': res.user_id.name,
- 'vacation': tuple(leaves),
- 'efficiency': resource_eff,
- }))
- return resource_objs
-
+
def compute_date(self, cr, uid, context=None):
"""
Schedule the tasks according to resource available and priority.
"""
-
- phase_obj = self.pool.get('project.phase')
- task_obj = self.pool.get('project.task')
- user_obj = self.pool.get('res.users')
-
+ phase_pool = self.pool.get('project.phase')
if context is None:
- # It makes no sense to continue on empty context
- return { 'warning': _("You must select some project phase to compute on")}
-
+ context = {}
if not 'active_id' in context:
return {}
- phase = phase_obj.browse(cr, uid, context['active_id'], context=context)
- task_ids = map(lambda x : x.id, (filter(lambda x : x.state in ['open', 'draft', 'pending'] , phase.task_ids)))
- if task_ids:
- task_ids.sort()
- tasks = task_obj.browse(cr, uid, task_ids, context=context)
- start_date = str(phase.date_start)
- if not phase.date_start:
- if not phase.project_id.date_start:
- start_date = datetime.datetime.now().strftime("%Y-%m-%d")
- else:
- start_date = phase.project_id.date_start
- date_start = datetime.datetime.strftime(datetime.datetime.strptime(start_date, "%Y-%m-%d"), "%Y-%m-%d %H:%M")
- calendar_id = phase.project_id.resource_calendar_id.id
- resources = self.create_resources(cr, uid, phase)
- priority_dict = {'0': 1000, '1': 800, '2': 500, '3': 300, '4': 100}
- # Create dynamic no of tasks with the resource specified
- def create_tasks(j, eff, priorty=500, obj=False):
- def task():
- """
- task is a dynamic method!
- """
- effort = eff
- if obj:
- resource = obj
- priority = priorty
- task.__doc__ = "TaskNO%d" %j
- task.__name__ = "task%d" %j
- return task
-
- # Create a 'Faces' project with all the tasks and resources
- def Project():
- title = "Project"
- start = date_start
- try:
- resource = reduce(operator.or_, resources)
- except:
- raise osv.except_osv(_('Error'), _('Phase must have resources assigned !'))
- minimum_time_unit = 1
- if calendar_id: # If project has working calendar
- working_days = wkcal.compute_working_calendar(cr, uid, calendar_id)
- vacation = tuple(wkcal.compute_leaves(cr, uid, calendar_id))
- # Dynamic creation of tasks
- i = 0
- for each_task in tasks:
- hours = str(each_task.planned_hours )+ 'H'
- if each_task.priority in priority_dict.keys():
- priorty = priority_dict[each_task.priority]
- resc = False
- if each_task.user_id:
- for resrce in resources:
- if resrce.__name__ == each_task.user_id.name:
- resc = resrce
- break
-
- task = create_tasks(i, hours, priorty, resc)
- i += 1
-
- project = BalancedProject(Project)
-
- loop_no = 0
- # Write back the computed dates
- for t in project:
- s_date = t.start.to_datetime()
- e_date = t.end.to_datetime()
- if loop_no > 0:
- ctx = context.copy()
- ctx.update({'scheduler': True})
- user_id = user_obj.search(cr, uid, [('name', '=', t.booked_resource[0].__name__)])
- task_obj.write(cr, uid, [tasks[loop_no-1].id], {
- 'date_start': s_date.strftime('%Y-%m-%d %H:%M:%S'),
- 'date_end': e_date.strftime('%Y-%m-%d %H:%M:%S'),
- 'user_id': user_id[0]
- }, context=ctx)
-
- loop_no += 1
- else:
- return {"warning": _("No tasks to compute for this phase") }
- return {}
-
+ return phase_pool.schedule_tasks(cr, uid, [context['active_id']], context=context)
project_schedule_task()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/project_long_term/wizard/working_calendar.py b/addons/project_long_term/wizard/working_calendar.py
deleted file mode 100644
index 139875b6236..00000000000
--- a/addons/project_long_term/wizard/working_calendar.py
+++ /dev/null
@@ -1,124 +0,0 @@
-# -*- coding: utf-8 -*-
-##############################################################################
-#
-# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2009 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 datetime
-
-import pooler
-
-def convert_timeformat(cr, uid, time_string, context=None):
- if context is None:
- context = {}
- """ Convert input time string: 8.5 to output time string 8:30."""
-
- split_list = str(time_string).split('.')
- hour_part = split_list[0]
- mins_part = split_list[1]
- round_mins = int(round(float(mins_part) * 60,-2))
- converted_string = hour_part + ':' + str(round_mins)[0:2]
- return converted_string
-
-def compute_leaves(cr, uid, calendar_id, resource_id=False, resource_calendar=False, context=None):
-
- if context is None:
- context = {}
-
- """Compute the leaves from the working calendar of the resource.
-
- Arguements: calendar_id -- working calendar of the project
- resource_id -- resource working on phase/task
- resource_calendar -- working calendar of the resource
-
- """
-
- pool = pooler.get_pool(cr.dbname)
- resource_calendar_leaves_obj = pool.get('resource.calendar.leaves')
- leave_list = []
- if resource_id:
- leave_ids = resource_calendar_leaves_obj.search(cr, uid, ['|', ('calendar_id', '=', calendar_id),
- ('calendar_id', '=', resource_calendar),
- ('resource_id', '=', resource_id)
- ], context=context)
- else:
- leave_ids = resource_calendar_leaves_obj.search(cr, uid, [('calendar_id', '=', calendar_id),
- ('resource_id', '=', False)
- ], context=context)
- leaves = resource_calendar_leaves_obj.read(cr, uid, leave_ids, ['date_from', 'date_to'], context=context)
- for i in range(len(leaves)):
- dt_start = datetime.datetime.strptime(leaves[i]['date_from'], '%Y-%m-%d %H:%M:%S')
- dt_end = datetime.datetime.strptime(leaves[i]['date_to'], '%Y-%m-%d %H:%M:%S')
- no = dt_end - dt_start
- [leave_list.append((dt_start + datetime.timedelta(days=x)).strftime('%Y-%m-%d')) for x in range(int(no.days + 1))]
- leave_list.sort()
- return leave_list
-
-def compute_working_calendar(cr, uid, calendar_id, context=None):
-
- if context is None:
- context = {}
-
- """Change the format of working calendar from 'Openerp' format to bring it into 'Faces' format.
-
- Arguement: calendar_id -- working calendar of the project
-
- """
-
- pool = pooler.get_pool(cr.dbname)
- resource_attendance_obj = pool.get('resource.calendar.attendance')
- time_range = "8:00-8:00"
- non_working = ""
- week_days = {"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_attendance_obj.search(cr, uid, [('calendar_id', '=', calendar_id)], context=context)
- weeks = resource_attendance_obj.read(cr, uid, week_ids, ['dayofweek', 'hour_from', 'hour_to'], context=context)
- # Convert time formats into appropriate format required
- # and create a list like [('mon', '8:00-12:00'), ('mon', '13:00-18:00')]
- for week in weeks:
- res_str = ""
- if week_days.has_key(week['dayofweek']):
- day = week_days[week['dayofweek']]
- wk_days[week['dayofweek']] = week_days[week['dayofweek']]
- hour_from_str = convert_timeformat(cr, uid, week['hour_from'])
- hour_to_str = convert_timeformat(cr, uid, week['hour_to'])
- res_str = hour_from_str + '-' + hour_to_str
- wktime_list.append((day, res_str))
- # Convert into format like [('mon', '8:00-12:00', '13:00-18:00')]
- for item in wktime_list:
- if wk_time.has_key(item[0]):
- wk_time[item[0]].append(item[1])
- else:
- wk_time[item[0]] = [item[0]]
- wk_time[item[0]].append(item[1])
- for k,v in wk_time.items():
- wktime_cal.append(tuple(v))
- # Add for the non-working days like: [('sat, sun', '8:00-8:00')]
- for k, v in wk_days.items():
- if week_days.has_key(k):
- week_days.pop(k)
- for v in week_days.itervalues():
- non_working += v + ','
- if non_working:
- wktime_cal.append((non_working[:-1], time_range))
- return wktime_cal
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/project_mailgate/project_mailgate_view.xml b/addons/project_mailgate/project_mailgate_view.xml
index b31eb85328e..8c8816ebbd5 100644
--- a/addons/project_mailgate/project_mailgate_view.xml
+++ b/addons/project_mailgate/project_mailgate_view.xml
@@ -8,9 +8,9 @@
-
+
-
+