@@ -153,7 +153,7 @@
project.issuetree
-
+
@@ -186,13 +186,11 @@
search
-
-
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
-
+
+
-
-
diff --git a/addons/project_issue/report/project_issue_report.py b/addons/project_issue/report/project_issue_report.py
index 70a08e2c7b4..92f170eb556 100644
--- a/addons/project_issue/report/project_issue_report.py
+++ b/addons/project_issue/report/project_issue_report.py
@@ -9,7 +9,6 @@ AVAILABLE_STATES = [
('done', 'Closed'),
('pending','Pending')
]
-
class project_issue_report(osv.osv):
_name = "project.issue.report"
_auto = False
@@ -51,9 +50,9 @@ class project_issue_report(osv.osv):
_columns = {
'name': fields.char('Year', size=64, required=False, readonly=True),
- 'user_id':fields.many2one('res.users', 'User', readonly=True),
+ 'user_id':fields.many2one('res.users', 'Responsible', readonly=True),
+ 'user_id2':fields.many2one('res.users', 'Assigned To', readonly=True),
'section_id':fields.many2one('crm.case.section', 'Section', readonly=True),
- 'nbr': fields.integer('# of Cases', readonly=True),
'state': fields.selection(AVAILABLE_STATES, 'State', size=16, readonly=True),
'avg_answers': fields.function(_get_data, string='Avg. Answers', method=True, type="integer"),
'perc_done': fields.function(_get_data, string='%Done', method=True, type="float"),
@@ -65,23 +64,30 @@ class project_issue_report(osv.osv):
('09', 'September'), ('10', 'October'),\
('11', 'November'), ('12', 'December')], 'Month', readonly=True),
'company_id': fields.many2one('res.company', 'Company', readonly=True),
- 'create_date': fields.datetime('Create Date', readonly=True),
'day': fields.char('Day', size=128, readonly=True),
+ 'opening_date': fields.date('Opening Date', readonly=True),
+ 'creation_date': fields.date('Creation Date', readonly=True),
+ 'date_closed': fields.date('Closed Date', readonly=True),
'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'project.issue')]"),
'stage_id': fields.many2one ('crm.case.stage', 'Stage', domain="[('object_id.model', '=', 'project.issue')]"),
'nbr': fields.integer('# of Issues', readonly=True),
+ 'working_hours_open': fields.float('# Working Open Hours', readonly=True),
+ 'working_hours_close': fields.float('# Working Closing Hours', readonly=True),
+ 'delay_open': fields.float('Avg opening Delay', digits=(16,2), readonly=True, group_operator="avg",
+ help="Number of Days to close the project issue"),
'delay_close': fields.float('Avg Closing Delay', digits=(16,2), readonly=True, group_operator="avg",
help="Number of Days to close the project issue"),
'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', 'Type', domain="[('object_id.model', '=', 'project.issue')]"),
- 'date_closed': fields.datetime('Close Date', readonly=True),
+ 'type_id': fields.many2one('crm.case.resource.type', 'Version', domain="[('object_id.model', '=', 'project.issue')]"),
+ 'user_id2losed': fields.date('Close Date', readonly=True),
'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),
'task_id': fields.many2one('project.task', 'Task',domain="[('object_id.model', '=', 'project.issue')]" )
}
+
def init(self, cr):
tools.drop_view_if_exists(cr, 'project_issue_report')
cr.execute("""
@@ -91,51 +97,60 @@ class project_issue_report(osv.osv):
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_open, 'YYYY-MM-DD') as opening_date,
+ to_char(c.create_date, 'YYYY-MM-DD') as creation_date,
c.state,
c.user_id,
+ c.working_hours_open,
+ c.working_hours_close,
c.section_id,
c.categ_id,
c.stage_id,
- to_char(c.date_closed, 'YYYY/mm/dd') as date_closed,
- u.company_id as company_id,
+ to_char(c.date_closed, 'YYYY-mm-dd') as date_closed,
+ c.company_id as company_id,
c.priority as priority,
c.project_id as project_id,
c.type_id as type_id,
- count(*) as nbr,
+ (select 1) as nbr,
c.assigned_to,
c.partner_id,
c.canal_id,
c.task_id,
date_trunc('day',c.create_date) as create_date,
+ avg(extract('epoch' from (c.date_open-c.create_date)))/(3600*24) as delay_open,
avg(extract('epoch' from (c.date_closed-c.create_date)))/(3600*24) as delay_close
from
project_issue c
- left join
- res_users u on (c.id = u.id)
+ where c.categ_id in (select res_id from ir_model_data where name='bug_categ')
group by
to_char(c.create_date, 'YYYY'),
to_char(c.create_date, 'MM'),
to_char(c.create_date, 'YYYY-MM-DD'),
c.state,
+ to_char(c.date_open, 'YYYY-MM-DD'),
+ to_char(c.date_closed, 'YYYY-mm-dd'),
c.user_id,
c.section_id,
c.categ_id,
c.stage_id,
- c.date_closed,
- u.company_id,
+ c.company_id,
c.priority,
+ c.working_hours_open,
+ c.working_hours_close,
c.project_id,
+ to_char(c.date_closed, 'YYYY-MM-DD'),
c.type_id,
+ c.working_hours_open,
+ c.working_hours_close,
date_trunc('day',c.create_date),
c.assigned_to,
c.partner_id,
c.canal_id,
c.task_id
- )""")
-
+ )""")
project_issue_report()
-# 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/project_issue/report/project_issue_report_view.xml b/addons/project_issue/report/project_issue_report_view.xml
index adc1b3c662f..b4d0af02185 100644
--- a/addons/project_issue/report/project_issue_report_view.xml
+++ b/addons/project_issue/report/project_issue_report_view.xml
@@ -12,10 +12,9 @@
-
+
-
@@ -24,10 +23,13 @@
-
+
+
+
+
@@ -51,29 +53,25 @@
-
-
-
-
-
-
-
+
+
-
-
-
+
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
@@ -179,7 +154,7 @@
project.issue.reportformgraph,tree
- {"search_default_This Month":1,"search_default_User":1,"search_default_user_id":uid,'group_by_no_leaf':1,'group_by':[]}
+ {'search_default_This Month':1,'search_default_project':1,'group_by_no_leaf':1,'group_by':[]}
diff --git a/addons/project_issue/security/ir.model.access.csv b/addons/project_issue/security/ir.model.access.csv
index 811387ed55e..2a0b1f24bce 100755
--- a/addons/project_issue/security/ir.model.access.csv
+++ b/addons/project_issue/security/ir.model.access.csv
@@ -1,3 +1,11 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
-"access_project_issue","project.issue","model_project_issue","crm.group_crm_manager",1,1,1,1
-"access_project_issue_report","project.issue.report","model_project_issue_report","crm.group_crm_manager",1,0,0,0
+"access_project_issue_all","project.issue","model_project_issue","project.group_project_manager",1,1,1,1
+"access_project_issue","project.issue","model_project_issue","project_issue.group_project_supporter",1,1,1,1
+"access_project_issue_report_all","project.issue.report","model_project_issue_report","project.group_project_manager",1,1,1,1
+"access_project_issue_report","project.issue.report","model_project_issue_report","project_issue.group_project_supporter",1,1,1,1
+"access_crm_case_categ_id","crm.case.categ","crm.model_crm_case_categ","project.group_project_manager",1,1,1,1
+"access_crm_case_categ_supp","crm.case.categ","crm.model_crm_case_categ","project_issue.group_project_supporter",1,0,0,0
+"access_crm_case_resource_type_project","crm_case_resource_type manager","crm.model_crm_case_resource_type","project.group_project_manager",1,1,1,1
+"access_crm_case_resource_supp","crm_case_resource_type manager","crm.model_crm_case_resource_type","project_issue.group_project_supporter",1,0,0,0
+"access_crm_case_stage_project","crm.case.stage","crm.model_crm_case_stage","project.group_project_manager",1,1,1,1
+"access_crm_case_stage_manager_suppo","crm.case.stage","crm.model_crm_case_stage","project_issue.group_project_supporter",1,0,0,0
diff --git a/addons/project_issue/security/project_issue_security.xml b/addons/project_issue/security/project_issue_security.xml
index 4f7c16cb70b..82b6c003d91 100644
--- a/addons/project_issue/security/project_issue_security.xml
+++ b/addons/project_issue/security/project_issue_security.xml
@@ -2,12 +2,9 @@
-
- project.issue.rule.group
-
-
- ['|',('project_id','=',False),('project_id','=',user.context_project_id)]
+
+ Project / Support Manager
-
+
diff --git a/addons/purchase/__openerp__.py b/addons/purchase/__openerp__.py
index 46d7c3296b9..e172e5e73f1 100644
--- a/addons/purchase/__openerp__.py
+++ b/addons/purchase/__openerp__.py
@@ -34,7 +34,7 @@
'depends': ['base', 'account', 'stock', 'process', 'mrp_procurement'],
'init_xml': [],
'update_xml': [
-
+
'security/purchase_security.xml',
'security/ir.model.access.csv',
'purchase_workflow.xml',
diff --git a/addons/purchase/i18n/et.po b/addons/purchase/i18n/et.po
index 5123b27b446..c967f8e0d2b 100644
--- a/addons/purchase/i18n/et.po
+++ b/addons/purchase/i18n/et.po
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
-"PO-Revision-Date: 2009-11-18 06:10+0000\n"
-"Last-Translator: Fabien (Open ERP) \n"
+"PO-Revision-Date: 2010-06-09 22:18+0000\n"
+"Last-Translator: lyyser \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-04-17 03:58+0000\n"
+"X-Launchpad-Export-Date: 2010-06-10 03:36+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: purchase
@@ -606,7 +606,7 @@ msgstr "Kättetoimetamine ja arved"
#. module: purchase
#: field:purchase.order,date_order:0
msgid "Date"
-msgstr ""
+msgstr "Kuupäev"
#. module: purchase
#: help:purchase.order,origin:0
@@ -666,7 +666,7 @@ msgstr "Kui ostukorraldus on heaks kiidetud, loob see pakkimise nimekirja."
#. module: purchase
#: view:purchase.order.line:0
msgid "History"
-msgstr ""
+msgstr "Ajalugu"
#. module: purchase
#: field:purchase.order,state:0
@@ -893,4 +893,4 @@ msgstr "Peale ostukorralduse heaks kiitmist läheb see kliendiarveks"
#. module: purchase
#: view:purchase.order.line:0
msgid "Stock Moves"
-msgstr ""
+msgstr "Lao liikumised"
diff --git a/addons/purchase/i18n/pl.po b/addons/purchase/i18n/pl.po
index af8ed99ffbe..09a529c020e 100644
--- a/addons/purchase/i18n/pl.po
+++ b/addons/purchase/i18n/pl.po
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-06-05 03:35+0000\n"
+"X-Launchpad-Export-Date: 2010-06-09 03:35+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: purchase
diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py
index 443a279e3f2..2cfd4247bcf 100644
--- a/addons/purchase/purchase.py
+++ b/addons/purchase/purchase.py
@@ -726,22 +726,24 @@ class mrp_procurement(osv.osv):
po_obj = self.pool.get('purchase.order')
for procurement in self.browse(cr, uid, ids):
res_id = procurement.move_id.id
- partner = procurement.product_id.seller_ids[0].name
- partner_id = partner.id
+ partner_list = sorted([(partner_id.sequence, partner_id) for partner_id in procurement.product_id.seller_ids if partner_id])
+ partner_rec = partner_list and partner_list[0] and partner_list[0][1] or False
+ partner = partner_rec.name or False
+ partner_id = partner_rec.id or False
address_id = partner_obj.address_get(cr, uid, [partner_id], ['delivery'])['delivery']
pricelist_id = partner.property_product_pricelist_purchase.id
uom_id = procurement.product_id.uom_po_id.id
qty = uom_obj._compute_qty(cr, uid, procurement.product_uom.id, procurement.product_qty, uom_id)
- if procurement.product_id.seller_ids[0].qty:
- qty = max(qty,procurement.product_id.seller_ids[0].qty)
+ if partner_rec.qty:
+ qty = max(qty,partner_rec.qty)
price = pricelist_obj.price_get(cr, uid, [pricelist_id], procurement.product_id.id, qty, False, {'uom': uom_id})[pricelist_id]
newdate = DateTime.strptime(procurement.date_planned, '%Y-%m-%d %H:%M:%S')
newdate = newdate - DateTime.RelativeDateTime(days=company.po_lead)
- newdate = newdate - procurement.product_id.seller_ids[0].delay
+ newdate = newdate - partner_rec.delay
#Passing partner_id to context for purchase order line integrity of Line name
context.update({'lang': partner.lang, 'partner_id': partner_id})
diff --git a/addons/purchase/purchase_view.xml b/addons/purchase/purchase_view.xml
index 10c5ccd9749..17fd47b7012 100644
--- a/addons/purchase/purchase_view.xml
+++ b/addons/purchase/purchase_view.xml
@@ -23,6 +23,7 @@
name="Incoming Shipments" sequence="9"/>
+
-
+
-
-
+
-
+
+
+
-
-
-
+
+
@@ -109,7 +109,6 @@
-
diff --git a/addons/sale_crm/__openerp__.py b/addons/sale_crm/__openerp__.py
index 9464db91b6f..49f867ee79d 100644
--- a/addons/sale_crm/__openerp__.py
+++ b/addons/sale_crm/__openerp__.py
@@ -38,7 +38,7 @@ crm modules.
'website': 'http://www.openerp.com',
'depends': ['sale', 'crm'],
'init_xml': [],
- 'update_xml': ['sale_crm_wizard.xml',
+ 'update_xml': ['wizard/crm_make_sale_view.xml',
'sale_crm_view.xml',
'process/sale_crm_process.xml',
'security/sale_crm_security.xml',
diff --git a/addons/sale_crm/i18n/hr.po b/addons/sale_crm/i18n/hr.po
index 2e5036d7030..e20aa353017 100644
--- a/addons/sale_crm/i18n/hr.po
+++ b/addons/sale_crm/i18n/hr.po
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-06-07 03:43+0000\n"
+"X-Launchpad-Export-Date: 2010-06-09 03:35+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"Language: hr\n"
diff --git a/addons/sale_crm/sale_crm_view.xml b/addons/sale_crm/sale_crm_view.xml
index bf5f1aaac52..ad7b1e2485a 100644
--- a/addons/sale_crm/sale_crm_view.xml
+++ b/addons/sale_crm/sale_crm_view.xml
@@ -9,7 +9,7 @@
-
+
diff --git a/addons/sale_crm/sale_crm_wizard.xml b/addons/sale_crm/sale_crm_wizard.xml
deleted file mode 100644
index 74dcf06e901..00000000000
--- a/addons/sale_crm/sale_crm_wizard.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/addons/sale_crm/wizard/__init__.py b/addons/sale_crm/wizard/__init__.py
index 87048a13fc4..04f40c92207 100644
--- a/addons/sale_crm/wizard/__init__.py
+++ b/addons/sale_crm/wizard/__init__.py
@@ -19,7 +19,7 @@
#
##############################################################################
-import makesale
+import crm_make_sale
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/sale_crm/wizard/crm_make_sale.py b/addons/sale_crm/wizard/crm_make_sale.py
new file mode 100644
index 00000000000..f53ce3d24d5
--- /dev/null
+++ b/addons/sale_crm/wizard/crm_make_sale.py
@@ -0,0 +1,180 @@
+# -*- 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
+from tools.translate import _
+from mx.DateTime import now
+
+
+class crm_make_sale(osv.osv_memory):
+ """ Make sale order for crm """
+
+ _name = "crm.make.sale"
+ _description = "Make sale"
+
+ def _selectPartner(self, cr, uid, context=None):
+ """
+ This function gets default value for partner_id field.
+ @param self: The object pointer
+ @param cr: the current row, from the database cursor,
+ @param uid: the current user’s ID for security checks,
+ @param context: A standard dictionary for contextual values
+ @return : default value of partner_id field.
+ """
+ if not context:
+ context = {}
+
+ data = context and context.get('active_ids', []) or []
+ case_obj = self.pool.get('crm.lead')
+ case = case_obj.read(cr, uid, data, ['partner_id'])
+ return case[0]['partner_id']
+
+ def makeOrder(self, cr, uid, ids, context=None):
+ """
+ This function create Quotation on given case.
+ @param self: The object pointer
+ @param cr: the current row, from the database cursor,
+ @param uid: the current user’s ID for security checks,
+ @param ids: List of crm make sale' ids
+ @param context: A standard dictionary for contextual values
+ @return : Dictionary value of created sale order.
+ """
+ if not context:
+ context = {}
+
+ mod_obj = self.pool.get('ir.model.data')
+
+
+ result = mod_obj._get_id(cr, uid, 'sale', 'view_sales_order_filter')
+ id = mod_obj.read(cr, uid, result, ['res_id'])
+
+ case_obj = self.pool.get('crm.lead')
+ sale_obj = self.pool.get('sale.order')
+ partner_obj = self.pool.get('res.partner')
+ sale_line_obj = self.pool.get('sale.order.line')
+
+ data = context and context.get('active_ids', []) or []
+
+ for make in self.browse(cr, uid, ids):
+ default_partner_addr = partner_obj.address_get(cr, uid, [make.partner_id.id],
+ ['invoice', 'delivery', 'contact'])
+ default_pricelist = partner_obj.browse(cr, uid, make.partner_id.id,
+ context).property_product_pricelist.id
+ fpos_data = partner_obj.browse(cr, uid, make.partner_id.id, context).property_account_position
+ new_ids = []
+
+ for case in case_obj.browse(cr, uid, data):
+ if case.partner_id and case.partner_id.id:
+ partner_id = case.partner_id.id
+ fpos = case.partner_id.property_account_position and case.partner_id.property_account_position.id or False
+ partner_addr = partner_obj.address_get(cr, uid, [case.partner_id.id],
+ ['invoice', 'delivery', 'contact'])
+ pricelist = partner_obj.browse(cr, uid, case.partner_id.id,
+ context).property_product_pricelist.id
+ else:
+ partner_id = make.partner_id.id
+ fpos = fpos_data and fpos_data.id or False
+ partner_addr = default_partner_addr
+ pricelist = default_pricelist
+
+ if False in partner_addr.values():
+ raise osv.except_osv(_('Data Insufficient!'),_('Customer has no addresses defined!'))
+
+ vals = {
+ 'origin': 'CRM-Opportunity:%s' % str(case.id),
+ 'section_id': case.section_id and case.section_id.id or False,
+ 'picking_policy': make.picking_policy,
+ 'shop_id': make.shop_id.id,
+ 'partner_id': partner_id,
+ 'pricelist_id': pricelist,
+ 'partner_invoice_id': partner_addr['invoice'],
+ 'partner_order_id': partner_addr['contact'],
+ 'partner_shipping_id': partner_addr['delivery'],
+ 'order_policy': 'manual',
+ 'date_order': now(),
+ 'fiscal_position': fpos,
+ }
+
+ if partner_id:
+ partner = partner_obj.browse(cr, uid, partner_id, context=context)
+ vals['user_id'] = partner.user_id and partner.user_id.id or uid
+
+ if make.analytic_account.id:
+ vals['project_id'] = make.analytic_account.id
+ new_id = sale_obj.create(cr, uid, vals)
+ for product_id in make.product_ids:
+ value = sale_line_obj.product_id_change(cr, uid, [], pricelist,
+ product_id.id, qty=1, partner_id=partner_id, fiscal_position=fpos)['value']
+ value['product_id'] = product_id.id
+ value['order_id'] = new_id
+ value['tax_id'] = [(6,0,value['tax_id'])]
+ sale_line_obj.create(cr, uid, value)
+
+ case_obj.write(cr, uid, [case.id], {'ref': 'sale.order,%s' % new_id})
+ new_ids.append(new_id)
+
+ if make.close:
+ case_obj.case_close(cr, uid, data)
+
+ if not new_ids:
+ return {}
+ if len(new_ids)<=1:
+ value = {
+ 'domain': str([('id', 'in', new_ids)]),
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'res_model': 'sale.order',
+ 'view_id': False,
+ 'type': 'ir.actions.act_window',
+ 'res_id': new_ids and new_ids[0]
+
+ }
+
+
+ else:
+ value = {
+ 'domain': str([('id', 'in', new_ids)]),
+ 'view_type': 'form',
+ 'view_mode': 'tree,form',
+ 'res_model': 'sale.order',
+ 'view_id': False,
+ 'type': 'ir.actions.act_window',
+ 'res_id':new_ids
+ }
+ return value
+
+ _columns = {
+ 'shop_id': fields.many2one('sale.shop', 'Shop', required = True),
+ 'partner_id': fields.many2one('res.partner', 'Customer', required = True, help = 'Use this partner if there is no partner on the case'),
+ 'picking_policy': fields.selection([('direct','Partial Delivery'),
+ ('one','Complete Delivery')], 'Picking Policy', required = True),
+ 'product_ids': fields.many2many('product.product', 'product_sale_rel',\
+ 'sale_id', 'product_id', 'Products'),
+ 'analytic_account': fields.many2one('account.analytic.account', 'Analytic Account'),
+ 'close': fields.boolean('Close Case', help = 'Check this to close the case after having created the sale order.'),
+ }
+ _defaults = {
+ 'partner_id': _selectPartner,
+ 'close': lambda *a: 1
+ }
+
+crm_make_sale()
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/sale_crm/wizard/crm_make_sale_view.xml b/addons/sale_crm/wizard/crm_make_sale_view.xml
new file mode 100644
index 00000000000..fd41bfde9ff
--- /dev/null
+++ b/addons/sale_crm/wizard/crm_make_sale_view.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+ crm.make.sale.form
+ crm.make.sale
+ form
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Make Quotation
+ ir.actions.act_window
+ crm.make.sale
+ form
+ form
+ new
+
+
+
+
diff --git a/addons/sale_crm/wizard/makesale.py b/addons/sale_crm/wizard/makesale.py
deleted file mode 100644
index e4aacce1044..00000000000
--- a/addons/sale_crm/wizard/makesale.py
+++ /dev/null
@@ -1,179 +0,0 @@
-# -*- coding: utf-8 -*-
-##############################################################################
-#
-# OpenERP, Open Source Management Solution
-# Copyright (C) 2004-2010 Tiny SPRL ().
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-#
-##############################################################################
-
-from mx.DateTime import now
-
-import wizard
-import netsvc
-import ir
-import pooler
-from tools.translate import _
-
-sale_form = """
-
-
-
-
-
-
-
-
-
"""
-
-sale_fields = {
- 'shop_id': {'string': 'Shop', 'type': 'many2one', 'relation': 'sale.shop'},
- 'partner_id': {'string': 'Customer', 'type': 'many2one',
- 'relation': 'res.partner',
- 'help': 'Use this partner if there is no partner on the case'},
- 'picking_policy': {'string': 'Picking Policy', 'type': 'selection',
- 'selection': [('direct', 'Partial Delivery'), ('one', 'Complete Delivery')]},
- 'products': {'string': 'Products', 'type': 'many2many',
- 'relation': 'product.product'},
- 'analytic_account': {'string': 'Analytic Account', 'type': 'many2one',
- 'relation': 'account.analytic.account'},
- 'close': {'string': 'Close Case', 'type': 'boolean', 'default': lambda *a: 1,
- 'help': 'Check this to close the case after having created the sale order.'},
-}
-
-
-class make_sale(wizard.interface):
-
- def _selectPartner(self, cr, uid, data, context):
- case_obj = pooler.get_pool(cr.dbname).get('crm.lead')
- case = case_obj.read(cr, uid, data['ids'], ['partner_id'])
- return {'partner_id': case[0]['partner_id']}
-
- def _makeOrder(self, cr, uid, data, context):
- pool = pooler.get_pool(cr.dbname)
- mod_obj = pool.get('ir.model.data')
- result = mod_obj._get_id(cr, uid, 'sale', 'view_sales_order_filter')
- id = mod_obj.read(cr, uid, result, ['res_id'])
- case_obj = pool.get('crm.lead')
- sale_obj = pool.get('sale.order')
- partner_obj = pool.get('res.partner')
- sale_line_obj = pool.get('sale.order.line')
-
- default_partner_addr = partner_obj.address_get(cr, uid, [data['form']['partner_id']],
- ['invoice', 'delivery', 'contact'])
- default_pricelist = partner_obj.browse(cr, uid, data['form']['partner_id'],
- context).property_product_pricelist.id
- fpos_data = partner_obj.browse(cr, uid, data['form']['partner_id'],context).property_account_position
- new_ids = []
-
- for case in case_obj.browse(cr, uid, data['ids']):
- if case.partner_id and case.partner_id.id:
- partner_id = case.partner_id.id
- fpos = case.partner_id.property_account_position and case.partner_id.property_account_position.id or False
- partner_addr = partner_obj.address_get(cr, uid, [case.partner_id.id],
- ['invoice', 'delivery', 'contact'])
- pricelist = partner_obj.browse(cr, uid, case.partner_id.id,
- context).property_product_pricelist.id
- else:
- partner_id = data['form']['partner_id']
- fpos = fpos_data and fpos_data.id or False
- partner_addr = default_partner_addr
- pricelist = default_pricelist
-
- if False in partner_addr.values():
- raise wizard.except_wizard(_('Data Insufficient!'),_('Customer has no addresses defined!'))
-
- vals = {
- 'origin': 'CRM-Opportunity:%s' % str(case.id),
- 'section_id': case.section_id and case.section_id.id or False,
- 'picking_policy': data['form']['picking_policy'],
- 'shop_id': data['form']['shop_id'],
- 'partner_id': partner_id,
- 'pricelist_id': pricelist,
- 'partner_invoice_id': partner_addr['invoice'],
- 'partner_order_id': partner_addr['contact'],
- 'partner_shipping_id': partner_addr['delivery'],
- 'order_policy': 'manual',
- 'date_order': now(),
- 'fiscal_position': fpos,
- }
-
- if partner_id:
- partner = partner_obj.browse(cr, uid, partner_id, context=context)
- vals['user_id'] = partner.user_id and partner.user_id.id or uid
-
- if data['form']['analytic_account']:
- vals['project_id'] = data['form']['analytic_account']
-
- vals.update( sale_obj.onchange_partner_id(cr, uid, [], partner_id).get('value',{}) )
- new_id = sale_obj.create(cr, uid, vals)
- if data['form']['products']:
- for product_id in data['form']['products'][0][2]:
- value = {
- 'price_unit': 0.0,
- 'product_id': product_id,
- 'order_id': new_id,
- }
- value.update( sale_line_obj.product_id_change(cr, uid, [], pricelist,product_id, qty=1, partner_id=partner_id, fiscal_position=fpos)['value'] )
- value['tax_id'] = [(6,0,value['tax_id'])]
- sale_line_obj.create(cr, uid, value)
-
- case_obj.write(cr, uid, [case.id], {'ref': 'sale.order,%s' % new_id})
- new_ids.append(new_id)
-
- if data['form']['close']:
- case_obj.case_close(cr, uid, data['ids'])
-
- if not new_ids:
- return {}
-
- if len(new_ids)<=1:
- value = {
- 'domain': str([('id', 'in', new_ids)]),
- 'view_type': 'form',
- 'view_mode': 'form',
- 'res_model': 'sale.order',
- 'view_id': False,
- 'type': 'ir.actions.act_window',
- 'res_id': new_ids and new_ids[0]
- }
- else:
- value = {
- 'domain': str([('id', 'in', new_ids)]),
- 'view_type': 'form',
- 'view_mode': 'tree,form',
- 'res_model': 'sale.order',
- 'view_id': False,
- 'type': 'ir.actions.act_window',
- 'res_id':new_ids
- }
-
- return value
-
- states = {
- 'init': {
- 'actions': [_selectPartner],
- 'result': {'type': 'form', 'arch': sale_form, 'fields': sale_fields,
- 'state' : [('end', 'Cancel', 'gtk-cancel'),('order', 'Create', 'gtk-apply')]}
- },
- 'order': {
- 'actions': [],
- 'result': {'type': 'action', 'action': _makeOrder, 'state': 'end'}
- }
- }
-
-make_sale('crm.opportunity.make_order')
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/sale_journal/i18n/hr.po b/addons/sale_journal/i18n/hr.po
index 8e1ce7fb070..2e1aacbfce7 100644
--- a/addons/sale_journal/i18n/hr.po
+++ b/addons/sale_journal/i18n/hr.po
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-06-07 03:43+0000\n"
+"X-Launchpad-Export-Date: 2010-06-09 03:35+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"Language: hr\n"
diff --git a/addons/scrum/scrum.py b/addons/scrum/scrum.py
index 2e3a0ca3fcb..698b490f1a2 100644
--- a/addons/scrum/scrum.py
+++ b/addons/scrum/scrum.py
@@ -28,8 +28,8 @@ import re
class scrum_project(osv.osv):
_inherit = 'project.project'
_columns = {
- 'product_owner_id': fields.many2one('res.users', 'Product Owner'),
- 'sprint_size': fields.integer('Sprint Days',help="Number of days allocated for sprint"),
+ 'product_owner_id': fields.many2one('res.users', 'Product Owner', help="The person who is responsible for the product"),
+ 'sprint_size': fields.integer('Sprint Days', help="Number of days allocated for sprint"),
'scrum': fields.integer('Is a Scrum Project'),
}
_defaults = {
diff --git a/addons/share/__init__.py b/addons/share/__init__.py
new file mode 100644
index 00000000000..eff88be137d
--- /dev/null
+++ b/addons/share/__init__.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+import share
+import wizard
diff --git a/addons/share/__openerp__.py b/addons/share/__openerp__.py
new file mode 100644
index 00000000000..e6762e91ef2
--- /dev/null
+++ b/addons/share/__openerp__.py
@@ -0,0 +1,44 @@
+# -*- 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 .
+#
+##############################################################################
+
+
+{
+ "name" : "Share Management",
+ "version" : "1.1",
+ "depends" : ["base"],
+ "author" : "Tiny",
+ "category": 'Generic Modules',
+ "description": """The goal is to implement a generic sharing mechanism, where user of OpenERP
+can share data from OpenERP to their colleagues, customers, or friends.
+The system will work by creating new users and groups on the fly, and by
+combining the appropriate access rights and ir.rules to ensure that the /shared
+users/ will only have access to the correct data.
+ """,
+ 'website': 'http://www.openerp.com',
+ 'init_xml': [],
+ 'update_xml': [
+ 'share_view.xml',
+ 'wizard/share_wizard_view.xml'
+ ],
+ 'installable': True,
+ 'active': False,
+}
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/share/share.py b/addons/share/share.py
new file mode 100644
index 00000000000..6e3c4932a1e
--- /dev/null
+++ b/addons/share/share.py
@@ -0,0 +1,36 @@
+# -*- 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, orm
+class res_groups(osv.osv):
+ _name = "res.groups"
+ _inherit = 'res.groups'
+ _columns = {
+ 'share': fields.boolean('Share')
+ }
+res_groups()
+
+class res_users(osv.osv):
+ _name = 'res.users'
+ _inherit = 'res.users'
+ _columns = {
+ 'share': fields.boolean('Share')
+ }
+res_users()
diff --git a/addons/share/share_view.xml b/addons/share/share_view.xml
new file mode 100644
index 00000000000..24736b3d53a
--- /dev/null
+++ b/addons/share/share_view.xml
@@ -0,0 +1,27 @@
+
+
+
+
+ res.groups.form
+ res.groups
+ form
+
+
+
+
+
+
+
+
+ res.users.form
+ res.users
+ form
+
+
+
+
+
+
+
+
+
diff --git a/addons/share/wizard/__init__.py b/addons/share/wizard/__init__.py
new file mode 100644
index 00000000000..b906abf5e56
--- /dev/null
+++ b/addons/share/wizard/__init__.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+import share_wizard
diff --git a/addons/share/wizard/share_wizard.py b/addons/share/wizard/share_wizard.py
new file mode 100644
index 00000000000..c5e2aef2ff6
--- /dev/null
+++ b/addons/share/wizard/share_wizard.py
@@ -0,0 +1,430 @@
+# -*- 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 osv, fields
+from tools.translate import _
+import tools
+
+def _generate_random_number():
+ import random
+ RANDOM_PASS_CHARACTERS = [chr(x) for x in range(48,58) + range(97,123) + range(65,91)]
+ RANDOM_PASS_CHARACTERS.remove('l') #lowercase l, easily mistaken as one or capital i
+ RANDOM_PASS_CHARACTERS.remove('I') #uppercase i, easily mistaken as one or lowercase l
+ RANDOM_PASS_CHARACTERS.remove('O') #uppercase o, mistaken with zero
+ RANDOM_PASS_CHARACTERS.remove('o') #lowercase o, mistaken with zero
+ RANDOM_PASS_CHARACTERS.remove('0') #zero, mistaken with o-letter
+ def generate_random_pass():
+ pass_chars = RANDOM_PASS_CHARACTERS[:]
+ random.shuffle(pass_chars)
+ return ''.join(pass_chars[0:10])
+ return generate_random_pass()
+
+class share_create(osv.osv_memory):
+ _name = 'share.create'
+ _description = 'Create share'
+
+ def _access(self, cr, uid, ids, field_name, arg, context=None):
+ if context is None:
+ context = {}
+ res = {}
+ action_id = context.get('action_id', False)
+ access_obj = self.pool.get('ir.model.access')
+ action_obj = self.pool.get('ir.actions.act_window')
+ model_obj = self.pool.get('ir.model')
+ user_obj = self.pool.get('res.users')
+ current_user = user_obj.browse(cr, uid, uid)
+ access_ids = []
+ if action_id:
+ action = action_obj.browse(cr, uid, action_id, context=context)
+ active_model_ids = model_obj.search(cr, uid, [('model','=',action.res_model)])
+ active_model_id = active_model_ids and active_model_ids[0] or False
+ access_ids = access_obj.search(cr, uid, [
+ ('group_id','in',map(lambda x:x.id, current_user.groups_id)),
+ ('model_id','',active_model_id)])
+ for rec_id in ids:
+ write_access = False
+ read_access = False
+ for access in access_obj.browse(cr, uid, access_ids, context=context):
+ if access.perm_write:
+ write_access = True
+ if access.perm_read:
+ read_access = True
+ res[rec_id]['write_access'] = write_access
+ res[rec_id]['read_access'] = read_access
+ return res
+
+ _columns = {
+ 'action_id': fields.many2one('ir.actions.act_window', 'Action', required=True),
+ 'domain': fields.char('Domain', size=64),
+ 'user_type': fields.selection( [ ('existing','Existing'),('new','New')],'User Type'),
+ 'user_ids': fields.many2many('res.users', 'share_user_rel', 'share_id','user_id', 'Share Users'),
+ 'new_user': fields.text("New user"),
+ 'access_mode': fields.selection( [ ('readonly','READ ONLY'),('readwrite','READ & WRITE')],'Access Mode'),
+ 'write_access': fields.function(_access, method=True, string='Write Access',type='boolean', multi='write_access'),
+ 'read_access': fields.function(_access, method=True, string='Write Access',type='boolean', multi='read_access'),
+ }
+ _defaults = {
+ 'user_type' : 'existing',
+ 'domain': '[]',
+ 'access_mode': 'readonly'
+ }
+
+ def default_get(self, cr, uid, fields, context=None):
+ """
+ To get default values for the object.
+ """
+
+ res = super(share_create, self).default_get(cr, uid, fields, context=context)
+ if not context:
+ context={}
+ action_id = context.get('action_id', False)
+ domain = context.get('domain', '[]')
+
+
+ if 'action_id' in fields:
+ res['action_id'] = action_id
+ if 'domain' in fields:
+ res['domain'] = domain
+ return res
+
+ def do_step_1(self, cr, uid, ids, context=None):
+ """
+ This action to excute step 1
+
+ """
+ if not context:
+ context = {}
+
+ data_obj = self.pool.get('ir.model.data')
+
+ step1_form_view = data_obj._get_id(cr, uid, 'share', 'share_step1_form')
+
+ if step1_form_view:
+ step1_form_view_id = data_obj.browse(cr, uid, step1_form_view, context=context).res_id
+
+ step1_id = False
+ for this in self.browse(cr, uid, ids, context=context):
+ vals ={
+ 'domain': this.domain,
+ 'action_id': this.action_id and this.action_id.id or False,
+ }
+
+ context.update(vals)
+ value = {
+ 'name': _('Step:2 Sharing Wizard'),
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'res_model': 'share.create',
+ 'view_id': False,
+ 'views': [(step1_form_view_id, 'form'), (False, 'tree'), (False, 'calendar'), (False, 'graph')],
+ 'type': 'ir.actions.act_window',
+ 'context': context,
+ 'target': 'new'
+ }
+ return value
+
+
+ def do_step_2(self, cr, uid, ids, context=None):
+ """
+ This action to excute step 2
+
+ """
+ if not context:
+ context = {}
+
+ data_obj = self.pool.get('ir.model.data')
+
+ step2_form_view = data_obj._get_id(cr, uid, 'share', 'share_step2_form')
+
+ if step2_form_view:
+ step2_form_view_id = data_obj.browse(cr, uid, step2_form_view, context=context).res_id
+
+ step1_id = False
+ for this in self.browse(cr, uid, ids, context=context):
+ vals ={
+ 'user_type': this.user_type,
+ 'existing_user_ids': map(lambda x:x.id, this.user_ids),
+ 'new_user': this.new_user,
+ 'domain': this.domain,
+ 'access_mode': this.access_mode,
+ 'action_id': this.action_id and this.action_id.id or False
+ }
+
+ context.update(vals)
+ value = {
+ 'name': _('Step:3 Sharing Wizard'),
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'res_model': 'share.create',
+ 'view_id': False,
+ 'views': [(step2_form_view_id, 'form'), (False, 'tree'), (False, 'calendar'), (False, 'graph')],
+ 'type': 'ir.actions.act_window',
+ 'context': context,
+ 'target': 'new'
+ }
+ return value
+
+
+ def do_step_3(self, cr, uid, ids, context=None):
+ """
+ This action to excute step 3
+
+ """
+ if not context:
+ context = {}
+
+ group_obj = self.pool.get('res.groups')
+ user_obj = self.pool.get('res.users')
+ fields_obj = self.pool.get('ir.model.fields')
+ model_access_obj = self.pool.get('ir.model.access')
+ model_obj = self.pool.get('ir.model')
+ rule_obj = self.pool.get('ir.rule')
+ action_obj = self.pool.get('ir.actions.act_window')
+
+ new_users = context.get('new_user', False)
+ action_id = context.get('action_id', False)
+ user_type = context.get('user_type', False)
+ access_mode = context.get('access_mode', False)
+ action = action_obj.browse(cr, uid, action_id, context=context)
+ active_model = action.res_model
+
+ active_id = False #TODO: Pass record id of res_model of action
+ existing_user_ids = context.get('existing_user_ids', False)
+ domain = eval(context.get('domain', '[]'))
+
+ # Create Share Group
+ share_group_name = '%s: %s' %('Sharing', active_model)
+ group_ids = group_obj.search(cr, uid, [('name','=',share_group_name)])
+ group_id = group_ids and group_ids[0] or False
+ if not group_id:
+ group_id = group_obj.create(cr, uid, {'name': share_group_name, 'share': True})
+ else:
+ group = group_obj.browse(cr, uid, group_id, context=context)
+ if not group.share:
+ raise osv.except_osv(_('Error'), _("Share Group is exits without sharing !"))
+
+ # Create new user
+
+ current_user = user_obj.browse(cr, uid, uid)
+ user_ids = []
+ if user_type == 'new' and new_users:
+ for new_user in new_users.split('\n'):
+ password = _generate_random_number()
+ user_id = user_obj.create(cr, uid, {
+ 'login': new_user,
+ 'password': password,
+ 'name': new_user,
+ 'user_email': new_user,
+ 'groups_id': [(6,0,[group_id])],
+ 'action_id': action_id,
+ 'share': True,
+ 'company_id': current_user.company_id and current_user.company_id.id})
+ user_ids.append(user_id)
+ context['new_user_ids'] = user_ids
+
+ # Modify existing user
+ if user_type == 'existing':
+ user_obj.write(cr, uid, existing_user_ids , {
+ 'groups_id': [(4,group_id)],
+ 'action_id': action_id
+ })
+
+
+ #ACCESS RIGHTS / IR.RULES COMPUTATION
+ #TODO: TO Resolve Recurrent Problems
+ active_model_ids = model_obj.search(cr, uid, [('model','=',active_model)])
+ active_model_id = active_model_ids and active_model_ids[0] or False
+
+ def _get_relation(model_id, ttypes, new_obj=[]):
+ obj = []
+ models = map(lambda x:x[1].model, new_obj)
+ field_ids = fields_obj.search(cr, uid, [('model_id','=',model_id),('ttype','in', ttypes)])
+ for field in fields_obj.browse(cr, uid, field_ids, context=context):
+ if field.relation not in models:
+ relation_model_ids = model_obj.search(cr, uid, [('model','=',field.relation)])
+ relation_model_id = relation_model_ids and relation_model_ids[0] or False
+ relation_model = model_obj.browse(cr, uid, relation_model_id, context=context)
+ obj.append((field.relation_field, relation_model))
+
+ if relation_model_id != model_id and field.ttype in ['one2many', 'many2many']:
+ obj += _get_relation(relation_model_id, [field.ttype], obj)
+
+ return obj
+
+ obj0 = model_obj.browse(cr, uid, active_model_id, context=context)
+ obj1 = _get_relation(active_model_id, ['one2many'])
+ obj2 = _get_relation(active_model_id, ['one2many', 'many2many'])
+ obj3 = _get_relation(active_model_id, ['many2one'])
+ for rel_field, model in obj1:
+ obj3 += _get_relation(model.id, ['many2one'])
+ if access_mode == 'readonly':
+ for rel_field, model in obj1+obj2+obj3:
+ model_access_obj.create(cr, uid, {
+ 'name': 'Read Access of group %s on %s model'%(share_group_name, model.name),
+ 'model_id' : model.id,
+ 'group_id' : group_id,
+ 'perm_read' : True
+ })
+ if access_mode == 'readwrite':
+ for rel_field, model in obj1+obj2+obj3:
+ model_access_obj.create(cr, uid, {
+ 'name': 'Read Access of group %s on %s model'%(share_group_name, model.name),
+ 'model_id' : model.id,
+ 'group_id' : group_id,
+ 'perm_read' : True,
+ 'perm_write' : True
+ })
+ for rel_field, model in obj2+obj3:
+ model_access_obj.create(cr, uid, {
+ 'name': 'Read Access of group %s on %s model'%(share_group_name, model.name),
+ 'model_id' : model.id,
+ 'group_id' : group_id,
+ 'perm_read' : True
+ })
+
+ rule_obj.create(cr, uid, {
+ 'name': '%s-%s'%(share_group_name, obj0.model),
+ 'model_id': obj0.id,
+ 'domain': domain,
+ 'group_ids': [(6,0,[group_id])]
+ })
+ for rel_field, model in obj1:
+ obj1_domain = []
+ for opr1, opt, opr2 in domain:
+ new_opr1 = '%s.%s'%(rel_field, opr1)
+ obj1_domain.append((new_opr1, opt, opr2))
+
+ rule_obj.create(cr, uid, {
+ 'name': '%s-%s'%(share_group_name, model.model),
+ 'model_id': model.id,
+ 'domain': obj1_domain,
+ 'groups': [(6,0,[group_id])]
+ })
+ # TODO:
+ # And on OBJ0, OBJ1, OBJ2, OBJ3: add all rules from groups of the user
+ # that is sharing in the many2many of the rules on the new group
+ # (rule must be copied instead of adding it if it contains a reference to uid
+ # or user.xxx so it can be replaced correctly)
+ context['share_model'] = active_model
+ context['share_rec_id'] = active_id
+
+
+ data_obj = self.pool.get('ir.model.data')
+
+ form_view = data_obj._get_id(cr, uid, 'share', 'share_result_form')
+ form_view_id = False
+ if form_view:
+ form_view_id = data_obj.browse(cr, uid, form_view, context=context).res_id
+
+
+ value = {
+ 'name': _('Step:4 Share Users Detail'),
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'res_model': 'share.result',
+ 'view_id': False,
+ 'views': [(form_view_id, 'form'), (False, 'tree'), (False, 'calendar'), (False, 'graph')],
+ 'type': 'ir.actions.act_window',
+ 'context': context,
+ 'target': 'new'
+ }
+ return value
+share_create()
+
+
+class share_result(osv.osv_memory):
+ _name = "share.result"
+ _columns = {
+ 'users': fields.text("Users", readonly=True),
+ }
+
+
+
+ def do_send_email(self, cr, uid, ids, context=None):
+ user_obj = self.pool.get('res.users')
+ if not context:
+ context={}
+ existing_user_ids = context.get('existing_user_ids', [])
+ new_user_ids = context.get('new_user_ids', [])
+ share_url = tools.config.get('share_root_url', False)
+ user = user_obj.browse(cr, uid, uid, context=context)
+ for share_user in user_obj.browse(cr, uid, new_user_ids+existing_user_ids, context=context):
+ email_to = share_user.user_email
+ subject = '%s wants to share private data with you' %(user.name)
+ body = """
+ Dear,
+
+ %s wants to share private data from OpenERP with you!
+ """%(user.name)
+ if share_url:
+ body += """
+ To view it, you can access the following URL:
+ %s
+ """%(user.name, share_url)
+ if share_user.id in new_user_ids:
+ body += """
+ You may use the following login and password to get access to this
+ protected area:
+ login: %s
+ password: %s
+ """%(user.login, user.password)
+ elif share_user.id in existing_user_ids:
+ body += """
+ You may use your existing login and password to get access to this
+ additional data. As a reminder, your login is %s.
+ """%(user.name)
+
+ flag = tools.email_send(
+ user.user_email,
+ email_to,
+ subject,
+ body
+ )
+ return flag
+
+
+ def default_get(self, cr, uid, fields, context=None):
+ """
+ To get default values for the object.
+ """
+
+ res = super(share_result, self).default_get(cr, uid, fields, context=context)
+ user_obj = self.pool.get('res.users')
+ if not context:
+ context={}
+ existing_user_ids = context.get('existing_user_ids', [])
+ new_user_ids = context.get('new_user_ids', [])
+ share_url = tools.config.get('share_root_url', False)
+ if 'users' in fields:
+ users = []
+ for user in user_obj.browse(cr, uid, new_user_ids):
+ txt = 'Login: %s Password: %s' %(user.login, user.password)
+ if share_url:
+ txt += ' Share URL: %s' %(share_url)
+ users.append(txt)
+ for user in user_obj.browse(cr, uid, existing_user_ids):
+ txt = 'Login: %s' %(user.login)
+ if share_url:
+ txt += ' Share URL: %s' %(share_url)
+ users.append(txt)
+ res['users'] = '\n'.join(users)
+ return res
+
+share_result()
diff --git a/addons/share/wizard/share_wizard_view.xml b/addons/share/wizard/share_wizard_view.xml
new file mode 100644
index 00000000000..9e9b23f7f43
--- /dev/null
+++ b/addons/share/wizard/share_wizard_view.xml
@@ -0,0 +1,108 @@
+
+
+
+
+
+ share.step0.form
+ share.create
+ form
+
+