merge
bzr revid: apa@tinyerp.com-20101001140857-rnp8exg3gswhbs9t bzr revid: apa@tinyerp.com-20101004095217-ydcn3huvfmz9csxq
This commit is contained in:
@@ -148,7 +148,6 @@ CREATE TABLE res_users (
|
||||
context_lang varchar(64) default '',
|
||||
-- No FK references below, will be added later by ORM
|
||||
-- (when the destination rows exist)
|
||||
action_id int,
|
||||
company_id int,
|
||||
primary key(id)
|
||||
);
|
||||
@@ -345,7 +344,7 @@ CREATE TABLE ir_model_data (
|
||||
-- Users
|
||||
---------------------------------
|
||||
|
||||
insert into res_users (id,login,password,name,action_id,active,company_id) values (1,'admin','admin','Administrator',NULL,True,1);
|
||||
insert into res_users (id,login,password,name,active,company_id) values (1,'admin','admin','Administrator',True,1);
|
||||
insert into ir_model_data (name,module,model,noupdate,res_id) values ('user_root','base','res.users',True,1);
|
||||
|
||||
-- Compatibility purpose, to remove V6.0
|
||||
|
||||
@@ -1053,8 +1053,6 @@
|
||||
<field name="address_id" ref="main_address"/>
|
||||
<field name="company_id" ref="main_company"/>
|
||||
<field name="company_ids" eval="[(4, ref('main_company'))]"/>
|
||||
<field name="action_id" ref="action_menu_admin"/>
|
||||
<field name="menu_id" ref="action_menu_admin"/>
|
||||
</record>
|
||||
|
||||
<record id="main_partner" model="res.partner">
|
||||
@@ -1375,6 +1373,9 @@
|
||||
<field name="currency_id" ref="UAH"/>
|
||||
<field eval="time.strftime('%Y-01-01')" name="name"/>
|
||||
</record>
|
||||
|
||||
<record id="res_bank_1" model="res.bank">
|
||||
<field name="name">Reserve</field>
|
||||
<field name="code">RSV</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
<field name="password">demo</field>
|
||||
<field name="name">Demo User</field>
|
||||
<field name="signature">Mr Demo</field>
|
||||
<field name="action_id" ref="action_menu_admin"/>
|
||||
<field name="menu_id" ref="action_menu_admin"/>
|
||||
<field name="address_id" ref="main_address"/>
|
||||
<field name="company_id" ref="main_company"/>
|
||||
<field name="groups_id" eval="[(6,0,[ref('base.group_user')])]"/>
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
<field name="user_email" widget="email"/>
|
||||
<field name="context_lang"/>
|
||||
<field domain="[('usage','=','menu')]" name="menu_id" required="True"/>
|
||||
<field name="action_id" required="True"/>
|
||||
<field name="action_id"/>
|
||||
|
||||
|
||||
<field name="context_tz"/>
|
||||
|
||||
@@ -7,13 +7,13 @@ msgstr ""
|
||||
"Project-Id-Version: OpenERP Server 5.0.0\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
|
||||
"PO-Revision-Date: 2010-09-12 21:46+0000\n"
|
||||
"Last-Translator: Bojan Markovic <Unknown>\n"
|
||||
"PO-Revision-Date: 2010-09-29 08:03+0000\n"
|
||||
"Last-Translator: OpenERP Administrators <Unknown>\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-09-29 04:42+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-09-30 04:36+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. module: base
|
||||
|
||||
@@ -8,13 +8,13 @@ msgstr ""
|
||||
"Project-Id-Version: openobject-server\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
|
||||
"PO-Revision-Date: 2010-09-11 15:00+0000\n"
|
||||
"Last-Translator: Martin Hood <Unknown>\n"
|
||||
"PO-Revision-Date: 2010-09-29 08:03+0000\n"
|
||||
"Last-Translator: OpenERP Administrators <Unknown>\n"
|
||||
"Language-Team: English (United Kingdom) <en_GB@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2010-09-29 04:46+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-09-30 04:38+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. module: base
|
||||
|
||||
@@ -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-12-18 08:39+0000\n"
|
||||
"PO-Revision-Date: 2010-09-21 14:25+0000\n"
|
||||
"Last-Translator: Tanel Kurvits <Unknown>\n"
|
||||
"PO-Revision-Date: 2010-09-29 07:51+0000\n"
|
||||
"Last-Translator: OpenERP Administrators <Unknown>\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-09-29 04:43+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-09-30 04:36+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. module: base
|
||||
|
||||
@@ -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-12-18 08:39+0000\n"
|
||||
"PO-Revision-Date: 2010-09-16 19:03+0000\n"
|
||||
"Last-Translator: Olivier Dony (OpenERP) <Unknown>\n"
|
||||
"PO-Revision-Date: 2010-09-29 08:01+0000\n"
|
||||
"Last-Translator: OpenERP Administrators <Unknown>\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-09-29 04:43+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-09-30 04:37+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. module: base
|
||||
|
||||
@@ -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-12-18 08:39+0000\n"
|
||||
"PO-Revision-Date: 2010-09-19 17:45+0000\n"
|
||||
"Last-Translator: Nicola Riolini - Micronaet <Unknown>\n"
|
||||
"PO-Revision-Date: 2010-09-29 08:28+0000\n"
|
||||
"Last-Translator: OpenERP Administrators <Unknown>\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-09-29 04:44+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-09-30 04:37+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. module: base
|
||||
|
||||
@@ -8,13 +8,13 @@ msgstr ""
|
||||
"Project-Id-Version: openobject-addons\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
|
||||
"PO-Revision-Date: 2010-09-13 08:00+0000\n"
|
||||
"PO-Revision-Date: 2010-09-29 08:13+0000\n"
|
||||
"Last-Translator: ub121 <ubs121@gmail.com>\n"
|
||||
"Language-Team: Mongolian <mn@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2010-09-29 04:44+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-09-30 04:37+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. module: base
|
||||
|
||||
+25
-17
@@ -7,13 +7,13 @@ msgstr ""
|
||||
"Project-Id-Version: OpenERP Server 5.0.0\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
|
||||
"PO-Revision-Date: 2010-09-09 18:36+0000\n"
|
||||
"Last-Translator: Anup (OpenERP) <ach@tinyerp.com>\n"
|
||||
"PO-Revision-Date: 2010-10-01 11:47+0000\n"
|
||||
"Last-Translator: OpenERP Administrators <Unknown>\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-09-29 04:42+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-10-02 05:05+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. module: base
|
||||
@@ -3366,7 +3366,7 @@ msgstr "U kunt het menu opnieuw laden met (Ctrl+t Ctrl+r)."
|
||||
#: view:ir.ui.view_sc:0
|
||||
#: field:res.partner.title,shortcut:0
|
||||
msgid "Shortcut"
|
||||
msgstr "Sneltoets"
|
||||
msgstr "Snelkoppeling"
|
||||
|
||||
#. module: base
|
||||
#: field:ir.model.data,date_init:0
|
||||
@@ -8109,34 +8109,35 @@ msgstr "U kunt niet twee gebruikers hebben met dezelfde gebruikersnaam !"
|
||||
#. module: base
|
||||
#: sql_constraint:ir.model.fields:0
|
||||
msgid "Size of the field can never be less than 1 !"
|
||||
msgstr ""
|
||||
msgstr "De veldlengte kan nooit kleiner dan 1 zijn !"
|
||||
|
||||
#. module: base
|
||||
#: sql_constraint:ir.ui.view_sc:0
|
||||
msgid "Shortcut for this menu already exists!"
|
||||
msgstr ""
|
||||
msgstr "Dit menu heeft al een snelkoppeling!"
|
||||
|
||||
#. module: base
|
||||
#: sql_constraint:ir.model.data:0
|
||||
msgid ""
|
||||
"You cannot have multiple records with the same id for the same module !"
|
||||
msgstr ""
|
||||
"U kunt niet meer records hebben met dezelfde id voor dezelfde module !"
|
||||
|
||||
#. module: base
|
||||
#: sql_constraint:maintenance.contract:0
|
||||
msgid "Your maintenance contract is already subscribed in the system !"
|
||||
msgstr ""
|
||||
msgstr "Uw onderhoudscontract is al ingeschreven in het systeem !"
|
||||
|
||||
#. module: base
|
||||
#: sql_constraint:ir.module.module:0
|
||||
#: sql_constraint:ir.module.web:0
|
||||
msgid "The name of the module must be unique !"
|
||||
msgstr ""
|
||||
msgstr "De modulenaam moet uniek zijn !"
|
||||
|
||||
#. module: base
|
||||
#: sql_constraint:ir.module.module:0
|
||||
msgid "The certificate ID of the module must be unique !"
|
||||
msgstr ""
|
||||
msgstr "Het kwaliteitscertificaat id van de module moet uniek zijn !"
|
||||
|
||||
#. module: base
|
||||
#: sql_constraint:res.partner.function:0
|
||||
@@ -8146,38 +8147,38 @@ msgstr ""
|
||||
#. module: base
|
||||
#: sql_constraint:res.partner:0
|
||||
msgid "The name of the Partner must be unique !"
|
||||
msgstr ""
|
||||
msgstr "De relatienaam moet uniek zijn !"
|
||||
|
||||
#. module: base
|
||||
#: sql_constraint:res.country:0
|
||||
msgid "The name of the country must be unique !"
|
||||
msgstr ""
|
||||
msgstr "De landnaam moet uniek zijn !"
|
||||
|
||||
#. module: base
|
||||
#: sql_constraint:res.country:0
|
||||
msgid "The code of the country must be unique !"
|
||||
msgstr ""
|
||||
msgstr "De landcode moet uniek zijn !"
|
||||
|
||||
#. module: base
|
||||
#: sql_constraint:res.lang:0
|
||||
msgid "The name of the language must be unique !"
|
||||
msgstr ""
|
||||
msgstr "De taalnaam moet uniek zijn !"
|
||||
|
||||
#. module: base
|
||||
#: sql_constraint:res.lang:0
|
||||
msgid "The code of the language must be unique !"
|
||||
msgstr ""
|
||||
msgstr "De taalcode moet uniek zijn !"
|
||||
|
||||
#. module: base
|
||||
#: sql_constraint:res.groups:0
|
||||
msgid "The name of the group must be unique !"
|
||||
msgstr ""
|
||||
msgstr "De groepsnaam moet uniek zijn !"
|
||||
|
||||
#. module: base
|
||||
#: code:addons/osv/osv.py:0
|
||||
#, python-format
|
||||
msgid "Constraint Error"
|
||||
msgstr ""
|
||||
msgstr "Voorwaarde Fout"
|
||||
|
||||
#. module: base
|
||||
#: code:addons/osv/osv.py:0
|
||||
@@ -8188,6 +8189,10 @@ msgid ""
|
||||
"reference it\n"
|
||||
"- creation/update: a mandatory field is not correctly set"
|
||||
msgstr ""
|
||||
"De bewerking kan niet worden afgerond, waarschijnlijk vanwege:\n"
|
||||
"- verwijdering: u probeert een record te verwijderen terwijl er nog door een "
|
||||
"ander aan wordt gerefereerd\n"
|
||||
"- maken/wijzigen: een verplicht veld is niet correct ingevuld"
|
||||
|
||||
#. module: base
|
||||
#: code:addons/osv/osv.py:0
|
||||
@@ -8197,12 +8202,15 @@ msgid ""
|
||||
"\n"
|
||||
"[object with reference: %s - %s]"
|
||||
msgstr ""
|
||||
"\n"
|
||||
"\n"
|
||||
"[object met referentie: %s - %s]"
|
||||
|
||||
#. module: base
|
||||
#: code:addons/osv/osv.py:0
|
||||
#, python-format
|
||||
msgid "Integrity Error"
|
||||
msgstr ""
|
||||
msgstr "Integriteit Fout"
|
||||
|
||||
#~ msgid "Main Company"
|
||||
#~ msgstr "Moederorganisatie"
|
||||
|
||||
@@ -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-12-18 08:39+0000\n"
|
||||
"PO-Revision-Date: 2010-09-26 10:02+0000\n"
|
||||
"Last-Translator: Michał Węgrzynek <Unknown>\n"
|
||||
"PO-Revision-Date: 2010-09-29 08:34+0000\n"
|
||||
"Last-Translator: OpenERP Administrators <Unknown>\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-09-29 04:45+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-09-30 04:37+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. module: base
|
||||
|
||||
@@ -7,13 +7,13 @@ msgstr ""
|
||||
"Project-Id-Version: pt_BR\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
|
||||
"PO-Revision-Date: 2010-09-09 18:12+0000\n"
|
||||
"PO-Revision-Date: 2010-09-29 08:12+0000\n"
|
||||
"Last-Translator: Anup (OpenERP) <ach@tinyerp.com>\n"
|
||||
"Language-Team: <pt@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2010-09-29 04:46+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-09-30 04:37+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. module: base
|
||||
|
||||
@@ -7,13 +7,13 @@ msgstr ""
|
||||
"Project-Id-Version: OpenERP Server 5.0.0\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
|
||||
"PO-Revision-Date: 2010-09-27 12:19+0000\n"
|
||||
"Last-Translator: Daniel Stenlöv (XCLUDE) <Unknown>\n"
|
||||
"PO-Revision-Date: 2010-09-29 08:22+0000\n"
|
||||
"Last-Translator: OpenERP Administrators <Unknown>\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-09-29 04:46+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-09-30 04:37+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. module: base
|
||||
|
||||
@@ -28,8 +28,9 @@ from tools.translate import _
|
||||
import netsvc
|
||||
import re
|
||||
import copy
|
||||
import sys
|
||||
import os
|
||||
from xml import dom
|
||||
from report.report_sxw import report_sxw, report_rml
|
||||
|
||||
class actions(osv.osv):
|
||||
_name = 'ir.actions.actions'
|
||||
@@ -89,6 +90,27 @@ class report_xml(osv.osv):
|
||||
res[report.id] = False
|
||||
return res
|
||||
|
||||
def register_all(self, cr):
|
||||
"""Report registration handler that may be overridden by subclasses to
|
||||
add their own kinds of report services.
|
||||
Loads all reports with no manual loaders (auto==True) and
|
||||
registers the appropriate services to implement them.
|
||||
"""
|
||||
opj = os.path.join
|
||||
cr.execute("SELECT * FROM ir_act_report_xml WHERE auto=%s ORDER BY id", (True,))
|
||||
result = cr.dictfetchall()
|
||||
svcs = netsvc.Service._services
|
||||
for r in result:
|
||||
if svcs.has_key('report.'+r['report_name']):
|
||||
continue
|
||||
if r['report_rml'] or r['report_rml_content_data']:
|
||||
report_sxw('report.'+r['report_name'], r['model'],
|
||||
opj('addons',r['report_rml'] or '/'), header=r['header'])
|
||||
if r['report_xsl']:
|
||||
report_rml('report.'+r['report_name'], r['model'],
|
||||
opj('addons',r['report_xml']),
|
||||
r['report_xsl'] and opj('addons',r['report_xsl']))
|
||||
|
||||
_name = 'ir.actions.report.xml'
|
||||
_table = 'ir_act_report_xml'
|
||||
_sequence = 'ir_actions_id_seq'
|
||||
@@ -98,7 +120,7 @@ class report_xml(osv.osv):
|
||||
'type': fields.char('Action Type', size=32, required=True),
|
||||
'report_name': fields.char('Service Name', size=64, required=True),
|
||||
'usage': fields.char('Action Usage', size=32),
|
||||
'report_type': fields.selection([ ('pdf','pdf'), ('html','html'), ('raw','raw'), ('sxw','sxw'), ('txt','txt'), ('odt','odt'), ('html2html','HTML from HTML'), ('mako2html','HTML from Mako'), ], string='Report Type', required=True),
|
||||
'report_type': fields.char('Report Type', size=32, required=True, help="Report Type, e.g. pdf, html, raw, sxw, odt, html2html, mako2html, ..."),
|
||||
'groups_id': fields.many2many('res.groups', 'res_groups_report_rel', 'uid', 'gid', 'Groups'),
|
||||
'multi': fields.boolean('On multiple doc.', help="If set to true, the action will not be displayed on the right toolbar of a form view."),
|
||||
'attachment': fields.char('Save As Attachment Prefix', size=128, help='This is the filename of the attachment used to store the printing result. Keep empty to not save the printed reports. You can use a python expression with the object and time variables.'),
|
||||
|
||||
@@ -137,7 +137,8 @@ class ir_rule(osv.osv):
|
||||
def domain_get(self, cr, uid, model_name, mode='read', context={}):
|
||||
dom = self._compute_domain(cr, uid, model_name, mode=mode)
|
||||
if dom:
|
||||
return self.pool.get(model_name)._where_calc(cr, uid, dom, active_test=False)
|
||||
query = self.pool.get(model_name)._where_calc(cr, uid, dom, active_test=False)
|
||||
return query.where_clause, query.where_clause_params, query.tables
|
||||
return [], [], ['"'+self.pool.get(model_name)._table+'"']
|
||||
|
||||
def unlink(self, cr, uid, ids, context=None):
|
||||
|
||||
@@ -19,27 +19,24 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import tarfile
|
||||
import re
|
||||
import urllib
|
||||
import os
|
||||
import imp
|
||||
import logging
|
||||
import tools
|
||||
from osv import fields, osv, orm
|
||||
import zipfile
|
||||
import release
|
||||
import os
|
||||
import re
|
||||
import urllib
|
||||
import zipimport
|
||||
|
||||
import wizard
|
||||
import addons
|
||||
import pooler
|
||||
import netsvc
|
||||
import pooler
|
||||
import release
|
||||
import tools
|
||||
|
||||
from tools.parse_version import parse_version
|
||||
from tools.translate import _
|
||||
|
||||
from osv import fields, osv, orm
|
||||
|
||||
class module_category(osv.osv):
|
||||
_name = "ir.module.category"
|
||||
_description = "Module Category"
|
||||
@@ -80,8 +77,9 @@ class module(osv.osv):
|
||||
info = addons.load_information_from_description_file(name)
|
||||
if 'version' in info:
|
||||
info['version'] = release.major_version + '.' + info['version']
|
||||
except:
|
||||
pass
|
||||
except Exception:
|
||||
self.__logger.debug('Error when trying to fetch informations for '
|
||||
'module %s', name, exc_info=True)
|
||||
return info
|
||||
|
||||
def _get_latest_version(self, cr, uid, ids, field_name=None, arg=None, context={}):
|
||||
@@ -116,17 +114,21 @@ class module(osv.osv):
|
||||
v = view_obj.browse(cr,uid,data_id.res_id)
|
||||
aa = v.inherit_id and '* INHERIT ' or ''
|
||||
res[mnames[data_id.module]]['views_by_module'] += aa + v.name + ' ('+v.type+')\n'
|
||||
except:
|
||||
pass
|
||||
except Exception:
|
||||
self.__logger.debug(
|
||||
'Unknown error while browsing ir.ui.view[%s]',
|
||||
data_id.res_id, exc_info=True)
|
||||
elif key=='ir.actions.report.xml':
|
||||
res[mnames[data_id.module]]['reports_by_module'] += report_obj.browse(cr,uid,data_id.res_id).name + '\n'
|
||||
elif key=='ir.ui.menu':
|
||||
try:
|
||||
m = menu_obj.browse(cr,uid,data_id.res_id)
|
||||
res[mnames[data_id.module]]['menus_by_module'] += m.complete_name + '\n'
|
||||
except:
|
||||
pass
|
||||
except KeyError, e:
|
||||
except Exception:
|
||||
self.__logger.debug(
|
||||
'Unknown error while browsing ir.ui.menu[%s]',
|
||||
data_id.res_id, exc_info=True)
|
||||
except KeyError:
|
||||
pass
|
||||
return res
|
||||
|
||||
@@ -393,7 +395,9 @@ class module(osv.osv):
|
||||
fp = file(fname, 'wb')
|
||||
fp.write(zipfile)
|
||||
fp.close()
|
||||
except Exception, e:
|
||||
except Exception:
|
||||
self.__logger.exception('Error when trying to create module '
|
||||
'file %s', fname)
|
||||
raise orm.except_orm(_('Error'), _('Can not create the module file:\n %s') % (fname,))
|
||||
terp = self.get_module_info(mod.name)
|
||||
self.write(cr, uid, mod.id, self.get_values_from_terp(terp))
|
||||
|
||||
@@ -392,7 +392,7 @@ class res_partner_bank(osv.osv):
|
||||
_columns = {
|
||||
'name': fields.char('Description', size=128),
|
||||
'acc_number': fields.char('Account Number', size=64, required=False),
|
||||
'bank': fields.many2one('res.bank', 'Bank'),
|
||||
'bank': fields.many2one('res.bank', 'Bank', required=True),
|
||||
'owner_name': fields.char('Account Owner', size=64),
|
||||
'street': fields.char('Street', size=128),
|
||||
'zip': fields.char('Zip', change_default=True, size=24),
|
||||
|
||||
@@ -242,8 +242,8 @@ class users(osv.osv):
|
||||
'signature': fields.text('Signature', size=64),
|
||||
'address_id': fields.many2one('res.partner.address', 'Company Address'),
|
||||
'active': fields.boolean('Active'),
|
||||
'action_id': fields.many2one('ir.actions.actions', 'Home Action'),
|
||||
'menu_id': fields.many2one('ir.actions.actions', 'Menu Action'),
|
||||
'action_id': fields.many2one('ir.actions.actions', 'Home Action', help="If specified, this action will be opened at logon for this user, in addition to the standard menu."),
|
||||
'menu_id': fields.many2one('ir.actions.actions', 'Menu Action', help="If specified, the action will replace the standard menu for this user."),
|
||||
'groups_id': fields.many2many('res.groups', 'res_groups_users_rel', 'uid', 'gid', 'Groups'),
|
||||
'roles_id': fields.many2many('res.roles', 'res_roles_users_rel', 'uid', 'rid', 'Roles'),
|
||||
|
||||
@@ -288,15 +288,6 @@ class users(osv.osv):
|
||||
result = override_password(result)
|
||||
else:
|
||||
result = map(override_password, result)
|
||||
|
||||
if isinstance(result, list):
|
||||
for rec in result:
|
||||
if not rec.get('action_id',True):
|
||||
rec['action_id'] = (self._get_menu(cr, uid),'Menu')
|
||||
else:
|
||||
if not result.get('action_id',True):
|
||||
result['action_id'] = (self._get_menu(cr, uid),'Menu')
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@@ -327,10 +318,6 @@ class users(osv.osv):
|
||||
self.__admin_ids[cr.dbname] = ir_model_data_obj.read(cr, 1, [mdid], ['res_id'])[0]['res_id']
|
||||
return self.__admin_ids[cr.dbname]
|
||||
|
||||
def _get_action(self,cr, uid, context={}):
|
||||
ids = self.pool.get('ir.ui.menu').search(cr, uid, [('usage','=','menu')])
|
||||
return ids and ids[0] or False
|
||||
|
||||
def _get_company(self,cr, uid, context=None, uid2=False):
|
||||
if not uid2:
|
||||
uid2 = uid
|
||||
@@ -344,12 +331,12 @@ class users(osv.osv):
|
||||
return [c]
|
||||
return False
|
||||
|
||||
def _get_menu(self,cr, uid, context={}):
|
||||
ids = self.pool.get('ir.actions.act_window').search(cr, uid, [('usage','=','menu')])
|
||||
def _get_menu(self,cr, uid, context=None):
|
||||
ids = self.pool.get('ir.actions.act_window').search(cr, uid, [('usage','=','menu')], context=context)
|
||||
return ids and ids[0] or False
|
||||
|
||||
def _get_group(self,cr, uid, context={}):
|
||||
ids = self.pool.get('res.groups').search(cr, uid, [('name','=','Employee')])
|
||||
def _get_group(self,cr, uid, context=None):
|
||||
ids = self.pool.get('res.groups').search(cr, uid, [('name','=','Employee')], context=context)
|
||||
return ids or False
|
||||
|
||||
_defaults = {
|
||||
@@ -357,7 +344,6 @@ class users(osv.osv):
|
||||
'context_lang': lambda *args: 'en_US',
|
||||
'active' : lambda *a: True,
|
||||
'menu_id': _get_menu,
|
||||
'action_id': _get_menu,
|
||||
'company_id': _get_company,
|
||||
'company_ids': _get_companies,
|
||||
'groups_id': _get_group,
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"access_ir_model_fields_all","ir_model_fields all","model_ir_model_fields",,1,0,0,0
|
||||
"access_ir_module_category_group_user","ir_module_category group_user","model_ir_module_category","group_system",1,0,0,0
|
||||
"access_ir_module_module_group_user","ir_module_module group_user","model_ir_module_module","group_system",1,1,1,1
|
||||
"access_ir_module_module_user","ir_module_module user","model_ir_module_module",,1,0,0,0
|
||||
"access_ir_module_module_dependency_group_system","ir_module_module_dependency group_system","model_ir_module_module_dependency","group_system",1,1,1,1
|
||||
"access_ir_property_group_user","ir_property group_user","model_ir_property",,1,0,0,0
|
||||
"access_ir_property_group_user_manager","ir_property group_manager","model_ir_property","base.group_partner_manager",1,1,1,0
|
||||
|
||||
|
+88
-120
@@ -54,6 +54,7 @@ from tools.config import config
|
||||
from tools.translate import _
|
||||
|
||||
import fields
|
||||
from query import Query
|
||||
import tools
|
||||
from tools.safe_eval import safe_eval as eval
|
||||
|
||||
@@ -914,7 +915,7 @@ class orm_template(object):
|
||||
nbrmax = max(nbrmax, max2)
|
||||
warning = warning + w2
|
||||
reduce(lambda x, y: x and y, newrow)
|
||||
row[field] = (reduce(lambda x, y: x or y, newrow.values()) and \
|
||||
row[field] = newrow and (reduce(lambda x, y: x or y, newrow.values()) and \
|
||||
[(0, 0, newrow)]) or []
|
||||
i = max2
|
||||
while (position+i) < len(datas):
|
||||
@@ -929,7 +930,7 @@ class orm_template(object):
|
||||
(newrow, max2, w2, translate2, data_id2, data_res_id2) = process_liness(
|
||||
self, datas, prefix+[field], current_module, relation_obj._name, newfd, position+i)
|
||||
warning = warning + w2
|
||||
if reduce(lambda x, y: x or y, newrow.values()):
|
||||
if newrow and reduce(lambda x, y: x or y, newrow.values()):
|
||||
row[field].append((0, 0, newrow))
|
||||
i += max2
|
||||
nbrmax = max(nbrmax, i)
|
||||
@@ -2203,35 +2204,15 @@ class orm(orm_template):
|
||||
if not fields:
|
||||
fields = self._columns.keys()
|
||||
|
||||
# compute the where, order by, limit and offset clauses
|
||||
(where_clause, where_clause_params, tables) = self._where_calc(cr, uid, domain, context=context)
|
||||
|
||||
# apply direct ir.rules from current model
|
||||
self._apply_ir_rules(cr, uid, where_clause, where_clause_params, tables, 'read', context=context)
|
||||
|
||||
# then apply the ir.rules from the parents (through _inherits), adding the appropriate JOINs if needed
|
||||
for inherited_model in self._inherits:
|
||||
previous_tables = list(tables)
|
||||
if self._apply_ir_rules(cr, uid, where_clause, where_clause_params, tables, 'read', model_name=inherited_model, context=context):
|
||||
# if some rules were applied, need to add the missing JOIN for them to make sense, passing the previous
|
||||
# list of table in case the inherited table was not in the list before (as that means the corresponding
|
||||
# JOIN(s) was(were) not present)
|
||||
self._inherits_join_add(inherited_model, previous_tables, where_clause)
|
||||
tables = list(set(tables).union(set(previous_tables)))
|
||||
query = self._where_calc(cr, uid, domain, context=context)
|
||||
self._apply_ir_rules(cr, uid, query, 'read', context=context)
|
||||
|
||||
# Take care of adding join(s) if groupby is an '_inherits'ed field
|
||||
groupby_list = groupby
|
||||
if groupby:
|
||||
if isinstance(groupby, list):
|
||||
groupby = groupby[0]
|
||||
tables, where_clause, qfield = self._inherits_join_calc(groupby, tables, where_clause)
|
||||
|
||||
if len(where_clause):
|
||||
where_clause = ' where ' + ' and '.join(where_clause)
|
||||
else:
|
||||
where_clause = ''
|
||||
limit_str = limit and ' limit %d' % limit or ''
|
||||
offset_str = offset and ' offset %d' % offset or ''
|
||||
self._inherits_join_calc(groupby, query)
|
||||
|
||||
assert not groupby or groupby in fields, "Fields in 'groupby' must appear in the list of fields to read (perhaps it's missing in the list view?)"
|
||||
|
||||
@@ -2263,8 +2244,13 @@ class orm(orm_template):
|
||||
flist += ','
|
||||
flist += operator+'('+f+') as '+f
|
||||
|
||||
gb = groupby and (' group by '+groupby) or ''
|
||||
cr.execute('select min(%s.id) as id,' % self._table + flist + ' from ' + ','.join(tables) + where_clause + gb + limit_str + offset_str, where_clause_params)
|
||||
gb = groupby and (' GROUP BY '+groupby) or ''
|
||||
|
||||
from_clause, where_clause, where_clause_params = query.get_sql()
|
||||
where_clause = where_clause and ' WHERE ' + where_clause
|
||||
limit_str = limit and ' limit %d' % limit or ''
|
||||
offset_str = offset and ' offset %d' % offset or ''
|
||||
cr.execute('SELECT min(%s.id) AS id,' % self._table + flist + ' FROM ' + from_clause + where_clause + gb + limit_str + offset_str, where_clause_params)
|
||||
alldata = {}
|
||||
groupby = group_by
|
||||
for r in cr.dictfetchall():
|
||||
@@ -2303,43 +2289,37 @@ class orm(orm_template):
|
||||
del d['id']
|
||||
return data
|
||||
|
||||
def _inherits_join_add(self, parent_model_name, tables, where_clause):
|
||||
def _inherits_join_add(self, parent_model_name, query):
|
||||
"""
|
||||
Add missing table SELECT and JOIN clause for reaching the parent table (no duplicates)
|
||||
Add missing table SELECT and JOIN clause to ``query`` for reaching the parent table (no duplicates)
|
||||
|
||||
:param parent_model_name: name of the parent model for which the clauses should be added
|
||||
:param tables: list of table._table names enclosed in double quotes as returned
|
||||
by _where_calc()
|
||||
:param where_clause: current list of WHERE clause params
|
||||
:param query: query object on which the JOIN should be added
|
||||
"""
|
||||
inherits_field = self._inherits[parent_model_name]
|
||||
parent_model = self.pool.get(parent_model_name)
|
||||
parent_table_name = parent_model._table
|
||||
quoted_parent_table_name = '"%s"' % parent_table_name
|
||||
if quoted_parent_table_name not in tables:
|
||||
tables.append(quoted_parent_table_name)
|
||||
where_clause.append('("%s".%s = %s.id)' % (self._table, inherits_field, parent_table_name))
|
||||
return (tables, where_clause)
|
||||
if quoted_parent_table_name not in query.tables:
|
||||
query.tables.append(quoted_parent_table_name)
|
||||
query.where_clause.append('("%s".%s = %s.id)' % (self._table, inherits_field, parent_table_name))
|
||||
|
||||
def _inherits_join_calc(self, field, tables, where_clause):
|
||||
def _inherits_join_calc(self, field, query):
|
||||
"""
|
||||
Adds missing table select and join clause(s) for reaching
|
||||
Adds missing table select and join clause(s) to ``query`` for reaching
|
||||
the field coming from an '_inherits' parent table (no duplicates).
|
||||
|
||||
:param tables: list of table._table names enclosed in double quotes as returned
|
||||
by _where_calc()
|
||||
:param where_clause: current list of WHERE clause params
|
||||
:return: (tables, where_clause, qualified_field) where ``tables`` and ``where_clause`` are the updated
|
||||
versions of the parameters, and ``qualified_field`` is the qualified name of ``field``
|
||||
in the form ``table.field``, to be referenced in queries.
|
||||
:param field: name of inherited field to reach
|
||||
:param query: query object on which the JOIN should be added
|
||||
:return: qualified name of field, to be used in SELECT clause
|
||||
"""
|
||||
current_table = self
|
||||
while field in current_table._inherit_fields and not field in current_table._columns:
|
||||
parent_model_name = current_table._inherit_fields[field][0]
|
||||
parent_table = self.pool.get(parent_model_name)
|
||||
self._inherits_join_add(parent_model_name, tables, where_clause)
|
||||
self._inherits_join_add(parent_model_name, query)
|
||||
current_table = parent_table
|
||||
return (tables, where_clause, '"%s".%s' % (current_table._table, field))
|
||||
return '"%s".%s' % (current_table._table, field)
|
||||
|
||||
def _parent_store_compute(self, cr):
|
||||
if not self._parent_store:
|
||||
@@ -3899,84 +3879,87 @@ class orm(orm_template):
|
||||
raise NotImplementedError(_('This method does not exist anymore'))
|
||||
|
||||
# TODO: ameliorer avec NULL
|
||||
def _where_calc(self, cr, user, args, active_test=True, context=None):
|
||||
def _where_calc(self, cr, user, domain, active_test=True, context=None):
|
||||
"""Computes the WHERE clause needed to implement an OpenERP domain.
|
||||
:param args: the domain to compute
|
||||
:type args: list
|
||||
:param domain: the domain to compute
|
||||
:type domain: list
|
||||
:param active_test: whether the default filtering of records with ``active``
|
||||
field set to ``False`` should be applied.
|
||||
:return: tuple with 3 elements: (where_clause, where_clause_params, tables) where
|
||||
``where_clause`` contains a list of where clause elements (to be joined with 'AND'),
|
||||
``where_clause_params`` is a list of parameters to be passed to the db layer
|
||||
for the where_clause expansion, and ``tables`` is the list of double-quoted
|
||||
table names that need to be included in the FROM clause.
|
||||
:rtype: tuple
|
||||
:return: the query expressing the given domain as provided in domain
|
||||
:rtype: osv.query.Query
|
||||
"""
|
||||
if not context:
|
||||
context = {}
|
||||
args = args[:]
|
||||
domain = domain[:]
|
||||
# if the object has a field named 'active', filter out all inactive
|
||||
# records unless they were explicitely asked for
|
||||
if 'active' in self._columns and (active_test and context.get('active_test', True)):
|
||||
if args:
|
||||
if domain:
|
||||
active_in_args = False
|
||||
for a in args:
|
||||
for a in domain:
|
||||
if a[0] == 'active':
|
||||
active_in_args = True
|
||||
if not active_in_args:
|
||||
args.insert(0, ('active', '=', 1))
|
||||
domain.insert(0, ('active', '=', 1))
|
||||
else:
|
||||
args = [('active', '=', 1)]
|
||||
domain = [('active', '=', 1)]
|
||||
|
||||
if args:
|
||||
if domain:
|
||||
import expression
|
||||
e = expression.expression(args)
|
||||
e = expression.expression(domain)
|
||||
e.parse(cr, user, self, context)
|
||||
tables = e.get_tables()
|
||||
qu1, qu2 = e.to_sql()
|
||||
qu1 = qu1 and [qu1] or []
|
||||
where_clause, where_params = e.to_sql()
|
||||
where_clause = where_clause and [where_clause] or []
|
||||
else:
|
||||
qu1, qu2, tables = [], [], ['"%s"' % self._table]
|
||||
where_clause, where_params, tables = [], [], ['"%s"' % self._table]
|
||||
|
||||
return (qu1, qu2, tables)
|
||||
return Query(tables, where_clause, where_params)
|
||||
|
||||
def _check_qorder(self, word):
|
||||
if not regex_order.match(word):
|
||||
raise except_orm(_('AccessError'), _('Invalid "order" specified. A valid "order" specification is a comma-separated list of valid field names (optionally followed by asc/desc for the direction)'))
|
||||
return True
|
||||
|
||||
def _apply_ir_rules(self, cr, uid, where_clause, where_clause_params, tables, mode='read', model_name=None, context=None):
|
||||
"""Add what's missing in ``where_clause``, ``where_params``, ``tables`` to implement
|
||||
all appropriate ir.rules (on the current object but also from it's _inherits parents)
|
||||
def _apply_ir_rules(self, cr, uid, query, mode='read', context=None):
|
||||
"""Add what's missing in ``query`` to implement all appropriate ir.rules
|
||||
(using the ``model_name``'s rules or the current model's rules if ``model_name`` is None)
|
||||
|
||||
:param where_clause: list with current elements of the WHERE clause (strings)
|
||||
:param where_clause_params: list with parameters for ``where_clause``
|
||||
:param tables: list with double-quoted names of the tables that are joined
|
||||
in ``where_clause``
|
||||
:param model_name: optional name of the model whose ir.rules should be applied (default:``self._name``)
|
||||
This could be useful for inheritance for example, but there is no provision to include
|
||||
the appropriate JOIN for linking the current model to the one referenced in model_name.
|
||||
:return: True if additional clauses where applied.
|
||||
:param query: the current query object
|
||||
"""
|
||||
added_clause, added_params, added_tables = self.pool.get('ir.rule').domain_get(cr, uid, model_name or self._name, mode, context=context)
|
||||
if added_clause:
|
||||
where_clause += added_clause
|
||||
where_clause_params += added_params
|
||||
for table in added_tables:
|
||||
if table not in tables:
|
||||
tables.append(table)
|
||||
return True
|
||||
return False
|
||||
def apply_rule(added_clause, added_params, added_tables):
|
||||
if added_clause:
|
||||
query.where_clause += added_clause
|
||||
query.where_clause_params += added_params
|
||||
for table in added_tables:
|
||||
if table not in query.tables:
|
||||
query.tables.append(table)
|
||||
return True
|
||||
return False
|
||||
|
||||
def _generate_m2o_order_by(self, order_field, tables, where_clause):
|
||||
# apply main rules on the object
|
||||
rule_obj = self.pool.get('ir.rule')
|
||||
apply_rule(*rule_obj.domain_get(cr, uid, self._name, mode, context=context))
|
||||
|
||||
# apply ir.rules from the parents (through _inherits), adding the appropriate JOINs if needed
|
||||
for inherited_model in self._inherits:
|
||||
if apply_rule(*rule_obj.domain_get(cr, uid, inherited_model, mode, context=context)):
|
||||
# if some rules were applied, need to add the missing JOIN for them to make sense, passing the previous
|
||||
# list of table in case the inherited table was not in the list before (as that means the corresponding
|
||||
# JOIN(s) was(were) not present)
|
||||
self._inherits_join_add(inherited_model, query)
|
||||
|
||||
def _generate_m2o_order_by(self, order_field, query):
|
||||
"""
|
||||
Add possibly missing JOIN and generate the ORDER BY clause for m2o fields,
|
||||
Add possibly missing JOIN to ``query`` and generate the ORDER BY clause for m2o fields,
|
||||
either native m2o fields or function/related fields that are stored, including
|
||||
intermediate JOINs for inheritance if required.
|
||||
|
||||
:return: the qualified field name to use in an ORDER BY clause to sort by ``order_field``
|
||||
"""
|
||||
if order_field not in self._columns and order_field in self._inherit_fields:
|
||||
# also add missing joins for reaching the table containing the m2o field
|
||||
tables, where_clause, qualified_field = self._inherits_join_calc(order_field, tables, where_clause)
|
||||
qualified_field = self._inherits_join_calc(order_field, query)
|
||||
order_field_column = self._inherit_fields[order_field][2]
|
||||
else:
|
||||
qualified_field = '"%s"."%s"' % (self._table, order_field)
|
||||
@@ -3995,16 +3978,14 @@ class orm(orm_template):
|
||||
# extract the first field name, to be able to qualify it and add desc/asc
|
||||
m2o_order = m2o_order.split(",",1)[0].strip().split(" ",1)[0]
|
||||
|
||||
# the perhaps missing join:
|
||||
quoted_model_table = '"%s"' % dest_model._table
|
||||
if quoted_model_table not in tables:
|
||||
tables.append(quoted_model_table)
|
||||
where_clause.append('%s = %s.id' % (qualified_field, quoted_model_table))
|
||||
|
||||
return ('%s.%s' % (quoted_model_table, m2o_order), tables, where_clause)
|
||||
# Join the dest m2o table if it's not joined yet. We use [LEFT] OUTER join here
|
||||
# as we don't want to exclude results that have NULL values for the m2o
|
||||
src_table, src_field = qualified_field.replace('"','').split('.', 1)
|
||||
query.join((src_table, dest_model._table, src_field, 'id'), outer=True)
|
||||
return '"%s"."%s"' % (dest_model._table, m2o_order)
|
||||
|
||||
|
||||
def _generate_order_by(self, order_spec, tables, where_clause):
|
||||
def _generate_order_by(self, order_spec, query):
|
||||
"""
|
||||
Attempt to consruct an appropriate ORDER BY clause based on order_spec, which must be
|
||||
a comma-separated list of valid field names, optionally followed by an ASC or DESC direction.
|
||||
@@ -4024,16 +4005,16 @@ class orm(orm_template):
|
||||
if order_column._classic_read:
|
||||
order_by_clause = '"%s"."%s"' % (self._table, order_field)
|
||||
elif order_column._type == 'many2one':
|
||||
order_by_clause, tables, where_clause = self._generate_m2o_order_by(order_field, tables, where_clause)
|
||||
order_by_clause = self._generate_m2o_order_by(order_field, query)
|
||||
else:
|
||||
continue # ignore non-readable or "non-joignable" fields
|
||||
elif order_field in self._inherit_fields:
|
||||
parent_obj = self.pool.get(self._inherit_fields[order_field][0])
|
||||
order_column = parent_obj._columns[order_field]
|
||||
if order_column._classic_read:
|
||||
tables, where_clause, order_by_clause = self._inherits_join_calc(order_field, tables, where_clause)
|
||||
order_by_clause = self._inherits_join_calc(order_field, query)
|
||||
elif order_column._type == 'many2one':
|
||||
order_by_clause, tables, where_clause = self._generate_m2o_order_by(order_field, tables, where_clause)
|
||||
order_by_clause = self._generate_m2o_order_by(order_field, query)
|
||||
else:
|
||||
continue # ignore non-readable or "non-joignable" fields
|
||||
order_by_elements.append("%s %s" % (order_by_clause, order_direction))
|
||||
@@ -4054,34 +4035,21 @@ class orm(orm_template):
|
||||
if context is None:
|
||||
context = {}
|
||||
self.pool.get('ir.model.access').check(cr, access_rights_uid or user, self._name, 'read', context=context)
|
||||
# compute the where, order by, limit and offset clauses
|
||||
(where_clause, where_clause_params, tables) = self._where_calc(cr, user, args, context=context)
|
||||
|
||||
# apply direct ir.rules from current model
|
||||
self._apply_ir_rules(cr, user, where_clause, where_clause_params, tables, 'read', context=context)
|
||||
query = self._where_calc(cr, user, args, context=context)
|
||||
self._apply_ir_rules(cr, user, query, 'read', context=context)
|
||||
order_by = self._generate_order_by(order, query)
|
||||
from_clause, where_clause, where_clause_params = query.get_sql()
|
||||
|
||||
# then apply the ir.rules from the parents (through _inherits), adding the appropriate JOINs if needed
|
||||
for inherited_model in self._inherits:
|
||||
previous_tables = list(tables)
|
||||
if self._apply_ir_rules(cr, user, where_clause, where_clause_params, tables, 'read', model_name=inherited_model, context=context):
|
||||
# if some rules were applied, need to add the missing JOIN for them to make sense, passing the previous
|
||||
# list of table in case the inherited table was not in the list before (as that means the corresponding
|
||||
# JOIN(s) was(were) not present)
|
||||
self._inherits_join_add(inherited_model, previous_tables, where_clause)
|
||||
tables = list(set(tables).union(set(previous_tables)))
|
||||
|
||||
where = where_clause
|
||||
order_by = self._generate_order_by(order, tables, where_clause)
|
||||
limit_str = limit and ' limit %d' % limit or ''
|
||||
offset_str = offset and ' offset %d' % offset or ''
|
||||
where_str = where and (" WHERE %s" % " AND ".join(where)) or ''
|
||||
where_str = where_clause and (" WHERE %s" % where_clause) or ''
|
||||
|
||||
if count:
|
||||
cr.execute('select count(%s.id) from ' % self._table +
|
||||
','.join(tables) + where_str + limit_str + offset_str, where_clause_params)
|
||||
cr.execute('SELECT count("%s".id) FROM ' % self._table + from_clause + where_str + limit_str + offset_str, where_clause_params)
|
||||
res = cr.fetchall()
|
||||
return res[0][0]
|
||||
cr.execute('select %s.id from ' % self._table + ','.join(tables) + where_str + order_by + limit_str+offset_str, where_clause_params)
|
||||
cr.execute('SELECT "%s".id FROM ' % self._table + from_clause + where_str + order_by + limit_str + offset_str, where_clause_params)
|
||||
res = cr.fetchall()
|
||||
return [x[0] for x in res]
|
||||
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2010 OpenERP S.A. http://www.openerp.com
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
def _quote(to_quote):
|
||||
if '"' not in to_quote:
|
||||
return '"%s"' % to_quote
|
||||
return to_quote
|
||||
|
||||
|
||||
class Query(object):
|
||||
"""
|
||||
Dumb implementation of a Query object, using 3 string lists so far
|
||||
for backwards compatibility with the (table, where_clause, where_params) previously used.
|
||||
|
||||
TODO: To be improved after v6.0 to rewrite part of the ORM and add support for:
|
||||
- auto-generated multiple table aliases
|
||||
- multiple joins to the same table with different conditions
|
||||
- dynamic right-hand-side values in domains (e.g. a.name = a.description)
|
||||
- etc.
|
||||
"""
|
||||
|
||||
def __init__(self, tables=None, where_clause=None, where_clause_params=None, joins=None):
|
||||
|
||||
# holds the list of tables joined using default JOIN.
|
||||
# the table names are stored double-quoted (backwards compatibility)
|
||||
self.tables = tables or []
|
||||
|
||||
# holds the list of WHERE clause elements, to be joined with
|
||||
# 'AND' when generating the final query
|
||||
self.where_clause = where_clause or []
|
||||
|
||||
# holds the parameters for the formatting of `where_clause`, to be
|
||||
# passed to psycopg's execute method.
|
||||
self.where_clause_params = where_clause_params or []
|
||||
|
||||
# holds table joins done explicitly, supporting outer joins. The JOIN
|
||||
# condition should not be in `where_clause`. The dict is used as follows:
|
||||
# self.joins = {
|
||||
# 'table_a': [
|
||||
# ('table_b', 'table_a_col1', 'table_b_col', 'LEFT JOIN'),
|
||||
# ('table_c', 'table_a_col2', 'table_c_col', 'LEFT JOIN'),
|
||||
# ('table_d', 'table_a_col3', 'table_d_col', 'JOIN'),
|
||||
# ]
|
||||
# }
|
||||
# which should lead to the following SQL:
|
||||
# SELECT ... FROM "table_a" LEFT JOIN "table_b" ON ("table_a"."table_a_col1" = "table_b"."table_b_col")
|
||||
# LEFT JOIN "table_c" ON ("table_a"."table_a_col2" = "table_c"."table_c_col")
|
||||
self.joins = joins or {}
|
||||
|
||||
def join(self, connection, outer=False):
|
||||
"""Adds the JOIN specified in ``connection``.
|
||||
|
||||
:param connection: a tuple ``(lhs, table, lhs_col, col)``.
|
||||
The join corresponds to the SQL equivalent of::
|
||||
|
||||
``(lhs.lhs_col = table.col)``
|
||||
|
||||
:param outer: True if a LEFT OUTER JOIN should be used, if possible
|
||||
(no promotion to OUTER JOIN is supported in case the JOIN
|
||||
was already present in the query, as for the moment
|
||||
implicit INNER JOINs are only connected from NON-NULL
|
||||
columns so it would not be correct (e.g. for
|
||||
``_inherits`` or when a domain criterion explicitly
|
||||
adds filtering)
|
||||
"""
|
||||
(lhs, table, lhs_col, col) = connection
|
||||
lhs = _quote(lhs)
|
||||
table = _quote(table)
|
||||
assert lhs in self.tables, "Left-hand-side table must already be part of the query!"
|
||||
if table in self.tables:
|
||||
# already joined, must ignore (promotion to outer and multiple joins not supported yet)
|
||||
pass
|
||||
else:
|
||||
# add JOIN
|
||||
self.tables.append(table)
|
||||
self.joins.setdefault(lhs, []).append((table, lhs_col, col, outer and 'LEFT JOIN' or 'JOIN'))
|
||||
return self
|
||||
|
||||
def get_sql(self):
|
||||
"""Returns (query_from, query_where, query_params)"""
|
||||
query_from = ''
|
||||
tables_to_process = list(self.tables)
|
||||
|
||||
def add_joins_for_table(table, query_from):
|
||||
for (dest_table, lhs_col, col, join) in self.joins.get(table,[]):
|
||||
tables_to_process.remove(dest_table)
|
||||
query_from += ' %s %s ON (%s."%s" = %s."%s")' % \
|
||||
(join, dest_table, table, lhs_col, dest_table, col)
|
||||
query_from = add_joins_for_table(dest_table, query_from)
|
||||
return query_from
|
||||
|
||||
for table in tables_to_process:
|
||||
query_from += table
|
||||
if table in self.joins:
|
||||
query_from = add_joins_for_table(table, query_from)
|
||||
query_from += ','
|
||||
query_from = query_from[:-1] # drop last comma
|
||||
return (query_from, " AND ".join(self.where_clause), self.where_clause_params)
|
||||
|
||||
def __str__(self):
|
||||
return '<osv.Query: "SELECT ... FROM %s WHERE %s" with params: %r>' % self.get_sql()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
+1
-2
@@ -44,12 +44,11 @@ def get_db_and_pool(db_name, force_demo=False, status=None, update_module=False,
|
||||
cr = db.cursor()
|
||||
try:
|
||||
pool.init_set(cr, False)
|
||||
pool.get('ir.actions.report.xml').register_all(cr)
|
||||
cr.commit()
|
||||
finally:
|
||||
cr.close()
|
||||
|
||||
import report
|
||||
report.interface.register_all(db)
|
||||
if pooljobs:
|
||||
pool.get('ir.cron').restart(db.dbname)
|
||||
return db, pool
|
||||
|
||||
@@ -219,25 +219,5 @@ class report_rml(report_int):
|
||||
obj.render()
|
||||
return obj.get()
|
||||
|
||||
from report_sxw import report_sxw
|
||||
|
||||
def register_all(db):
|
||||
opj = os.path.join
|
||||
cr = db.cursor()
|
||||
cr.execute("SELECT * FROM ir_act_report_xml WHERE auto=%s ORDER BY id", (True,))
|
||||
result = cr.dictfetchall()
|
||||
cr.close()
|
||||
svcs = netsvc.Service._services
|
||||
for r in result:
|
||||
if svcs.has_key('report.'+r['report_name']):
|
||||
continue
|
||||
if r['report_rml'] or r['report_rml_content_data']:
|
||||
report_sxw('report.'+r['report_name'], r['model'],
|
||||
opj('addons',r['report_rml'] or '/'), header=r['header'])
|
||||
if r['report_xsl']:
|
||||
report_rml('report.'+r['report_name'], r['model'],
|
||||
opj('addons',r['report_xml']),
|
||||
r['report_xsl'] and opj('addons',r['report_xsl']))
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -98,6 +98,7 @@ class report_printscreen_list(report_int):
|
||||
continue
|
||||
child_ids = model.search(cr, uid, inner_domain)
|
||||
res = model.read(cr, uid, child_ids, result['fields'].keys(), context)
|
||||
res.sort(lambda x,y: cmp(ids.index(x['id']), ids.index(y['id'])))
|
||||
rows.extend(res)
|
||||
dom = [('id','in',ids)]
|
||||
if self.groupby_no_leaf and len(ids) and not ids[0]:
|
||||
|
||||
@@ -39,6 +39,7 @@ import tools
|
||||
import warnings
|
||||
import zipfile
|
||||
import common
|
||||
from osv.fields import float as float_class, function as function_class
|
||||
|
||||
DT_FORMAT = '%Y-%m-%d'
|
||||
DHM_FORMAT = '%Y-%m-%d %H:%M:%S'
|
||||
@@ -240,9 +241,36 @@ class rml_parse(object):
|
||||
self.default_lang[lang] = self.lang_dict.copy()
|
||||
return True
|
||||
|
||||
def formatLang(self, value, digits=2, date=False,date_time=False, grouping=True, monetary=False):
|
||||
def digits_fmt(self, obj=None, f=None, dp=None):
|
||||
digits = self.get_digits(obj, f, dp)
|
||||
return "%%.%df" % (digits, )
|
||||
|
||||
def get_digits(self, obj=None, f=None, dp=None):
|
||||
d = DEFAULT_DIGITS = 2
|
||||
if dp:
|
||||
decimal_precision_obj = self.pool.get('decimal.precision')
|
||||
ids = decimal_precision_obj.search(self.cr, self.uid, [('name', '=', dp)])
|
||||
if ids:
|
||||
d = decimal_precision_obj.browse(self.cr, self.uid, ids)[0].digits
|
||||
elif obj and f:
|
||||
res_digits = getattr(obj._columns[f], 'digits', lambda x: ((16,DEFAULT_DIGITS)))
|
||||
if isinstance(res_digits, tuple):
|
||||
d = res_digits[1]
|
||||
else:
|
||||
d = res_digits(self.cr)[1]
|
||||
elif (hasattr(obj, '_field') and\
|
||||
isinstance(obj._field, (float_class, function_class)) and\
|
||||
obj._field.digits):
|
||||
d = obj._field.digits[1] or DEFAULT_DIGITS
|
||||
return d
|
||||
|
||||
def formatLang(self, value, digits=None, date=False, date_time=False, grouping=True, monetary=False):
|
||||
if digits is None:
|
||||
digits = self.get_digits(value)
|
||||
|
||||
if isinstance(value, (str, unicode)) and not value:
|
||||
return ''
|
||||
|
||||
if not self.lang_dict_called:
|
||||
self._get_lang_dict()
|
||||
self.lang_dict_called = True
|
||||
@@ -250,6 +278,7 @@ class rml_parse(object):
|
||||
if date or date_time:
|
||||
if not str(value):
|
||||
return ''
|
||||
|
||||
date_format = self.lang_dict['date_format']
|
||||
parse_format = DT_FORMAT
|
||||
if date_time:
|
||||
@@ -258,9 +287,11 @@ class rml_parse(object):
|
||||
parse_format = DHM_FORMAT
|
||||
if not isinstance(value, time.struct_time):
|
||||
return time.strftime(date_format, time.strptime(value, parse_format))
|
||||
|
||||
else:
|
||||
date = datetime(*value.timetuple()[:6])
|
||||
return date.strftime(date_format)
|
||||
|
||||
return self.lang_dict['lang_obj'].format('%.' + str(digits) + 'f', value, grouping=grouping, monetary=monetary)
|
||||
|
||||
def repeatIn(self, lst, name,nodes_parent=False):
|
||||
@@ -305,6 +336,8 @@ class rml_parse(object):
|
||||
def set_context(self, objects, data, ids, report_type = None):
|
||||
self.localcontext['data'] = data
|
||||
self.localcontext['objects'] = objects
|
||||
self.localcontext['digits_fmt'] = self.digits_fmt
|
||||
self.localcontext['get_digits'] = self.get_digits
|
||||
self.datas = data
|
||||
self.ids = ids
|
||||
self.objects = objects
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2010 OpenERP S.A. http://www.openerp.com
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import unittest
|
||||
|
||||
import test
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.TextTestRunner(verbosity=2).run(unittest.defaultTestLoader.loadTestsFromModule(test))
|
||||
@@ -0,0 +1,22 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2010 OpenERP S.A. http://www.openerp.com
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from test_osv import *
|
||||
@@ -0,0 +1,64 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2010 OpenERP S.A. http://www.openerp.com
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import unittest
|
||||
from osv.query import Query
|
||||
|
||||
class QueryTestCase(unittest.TestCase):
|
||||
|
||||
def test_basic_query(self):
|
||||
query = Query()
|
||||
query.tables.extend(['"product_product"','"product_template"'])
|
||||
query.where_clause.append("product_product.template_id = product_template.id")
|
||||
query.join(("product_template", "product_category", "categ_id", "id"), outer=False) # add normal join
|
||||
query.join(("product_product", "res_user", "user_id", "id"), outer=True) # outer join
|
||||
self.assertEquals(query.get_sql()[0].strip(),
|
||||
""""product_product" LEFT JOIN "res_user" ON ("product_product"."user_id" = "res_user"."id"),"product_template" JOIN "product_category" ON ("product_template"."categ_id" = "product_category"."id") """.strip())
|
||||
self.assertEquals(query.get_sql()[1].strip(), """product_product.template_id = product_template.id""".strip())
|
||||
|
||||
def test_query_chained_explicit_joins(self):
|
||||
query = Query()
|
||||
query.tables.extend(['"product_product"','"product_template"'])
|
||||
query.where_clause.append("product_product.template_id = product_template.id")
|
||||
query.join(("product_template", "product_category", "categ_id", "id"), outer=False) # add normal join
|
||||
query.join(("product_category", "res_user", "user_id", "id"), outer=True) # CHAINED outer join
|
||||
self.assertEquals(query.get_sql()[0].strip(),
|
||||
""""product_product","product_template" JOIN "product_category" ON ("product_template"."categ_id" = "product_category"."id") LEFT JOIN "res_user" ON ("product_category"."user_id" = "res_user"."id")""".strip())
|
||||
self.assertEquals(query.get_sql()[1].strip(), """product_product.template_id = product_template.id""".strip())
|
||||
|
||||
def test_mixed_query_chained_explicit_implicit_joins(self):
|
||||
query = Query()
|
||||
query.tables.extend(['"product_product"','"product_template"'])
|
||||
query.where_clause.append("product_product.template_id = product_template.id")
|
||||
query.join(("product_template", "product_category", "categ_id", "id"), outer=False) # add normal join
|
||||
query.join(("product_category", "res_user", "user_id", "id"), outer=True) # CHAINED outer join
|
||||
query.tables.append('"account.account"')
|
||||
query.where_clause.append("product_category.expense_account_id = account_account.id") # additional implicit join
|
||||
self.assertEquals(query.get_sql()[0].strip(),
|
||||
""""product_product","product_template" JOIN "product_category" ON ("product_template"."categ_id" = "product_category"."id") LEFT JOIN "res_user" ON ("product_category"."user_id" = "res_user"."id"),"account.account" """.strip())
|
||||
self.assertEquals(query.get_sql()[1].strip(), """product_product.template_id = product_template.id AND product_category.expense_account_id = account_account.id""".strip())
|
||||
|
||||
|
||||
def test_raise_missing_lhs(self):
|
||||
query = Query()
|
||||
query.tables.append('"product_product"')
|
||||
self.assertRaises(AssertionError, query.join, ("product_template", "product_category", "categ_id", "id"), outer=False)
|
||||
|
||||
Vendored
+3
-3
@@ -8,13 +8,13 @@ msgstr ""
|
||||
"Project-Id-Version: openobject-server\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2009-08-24 22:41+0300\n"
|
||||
"PO-Revision-Date: 2010-09-15 02:58+0000\n"
|
||||
"Last-Translator: barge <Unknown>\n"
|
||||
"PO-Revision-Date: 2010-09-29 08:30+0000\n"
|
||||
"Last-Translator: OpenERP Administrators <Unknown>\n"
|
||||
"Language-Team: Korean <ko@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2010-09-29 04:47+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-09-30 04:38+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. Type: string
|
||||
|
||||
Vendored
+2
-2
@@ -8,13 +8,13 @@ msgstr ""
|
||||
"Project-Id-Version: openobject-server\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2009-08-24 22:41+0300\n"
|
||||
"PO-Revision-Date: 2010-09-10 03:13+0000\n"
|
||||
"PO-Revision-Date: 2010-09-29 08:02+0000\n"
|
||||
"Last-Translator: ub121 <ubs121@gmail.com>\n"
|
||||
"Language-Team: Mongolian <mn@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2010-09-29 04:47+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-09-30 04:38+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. Type: string
|
||||
|
||||
Reference in New Issue
Block a user