diff --git a/addons/crm/__openerp__.py b/addons/crm/__openerp__.py
index a490a800beb..f23b61df5ea 100644
--- a/addons/crm/__openerp__.py
+++ b/addons/crm/__openerp__.py
@@ -85,6 +85,8 @@ Create dashboard for CRM that includes:
'wizard/crm_forward_to_partner_view.xml',
'wizard/crm_send_email_view.xml',
+ 'wizard/crm_custom_create_menu_view.xml',
+
'crm_view.xml',
'crm_action_rule_view.xml',
diff --git a/addons/crm/board_crm_statistical_view.xml b/addons/crm/board_crm_statistical_view.xml
index b23fdeac1cd..01d0472c21e 100644
--- a/addons/crm/board_crm_statistical_view.xml
+++ b/addons/crm/board_crm_statistical_view.xml
@@ -36,7 +36,7 @@
-
+
@@ -60,7 +60,7 @@
- Number of Opportunities by stage
+ Planned revenue by user and stage
crm.lead.report
form
graph,tree,form
@@ -93,7 +93,7 @@
diff --git a/addons/crm/board_crm_view.xml b/addons/crm/board_crm_view.xml
index ed6044a6fd6..ccaf0f7e35c 100644
--- a/addons/crm/board_crm_view.xml
+++ b/addons/crm/board_crm_view.xml
@@ -51,7 +51,7 @@
form
graph,tree,form
- ['&', ('user_id','=',uid), '!' , '&', ('state', '=', 'done'), ('date_closed','>',(datetime.date.today()-datetime.timedelta(days=30)).strftime('%Y-%m-%d'))]
+ ['&', '&', ('user_id','=',uid), ('type', '=', 'opportunity'), '!' , '&', ('state', '=', 'done'), ('date_closed','>',(datetime.date.today()-datetime.timedelta(days=30)).strftime('%Y-%m-%d'))]
@@ -84,11 +84,11 @@
diff --git a/addons/crm/crm.py b/addons/crm/crm.py
index 575c2a8a3e3..9dd021183f4 100644
--- a/addons/crm/crm.py
+++ b/addons/crm/crm.py
@@ -639,4 +639,86 @@ class res_partner(osv.osv):
}
res_partner()
+
+class crm_case_section_custom(osv.osv):
+ _name = "crm.case.section.custom"
+ _description = 'Custom CRM Case Section'
+
+ _columns = {
+ 'name': fields.char('Case Section',size=64, required=True, translate=True),
+ 'code': fields.char('Section Code',size=8),
+ 'active': fields.boolean('Active'),
+ 'allow_unlink': fields.boolean('Allow Delete', help="Allows to delete non draft cases"),
+ 'sequence': fields.integer('Sequence'),
+ 'user_id': fields.many2one('res.users', 'Responsible User'),
+ 'reply_to': fields.char('Reply-To', size=64, help="The email address put in the 'Reply-To' of all emails sent by Open ERP about cases in this section"),
+ 'parent_id': fields.many2one('crm.case.section', 'Parent Section'),
+ 'note': fields.text('Notes'),
+ }
+
+ _defaults = {
+ 'active': 1,
+ 'allow_unlink': 1,
+ }
+
+ _sql_constraints = [
+ ('code_uniq', 'unique (code)', 'The code of the section must be unique !')
+ ]
+
+ def _check_recursion(self, cr, uid, ids):
+ level = 100
+ while len(ids):
+ cr.execute('SELECT DISTINCT parent_id FROM crm_case_section '\
+ 'WHERE id IN %s',
+ (tuple(ids),))
+ ids = filter(None, map(lambda x:x[0], cr.fetchall()))
+ if not level:
+ return False
+ level -= 1
+ return True
+ _constraints = [
+ (_check_recursion, 'Error ! You cannot create recursive sections.', ['parent_id'])
+ ]
+
+crm_case_section_custom()
+
+
+class crm_case_custom(osv.osv, crm_case):
+ _name = 'crm.case.custom'
+ _inherit = 'mailgate.thread'
+ _description = "Custom CRM Case"
+
+ _columns = {
+ 'id': fields.integer('ID', readonly=True),
+ 'name': fields.char('Name',size=64,required=True),
+ 'priority': fields.selection(AVAILABLE_PRIORITIES, 'Priority'),
+ 'active': fields.boolean('Active'),
+ 'description': fields.text('Description'),
+ 'section_id': fields.many2one('crm.case.section.custom', 'Section', required=True, select=True),
+ 'probability': fields.float('Probability (%)'),
+ 'email_from': fields.char('Partner Email', size=128),
+ 'email_cc': fields.char('CC', size=252),
+ 'partner_id': fields.many2one('res.partner', 'Partner'),
+ 'partner_address_id': fields.many2one('res.partner.address', 'Partner Contact', domain="[('partner_id','=',partner_id)]"),
+ 'date': fields.datetime('Date'),
+ 'create_date': fields.datetime('Created' ,readonly=True),
+ 'date_deadline': fields.datetime('Deadline'),
+ 'date_closed': fields.datetime('Closed', readonly=True),
+ 'user_id': fields.many2one('res.users', 'Responsible'),
+ 'state': fields.selection(AVAILABLE_STATES, 'Status', size=16, readonly=True),
+ 'ref' : fields.reference('Reference', selection=_links_get, size=128),
+ 'date_action_last': fields.datetime('Last Action', readonly=1),
+ 'date_action_next': fields.datetime('Next Action', readonly=1),
+ }
+
+ _defaults = {
+ 'active': 1,
+ 'state': 'draft',
+ 'priority': AVAILABLE_PRIORITIES[2][0],
+ 'date': time.strftime('%Y-%m-%d %H:%M:%S'),
+ }
+
+crm_case_custom()
+
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/crm/crm_view.xml b/addons/crm/crm_view.xml
index 74786ad91f6..e42a3db0584 100644
--- a/addons/crm/crm_view.xml
+++ b/addons/crm/crm_view.xml
@@ -428,5 +428,262 @@
+
+
+
+
+ crm.case.section.custom.form
+ crm.case.section.custom
+ form
+
+
+
+
+
+ crm.case.section.custom.tree
+ crm.case.section.custom
+ tree
+
+
+
+
+
+
+
+
+
+
+
+
+ Custom Cases - Tree
+ crm.case.custom
+ tree
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Custom Cases - Form
+ crm.case.custom
+ form
+
+
+
+
+
+
+
+ Custom Cases - Calendar
+ crm.case.custom
+ calendar
+
+
+
+
+
+
+
+
+
+
+
+
+ Custom Cases - Search
+ crm.case.custom
+ search
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/crm/wizard/__init__.py b/addons/crm/wizard/__init__.py
index e4eb233a9b8..8c6a650b8da 100644
--- a/addons/crm/wizard/__init__.py
+++ b/addons/crm/wizard/__init__.py
@@ -30,5 +30,7 @@ import crm_phonecall_to_partner
import crm_phonecall_to_opportunity
import crm_partner_to_opportunity
+import crm_custom_create_menu
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/crm/wizard/crm_custom_create_menu.py b/addons/crm/wizard/crm_custom_create_menu.py
new file mode 100644
index 00000000000..2d0bb8947f1
--- /dev/null
+++ b/addons/crm/wizard/crm_custom_create_menu.py
@@ -0,0 +1,78 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+from osv import fields,osv
+
+
+class crm_case_custom_create_menu(osv.osv_memory):
+ '''
+ Create menu for custom Cases
+ '''
+ _name = 'crm.custom.create.menu'
+ _description = 'Create menu for custom Cases'
+
+ _columns = {
+ 'name': fields.char('Menu Name', size=64, required=True),
+ 'menu_parent_id': fields.many2one('ir.ui.menu', 'Parent Menu', required=True),
+ 'section_id': fields.many2one('crm.case.section.custom', 'Section', required=True),
+ 'view_form': fields.many2one('ir.ui.view', 'Form View', domain=[('type','=','form'),('model','=','crm.case.custom')]),
+ 'view_tree': fields.many2one('ir.ui.view', 'Tree View', domain=[('type','=','tree'),('model','=','crm.case.custom')]),
+ 'view_calendar': fields.many2one('ir.ui.view', 'Calendar View', domain=[('type','=','calendar'),('model','=','crm.case.custom')]),
+ 'view_search': fields.many2one('ir.ui.view', 'Search View', domain=[('type','=','search'),('model','=','crm.case.custom')]),
+ }
+
+ def menu_create(self, cr, uid, ids, context=None):
+ """
+ Creates Menus for selected custom section
+ """
+ data_obj = self.pool.get('ir.model.data')
+ for this in self.browse(cr, uid, ids, context=context):
+ domain = [('section_id', '=', this.section_id)]
+ view_mode = [this.view_tree and 'tree', this.view_form and 'form', this.view_calendar and 'calendar']
+ view_mode = filter(None , view_mode)
+ action_id = self.pool.get('ir.actions.act_window').create(cr,uid, {
+ 'name': this.name,
+ 'res_model': 'crm.case.custom',
+ 'domain': domain,
+ 'view_type': 'form',
+ 'view_mode': ','.join(view_mode),
+ 'search_view_id': this.view_search.id or False,
+ 'context': {'default_section_id': this.section_id.id, 'default_user_id': uid}
+ })
+ menu_id=self.pool.get('ir.ui.menu').create(cr, uid, {
+ 'name': this.name,
+ 'parent_id': this.menu_parent_id.id,
+ 'icon': 'STOCK_JUSTIFY_FILL'
+ })
+ self.pool.get('ir.values').create(cr, uid, {
+ 'name': 'Custom Cases',
+ 'key2': 'tree_but_open',
+ 'model': 'ir.ui.menu',
+ 'res_id': menu_id,
+ 'value': 'ir.actions.act_window,%d'%action_id,
+ 'object': True
+ })
+ return {}
+
+crm_case_custom_create_menu()
+
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/crm/wizard/crm_custom_create_menu_view.xml b/addons/crm/wizard/crm_custom_create_menu_view.xml
new file mode 100644
index 00000000000..930a9eb99ec
--- /dev/null
+++ b/addons/crm/wizard/crm_custom_create_menu_view.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/event/event.py b/addons/event/event.py
index 73ff7f6755a..8efa132477b 100644
--- a/addons/event/event.py
+++ b/addons/event/event.py
@@ -454,7 +454,7 @@ and users by email"),
contact_id = self.pool.get('res.partner.contact').browse(cr, uid, contact)
data['badge_name'] = contact_id.name
- data['badge_title'] = contact_id.title
+ data['badge_title'] = contact_id.title.name
if partner:
partner_addresses = self.pool.get('res.partner.address').search(cr, uid, [('partner_id', '=', partner)])
job_ids = self.pool.get('res.partner.job').search(cr, uid, [('contact_id', '=', contact), ('address_id', 'in', partner_addresses)])
@@ -471,7 +471,9 @@ and users by email"),
data_event = self.pool.get('event.event').browse(cr, uid, event_id)
context['currency_id'] = data_event.currency_id.id
-
+ if data_event.user_id.id:
+ return {'value': {'user_id':data_event.user_id.id}}
+
if data_event.product_id:
if not partner_invoice_id:
unit_price=self.pool.get('product.product').price_get(cr, uid, [data_event.product_id.id], context=context)[data_event.product_id.id]
@@ -516,6 +518,7 @@ and users by email"),
data_event = self.pool.get('event.event').browse(cr, uid, event_id)
if data_event.product_id:
+ data['event_product']=data_event.product_id.name
if not partner_invoice_id:
data['unit_price']=self.pool.get('product.product').price_get(cr, uid, [data_event.product_id.id], context=context)[data_event.product_id.id]
return {'value': data}
diff --git a/addons/procurement/procurement.py b/addons/procurement/procurement.py
index b098d279d78..34a5c029d51 100644
--- a/addons/procurement/procurement.py
+++ b/addons/procurement/procurement.py
@@ -228,7 +228,14 @@ class procurement_order(osv.osv):
return False
def check_produce_service(self, cr, uid, procurement, context=[]):
- return True
+ """ Checks project_mrp install or not.
+ @return: True or False"""
+ obj_module = self.pool.get('ir.module.module')
+ module_id = obj_module.search(cr, uid, [('name', '=', 'project_mrp'),('state', '=', 'installed')])
+ if module_id:
+ return True
+ cr.execute('update procurement_order set message=%s where id=%s', (_('Project_mrp module not installed !'), procurement.id))
+ return False
def check_produce_product(self, cr, uid, procurement, context=[]):
""" Finds BoM of a product if not found writes exception message.
@@ -344,6 +351,10 @@ class procurement_order(osv.osv):
return True
def _check_make_to_stock_service(self, cr, uid, procurement, context={}):
+ """
+ This method may be overrided by objects that override procurement.order
+ for computing their own purpose
+ @return: True"""
return True
def _check_make_to_stock_product(self, cr, uid, procurement, context={}):
diff --git a/addons/project_retro_planning/test/deadline_change.yml b/addons/project_retro_planning/test/deadline_change.yml
index 717dccd5d97..b5f65d5b6eb 100644
--- a/addons/project_retro_planning/test/deadline_change.yml
+++ b/addons/project_retro_planning/test/deadline_change.yml
@@ -3,10 +3,9 @@
-
!record {model: project.project, id: project_project_retroplanning0}:
company_id: base.main_company
- date: '2010-06-10'
+ date: !eval time.strftime('%Y-%m-%d')
name: Retro Planning
-
-
Create task 'Plan all projects'
-
@@ -19,12 +18,11 @@
project_id: project_project_retroplanning0
remaining_hours: 24.0
state: draft
-
-
Check if task deadline_date and start_date changes upon changing its project's end_date
-
!python {model: project.project}: |
- from datetime import datetime, date
+ from datetime import datetime, date, timedelta
import time
data_project = self.browse(cr,uid,[ref("project_project_retroplanning0")])
prj = data_project[0]
@@ -32,17 +30,19 @@
if prj.date:
old_end_date = date(*time.strptime(prj.date,'%Y-%m-%d')[:3])
if old_end_date:
- new_end_date = date(*time.strptime('2010-06-10','%Y-%m-%d')[:3])
+ new_end_date = date.today()+timedelta(1)
res={}
for task in prj.tasks:
start_dt = (datetime(*time.strptime(task.date_start,'%Y-%m-%d %H:%M:%S')[:6])+(new_end_date-old_end_date)).strftime('%Y-%m-%d %H:%M:%S')
deadline_dt=''
if task.date_deadline:
- deadline_dt = (datetime(*time.strptime(task.date_deadline,'%Y-%m-%d')[:6])+(new_end_date-old_end_date)).strftime('%Y-%m-%d')
+ deadline_dt = (datetime(*time.strptime(task.date_deadline,'%Y-%m-%d')[:6])+(new_end_date-old_end_date)).strftime('%Y-%m-%d')
res[task.id]=[start_dt,deadline_dt]
- self.write(cr, uid, [ref("project_project_retroplanning0")], {'date':'2010-06-10'})
+ self.write(cr, uid, [ref("project_project_retroplanning0")], {'date' : (datetime.datetime.now()+datetime.timedelta(1)).strftime('%Y-%m-%d')
+})
data_project = self.browse(cr,uid,[ref("project_project_retroplanning0")])
prj = data_project[0]
+
for task in prj.tasks:
assert task.date_start == res[task.id][0], "task start date differs, expected %s, got %s"%(res[task.id][0], task.date_start)
assert task.date_deadline == res[task.id][1], "task deadline date differs, expected %s, got %s"%(res[task.id][1], task.date_deadline)
\ No newline at end of file
diff --git a/addons/purchase/purchase_workflow.xml b/addons/purchase/purchase_workflow.xml
index a194cd16713..d14530e5f48 100644
--- a/addons/purchase/purchase_workflow.xml
+++ b/addons/purchase/purchase_workflow.xml
@@ -103,6 +103,7 @@
+ purchase_approve
diff --git a/addons/purchase/test/procurement_buy.yml b/addons/purchase/test/procurement_buy.yml
new file mode 100644
index 00000000000..011e70d0cdc
--- /dev/null
+++ b/addons/purchase/test/procurement_buy.yml
@@ -0,0 +1,109 @@
+-
+ In order to test the procurement with product type buy in OpenERP, I will create product
+ and then I will create procurement for this product.
+-
+ I create product.
+-
+ !record {model: product.product, id: product_product_cddrive0}:
+ categ_id: product.product_category_3
+ cost_method: standard
+ mes_type: fixed
+ name: CD drive
+ procure_method: make_to_order
+ supply_method: buy
+ type: product
+ uom_id: product.product_uom_unit
+ uom_po_id: product.product_uom_unit
+ valuation: manual_periodic
+ volume: 0.0
+ warranty: 0.0
+ weight: 0.0
+ weight_net: 0.0
+ seller_ids:
+ - delay: 1
+ name: base.res_partner_asus
+ qty: 5.0
+-
+ I create procurement order.
+-
+ !record {model: procurement.order, id: procurement_order_testcase0}:
+ company_id: base.main_company
+ date_planned: '2010-07-07 15:38:53'
+ location_id: stock.stock_location_stock
+ name: Test Case
+ priority: '1'
+ procure_method: make_to_order
+ product_id: product_product_cddrive0
+ product_qty: 5.0
+ product_uom: product.product_uom_unit
+ product_uos: product.product_uom_unit
+ product_uos_qty: 0.0
+ state: draft
+-
+ I confirm on procurement order.
+-
+ !workflow {model: procurement.order, action: button_confirm, ref: procurement_order_testcase0}
+-
+ I run the scheduler.
+-
+ !workflow {model: procurement.order, action: button_check, ref: procurement_order_testcase0}
+-
+ I check that purchase order is generated.
+-
+ !python {model: procurement.order}: |
+ from tools.translate import _
+ proc_ids = self.browse(cr, uid, [ref('procurement_order_testcase0')])[0]
+ assert(proc_ids.purchase_id), _('Purchase Order is not Created!')
+-
+ I check the state is running.
+-
+ !python {model: procurement.order}: |
+ from tools.translate import _
+ proc_ids = self.browse(cr, uid, [ref('procurement_order_testcase0')])[0]
+ assert(proc_ids.state == 'running'), _('Exception')
+-
+ I confirm and Approve the purchase order.
+-
+ !python {model: purchase.order}: |
+ procurement_obj = self.pool.get('procurement.order')
+ proc_ids = procurement_obj.browse(cr, uid, [ref('procurement_order_testcase0')])[0]
+ import netsvc
+ wf_service = netsvc.LocalService("workflow")
+ wf_service.trg_validate(uid, 'purchase.order',proc_ids.purchase_id.id,'purchase_confirm', cr)
+ wf_service.trg_validate(uid, 'purchase.order',proc_ids.purchase_id.id,'purchase_approve', cr)
+-
+ I receive the order of the supplier ASUStek from the Incoming Shipments menu.
+-
+ !python {model: stock.picking }: |
+ import time
+ procurement_obj = self.pool.get('procurement.order')
+ proc_ids = procurement_obj.browse(cr, uid, [ref('procurement_order_testcase0')])[0]
+ picking_id = self.search(cr, uid, [('origin', '=', proc_ids.purchase_id.name)])
+ if picking_id:
+ pick=self.browse(cr,uid,picking_id[0])
+ move =pick.move_lines[0]
+ partial_datas = {
+ 'partner_id':pick.address_id.partner_id.id,
+ 'address_id': pick.address_id.id,
+ 'delivery_date' : time.strftime('%Y-%m-%d')
+ }
+ partial_datas['move%s'%(move.id)]= {
+ 'product_id': move.product_id,
+ 'product_qty': move.product_qty,
+ 'product_uom': move.product_uom.id,
+ }
+ self.do_partial(cr, uid, picking_id,partial_datas)
+-
+ I confirm the Reservation.
+-
+ !python {model: stock.move }: |
+ procurement_obj = self.pool.get('procurement.order')
+ proc_ids = procurement_obj.browse(cr, uid, [ref('procurement_order_testcase0')])[0]
+ self.action_done(cr,uid,[proc_ids.move_id.id])
+-
+ I check the state is Done.
+-
+ !python {model: procurement.order}: |
+ from tools.translate import _
+ proc_ids = self.browse(cr, uid, [ref('procurement_order_testcase0')])[0]
+ assert(proc_ids.state == 'done'), _('Order is not in done state')
diff --git a/addons/sale/wizard/sale_make_invoice_advance.py b/addons/sale/wizard/sale_make_invoice_advance.py
index 82a5f1c2d16..19c23eca13f 100644
--- a/addons/sale/wizard/sale_make_invoice_advance.py
+++ b/addons/sale/wizard/sale_make_invoice_advance.py
@@ -64,7 +64,7 @@ class sale_advance_payment_inv(osv.osv_memory):
_("You cannot make an advance on a sale order \
that is defined as 'Automatic Invoice after delivery'."))
val = obj_lines.product_id_change(cr, uid, [], sale_adv_obj.product_id.id,
- uom = False, partner_id = sale.partner_id.id, fiscal_position = sale.fiscal_position.id)
+ uom = False, partner_id = sale.partner_id.id, fposition_id = sale.fiscal_position.id)
line_id =obj_lines.create(cr, uid, {
'name': val['value']['name'],
'account_id': val['value']['account_id'],
diff --git a/addons/wiki/__openerp__.py b/addons/wiki/__openerp__.py
index 1b65dd4d92b..d5c5cc16b30 100644
--- a/addons/wiki/__openerp__.py
+++ b/addons/wiki/__openerp__.py
@@ -31,6 +31,7 @@ keep track for the wiki groups, pages, and history
'author': 'Tiny & Axelor',
'website': 'http://openerp.com',
'depends': ['knowledge'],
+ 'web_depends': ['widget_wiki'],
'init_xml': [],
'update_xml': [
'wizard/wiki_wiki_page_open_view.xml',