bzr revid: vir@tinyerp.com-20101022042823-bo6lvr3gvinr52l7
This commit is contained in:
Vir (Open ERP) 2010-10-22 09:58:23 +05:30
commit a85ac78f8d
17 changed files with 223 additions and 52 deletions

View File

@ -21,6 +21,7 @@
from osv import osv
from tools.translate import _
import tools
class account_move_journal(osv.osv_memory):
_name = "account.move.journal"
@ -100,7 +101,7 @@ class account_move_journal(osv.osv_memory):
<button icon="gtk-cancel" special="cancel" string="Cancel"/>
<button icon="terp-gtk-go-back-rtl" string="Open" name="action_open_window" default_focus="1" type="object"/>
</group>
</form>""" % (str(journal), str(period))
</form>""" % (tools.ustr(journal), tools.ustr(period))
res.update({
'arch':view

View File

@ -181,9 +181,6 @@
<field name="amount_unreconciled" sum="Open Balance" readonly="1"/>
<field name="amount" sum="Payment"/>
</tree>
<form string="Payment Information">
<label string="Form view not available for Payment Lines"/>
</form>
</field>
<field name="line_cr_ids" colspan="4" nolabel="1" attrs="{'invisible': [('pre_line','=',False)]}" default_get="{'journal_id':journal_id, 'partner_id':partner_id}">
<tree string="Credits" editable="bottom">

View File

@ -477,7 +477,7 @@ property or property parameter."),
@param context: A standard dictionary for contextual values
@return: True
"""
if not context:
if context is None:
context = {}
company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.name
@ -555,7 +555,7 @@ property or property parameter."),
@param context: A standard dictionary for contextual values
@return: True
"""
if not context:
if context is None:
context = {}
for vals in self.browse(cr, uid, ids, context=context):
@ -575,7 +575,7 @@ property or property parameter."),
@param ids: List of calendar attendees IDs
@param *args: Get Tupple value
@param context: A standard dictionary for contextual values """
if not context:
if context is None:
context = {}
return self.write(cr, uid, ids, {'state': 'declined'}, context)
@ -587,7 +587,7 @@ property or property parameter."),
@param vals: Get Values
@param context: A standard dictionary for contextual values """
if not context:
if context is None:
context = {}
if not vals.get("email") and vals.get("cn"):
cnval = vals.get("cn").split(':')
@ -641,7 +641,7 @@ true, it will allow you to hide the event alarm information without removing it.
@param context: A standard dictionary for contextual values
@return: True
"""
if not context:
if context is None:
context = {}
alarm_obj = self.pool.get('calendar.alarm')
res_alarm_obj = self.pool.get('res.alarm')
@ -713,7 +713,7 @@ true, it will allow you to hide the event alarm information without removing it.
@param model: Model name for which alarm is to be cleared.
@return: True
"""
if not context:
if context is None:
context = {}
alarm_obj = self.pool.get('calendar.alarm')
ir_obj = self.pool.get('ir.model')
@ -781,7 +781,7 @@ class calendar_alarm(osv.osv):
@param context: A standard dictionary for contextual values
@return: new record id for calendar_alarm.
"""
if not context:
if context is None:
context = {}
event_date = vals.get('event_date', False)
if event_date:
@ -808,7 +808,7 @@ class calendar_alarm(osv.osv):
@param context: A standard dictionary for contextual values
"""
return True # XXX FIXME REMOVE THIS AFTER FIXING get_recurrent_dates!!
if not context:
if context is None:
context = {}
current_datetime = datetime.now()
request_obj = self.pool.get('res.request')
@ -943,8 +943,9 @@ class calendar_event(osv.osv):
@param end_date: Ending Datee
@param context: A standard dictionary for contextual values
"""
if not context:
if context is None:
context = {}
value = {}
if not start_date:
return value
@ -967,6 +968,14 @@ class calendar_event(osv.osv):
elif not end_date:
end = start + timedelta(hours=duration)
value['date_deadline'] = end.strftime("%Y-%m-%d %H:%M:%S")
elif end_date and duration:
# we have both, keep them synchronized:
# set duration based on end_date (arbitrary decision: this avoid
# getting dates like 06:31:48 instead of 06:32:00)
end = datetime.strptime(end_date, "%Y-%m-%d %H:%M:%S")
diff = end - start
duration = float(diff.days)* 24 + (float(diff.seconds) / 3600)
value['duration'] = round(duration, 2)
return {'value': value}
@ -975,7 +984,7 @@ class calendar_event(osv.osv):
This function deletes event which are linked with the event with recurrent_uid
(Removes the events which refers to the same UID value)
"""
if not context:
if context is None:
context = {}
for event_id in ids:
cr.execute("select id from %s where recurrent_uid=%%s" % (self._table), (event_id,))
@ -992,7 +1001,7 @@ class calendar_event(osv.osv):
@param context: A standard dictionary for contextual values
@return: dictionary of rrule value.
"""
if not context:
if context is None:
context = {}
cr.execute("UPDATE %s set freq='None',interval=0,count=0,end_date=Null,\
mo=False,tu=False,we=False,th=False,fr=False,sa=False,su=False,\
@ -1203,7 +1212,7 @@ true, it will allow you to hide the event alarm information without removing it.
@param context: A standard dictionary for contextual values
@return: Dictionary value which open Crm Meeting form.
"""
if not context:
if context is None:
context = {}
data_obj = self.pool.get('ir.model.data')
@ -1448,7 +1457,7 @@ true, it will allow you to hide the event alarm information without removing it.
@param context: A standard dictionary for contextual values
@return: True
"""
if not context:
if context is None:
context = {}
if isinstance(ids, (str, int, long)):
select = [ids]
@ -1477,14 +1486,23 @@ true, it will allow you to hide the event alarm information without removing it.
if vals.get('vtimezone', '').startswith('/freeassociation.sourceforge.net/tzfile/'):
vals['vtimezone'] = vals['vtimezone'][40:]
updated_vals = self.onchange_dates(cr, uid, new_ids,
vals.get('date', False),
vals.get('duration', False),
vals.get('date_deadline', False),
vals.get('allday', False),
context=context)
vals.update(updated_vals.get('value', {}))
if new_ids:
res = super(calendar_event, self).write(cr, uid, new_ids, vals, context=context)
if (vals.has_key('alarm_id') or vals.has_key('base_calendar_alarm_id'))\
or (vals.has_key('date') or vals.has_key('duration') or vals.has_key('date_deadline')):
if ('alarm_id' in vals or 'base_calendar_alarm_id' in vals)\
or ('date' in vals or 'duration' in vals or 'date_deadline' in vals):
# change alarm details
alarm_obj = self.pool.get('res.alarm')
alarm_obj.do_alarm_create(cr, uid, new_ids, self._name, 'date', \
context=context)
alarm_obj.do_alarm_create(cr, uid, new_ids, self._name, 'date', context=context)
return res
def browse(self, cr, uid, ids, context=None, list_class=None, fields_process=None):
@ -1520,7 +1538,7 @@ true, it will allow you to hide the event alarm information without removing it.
@return: List of Dictionary of form [{name_of_the_field: value, ...}, ...]
"""
# FIXME This whole id mangling has to go!
if not context:
if context is None:
context = {}
if isinstance(ids, (str, int, long)):
@ -1558,7 +1576,7 @@ true, it will allow you to hide the event alarm information without removing it.
@param context: A standard dictionary for contextual values
@return: Duplicate record id.
"""
if not context:
if context is None:
context = {}
res = super(calendar_event, self).copy(cr, uid, base_calendar_id2real_id(id), default, context)
alarm_obj = self.pool.get('res.alarm')
@ -1607,10 +1625,12 @@ true, it will allow you to hide the event alarm information without removing it.
@param context: A standard dictionary for contextual values
@return: new created record id.
"""
if not context:
if context is None:
context = {}
if vals.get('vtimezone', '') and vals.get('vtimezone', '').startswith('/freeassociation.sourceforge.net/tzfile/'):
vals['vtimezone'] = vals['vtimezone'][40:]
res = super(calendar_event, self).create(cr, uid, vals, context)
alarm_obj = self.pool.get('res.alarm')
alarm_obj.do_alarm_create(cr, uid, [res], self._name, 'date', context=context)
@ -1770,7 +1790,7 @@ class ir_values(osv.osv):
@param uid: the current users ID for security checks,
@param model: Get The Model
"""
if not context:
if context is None:
context = {}
new_model = []
for data in models:
@ -1798,7 +1818,7 @@ class ir_model(osv.osv):
@param context: A standard dictionary for contextual values
"""
new_ids = isinstance(ids, (str, int, long)) and [ids] or ids
if not context:
if context is None:
context = {}
data = super(ir_model, self).read(cr, uid, new_ids, fields=fields, \
context=context, load=load)

View File

@ -26,6 +26,7 @@
<field name="res_model">crm.case.categ</field>
<field name="view_type">form</field>
<field name="view_id" ref="crm_case_categ_tree-view"/>
<field name="context">{'object_id': 'crm.lead'}</field>
<field name="domain">[('object_id.model', '=', 'crm.lead')]</field>
<field name="help">Create specific categories that fit your company's activities in order to better classify and analyse them after they have been maintained in your leads and opportunities. You can use categories to reflect your product structure or the different types of sales you do.</field>
</record>

View File

@ -115,7 +115,7 @@ class hr_job(osv.osv):
def on_change_expected_employee(self, cr, uid, ids, expected_employee, no_of_employee, context=None):
if context is None:
context = {}
result={}
result = {}
if expected_employee:
result['no_of_recruitment'] = expected_employee - no_of_employee
return {'value': result}
@ -165,23 +165,19 @@ class hr_employee(osv.osv):
'passport_id':fields.char('Passport', size=64)
}
def onchange_company(self, cr, uid, ids, company, context=None):
company_id = self.pool.get('res.company').browse(cr,uid,company)
for address in company_id.partner_id.address:
return {'value': {'address_id': address.id}}
return {'value':{'address_id':False}}
def onchange_department(self, cr, uid, ids, department_id, context=None):
if not department_id:
return {'value':{'parent_id': False}}
manager = self.pool.get('hr.department').browse(cr, uid, department_id).manager_id
return {'value': {'parent_id':manager and manager.id or False}}
def onchange_company(self, cr, uid, ids, company, context=None):
address_id = False
if company:
company_id = self.pool.get('res.company').browse(cr,uid,company)
address = self.pool.get('res.partner').address_get(cr, uid, [company_id.partner_id.id], ['default'])
address_id = address and address['default'] or False
return {'value': {'address_id' : address_id}}
def onchange_user(self, cr, uid, ids, user_id, context=None):
if not user_id:
return {'value':{'work_email': False}}
mail = self.pool.get('res.users').browse(cr,uid,user_id)
return {'value': {'work_email':mail.user_email}}
work_email = False
if user_id:
work_email = self.pool.get('res.users').browse(cr, uid, user_id).user_email
return {'value': {'work_email' : work_email}}
def _get_photo(self, cr, uid, context=None):
return open(os.path.join(

View File

@ -27,7 +27,7 @@
<field name="company_id" widget="selection" groups="base.group_multi_company,base.group_extended" on_change="onchange_company(company_id)"/>
<field name="active" groups="base.group_extended"/>
<newline/>
<field name="department_id" widget="selection" on_change="onchange_department(department_id)"/>
<field name="department_id" widget="selection" />
<field name="parent_id" />
</group>
<group colspan="2" col="1">

View File

@ -99,10 +99,10 @@ class hr_expense_expense(osv.osv):
}
def onchange_employee_id(self, cr, uid, ids, employee_id, context=None):
if not employee_id:
return {'value':{'department_id': False}}
dept = self.pool.get('hr.employee').browse(cr, uid, employee_id).department_id
return {'value': {'department_id':dept and dept.id or False}}
department_id = False
if employee_id:
department_id = self.pool.get('hr.employee').browse(cr, uid, employee_id).department_id.id or False
return {'value':{'department_id':department_id}}
def expense_confirm(self, cr, uid, ids, *args):
self.write(cr, uid, ids, {
@ -248,17 +248,17 @@ class hr_expense_line(osv.osv):
def onchange_product_id(self, cr, uid, ids, product_id, uom_id, employee_id, context=None):
if context is None:
context = {}
v = {}
res = {}
if product_id:
product = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
v['name'] = product.name
res['name'] = product.name
# Compute based on pricetype of employee company
context['currency_id'] = self.pool.get('hr.employee').browse(cr, uid, employee_id, context=context).user_id.company_id.currency_id.id
amount_unit = product.price_get('standard_price', context)[product.id]
v['unit_amount'] = amount_unit
res['unit_amount'] = amount_unit
if not uom_id:
v['uom_id'] = product.uom_id.id
return {'value': v}
res['uom_id'] = product.uom_id.id
return {'value': res}
hr_expense_line()

15
addons/pad/LICENSE Normal file
View File

@ -0,0 +1,15 @@
OpenERP, Open Source Management Solution
Copyright © 2010 OpenERP SA (<http://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 Lice
along with this program. If not, see <http://www.gnu.org/licenses/>.

2
addons/pad/__init__.py Normal file
View File

@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-
import company_pad

20
addons/pad/__openerp__.py Normal file
View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
{
'name': 'Enhanced support for (Ether)Pad attachments',
'version': '1.0',
'category': 'Generic Modules/Others',
'description': """
Adds enhanced support for (Ether)Pad attachments in the web client, lets the
company customize which Pad installation should be used to link to new pads
(by default, pad.openerp.com)
""",
'author': 'OpenERP SA',
'website': 'http://openerp.com',
'depends': ['base'],
'update_xml': [
'company_pad.xml'
],
'installable': True,
'active': False,
'web': True,
}

15
addons/pad/company_pad.py Normal file
View File

@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
from osv import fields, osv
class company_pad(osv.osv):
_inherit = 'res.company'
_columns = {
'pad_index': fields.char('Pad root URL', size=64, required=True,
help="The root URL of the company's pad "
"instance"),
}
_defaults = {
'pad_index': 'http://pad.openerp.com'
}
company_pad()

View File

@ -0,0 +1,16 @@
<openerp>
<data>
<record id="view_company_form_with_pad" model="ir.ui.view">
<field name="name">res.company.form.pad</field>
<field name="model">res.company</field>
<field name="type">form</field>
<field name="inherit_id" ref="base.view_company_form"/>
<field name="arch" type="xml">
<xpath expr="//page[@string='Configuration']" position="inside">
<separator string="Pad" colspan="4"/>
<field name="pad_index"/>
</xpath>
</field>
</record>
</data>
</openerp>

View File

@ -0,0 +1,2 @@
import controllers
import editors

View File

@ -0,0 +1,34 @@
import urlparse
import cherrypy
from openobject.tools import expose
import openerp.controllers
from openerp.utils import rpc, TinyDict
class Piratepad(openerp.controllers.SecuredController):
_cp_path = "/piratepad"
def get_root(self):
return rpc.RPCProxy('res.company').read(
[rpc.session.company_id], ['pad_index'])[0]['pad_index']
def make_url(self, pad_name):
return urlparse.urljoin(
self.get_root(), '-'.join(pad_name.split())
)
@expose('json', methods=('POST',))
def link(self, pad_name):
params, data = TinyDict.split(cherrypy.session['params'])
ctx = dict(rpc.session.context,
default_res_model=params.model, default_res_id=params.id,
active_id=False, active_ids=[])
pad_link = self.make_url(pad_name)
attachment_id = rpc.RPCProxy('ir.attachment').create({
'name': pad_name,
'url': pad_link,
}, ctx)
return {'id': attachment_id, 'name': pad_name, 'url': pad_link}

46
addons/pad/web/editors.py Normal file
View File

@ -0,0 +1,46 @@
# -*- coding: utf-8 -*-
import openobject.templating
class SidebarTemplateEditor(openobject.templating.TemplateEditor):
templates = ['/openerp/widgets/templates/sidebar.mako']
ADD_ATTACHMENT_BUTTON = u'id="add-attachment"'
BINARY_ATTACHMENTS_FORM = u'<form id="attachment-box"'
def insert_pad_link(self, output):
# Insert the link on the line right after the link to open the
# attachment form
form_opener_insertion = output.index(
'\n',
output.index(self.ADD_ATTACHMENT_BUTTON)) + 1
output = output[:form_opener_insertion] + \
'''<a href="#" id="add-pad" class="button-a"
style="right: 44px;"
>${_("Pad")}</a>\n''' + \
output[form_opener_insertion:]
return output
def edit(self, template, template_text):
output = super(SidebarTemplateEditor, self).edit(template, template_text)
output = self.insert_pad_link(output)
form_insertion_point = output.index(self.BINARY_ATTACHMENTS_FORM)
return output[:form_insertion_point] + '''
<form id="pad-form" action="/piratepad/link" method="post">
<label for="sidebar_pad_datas">${_("Name")}:</label>
<input id="sidebar_pad_datas"
name="pad_name" size="5" />
<button>${_("Ok")}</button>
</form>
<script type="text/javascript">
jQuery(document).ready(function() {
var $padForm = jQuery('#pad-form')
.hide()
.submit(createAttachment);
jQuery('#add-pad').click(function(e){
$padForm.show();
e.preventDefault();
});
});
</script>
''' + output[form_insertion_point:]

View File

@ -31,6 +31,11 @@ class misc_tools_installer(osv.osv_memory):
'idea':fields.boolean('Ideas Box',help='Promote ideas of the employees, votes and discussion on best ideas.'),
'share':fields.boolean('Share Data / Portals',help='This module allows you to easily give restricted access of any filtered list of objects to any customer or supplier.' \
'Just click on the share icon to give access to your customers on their project\'s tasks, support requests, invoices, etc.'),
'pad': fields.boolean('Native pad integration',
help="This module creates a tighter integration between a Pad "
"instance of your choosing and your OpenERP Web Client by "
"letting you easily link pads to OpenERP objects via "
"OpenERP attachments."),
}
_defaults = {
}

View File

@ -30,6 +30,7 @@
<field name="idea"/>
<field name="survey"/>
<field name="subscription" groups="base.group_extended"/>
<field name="pad"/>
</group>
</data>
</field>