diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py
index ac17ec4d170..823bb56a7a9 100644
--- a/addons/account/__openerp__.py
+++ b/addons/account/__openerp__.py
@@ -32,7 +32,7 @@
Customer and Supplier Invoices
Bank statements
Reconciliation process by partner
- Creates a dashboards for accountants that includes:
+ Creates a dashboard for accountants that includes:
* List of uninvoiced quotations
* Graph of aged receivables
* Graph of aged incomes
diff --git a/addons/account/account_bank_statement.py b/addons/account/account_bank_statement.py
index 6b8f07d0e52..647d80e61be 100644
--- a/addons/account/account_bank_statement.py
+++ b/addons/account/account_bank_statement.py
@@ -412,7 +412,7 @@ class account_bank_statement(osv.osv):
if t['state'] in ('draft'):
unlink_ids.append(t['id'])
else:
- raise osv.except_osv(_('Invalid action !'), _('Cannot delete bank statement which are already confirmed !'))
+ raise osv.except_osv(_('Invalid action !'), _('Cannot delete bank statement(s) which are already confirmed !'))
osv.osv.unlink(self, cr, uid, unlink_ids, context=context)
return True
diff --git a/addons/account/account_installer.xml b/addons/account/account_installer.xml
index a9de51c3afb..a3570fae79a 100644
--- a/addons/account/account_installer.xml
+++ b/addons/account/account_installer.xml
@@ -73,7 +73,7 @@
- Add extra Accounting Addons to the ones already installed. Remember you can always install them at a later stage.
+ Add extra Accounting functionalities to the ones already installed.Configure
diff --git a/addons/account/partner_view.xml b/addons/account/partner_view.xml
index d53fb9fe80a..ca489acd9bd 100644
--- a/addons/account/partner_view.xml
+++ b/addons/account/partner_view.xml
@@ -72,7 +72,7 @@
2
-
+
diff --git a/addons/account/project/report/analytic_balance.py b/addons/account/project/report/analytic_balance.py
index 3df4fd9584b..8050b62753f 100644
--- a/addons/account/project/report/analytic_balance.py
+++ b/addons/account/project/report/analytic_balance.py
@@ -19,7 +19,6 @@
#
##############################################################################
-import pooler
import time
from report import report_sxw
@@ -43,7 +42,6 @@ class account_analytic_balance(report_sxw.rml_parse):
self.acc_sum_list = []# maintains a list of all ids
def get_children(self, ids):
- ids2 = []
read_data = self.pool.get('account.analytic.account').read(self.cr, self.uid, ids,['child_ids','code','complete_name','balance'])
for data in read_data:
if (data['id'] not in self.acc_ids):
@@ -54,7 +52,7 @@ class account_analytic_balance(report_sxw.rml_parse):
self.acc_ids.append(data['id'])
self.read_data.append(data)
if data['child_ids']:
- res = self.get_children(data['child_ids'])
+ self.get_children(data['child_ids'])
return True
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_report.yml b/addons/account/test/account_report.yml
index bd9af0f2a34..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
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_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/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_followup/__openerp__.py b/addons/account_followup/__openerp__.py
index ea2f79c967d..ae6fb8e4fce 100644
--- a/addons/account_followup/__openerp__.py
+++ b/addons/account_followup/__openerp__.py
@@ -27,18 +27,18 @@
Modules to automate letters for unpaid invoices, with multi-level recalls.
You can define your multiple levels of recall through the menu:
- Financial Management/Configuration/Follow-Ups
+ Accounting/Configuration/Miscellaneous/Follow-Ups
- Once it's defined, you can automatically print recalls every day
+ Once it is defined, you can automatically print recalls every day
through simply clicking on the menu:
- Financial Management/Periodical Processing/Send followups
+ Accounting/Periodical Processing/Billing/Send followups
- It will generate a PDF with all the letters according the the
+ It will generate a PDF with all the letters according to the the
different levels of recall defined. You can define different policies
- for different companies. You can send also mail to the customer.
+ for different companies. You can also send mail to the customer.
- Note that if you want to change the followup level for a given partner/account entry, you can do it in the menu:
- Accounting/Reporting/Follow-Ups/All receivable entries
+ Note that if you want to change the followup level for a given partner/account entry, you can do from in the menu:
+ Accounting/Reporting/Generic Reporting/Partner Accounts/Follow-ups Sent
""",
'author': 'OpenERP SA',
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_invoice_layout/report/report_account_invoice_layout.rml b/addons/account_invoice_layout/report/report_account_invoice_layout.rml
index 0e17cfeef68..f92cd477f1a 100644
--- a/addons/account_invoice_layout/report/report_account_invoice_layout.rml
+++ b/addons/account_invoice_layout/report/report_account_invoice_layout.rml
@@ -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') ]]
diff --git a/addons/account_report/__openerp__.py b/addons/account_report/__openerp__.py
index b8029bf3563..57db73ce6ff 100644
--- a/addons/account_report/__openerp__.py
+++ b/addons/account_report/__openerp__.py
@@ -27,7 +27,7 @@
'description': """Financial and accounting reporting
Fiscal statements
Indicators
- Add a dashboards for accountant that include Indicators reporting.
+ Adds a dashboard for accountant that include Indicators reporting.
""",
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
diff --git a/addons/account_tax_include/__openerp__.py b/addons/account_tax_include/__openerp__.py
index f1e6c3dfb74..a6bab18ce01 100644
--- a/addons/account_tax_include/__openerp__.py
+++ b/addons/account_tax_include/__openerp__.py
@@ -27,7 +27,7 @@
'description': """Allow the user to work tax included prices.
Especially useful for b2c businesses.
-This module implement the modification on the invoice form.
+This module implements the modification on the invoice form.
""",
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
diff --git a/addons/account_voucher/test/account_voucher.yml b/addons/account_voucher/test/account_voucher.yml
index b63bfc9d129..424ec0e5cc7 100644
--- a/addons/account_voucher/test/account_voucher.yml
+++ b/addons/account_voucher/test/account_voucher.yml
@@ -23,7 +23,7 @@
!assert {model: account.voucher, id: account_voucher_voucherforaxelor0}:
- state == 'draft'
-
- I compute the voucher to calculate the taxes by clicking Cpmpute button
+ I compute the voucher to calculate the taxes by clicking Compute button
-
!workflow {model: account.voucher, action: proforma_voucher, ref: account_voucher_voucherforaxelor0}
-
diff --git a/addons/analytic/analytic.py b/addons/analytic/analytic.py
index b97edb9a546..cf96028f01c 100644
--- a/addons/analytic/analytic.py
+++ b/addons/analytic/analytic.py
@@ -282,6 +282,7 @@ class account_analytic_line(osv.osv):
_defaults = {
'date': time.strftime('%Y-%m-%d'),
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'account.analytic.line', context=c),
+ 'amount' : 0.00
}
_order = 'date desc'
diff --git a/addons/association/profile_association.py b/addons/association/profile_association.py
index f102d710fd8..2b73dd69885 100644
--- a/addons/association/profile_association.py
+++ b/addons/association/profile_association.py
@@ -20,20 +20,24 @@
##############################################################################
from osv import fields, osv
-import pooler
class profile_association_config_install_modules_wizard(osv.osv_memory):
_name='profile.association.config.install_modules_wizard'
_inherit = 'res.config.installer'
_columns = {
- 'hr_expense':fields.boolean('Expenses Tracking', help="Tracks the personal expenses process, from the employee expense encoding, to the reimbursement of the employee up to the reinvoicing to the final customer."),
- 'project':fields.boolean('Project Management'),
- 'event_project':fields.boolean('Organization and management of Events', help="This module allows you to create retro planning for managing your events."),
+ 'hr_expense':fields.boolean('Expenses Tracking', help="Tracks and manages employee expenses, and can "
+ "automatically re-invoice clients if the expenses are "
+ "project-related."),
+ 'project':fields.boolean('Project Management',
+ help="Helps you manage your projects and tasks by tracking them, "
+ "generating plannings, etc..."),
+ 'event_project':fields.boolean('Events', help="Helps you to manage and organize your events."),
'project_gtd':fields.boolean('Getting Things Done',
help="GTD is a methodology to efficiently organise yourself and your tasks. This module fully integrates GTD principle with OpenERP's project management."),
- 'wiki': fields.boolean('Wiki',
- help="An integrated wiki content management system. This is really usefull to manage FAQ, quality manuals, etc.")
+ 'wiki': fields.boolean('Wiki', help="Lets you create wiki pages and page groups in order "
+ "to keep track of business knowledge and share it with "
+ "and between your employees."),
}
profile_association_config_install_modules_wizard()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/auction/auction.py b/addons/auction/auction.py
index a1fb726339e..834e7e9b150 100644
--- a/addons/auction/auction.py
+++ b/addons/auction/auction.py
@@ -646,7 +646,6 @@ class auction_lots(osv.osv):
if not context:
context={}
inv_ref=self.pool.get('account.invoice')
- partner_obj = self.pool.get('res.partner')
inv_line_obj = self.pool.get('account.invoice.line')
wf_service = netsvc.LocalService('workflow')
for lot in self.browse(cr, uid, ids, context):
@@ -655,7 +654,6 @@ class auction_lots(osv.osv):
if lot.bord_vnd_id.id in invoices:
inv_id = invoices[lot.bord_vnd_id.id]
else:
- res = partner_obj.address_get(cr, uid, [lot.bord_vnd_id.partner_id.id], ['contact', 'invoice'])
inv = {
'name': 'Auction:' +lot.name,
'journal_id': lot.auction_id.journal_seller_id.id,
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/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/base_calendar/test/base_calendar_test.yml b/addons/base_calendar/test/base_calendar_test.yml
index 5ea382babb4..a9a1c039e62 100644
--- a/addons/base_calendar/test/base_calendar_test.yml
+++ b/addons/base_calendar/test/base_calendar_test.yml
@@ -12,18 +12,18 @@
name: Technical Presentation
rrule_type: none
- |
- Now I will set recurrence for this event to occure monday and friday of week
+ Now I will set recurrence for this event to occur monday and friday of week
-
!python {model: calendar.event}: |
self.write(cr, uid, [ref("calendar_event_technicalpresentation0")], {'fr': 1, 'mo': 1, 'interval': 1, 'freq': 'weekly', 'rrule_type': 'custom'})
- |
- In order to check that recurrent events are views successfully in calenadar view,
+ In order to check that recurrent events are views successfully in calendar view,
I will open calendar view of events
-
!python {model: calendar.event}: |
self.fields_view_get(cr, uid, False, 'calendar', context)
- |
- In order to check that recurrent events are views successfully in calenadar view,
+ In order to check that recurrent events are views successfully in calendar view,
I will search for one of the recurrent event and count the number of events
-
!python {model: calendar.event}: |
diff --git a/addons/base_module_doc_rst/__openerp__.py b/addons/base_module_doc_rst/__openerp__.py
index 8a7fe96b6bd..9a2e33240ac 100644
--- a/addons/base_module_doc_rst/__openerp__.py
+++ b/addons/base_module_doc_rst/__openerp__.py
@@ -24,10 +24,10 @@
'version': '1.0',
'category': 'Generic Modules/Base',
'description': """
- * This module generate the Technical Guides of selected modules in Restructured Text format (RST)
+ * This module generates the Technical Guides of selected modules in Restructured Text format (RST)
* It uses the Sphinx (http://sphinx.pocoo.org) implementation of RST
* It creates a tarball (.tgz file suffix) containing an index file and one file per module
- * Generate Relationship Graph
+ * Generates Relationship Graph
""",
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
diff --git a/addons/base_module_quality/__openerp__.py b/addons/base_module_quality/__openerp__.py
index 53e2d0ebb24..a53dde3afe3 100644
--- a/addons/base_module_quality/__openerp__.py
+++ b/addons/base_module_quality/__openerp__.py
@@ -25,7 +25,7 @@
'version': '1.0',
'category': 'OpenERP SA Specific Modules/Base module quality',
'description': """
-This module's aim is to check the quality of other modules.
+The aim of this module is to check the quality of other modules.
It defines a wizard on the list of modules in OpenERP, which allows you to
evaluate them on different criteria such as: the respect of OpenERP coding
diff --git a/addons/base_module_record/__openerp__.py b/addons/base_module_record/__openerp__.py
index 5c6eaa5f712..4d3256dc44d 100644
--- a/addons/base_module_record/__openerp__.py
+++ b/addons/base_module_record/__openerp__.py
@@ -39,7 +39,7 @@ for custom configurations and demo/testing data.
How to use it:
Run Administration/Customization/Module Creation/Export Customizations As a Module wizard.
-Select datetime critearia of recording and objects to be recorded and Record module.
+Select datetime criteria of recording and objects to be recorded and Record module.
""",
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
diff --git a/addons/base_setup/installer.py b/addons/base_setup/installer.py
index 0c8478ba57d..f415447e5fb 100644
--- a/addons/base_setup/installer.py
+++ b/addons/base_setup/installer.py
@@ -58,7 +58,7 @@ class base_setup_installer(osv.osv_memory):
help="Helps you manage your purchase-related processes such as "
"requests for quotations, supplier invoices, etc..."),
'hr':fields.boolean('Human Resources',
- help="Helps you manage your human resources by encoding your employees structure, generating work sheets, tracking attendance and more"),
+ help="Helps you manage your human resources by encoding your employees structure, generating work sheets, tracking attendance and more."),
'point_of_sale':fields.boolean('Point of Sales',
help="Helps you get the most out of your points of sales with "
"fast sale encoding, simplified payment mode encoding, "
@@ -74,7 +74,7 @@ class base_setup_installer(osv.osv_memory):
# Vertical modules
'product_expiry':fields.boolean('Food Industry',
help="Installs a preselected set of OpenERP applications "
- "which will help you manage your industry"),
+ "which will help you manage your industry."),
'association':fields.boolean('Associations',
help="Installs a preselected set of OpenERP "
"applications which will help you manage your association "
diff --git a/addons/base_vat/__openerp__.py b/addons/base_vat/__openerp__.py
index ab148f97494..0dbeac6e806 100644
--- a/addons/base_vat/__openerp__.py
+++ b/addons/base_vat/__openerp__.py
@@ -26,7 +26,7 @@
Enable the VAT Number for the partner. Check the validity of that VAT Number.
This module follows the methods stated at http://sima-pc.com/nif.php for
- checking the validity of VAT Number assinged to partners in European countries.
+ checking the validity of VAT Number assigned to partners in European countries.
""",
'author': 'OpenERP SA',
'depends': ['account'],
diff --git a/addons/caldav/caldav_node.py b/addons/caldav/caldav_node.py
index 63e683bafb7..11f720bdcab 100644
--- a/addons/caldav/caldav_node.py
+++ b/addons/caldav/caldav_node.py
@@ -19,10 +19,6 @@
#
##############################################################################
-from osv import osv, fields
-from tools.translate import _
-import pooler
-import tools
import time
from document import nodes
import StringIO
@@ -103,7 +99,12 @@ class node_calendar_collection(nodes.node_dir):
class node_calendar(nodes.node_class):
our_type = 'collection'
DAV_PROPS = {
- "http://calendarserver.org/ns/" : ('getctag',),
+ "DAV:": ('principal-collection-set'),
+ "http://cal.me.com/_namespace/" : ('user-state'),
+ "http://calendarserver.org/ns/" : (
+ 'dropbox-home-URL',
+ 'notification-URL',
+ 'getctag',),
'http://groupdav.org/': ('resourcetype',),
"urn:ietf:params:xml:ns:caldav" : (
'calendar-description',
@@ -114,6 +115,7 @@ class node_calendar(nodes.node_class):
'schedule-outbox-URL',)}
DAV_M_NS = {
"DAV:" : '_get_dav',
+ "http://cal.me.com/_namespace/": '_get_dav',
'http://groupdav.org/': '_get_gdav',
"http://calendarserver.org/ns/" : '_get_dav',
"urn:ietf:params:xml:ns:caldav" : '_get_caldav'}
@@ -134,6 +136,33 @@ class node_calendar(nodes.node_class):
result = self._get_ttag(cr) + ':' + str(time.time())
return str(result)
+ def _get_dav_dropbox_home_URL(self, cr):
+ import urllib
+ uid = self.context.uid
+ ctx = self.context.context.copy()
+ ctx.update(self.dctx)
+ calendar_obj = self.context._dirobj.pool.get('basic.calendar')
+ calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx)
+ res = '%s/%s' %(calendar.collection_id.name, calendar.name)
+ url = urllib.quote('/%s/%s' % (cr.dbname, res))
+ return url
+
+ def _get_dav_notification_URL(self, cr):
+ import urllib
+ uid = self.context.uid
+ ctx = self.context.context.copy()
+ ctx.update(self.dctx)
+ calendar_obj = self.context._dirobj.pool.get('basic.calendar')
+ calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx)
+ res = '%s/%s' %(calendar.collection_id.name, calendar.name)
+ url = urllib.quote('/%s/%s' % (cr.dbname, res))
+ return url
+
+ def _get_dav_user_state(self, cr):
+ #TODO
+ return True
+
+
def get_dav_resourcetype(self, cr):
res = [ ('collection', 'DAV:'),
(str(self.cal_type + '-collection'), 'http://groupdav.org/'),
@@ -258,6 +287,86 @@ class node_calendar(nodes.node_class):
def rmcol(self, cr):
return False
+
+ def _get_caldav_calendar_data(self, cr):
+ res = []
+ for child in self.children(cr):
+ res.append(child._get_caldav_calendar_data(cr))
+ return res
+
+ def _get_caldav_calendar_description(self, cr):
+ uid = self.context.uid
+ calendar_obj = self.context._dirobj.pool.get('basic.calendar')
+ ctx = self.context.context.copy()
+ ctx.update(self.dctx)
+ calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx)
+ return calendar.description
+
+ def _get_dav_principal_collection_set(self, cr):
+ import xml
+ import urllib
+ uid = self.context.uid
+ ctx = self.context.context.copy()
+ ctx.update(self.dctx)
+ calendar_obj = self.context._dirobj.pool.get('basic.calendar')
+ calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx)
+ res = '%s/%s' %(calendar.collection_id.name, calendar.name)
+ doc = xml.dom.minidom.getDOMImplementation().createDocument(None, 'href', None)
+ href = doc.documentElement
+ href.tagName = 'D:href'
+ huri = doc.createTextNode(urllib.quote('/%s/%s' % (cr.dbname, res)))
+ href.appendChild(huri)
+ return href
+
+ def _get_caldav_calendar_home_set(self, cr):
+ import xml.dom.minidom
+ import urllib
+ uid = self.context.uid
+ ctx = self.context.context.copy()
+ ctx.update(self.dctx)
+ doc = xml.dom.minidom.getDOMImplementation().createDocument(None, 'href', None)
+
+ calendar_obj = self.context._dirobj.pool.get('basic.calendar')
+ calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx)
+ huri = doc.createTextNode(urllib.quote('/%s/%s' % (cr.dbname, calendar.collection_id.name)))
+ href = doc.documentElement
+ href.tagName = 'D:href'
+ href.appendChild(huri)
+ return href
+
+ def _get_caldav_calendar_user_address_set(self, cr):
+ import xml.dom.minidom
+ uid = self.context.uid
+ ctx = self.context.context.copy()
+ ctx.update(self.dctx)
+ user_obj = self.context._dirobj.pool.get('res.users')
+ user = user_obj.browse(cr, uid, uid, context=ctx)
+ doc = xml.dom.minidom.getDOMImplementation().createDocument(None, 'href', None)
+ href = doc.documentElement
+ href.tagName = 'D:href'
+ huri = doc.createTextNode('MAILTO:' + str(user.email) or str(user.name))
+ href.appendChild(huri)
+ return href
+
+ def _get_caldav_schedule_outbox_URL(self, cr):
+ return self._get_caldav_schedule_inbox_URL(cr)
+
+ def _get_caldav_schedule_inbox_URL(self, cr):
+ import xml.dom.minidom
+ import urllib
+ uid = self.context.uid
+ ctx = self.context.context.copy()
+ ctx.update(self.dctx)
+ calendar_obj = self.context._dirobj.pool.get('basic.calendar')
+ calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx)
+ res = '%s/%s' %(calendar.collection_id.name, calendar.name)
+ doc = xml.dom.minidom.getDOMImplementation().createDocument(None, 'href', None)
+ href = doc.documentElement
+ href.tagName = 'D:href'
+ huri = doc.createTextNode(urllib.quote('/%s/%s' % (cr.dbname, res)))
+ href.appendChild(huri)
+ return href
+
class res_node_calendar(nodes.node_class):
our_type = 'file'
@@ -295,7 +404,6 @@ class res_node_calendar(nodes.node_class):
self.res_id = res_id
def open(self, cr, mode=False):
- uid = self.context.uid
if self.type in ('collection','database'):
return False
s = StringIO.StringIO(self.get_data(cr))
@@ -309,6 +417,9 @@ class res_node_calendar(nodes.node_class):
context.update({'model': self.model, 'res_id':self.res_id})
res = calendar_obj.export_cal(cr, uid, [self.calendar_id], context=context)
return res
+
+ def _get_caldav_calendar_data(self, cr):
+ return self.get_data(cr)
def get_data_len(self, cr, fil_obj = None):
return self.content_length
@@ -327,67 +438,6 @@ class res_node_calendar(nodes.node_class):
res = '%d' % (self.calendar_id)
return res
- def _get_caldav_calendar_data(self, cr):
- return self.get_data(cr)
-
-
- def _get_caldav_calendar_description(self, cr):
- uid = self.context.uid
- calendar_obj = self.context._dirobj.pool.get('basic.calendar')
- ctx = self.context.context.copy()
- ctx.update(self.dctx)
- calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx)
- return calendar.description
-
-
- def _get_caldav_calendar_home_set(self, cr):
- import xml.dom.minidom
- import urllib
- uid = self.context.uid
- ctx = self.context.context.copy()
- ctx.update(self.dctx)
- doc = xml.dom.minidom.getDOMImplementation().createDocument(None, 'href', None)
-
- calendar_obj = self.context._dirobj.pool.get('basic.calendar')
- calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx)
- huri = doc.createTextNode(urllib.quote('/%s/%s' % (cr.dbname, calendar.collection_id.name)))
- href = doc.documentElement
- href.tagName = 'D:href'
- href.appendChild(huri)
- return href
-
- def _get_caldav_calendar_user_address_set(self, cr):
- import xml.dom.minidom
- dirobj = self.context._dirobj
- uid = self.context.uid
- ctx = self.context.context.copy()
- ctx.update(self.dctx)
- user_obj = self.context._dirobj.pool.get('res.users')
- user = user_obj.browse(cr, uid, uid, context=ctx)
- doc = xml.dom.minidom.getDOMImplementation().createDocument(None, 'href', None)
- href = doc.documentElement
- href.tagName = 'D:href'
- huri = doc.createTextNode('MAILTO:' + user.email)
- href.appendChild(huri)
- return href
-
-
- def _get_caldav_schedule_inbox_URL(self, cr):
- import xml.dom.minidom
- import urllib
- uid = self.context.uid
- ctx = self.context.context.copy()
- ctx.update(self.dctx)
- calendar_obj = self.context._dirobj.pool.get('basic.calendar')
- calendar = calendar_obj.browse(cr, uid, self.calendar_id, context=ctx)
- res = '%s/%s' %(calendar.name, calendar.collection_id.name)
- doc = xml.dom.minidom.getDOMImplementation().createDocument(None, 'href', None)
- href = doc.documentElement
- href.tagName = 'D:href'
- huri = doc.createTextNode(urllib.quote('/%s/%s' % (cr.dbname, res)))
- href.appendChild(huri)
- return href
-
def rm(self, cr):
uid = self.context.uid
@@ -401,7 +451,6 @@ class res_node_calendar(nodes.node_class):
return res
- def _get_caldav_schedule_outbox_URL(self, cr):
- return self._get_caldav_schedule_inbox_URL(cr)
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4
diff --git a/addons/caldav/calendar.py b/addons/caldav/calendar.py
index 01c35880fbb..88b0549a3de 100644
--- a/addons/caldav/calendar.py
+++ b/addons/caldav/calendar.py
@@ -293,7 +293,6 @@ class CalDAV(object):
att_data = []
exdates = []
- _server_tzinfo = pytz.timezone(tools.get_server_timezone())
for cal_data in child.getChildren():
if cal_data.name.lower() == 'organizer':
@@ -453,7 +452,7 @@ class CalDAV(object):
else:
for key1, val1 in self.ical_get(field, 'mapping').items():
if val1 == data[map_field]:
- vevent.add(field).value = key1
+ vevent.add(field).value = key1.upper()
return vevent
def check_import(self, cr, uid, vals, context=None):
@@ -521,7 +520,7 @@ class CalDAV(object):
ical = vobject.iCalendar()
self.create_ics(cr, uid, datas, vobj, ical, context=context)
return ical
- except Exception, e:
+ except:
raise # osv.except_osv(('Error !'), (str(e)))
def import_cal(self, cr, uid, content, data_id=None, context=None):
@@ -654,7 +653,7 @@ class Calendar(CalDAV, osv.osv):
data_id = self.search(cr, uid, [])[0]
cal = self.browse(cr, uid, data_id, context=context)
cal_children = {}
- count = 0
+
for line in cal.line_ids:
cal_children[line.name] = line.object_id.model
objs = []
diff --git a/addons/crm/crm.py b/addons/crm/crm.py
index c8dde37d9e5..c6f7759859c 100644
--- a/addons/crm/crm.py
+++ b/addons/crm/crm.py
@@ -20,8 +20,6 @@
##############################################################################
import time
-from datetime import datetime
-from datetime import timedelta
import base64
import tools
from osv import fields
@@ -431,7 +429,7 @@ class crm_case(object):
# Send an email
subject = "Reminder: [%s] %s" % (str(case.id), case.name, )
- flag = tools.email_send(
+ tools.email_send(
src,
[dest],
subject,
@@ -587,7 +585,7 @@ class crm_case_categ(osv.osv):
_description = "Category of case"
_columns = {
- 'name': fields.char('Case Category Name', size=64, required=True, translate=True),
+ 'name': fields.char('Name', size=64, required=True, translate=True),
'section_id': fields.many2one('crm.case.section', 'Sales Team'),
'object_id': fields.many2one('ir.model', 'Object Name'),
}
@@ -636,7 +634,7 @@ class crm_case_stage(osv.osv):
'section_id': fields.many2one('crm.case.section', 'Sales Team'),
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of case stages."),
'object_id': fields.many2one('ir.model', 'Object Name'),
- 'probability': fields.float('Probability (%)', required=True),
+ 'probability': fields.float('Probability (%)', required=True, help="This percentage depicts the default/average probability of the Case for this stage to be a success"),
'on_change': fields.boolean('Change Probability Automatically', \
help="Change Probability on next and previous stages."),
'requirements': fields.text('Requirements')
diff --git a/addons/crm/crm_installer.py b/addons/crm/crm_installer.py
index 6797afc62e0..32551d438c4 100644
--- a/addons/crm/crm_installer.py
+++ b/addons/crm/crm_installer.py
@@ -20,12 +20,7 @@
##############################################################################
from lxml import etree
-from operator import itemgetter
from osv import fields, osv
-import netsvc
-import os
-import pooler
-import tools
class crm_installer(osv.osv_memory):
_name = 'crm.installer'
@@ -33,15 +28,15 @@ class crm_installer(osv.osv_memory):
_columns = {
'name': fields.char('Name', size=64),
- 'crm_helpdesk': fields.boolean('Helpdesk', help="Manages an Helpdesk service."),
+ 'crm_helpdesk': fields.boolean('Helpdesk', help="Manages a Helpdesk service."),
'crm_fundraising': fields.boolean('Fundraising', help="This may help associations in their fundraising process and tracking."),
'crm_claim': fields.boolean('Claims', help="Manages the suppliers and customers claims, including your corrective or preventive actions."),
'crm_caldav': fields.boolean('Calendar Synchronizing', help="Helps you to synchronize the meetings with other calendar clients and mobiles."),
'sale_crm': fields.boolean('Opportunity to Quotation', help="This module relates sale from opportunity cases in the CRM."),
- 'fetchmail': fields.boolean('Fetch Emails', help="Fetchmail Server."),
- 'thunderbird': fields.boolean('Thunderbird', help="Allows you to link your e-mail to OpenERP's documents. You can attach it to any existing one in OpenERP or create a new one"),
- 'outlook': fields.boolean('MS-Outlook', help="Allows you to link your e-mail to OpenERP's documents. You can attach it to any existing one in OpenERP or create a new one"),
- 'wiki_sale_faq': fields.boolean('Sale FAQ', help="Sale FAQ."),
+ 'fetchmail': fields.boolean('Fetch Emails', help="Allows you to receive E-Mails from POP/IMAP server."),
+ 'thunderbird': fields.boolean('Thunderbird', help="Allows you to link your e-mail to OpenERP's documents. You can attach it to any existing one in OpenERP or create a new one."),
+ 'outlook': fields.boolean('MS-Outlook', help="Allows you to link your e-mail to OpenERP's documents. You can attach it to any existing one in OpenERP or create a new one."),
+ 'wiki_sale_faq': fields.boolean('Sale FAQ', help="Helps you manage wiki pages for Frequently Asked Questions on Sales Application."),
}
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
diff --git a/addons/crm/crm_installer_view.xml b/addons/crm/crm_installer_view.xml
index 5fad3f41a3d..ece3bae31ec 100644
--- a/addons/crm/crm_installer_view.xml
+++ b/addons/crm/crm_installer_view.xml
@@ -16,7 +16,7 @@
- Enhance your CRM basic Application with additional Addons.
+ Enhance your core CRM Application with additional functionalities.13
diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py
index da09795547a..0a552a4165a 100644
--- a/addons/crm/crm_lead.py
+++ b/addons/crm/crm_lead.py
@@ -125,6 +125,7 @@ class crm_lead(crm_case, osv.osv):
domain="['|',('section_id','=',section_id),('section_id','=',False)]"),
'channel_id': fields.many2one('res.partner.canal', 'Channel'),
+ 'contact_name': fields.char('Contact Name', size=64),
'partner_name': fields.char("Partner Name", size=64),
'optin': fields.boolean('Opt-In'),
'optout': fields.boolean('Opt-Out'),
diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml
index 41d41ef0502..2df1369bbb1 100644
--- a/addons/crm/crm_lead_view.xml
+++ b/addons/crm/crm_lead_view.xml
@@ -55,7 +55,7 @@
-
@@ -235,8 +238,8 @@
-
-
+
+
@@ -299,7 +302,7 @@
-
+
@@ -337,6 +340,7 @@
help="Show Sales Team"/>
+
@@ -365,7 +369,7 @@
-
diff --git a/addons/crm/crm_meeting_view.xml b/addons/crm/crm_meeting_view.xml
index 55ef2c7d5e3..06cb0280567 100644
--- a/addons/crm/crm_meeting_view.xml
+++ b/addons/crm/crm_meeting_view.xml
@@ -317,32 +317,31 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/crm/crm_opportunity_view.xml b/addons/crm/crm_opportunity_view.xml
index 8101a0bcfb2..c2713b91f89 100644
--- a/addons/crm/crm_opportunity_view.xml
+++ b/addons/crm/crm_opportunity_view.xml
@@ -133,7 +133,7 @@
-
+
-
-
@@ -272,7 +272,7 @@
+
+
+
-
-
-
-
+
diff --git a/addons/crm/crm_phonecall_menu.xml b/addons/crm/crm_phonecall_menu.xml
index 481e92ec134..8585ddc7fe4 100644
--- a/addons/crm/crm_phonecall_menu.xml
+++ b/addons/crm/crm_phonecall_menu.xml
@@ -13,7 +13,8 @@
groups="base.group_extended"
/>
-
+
diff --git a/addons/crm/crm_phonecall_view.xml b/addons/crm/crm_phonecall_view.xml
index 4f60b91b3c2..0832c0a16ee 100644
--- a/addons/crm/crm_phonecall_view.xml
+++ b/addons/crm/crm_phonecall_view.xml
@@ -16,19 +16,6 @@
-
-
-
- Phonecall Campaigns
- crm.case.resource.type
- form
-
-
-
-
-
@@ -47,9 +34,10 @@
@@ -94,7 +82,7 @@
@@ -121,7 +109,7 @@
states="draft,pending" type="object"
icon="gtk-go-forward" />
+ states="open" type="object" icon="gtk-media-pause" />
@@ -172,7 +160,7 @@
@@ -219,10 +207,14 @@
string="Type" />
+
-
-
-
-
+ context="{'group_by':'date'}" help="Date of Call" />
diff --git a/addons/crm/crm_view.xml b/addons/crm/crm_view.xml
index db248be7492..061888d02fb 100644
--- a/addons/crm/crm_view.xml
+++ b/addons/crm/crm_view.xml
@@ -113,7 +113,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 c5818536f8c..4003cded168 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/hr_recruitment/report/hr_recruitment_report.py b/addons/hr_recruitment/report/hr_recruitment_report.py
index 524a2265e23..2a2ab8fce2b 100644
--- a/addons/hr_recruitment/report/hr_recruitment_report.py
+++ b/addons/hr_recruitment/report/hr_recruitment_report.py
@@ -23,10 +23,10 @@ from osv import fields,osv
from hr_recruitment import hr_recruitment
AVAILABLE_STATES = [
- ('draft','Draft'),
+ ('draft','New'),
('open','Open'),
- ('cancel', 'Cancelled'),
- ('done', 'Closed'),
+ ('cancel', 'Refused'),
+ ('done', 'Hired'),
('pending','Pending')
]
@@ -69,10 +69,11 @@ class hr_recruitment_report(osv.osv):
'date_closed': fields.date('Closed', readonly=True),
'job_id': fields.many2one('hr.job', 'Applied Job',readonly=True),
'stage_id': fields.many2one ('hr.recruitment.stage', 'Stage'),
- 'type_id': fields.many2one('crm.case.resource.type', 'Degree', domain="[('object_id.model', '=', 'hr.applicant')]"),
+ 'type_id': fields.many2one('hr.recruitment.degree', 'Degree'),
'department_id':fields.many2one('hr.department','Department',readonly=True),
'priority': fields.selection(hr_recruitment.AVAILABLE_PRIORITIES, 'Appreciation'),
'salary_prop' : fields.float("Salary Proposed"),
+ 'salary_prop_avg' : fields.float("Avg Salary Proposed", group_operator="avg"),
'salary_exp' : fields.float("Salary Expected"),
'partner_id': fields.many2one('res.partner', 'Partner',readonly=True),
'partner_address_id': fields.many2one('res.partner.address', 'Partner Contact Name',readonly=True),
@@ -107,6 +108,7 @@ class hr_recruitment_report(osv.osv):
s.priority,
s.stage_id,
sum(salary_proposed) as salary_prop,
+ (sum(salary_proposed)/count(*)) as salary_prop_avg,
sum(salary_expected) as salary_exp,
extract('epoch' from (s.date_open-s.create_date))/(3600*24) as delay_open,
extract('epoch' from (s.date_closed-s.create_date))/(3600*24) as delay_close,
diff --git a/addons/hr_recruitment/report/hr_recruitment_report_view.xml b/addons/hr_recruitment/report/hr_recruitment_report_view.xml
index edb00d1f727..d1f06577fb2 100644
--- a/addons/hr_recruitment/report/hr_recruitment_report_view.xml
+++ b/addons/hr_recruitment/report/hr_recruitment_report_view.xml
@@ -21,11 +21,12 @@
-
-
-
-
+
+
+
+
+
@@ -49,18 +50,18 @@
-
-
+
-
+
+ domain="[('date','<=', (datetime.date (int(time.strftime('%%Y')), datetime.date.today().month, 1) - datetime.timedelta (days = 1)).strftime('%%Y-%%m-%%d')),('date','>',(datetime.date (int(time.strftime('%%Y')), datetime.date.today().month-1, 1)).strftime('%%Y-%%m-%%d'))]"
+ help="Recruitment during last month"/>
+
-
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -127,10 +130,10 @@
hr.recruitment.reportformtree,graph
- {'search_default_month':1,'search_default_User':1,'search_default_user_id':uid,'group_by_no_leaf':1,'group_by':[]}
+ {'search_default_month':1,'search_default_department':1,'group_by_no_leaf':1,'group_by':[]}
-
+
diff --git a/addons/hr_recruitment/security/ir.model.access.csv b/addons/hr_recruitment/security/ir.model.access.csv
index bc7bc365b00..92dc912180d 100644
--- a/addons/hr_recruitment/security/ir.model.access.csv
+++ b/addons/hr_recruitment/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_hr_applicant_user","hr.applicant.user","model_hr_applicant","base.group_hr_user",1,1,1,1
-"access_hr_recruitment_report","hr.recruitment.report","model_hr_recruitment_report","base.group_hr_manager",1,0,0,0
+"access_hr_recruitment_report","hr.recruitment.report","model_hr_recruitment_report","base.group_hr_manager",1,1,1,1
"access_hr_recruitment_stage_user","hr.recruitment.stage.user","model_hr_recruitment_stage","base.group_hr_user",1,1,1,1
"access_hr_recruitment_degree","hr.recruitment.degree","model_hr_recruitment_degree","base.group_hr_user",1,1,1,1
"access_hr_recruitment_stage_system","hr.recruitment.stage.system","model_hr_recruitment_stage","base.group_system",1,1,1,1
-"access_hr_applicant_manager","hr.applicant.manager","model_hr_applicant","base.group_hr_manager",1,0,0,0
+"access_hr_applicant_manager","hr.applicant.manager","model_hr_applicant","base.group_hr_manager",1,1,1,1
"access_hr_applicant_system","hr.applicant.system","model_hr_applicant","base.group_system",1,0,0,0
-"access_hr_recruitment_stage_manager","hr.recruitment.stage.manager","model_hr_recruitment_stage","base.group_hr_manager",1,0,0,0
+"access_hr_recruitment_stage_manager","hr.recruitment.stage.manager","model_hr_recruitment_stage","base.group_hr_manager",1,1,1,1
+"access_hr_recruitment_degree_manager","hr.recruitment.degree.manager","model_hr_recruitment_degree","base.group_hr_manager",1,1,1,1
diff --git a/addons/hr_recruitment/wizard/hr_recruitment_phonecall.py b/addons/hr_recruitment/wizard/hr_recruitment_phonecall.py
index 99d064a67e8..7cb5366a275 100644
--- a/addons/hr_recruitment/wizard/hr_recruitment_phonecall.py
+++ b/addons/hr_recruitment/wizard/hr_recruitment_phonecall.py
@@ -98,7 +98,7 @@ class job2phonecall(osv.osv_memory):
new_phonecall = phonecall_case_obj.browse(cr, uid, new_phonecall_id, context=context)
vals = {}
job_case_obj.write(cr, uid, [job.id], vals, context=context)
- job_case_obj.case_cancel(cr, uid, [job.id])
+# job_case_obj.case_cancel(cr, uid, [job.id])
phonecall_case_obj.case_open(cr, uid, [new_phonecall_id])
return {
diff --git a/addons/hr_timesheet/hr_timesheet.py b/addons/hr_timesheet/hr_timesheet.py
index de448ced584..ee4abdb35c4 100644
--- a/addons/hr_timesheet/hr_timesheet.py
+++ b/addons/hr_timesheet/hr_timesheet.py
@@ -64,7 +64,7 @@ class hr_analytic_timesheet(osv.osv):
if prod_id and unit_amount:
# find company
company_id = self.pool.get('res.company')._company_default_get(cr, uid, 'account.analytic.line', context=context)
- res = self.pool.get('account.analytic.line').on_change_unit_amount(cr, uid, id, prod_id, unit_amount, company_id, unit, context=context)
+ res.update(self.pool.get('account.analytic.line').on_change_unit_amount(cr, uid, id, prod_id, unit_amount, company_id, unit, context=context))
# update unit of measurement
if prod_id:
uom = self.pool.get('product.product').browse(cr, uid, prod_id, context=context)
diff --git a/addons/hr_timesheet/hr_timesheet_view.xml b/addons/hr_timesheet/hr_timesheet_view.xml
index 6029336542d..4165f71d73f 100644
--- a/addons/hr_timesheet/hr_timesheet_view.xml
+++ b/addons/hr_timesheet/hr_timesheet_view.xml
@@ -16,8 +16,8 @@
-
+
@@ -67,16 +67,22 @@
-
-
+
+
+
+
+
+
+
+
+
+
@@ -113,7 +119,7 @@
hr.employee
-
+
diff --git a/addons/hr_timesheet/security/ir.model.access.csv b/addons/hr_timesheet/security/ir.model.access.csv
index 0b75f11e2c4..2b01017fb65 100644
--- a/addons/hr_timesheet/security/ir.model.access.csv
+++ b/addons/hr_timesheet/security/ir.model.access.csv
@@ -5,6 +5,12 @@
"access_product_product_user","product.product user","product.model_product_product","base.group_hr_user",1,0,0,0
"access_product_template_hr_timesheet","product.template.hr.timesheet","product.model_product_template","base.group_hr_user",1,0,0,0
"access_product_uom_hr_timesheet","product.uom.hr.timesheet","product.model_product_uom","base.group_hr_user",1,0,0,0
-"access_hr_analytic_timesheet_manager","hr.analytic.timesheet.manager","model_hr_analytic_timesheet","base.group_hr_manager",1,0,0,0
+"access_hr_analytic_timesheet_manager","hr.analytic.timesheet.manager","model_hr_analytic_timesheet","base.group_hr_manager",1,1,1,1
"access_hr_analytic_timesheet_system","hr.analytic.timesheet.system","model_hr_analytic_timesheet","base.group_system",1,0,0,0
+"access_hr_account_analytic_line_manager","account.account.analytic.line.manager","account.model_account_analytic_line","base.group_hr_manager",1,1,1,1
+"access_account_analytic_journal_manager","account.account.analytic.journal.manager","account.model_account_analytic_journal","base.group_hr_manager",1,1,1,1
+"access_product_product_manager","product.product.manager","product.model_product_product","base.group_hr_manager",1,1,1,1
+"access_product_template_hr_timesheet_manager","product.template.hr.timesheet.manager","product.model_product_template","base.group_hr_manager",1,1,1,1
+"access_product_uom_hr_timesheet_manager","product.uom.hr.timesheet.manager","product.model_product_uom","base.group_hr_manager",1,1,1,1
"access_hr_analytic_timesheet_employee","hr.analytic.timesheet.employee","model_hr_analytic_timesheet","base.group_user",1,1,1,0
+"access_account_analytic_line_user","account.account.analytic.line.user","account.model_account_analytic_line","base.group_user",1,0,0,0
diff --git a/addons/hr_timesheet_invoice/board_hr_timesheet_invoice.xml b/addons/hr_timesheet_invoice/board_hr_timesheet_invoice.xml
index 2d38011f279..ff61617661c 100644
--- a/addons/hr_timesheet_invoice/board_hr_timesheet_invoice.xml
+++ b/addons/hr_timesheet_invoice/board_hr_timesheet_invoice.xml
@@ -65,7 +65,7 @@
board.hr.timesheet.uninvoiced.formboard.boardform
-
+
diff --git a/addons/hr_timesheet_invoice/hr_timesheet_invoice.py b/addons/hr_timesheet_invoice/hr_timesheet_invoice.py
index ed1c8394de1..7f79051edce 100644
--- a/addons/hr_timesheet_invoice/hr_timesheet_invoice.py
+++ b/addons/hr_timesheet_invoice/hr_timesheet_invoice.py
@@ -82,7 +82,7 @@ class account_analytic_line(osv.osv):
_inherit = 'account.analytic.line'
_columns = {
'invoice_id': fields.many2one('account.invoice', 'Invoice', ondelete="set null"),
- 'to_invoice': fields.many2one('hr_timesheet_invoice.factor', 'Type of Invoicing'),
+ 'to_invoice': fields.many2one('hr_timesheet_invoice.factor', 'Type of Invoicing', help="It allows to set the discount while making invoice"),
}
def unlink(self, cursor, user, ids, context=None):
diff --git a/addons/hr_timesheet_invoice/hr_timesheet_invoice_view.xml b/addons/hr_timesheet_invoice/hr_timesheet_invoice_view.xml
index 1befaebf168..c7435127466 100644
--- a/addons/hr_timesheet_invoice/hr_timesheet_invoice_view.xml
+++ b/addons/hr_timesheet_invoice/hr_timesheet_invoice_view.xml
@@ -10,7 +10,7 @@
-
+
@@ -21,6 +21,17 @@
+
hr.analytic.timesheet.formhr.analytic.timesheet
diff --git a/addons/hr_timesheet_invoice/report/hr_timesheet_invoice_report_view.xml b/addons/hr_timesheet_invoice/report/hr_timesheet_invoice_report_view.xml
index 163e641582c..ba155d3590a 100644
--- a/addons/hr_timesheet_invoice/report/hr_timesheet_invoice_report_view.xml
+++ b/addons/hr_timesheet_invoice/report/hr_timesheet_invoice_report_view.xml
@@ -60,7 +60,7 @@
domain="[('date','<=', time.strftime('%%Y-%%m-%%d')), ('date','>',(datetime.date.today()-datetime.timedelta(days=7)).strftime('%%Y-%%m-%%d'))]"
help="Timesheet lines during last 7 days"/>
-
+
-
+
+
+
+
+
+
+
@@ -80,12 +86,6 @@
-
-
-
-
-
-
diff --git a/addons/hr_timesheet_invoice/security/ir.model.access.csv b/addons/hr_timesheet_invoice/security/ir.model.access.csv
index 7089e184f98..2dd928fc924 100644
--- a/addons/hr_timesheet_invoice/security/ir.model.access.csv
+++ b/addons/hr_timesheet_invoice/security/ir.model.access.csv
@@ -14,3 +14,7 @@
"access_report_timesheet_line","report.timesheet.line","model_report_timesheet_line","base.group_hr_manager",1,0,0,0
"access_account_invoice_hr_user","account.invoice.hr.user","account.model_account_invoice","base.group_hr_user",1,1,1,0
"access_account_fiscalyear_hr_user","account.fiscalyear.hr.user","account.model_account_fiscalyear","base.group_hr_user",1,1,1,0
+"access_account_invoice_hr_manager","account.invoice.hr.manager","account.model_account_invoice","base.group_hr_manager",1,1,1,1
+"access_hr_timesheet_invoice_factor_hr_manager","hr_timesheet_invoice.factor.hr.manager","model_hr_timesheet_invoice_factor","base.group_hr_manager",1,1,1,1
+"access_account_invoice_tax_hr_manager","account.invoice.tax.hr.manager","account.model_account_invoice_tax","base.group_hr_manager",1,1,1,1
+"access_report_timesheet_line_employee","report.timesheet.line.employee","model_report_timesheet_line","base.group_user",1,1,1,0
diff --git a/addons/hr_timesheet_sheet/board_hr_timesheet_view.xml b/addons/hr_timesheet_sheet/board_hr_timesheet_view.xml
index 1fa5206fa90..f299cb94298 100644
--- a/addons/hr_timesheet_sheet/board_hr_timesheet_view.xml
+++ b/addons/hr_timesheet_sheet/board_hr_timesheet_view.xml
@@ -52,7 +52,7 @@
board.hr.timesheet.formboard.board
-
+ form
@@ -77,5 +77,31 @@
+
+ My Total Attendances By Week
+ hr_timesheet_sheet.sheet
+ form
+ graph
+ [('user_id','=',uid)]
+
+
+
+ board.hr.timesheet.sheet.form
+ board.board
+
+ form
+
+
+
+
+
+
+
diff --git a/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml b/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml
index d9b666cfbf1..19a9af3c33d 100644
--- a/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml
+++ b/addons/hr_timesheet_sheet/hr_timesheet_sheet_view.xml
@@ -148,10 +148,10 @@
-
+
-
+
@@ -313,7 +313,17 @@
-
+
+ hr.timesheet.sheet.sheet.graph
+ hr_timesheet_sheet.sheet
+ graph
+
+
+
+
+
+
+
diff --git a/addons/hr_timesheet_sheet/report/hr_timesheet_report.py b/addons/hr_timesheet_sheet/report/hr_timesheet_report.py
index 100041ca35a..84ef868ab81 100644
--- a/addons/hr_timesheet_sheet/report/hr_timesheet_report.py
+++ b/addons/hr_timesheet_sheet/report/hr_timesheet_report.py
@@ -28,6 +28,7 @@ class hr_timesheet_report(osv.osv):
_auto = False
_columns = {
'year': fields.char('Year',size=64,required=False, readonly=True),
+ 'day': fields.char('Day', size=128, 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),
@@ -50,6 +51,7 @@ class hr_timesheet_report(osv.osv):
select
min(t.id) as id,
l.date as date,
+ to_char(l.date, 'YYYY-MM-DD') as day,
to_char(l.date,'YYYY') as year,
to_char(l.date,'MM') as month,
sum(l.amount) as cost,
diff --git a/addons/hr_timesheet_sheet/report/hr_timesheet_report_view.xml b/addons/hr_timesheet_sheet/report/hr_timesheet_report_view.xml
index 4515215e4a1..9c0588f618e 100644
--- a/addons/hr_timesheet_sheet/report/hr_timesheet_report_view.xml
+++ b/addons/hr_timesheet_sheet/report/hr_timesheet_report_view.xml
@@ -21,7 +21,7 @@
-
+
@@ -41,37 +41,23 @@
-
-
+
-
+ domain="[('date','<=', time.strftime('%%Y-%%m-%%d')),('date','>=',time.strftime('%%Y-%%m-01'))]"
+ help="Timesheet in current month"/>
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -81,6 +67,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/hr_timesheet_sheet/report/timesheet_report_view.xml b/addons/hr_timesheet_sheet/report/timesheet_report_view.xml
index a786a123529..08abc6db63b 100644
--- a/addons/hr_timesheet_sheet/report/timesheet_report_view.xml
+++ b/addons/hr_timesheet_sheet/report/timesheet_report_view.xml
@@ -49,18 +49,17 @@
-
-
+
-
+ help="Timesheet in current month"/>
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -91,23 +104,9 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
diff --git a/addons/hr_timesheet_sheet/security/ir.model.access.csv b/addons/hr_timesheet_sheet/security/ir.model.access.csv
index de19d325f5f..116396612e8 100644
--- a/addons/hr_timesheet_sheet/security/ir.model.access.csv
+++ b/addons/hr_timesheet_sheet/security/ir.model.access.csv
@@ -5,7 +5,7 @@
"access_hr_timesheet_report","hr.timesheet.report","model_hr_timesheet_report","base.group_hr_manager",1,1,1,1
"access_hr_timesheet_sheet_sheet_manager","hr_timesheet_sheet.sheet.manager","model_hr_timesheet_sheet_sheet","base.group_hr_manager",1,1,1,1
"access_hr_timesheet_sheet_sheet_system","hr_timesheet_sheet.sheet.system","model_hr_timesheet_sheet_sheet","base.group_system",1,0,0,0
-"access_timesheet_report_manager","timesheet.report.manager","model_timesheet_report","base.group_hr_manager",1,1,1,1
+"access_timesheet_report_employee","timesheet.report.employee","model_timesheet_report","base.group_user",1,1,1,0
"access_hr_timesheet_sheet_sheet_employee","hr_timesheet_sheet.sheet.employee","model_hr_timesheet_sheet_sheet","base.group_user",1,1,1,0
"access_hr_timesheet_sheet_sheet_day_manager","hr_timesheet_sheet.sheet.day.manager","model_hr_timesheet_sheet_sheet_day","base.group_hr_manager",1,1,1,1
"access_hr_timesheet_sheet_sheet_account_manager","hr_timesheet_sheet.sheet.account.manager","model_hr_timesheet_sheet_sheet_account","base.group_hr_manager",1,1,1,1
diff --git a/addons/idea/report/report_vote_view.xml b/addons/idea/report/report_vote_view.xml
index 201bdd40721..9556f86a281 100644
--- a/addons/idea/report/report_vote_view.xml
+++ b/addons/idea/report/report_vote_view.xml
@@ -31,15 +31,15 @@
+ help="Idea Vote created in curren year"/>
+ help="Idea Vote created in current month"/>
+ help="Idea Vote created last month"/>
-
+
-
+
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 4fadcdce471..7aafee1a447 100644
--- a/addons/mrp_repair/mrp_repair.py
+++ b/addons/mrp_repair/mrp_repair.py
@@ -428,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:
diff --git a/addons/point_of_sale/report/all_closed_cashbox_of_the_day.py b/addons/point_of_sale/report/all_closed_cashbox_of_the_day.py
index 8ec13ede5f5..28b96f7aebe 100644
--- a/addons/point_of_sale/report/all_closed_cashbox_of_the_day.py
+++ b/addons/point_of_sale/report/all_closed_cashbox_of_the_day.py
@@ -24,7 +24,7 @@ from report import report_sxw
class all_closed_cashbox_of_the_day(report_sxw.rml_parse):
-
+ #TOFIX: sql injection problem: SQL Request must be pass from sql injection...
def __init__(self, cr, uid, name, context):
super(all_closed_cashbox_of_the_day, self).__init__(cr, uid, name, context)
self.localcontext.update({
@@ -91,13 +91,13 @@ class all_closed_cashbox_of_the_day(report_sxw.rml_parse):
return False
def _get_partner(self,statement):
res = {}
- sql =""" select rp.name from account_bank_statement_line as absl,res_partner as rp
- where absl.partner_id = rp.id
- and absl.pos_statement_id = %d"""%(statement['pos_statement_id'])
- self.cr.execute(sql)
- res = self.cr.dictfetchall()
- if res :
- return res[0]['name']
+ if statement['pos_statement_id']:
+ sql =""" select rp.name from account_bank_statement_line as absl,res_partner as rp
+ where absl.partner_id = rp.id
+ and absl.pos_statement_id = %d"""%(statement['pos_statement_id'])
+ self.cr.execute(sql)
+ res = self.cr.dictfetchall() or {}
+ return res and res[0]['name']
else :
return 0.00
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/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/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 @@
+
-
+
-
+
+
+
+
+
+
+
@@ -110,9 +117,9 @@
-
+
-
+
@@ -239,7 +246,7 @@
-
+
@@ -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 @@
-
+
-
+