[MERGE]: Merge with lp:openobject-trunk-dev-addons2

bzr revid: ksa@tinyerp.co.in-20101028134935-8s5pw01j1ih1qq4n
This commit is contained in:
ksa (Open ERP)
2010-10-28 19:19:35 +05:30
45 changed files with 302 additions and 413 deletions
+1 -1
View File
@@ -130,7 +130,7 @@ class account_payment_term_line(osv.osv):
return True
_constraints = [
(_check_percent, _('Percentages for Payment Term Line must be between 0 and 1, Example: 0.02 for 2% '), ['value_amount']),
(_check_percent, 'Percentages for Payment Term Line must be between 0 and 1, Example: 0.02 for 2% ', ['value_amount']),
]
account_payment_term_line()
+3 -1
View File
@@ -63,7 +63,9 @@
<field domain="[('type','&lt;&gt;','view'), ('company_id', '=', parent.company_id), ('parent_id', '!=', False)]" name="account_analytic_id" groups="analytic.group_analytic_accounting"/>
<newline/>
<field name="company_id" groups="base.group_multi_company" readonly="1"/>
<field colspan="4" name="invoice_line_tax_id" context="{'type':parent.type}" domain="[('parent_id','=',False),('company_id', '=', parent.company_id)]"/>
<separator colspan="4" string="Taxes"/>
<field colspan="4" name="invoice_line_tax_id" context="{'type':parent.type}" domain="[('parent_id','=',False),('company_id', '=', parent.company_id)]"
nolabel="1"/>
</page>
<page string="Notes">
<field colspan="4" name="note" nolabel="1"/>
+5 -6
View File
@@ -405,7 +405,7 @@
<field name="arch" type="xml">
<form string="Account Journal">
<group colspan="4" col="6">
<field name="name" select="1"/>
<field name="name" select="1" colspan="4"/>
<field name="code" select="1"/>
<field name="type" on_change="onchange_type(type, currency)"/>
</group>
@@ -465,7 +465,6 @@
<field name="view_mode">tree,form</field>
</record>
<menuitem action="action_account_journal_form" id="menu_action_account_journal_form" parent="account_account_menu"/>
<record id="view_account_bank_statement_filter" model="ir.ui.view">
<field name="name">account.cash.statement.select</field>
<field name="model">account.bank.statement</field>
@@ -490,7 +489,6 @@
</search>
</field>
</record>
<record id="view_bank_statement_tree" model="ir.ui.view">
<field name="name">account.bank.statement.tree</field>
<field name="model">account.bank.statement</field>
@@ -950,7 +948,6 @@
<field name="domain">[('parent_id','=',False)]</field>
</record>
<menuitem action="action_tax_form" id="menu_action_tax_form" parent="next_id_27"/>
<record id="action_tax_code_tree" model="ir.actions.act_window">
<field name="name">Chart of Taxes</field>
<field name="res_model">account.tax.code</field>
@@ -1417,6 +1414,10 @@
<field name="period_id"/>
</group>
<newline/>
<group col="10" colspan="4">
<field name="journal_id" widget="selection" context="{'journal_id':self, 'visible_id':self or 0, 'normal_view':False}"/>
<field name="period_id" widget="selection" context="{'period_id':self}"/>
</group>
<group expand="0" string="Group By..." colspan="12" col="10">
<filter string="Partner" icon="terp-personal" domain="[]" context="{'group_by':'partner_id'}"/>
<separator orientation="vertical"/>
@@ -2571,7 +2572,6 @@ action = self.pool.get('res.config').next(cr, uid, [], context)
</tree>
</field>
</record>
<record id="view_bank_statement_form2" model="ir.ui.view">
<field name="name">account.bank.statement.form</field>
<field name="model">account.bank.statement</field>
@@ -2586,7 +2586,6 @@ action = self.pool.get('res.config').next(cr, uid, [], context)
<field name="period_id" select="1"/>
<field name="currency" invisible="1"/>
</group>
<notebook colspan="4">
<page string="Cash Transactions" attrs="{'invisible': [('state','=','draft')]}">
<field colspan="4" name="line_ids" nolabel="1">
@@ -1,3 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_account_analytic_analysis_summary_user,account_analytic_analysis.summary.user,model_account_analytic_analysis_summary_user,account.group_account_manager,1,0,0,0
access_account_analytic_analysis_summary_month,account_analytic_analysis.summary.month,model_account_analytic_analysis_summary_month,account.group_account_manager,1,0,0,0
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"access_account_analytic_analysis_summary_user","account_analytic_analysis.summary.user","model_account_analytic_analysis_summary_user","account.group_account_manager",1,0,0,0
"access_account_analytic_analysis_summary_month","account_analytic_analysis.summary.month","model_account_analytic_analysis_summary_month","account.group_account_manager",1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_account_analytic_analysis_summary_user account_analytic_analysis.summary.user model_account_analytic_analysis_summary_user account.group_account_manager 1 0 0 0
3 access_account_analytic_analysis_summary_month account_analytic_analysis.summary.month model_account_analytic_analysis_summary_month account.group_account_manager 1 0 0 0
+68 -68
View File
@@ -24,7 +24,7 @@ from tools.translate import _
from datetime import datetime
from datetime import timedelta
from tools.safe_eval import safe_eval
import pooler
import pooler
import re
import time
import tools
@@ -34,7 +34,7 @@ class base_action_rule(osv.osv):
_name = 'base.action.rule'
_description = 'Action Rules'
def _state_get(self, cr, uid, context={}):
""" Get State
@param self: The object pointer
@@ -50,7 +50,7 @@ class base_action_rule(osv.osv):
@param uid: the current user’s ID for security checks,
@param context: A standard dictionary for contextual values """
return [('', '')]
def priority_get(self, cr, uid, context={}):
""" Get Priority
@param self: The object pointer
@@ -60,57 +60,57 @@ class base_action_rule(osv.osv):
return [('', '')]
_columns = {
'name': fields.char('Rule Name', size=64, required=True),
'model_id': fields.many2one('ir.model', 'Object', required=True),
'create_date': fields.datetime('Create Date', readonly=1),
'name': fields.char('Rule Name', size=64, required=True),
'model_id': fields.many2one('ir.model', 'Object', required=True),
'create_date': fields.datetime('Create Date', readonly=1),
'active': fields.boolean('Active', help="If the active field is set to False,\
it will allow you to hide the rule without removing it."),
it will allow you to hide the rule without removing it."),
'sequence': fields.integer('Sequence', help="Gives the sequence order \
when displaying a list of rules."),
when displaying a list of rules."),
'trg_date_type': fields.selection([
('none', 'None'),
('create', 'Creation Date'),
('action_last', 'Last Action Date'),
('date', 'Date'),
('deadline', 'Deadline'),
], 'Trigger Date', size=16),
('none', 'None'),
('create', 'Creation Date'),
('action_last', 'Last Action Date'),
('date', 'Date'),
('deadline', 'Deadline'),
], 'Trigger Date', size=16),
'trg_date_range': fields.integer('Delay after trigger date', \
help="Delay After Trigger Date,\
specifies you can put a negative number. If you need a delay before the \
trigger date, like sending a reminder 15 minutes before a meeting."),
trigger date, like sending a reminder 15 minutes before a meeting."),
'trg_date_range_type': fields.selection([('minutes', 'Minutes'), ('hour', 'Hours'), \
('day', 'Days'), ('month', 'Months')], 'Delay type'),
'trg_user_id': fields.many2one('res.users', 'Responsible'),
'trg_partner_id': fields.many2one('res.partner', 'Partner'),
'trg_partner_categ_id': fields.many2one('res.partner.category', 'Partner Category'),
'trg_state_from': fields.selection(_state_get, 'State', size=16),
'trg_state_to': fields.selection(_state_get, 'Button Pressed', size=16),
('day', 'Days'), ('month', 'Months')], 'Delay type'),
'trg_user_id': fields.many2one('res.users', 'Responsible'),
'trg_partner_id': fields.many2one('res.partner', 'Partner'),
'trg_partner_categ_id': fields.many2one('res.partner.category', 'Partner Category'),
'trg_state_from': fields.selection(_state_get, 'State', size=16),
'trg_state_to': fields.selection(_state_get, 'Button Pressed', size=16),
'act_method': fields.char('Call Object Method', size=64),
'act_user_id': fields.many2one('res.users', 'Set Responsible to'),
'act_state': fields.selection(_state_get, 'Set State to', size=16),
'act_method': fields.char('Call Object Method', size=64),
'act_user_id': fields.many2one('res.users', 'Set Responsible to'),
'act_state': fields.selection(_state_get, 'Set State to', size=16),
'act_email_cc': fields.char('Add Watchers (Cc)', size=250, help="\
These people will receive a copy of the future communication between partner \
and users by email"),
and users by email"),
'act_remind_partner': fields.boolean('Remind Partner', help="Check \
this if you want the rule to send a reminder by email to the partner."),
this if you want the rule to send a reminder by email to the partner."),
'act_remind_user': fields.boolean('Remind Responsible', help="Check \
this if you want the rule to send a reminder by email to the user."),
'act_reply_to': fields.char('Reply-To', size=64),
'act_remind_attach': fields.boolean('Remind with Attachment', help="Check this if you want that all documents attached to the object be attached to the reminder email sent."),
this if you want the rule to send a reminder by email to the user."),
'act_reply_to': fields.char('Reply-To', size=64),
'act_remind_attach': fields.boolean('Remind with Attachment', help="Check this if you want that all documents attached to the object be attached to the reminder email sent."),
'act_mail_to_user': fields.boolean('Mail to Responsible', help="Check\
this if you want the rule to send an email to the responsible person."),
'act_mail_to_watchers': fields.boolean('Mail to Watchers (CC)',
this if you want the rule to send an email to the responsible person."),
'act_mail_to_watchers': fields.boolean('Mail to Watchers (CC)',
help="Check this if you want \
the rule to mark CC(mail to any other person defined in actions)."),
the rule to mark CC(mail to any other person defined in actions)."),
'act_mail_to_email': fields.char('Mail to these Emails', size=128, \
help="Email-id of the persons whom mail is to be sent"),
'act_mail_body': fields.text('Mail body', help="Content of mail"),
help="Email-id of the persons whom mail is to be sent"),
'act_mail_body': fields.text('Mail body', help="Content of mail"),
'regex_name': fields.char('Regex on Resource Name', size=128, help="Regular expression for matching name of the resource\
\ne.g.: 'urgent.*' will search for records having name starting with the string 'urgent'\
\nNote: This is case sensitive search."),
'server_action_id': fields.many2one('ir.actions.server', 'Server Action', help="Describes the action name.\neg:on which object which action to be taken on basis of which condition"),
'filter_id':fields.many2one('ir.filters', 'Filter', required=False),
\nNote: This is case sensitive search."),
'server_action_id': fields.many2one('ir.actions.server', 'Server Action', help="Describes the action name.\neg:on which object which action to be taken on basis of which condition"),
'filter_id':fields.many2one('ir.filters', 'Filter', required=False),
'act_email_from' : fields.char('Email From', size=64, required=False,
help="Use a python expression to specify the right field on which one than we will use for the 'From' field of the header"),
'act_email_to' : fields.char('Email To', size=64, required=False,
@@ -118,17 +118,17 @@ the rule to mark CC(mail to any other person defined in actions)."),
}
_defaults = {
'active': lambda *a: True,
'trg_date_type': lambda *a: 'none',
'trg_date_range_type': lambda *a: 'day',
'act_mail_to_user': lambda *a: 0,
'act_remind_partner': lambda *a: 0,
'act_remind_user': lambda *a: 0,
'act_mail_to_watchers': lambda *a: 0,
'active': lambda *a: True,
'trg_date_type': lambda *a: 'none',
'trg_date_range_type': lambda *a: 'day',
'act_mail_to_user': lambda *a: 0,
'act_remind_partner': lambda *a: 0,
'act_remind_user': lambda *a: 0,
'act_mail_to_watchers': lambda *a: 0,
}
_order = 'sequence'
def onchange_model_id(self, cr, uid, ids, name):
#This is not a good solution as it will affect the domain only on onchange
res = {'domain':{'filter_id':[]}}
@@ -165,7 +165,7 @@ the rule to mark CC(mail to any other person defined in actions)."),
self.pre_action(cr, uid, [new_id], model, context=context)
return new_id
return make_call_old
def _write(self, old_write, model, context=None):
if not context:
context = {}
@@ -191,9 +191,9 @@ the rule to mark CC(mail to any other person defined in actions)."),
return True
def create(self, cr, uid, vals, context=None):
res_id = super(base_action_rule, self).create(cr, uid, vals, context)
self._register_hook(cr, uid, [res_id], context=context)
self._register_hook(cr, uid, [res_id], context=context)
return res_id
def write(self, cr, uid, ids, vals, context=None):
res = super(base_action_rule, self).write(cr, uid, ids, vals, context)
self._register_hook(cr, uid, ids, context=context)
@@ -207,7 +207,7 @@ the rule to mark CC(mail to any other person defined in actions)."),
rule_pool = self.pool.get('base.action.rule')
rule_ids = rule_pool.search(cr, uid, [], context=context)
return self._register_hook(cr, uid, rule_ids, context=context)
def format_body(self, body):
""" Foramat Action rule's body
@@ -219,18 +219,18 @@ the rule to mark CC(mail to any other person defined in actions)."),
@param self: The object pointer """
data = {
'object_id': obj.id,
'object_subject': hasattr(obj, 'name') and obj.name or False,
'object_date': hasattr(obj, 'date') and obj.date or False,
'object_description': hasattr(obj, 'description') and obj.description or False,
'object_user': hasattr(obj, 'user_id') and (obj.user_id and obj.user_id.name) or '/',
'object_id': obj.id,
'object_subject': hasattr(obj, 'name') and obj.name or False,
'object_date': hasattr(obj, 'date') and obj.date or False,
'object_description': hasattr(obj, 'description') and obj.description or False,
'object_user': hasattr(obj, 'user_id') and (obj.user_id and obj.user_id.name) or '/',
'object_user_email': hasattr(obj, 'user_id') and (obj.user_id and \
obj.user_id.address_id and obj.user_id.address_id.email) or '/',
obj.user_id.address_id and obj.user_id.address_id.email) or '/',
'object_user_phone': hasattr(obj, 'user_id') and (obj.user_id and\
obj.user_id.address_id and obj.user_id.address_id.phone) or '/',
'partner': hasattr(obj, 'partner_id') and (obj.partner_id and obj.partner_id.name) or '/',
obj.user_id.address_id and obj.user_id.address_id.phone) or '/',
'partner': hasattr(obj, 'partner_id') and (obj.partner_id and obj.partner_id.name) or '/',
'partner_email': hasattr(obj, 'partner_address_id') and (obj.partner_address_id and\
obj.partner_address_id.email) or '/',
obj.partner_address_id.email) or '/',
}
return self.format_body(body % data)
@@ -259,7 +259,7 @@ the rule to mark CC(mail to any other person defined in actions)."),
emailfrom = tools.ustr(emailfrom)
reply_to = emailfrom
if not emailfrom:
raise osv.except_osv(_('Error!'),
raise osv.except_osv(_('Error!'),
_("No E-Mail ID Found for your Company address!"))
return tools.email_send(emailfrom, emails, name, body, reply_to=reply_to, openobject_id=str(obj.id))
@@ -272,7 +272,7 @@ the rule to mark CC(mail to any other person defined in actions)."),
@param context: A standard dictionary for contextual values """
if context is None:
context = {}
ok = True
ok = True
if action.filter_id:
if action.model_id.model == action.filter_id.model_id:
context.update(eval(action.filter_id.context))
@@ -418,10 +418,10 @@ the rule to mark CC(mail to any other person defined in actions)."),
base = datetime.strptime(obj.date, '%Y-%m-%d %H:%M:%S')
if base:
fnct = {
'minutes': lambda interval: timedelta(minutes=interval),
'day': lambda interval: timedelta(days=interval),
'hour': lambda interval: timedelta(hours=interval),
'month': lambda interval: timedelta(months=interval),
'minutes': lambda interval: timedelta(minutes=interval),
'day': lambda interval: timedelta(days=interval),
'hour': lambda interval: timedelta(hours=interval),
'month': lambda interval: timedelta(months=interval),
}
d = base + fnct[action.trg_date_range_type](action.trg_date_range)
dt = d.strftime('%Y-%m-%d %H:%M:%S')
@@ -463,15 +463,15 @@ the rule to mark CC(mail to any other person defined in actions)."),
return True
_constraints = [
(_check_mail, 'Error: The mail is not well formated', ['act_mail_body']),
(_check_mail, 'Error: The mail is not well formated', ['act_mail_body']),
]
base_action_rule()
class ir_cron(osv.osv):
_inherit = 'ir.cron'
_inherit = 'ir.cron'
def _poolJobs(self, db_name, check=False):
try:
db = pooler.get_db(db_name)
@@ -42,8 +42,8 @@
name: All day test event
rrule_type: none
- |
In order to check reminder I will first create reminder
-
In order to check reminder I will first create reminder
-
!record {model: res.alarm, id: res_alarm_daybeforeeventstarts0}:
name: 1 Day before event starts
trigger_duration: 1
@@ -57,7 +57,7 @@
self.write(cr, uid, [ref("calendar_event_alldaytestevent0")], {'alarm_id': ref("res_alarm_daybeforeeventstarts0")})
- |
In order to assign attendee I will invite Demo user
-
-
!record {model: base_calendar.invite.attendee, id: base_calendar_invite_attendee_0}:
type: internal
send_mail: False
@@ -1,24 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -1,114 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import os
from osv import fields, osv
from tools.translate import _
import pooler
from tools import config
from base_module_quality import base_module_quality
class quality_test(base_module_quality.abstract_quality_check):
def __init__(self):
super(quality_test, self).__init__()
self.bool_installed_only = True
self.name = _("Unit Test")
self.note = _("""
This test checks the Unit Test(PyUnit) Cases of the module. Note that 'unit_test/test.py' is needed in module.
""")
self.min_score = 0
self.message = 'This test does not calculate score'
self.bool_count_score = False
return None
def run_test(self, cr, uid, module_path):
pool = pooler.get_pool(cr.dbname)
module_name = module_path.split('/')[-1]
test_file = config['addons_path'] +'/' + module_name +'/unit_test/test.py'
if not os.path.isfile(test_file):
self.result += _("Module does not have 'unit_test/test.py' file")
return None
module_obj = pool.get('ir.module.module')
module_ids = module_obj.search(cr, uid, [('name', '=', module_name)])
module = module_obj.browse(cr, uid, module_ids)
if not len(module):
self.result += _("Error! Module is not properly loaded/installed")
return None
module = module[0]
test = module.name + '.' + 'unit_test.test'
test_module = __import__(test)
test_file = getattr(test_module, 'unit_test')
test_obj = getattr(test_file, 'test')
test_result = test_obj.runTest(cr,uid)
self.result = self.get_result(test_result)
self.result_details += self.get_result_details(test_result)
return None
def get_result(self, data_list):
header = ('{| border="1" cellspacing="0" cellpadding="5" align="left" \n! %-40s \n! %-40s \n', [_('Summary'), _('Status')])
result_unit = {}
res_list = []
if data_list[0]:
res = data_list[1].split('\n')
res_list.append(res[-4:][0])
res_list.append(res[-4:][2])
result_unit['unit_test'] = res_list
return self.format_table(header, data_list=result_unit)
return "Unit Test Fail"
def get_result_details(self, data_list):
detail = '''<html><head>%s</head><body><table class="tablestyle">
<tr><th class="tdatastyle">Test Cases</th ><th class="tdatastyle">Result</th>'''%(self.get_style())
html = ''
if data_list[0] == True:
data = data_list[1].split('... ok')
for case in map(lambda x:x[0].replace('\n',''),map(lambda x: x.split(' ('),data)):
if case.find('Ran') != -1:
case = case[case.index('Ran'):-2]
html += '<tr><th class="tdatastyle">%s</th><th class="tdatastyle">OK</th></tr>'%(case)
else:
html += '<tr><td class="tdatastyle">%s</td><td class="tdatastyle">OK</td></tr>'%(case)
res = detail + html + '</table></body></html>'
return res
else:
detail_dict = {}
detail += '''<th class="tdatastyle">Details</th></tr>'''
data = data_list[1].split("======================================================================")
test = data[0].split('\n')
for err in (data_list[0].failures,data_list[0].errors):
for value in err:
detail_dict[value[0]._testMethodName] = value[1]
for case in map(lambda x:x.split('...'), test):
if len(case[0]) < 2:
continue
test_name = case[0].split(' (')[0]
if not detail_dict.has_key(test_name):
detail_dict[test_name] = ''
html += '<tr><th class="tdatastyle">%s</th><th class="tdatastyle">%s</th><td class="tdatastyle">%s</td></tr>'%(test_name, case[1], detail_dict[test_name])
return detail + html +'</tr></table></body></html>'
return ''
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+4 -4
View File
@@ -100,7 +100,7 @@ class crm_lead(crm_case, osv.osv):
_columns = {
# Overridden from res.partner.address:
'partner_id': fields.many2one('res.partner', 'Partner', ondelete='set null',
'partner_id': fields.many2one('res.partner', 'Partner', ondelete='set null',
select=True, help="Optional linked partner, usually after conversion of the lead"),
# From crm.case
@@ -124,7 +124,7 @@ class crm_lead(crm_case, osv.osv):
domain="['|',('section_id','=',section_id),('section_id','=',False)]"),
'channel_id': fields.many2one('res.partner.canal', 'Channel'),
'contact_name': fields.char('Contact Name', size=64),
'contact_name': fields.char('Contact Name', size=64),
'partner_name': fields.char("Customer Name", size=64),
'optin': fields.boolean('Opt-In', help="If opt-in is checked, this contact has accepted to receive emails."),
'optout': fields.boolean('Opt-Out', help="If opt-out is checked, this contact has refused to receive emails or unsubscribed to a campaign."),
@@ -147,7 +147,7 @@ class crm_lead(crm_case, osv.osv):
help='The state is set to \'Draft\', when a case is created.\
\nIf the case is in progress the state is set to \'Open\'.\
\nWhen the case is over, the state is set to \'Done\'.\
\nIf the case needs to be reviewed then the state is set to \'Pending\'.'),
\nIf the case needs to be reviewed then the state is set to \'Pending\'.'),
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
}
@@ -341,7 +341,7 @@ class crm_lead(crm_case, osv.osv):
@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 update mail’s IDs
@param ids: List of update mail’s IDs
"""
if isinstance(ids, (str, int, long)):
+5 -5
View File
@@ -45,12 +45,12 @@ class crm_meeting(crm_case, osv.osv):
_inherit = ['mailgate.thread',"calendar.event"]
_columns = {
# From crm.case
'name': fields.char('Summary', size=124, required=True, states={'done': [('readonly', True)]}),
'partner_id': fields.many2one('res.partner', 'Partner', states={'done': [('readonly', True)]}),
'name': fields.char('Summary', size=124, required=True, states={'done': [('readonly', True)]}),
'partner_id': fields.many2one('res.partner', 'Partner', states={'done': [('readonly', True)]}),
'partner_address_id': fields.many2one('res.partner.address', 'Partner Contact', \
domain="[('partner_id','=',partner_id)]", states={'done': [('readonly', True)]}),
domain="[('partner_id','=',partner_id)]", states={'done': [('readonly', True)]}),
'section_id': fields.many2one('crm.case.section', 'Sales Team', states={'done': [('readonly', True)]}, \
select=True, help='Sales team to which Case belongs to.'),
select=True, help='Sales team to which Case belongs to.'),
'email_from': fields.char('Email', size=128, states={'done': [('readonly', True)]}, help="These people will receive email."),
'id': fields.integer('ID'),
'create_date': fields.datetime('Creation Date' , readonly=True),
@@ -76,7 +76,7 @@ class crm_meeting(crm_case, osv.osv):
}
_defaults = {
'state': lambda *a: 'draft',
'state': lambda *a: 'draft',
'active': lambda *a: 1,
'user_id': lambda self, cr, uid, ctx: uid,
}
+1 -1
View File
@@ -107,7 +107,7 @@ class crm_lead_report(osv.osv):
c.partner_id,
c.country_id,
c.planned_revenue,
c.planned_revenue*(c.probability/100) as probable_revenue,
c.planned_revenue*(c.probability/100) as probable_revenue,
1 as nbr,
(SELECT count(id) FROM mailgate_message WHERE model='crm.lead' AND res_id=c.id AND history=True) AS email,
date_trunc('day',c.create_date) as create_date,
+1 -2
View File
@@ -38,7 +38,6 @@ class crm_phonecall_report(osv.osv):
_name = "crm.phonecall.report"
_description = "Phone calls by user and section"
_auto = False
_columns = {
'name': fields.char('Year', size=64, required=False, readonly=True),
'user_id':fields.many2one('res.users', 'User', readonly=True),
@@ -53,7 +52,7 @@ class crm_phonecall_report(osv.osv):
('09', 'September'), ('10', 'October'),\
('11', 'November'), ('12', 'December')], 'Month', readonly=True),
'create_date': fields.datetime('Create Date', readonly=True),
'day': fields.char('Day', size=128, readonly=True),
'day': fields.char('Day', size=128, readonly=True),
'delay_close': fields.float('Delay to close', digits=(16,2),readonly=True, group_operator="avg",help="Number of Days to close the case"),
'duration': fields.float('Duration', digits=(16,2),readonly=True, group_operator="avg"),
'delay_open': fields.float('Delay to open',digits=(16,2),readonly=True, group_operator="avg",help="Number of Days to open the case"),
+1
View File
@@ -20,6 +20,7 @@
<field name="domain_force">['|',('user_id','=',user.id),('user_id','=',False)]</field>
<field name="groups" eval="[(4, ref('base.group_sale_salesman'))]"/>
</record>
<record id="crm_rule_all_lead" model="ir.rule">
<field name="name">All Leads</field>
<field ref="model_crm_lead" name="model_id"/>
@@ -82,10 +82,6 @@ class crm_partner2opportunity(osv.osv_memory):
part_obj = self.pool.get('res.partner')
address = part_obj.address_get(cr, uid, data)
categ_obj = self.pool.get('crm.case.categ')
categ_ids = categ_obj.search(cr, uid, [('name','ilike','Part%')])
case_obj = self.pool.get('crm.lead')
opp_id = case_obj.create(cr, uid, {
'name' : make_opportunity_obj.name,
@@ -93,7 +89,6 @@ class crm_partner2opportunity(osv.osv_memory):
'probability' : make_opportunity_obj.probability,
'partner_id' : make_opportunity_obj.partner_id.id,
'partner_address_id' : address['default'],
'categ_id' : categ_ids[0],
'state' :'draft',
'type': 'opportunity'
})
+1 -2
View File
@@ -45,7 +45,6 @@ class crm_claim_report(osv.osv):
_name = "crm.claim.report"
_auto = False
_description = "CRM Claim Report"
_columns = {
'name': fields.char('Year', size=64, required=False, readonly=True),
'user_id':fields.many2one('res.users', 'User', readonly=True),
@@ -60,7 +59,7 @@ class crm_claim_report(osv.osv):
('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),
'day': fields.char('Day', size=128, readonly=True),
'delay_close': fields.float('Delay to close', digits=(16,2),readonly=True, group_operator="avg",help="Number of Days to close the case"),
'stage_id': fields.many2one ('crm.case.stage', 'Stage', readonly=True),
'categ_id': fields.many2one('crm.case.categ', 'Category',\
@@ -36,7 +36,6 @@ class crm_fundraising_report(osv.osv):
_name = "crm.fundraising.report"
_auto = False
_description = "CRM Fundraising Report"
_columns = {
'name': fields.char('Year', size=64, required=False, readonly=True),
'user_id':fields.many2one('res.users', 'User', readonly=True),
@@ -51,7 +50,7 @@ class crm_fundraising_report(osv.osv):
('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),
'day': fields.char('Day', size=128, readonly=True),
'categ_id': fields.many2one('crm.case.categ', 'Category', \
domain="[('section_id','=',section_id),\
('object_id.model', '=', 'crm.fundraising')]"),
+25 -25
View File
@@ -54,7 +54,7 @@ For data /storage/ we have the cases:
Have (ir.attachment, context), we modify the file (save, update, rename etc).
Have (directory, context), we create a file.
Have (path, context), we create or modify a file.
Note that in all above cases, we don't explicitly choose the storage media,
but always require a context to be present.
@@ -63,7 +63,7 @@ nodes, for once, won't. Their metadata will be computed by the parent storage
media + directory.
The algorithm says that in any of the above cases, our first goal is to locate
the node for any combination of search criteria. It would be wise NOT to
the node for any combination of search criteria. It would be wise NOT to
represent each node in the path (like node[/] + node[/dir1] + node[/dir1/dir2])
but directly jump to the end node (like node[/dir1/dir2]) whenever possible.
@@ -100,7 +100,7 @@ class nodefd_file(nodes.node_descriptor):
if mode.endswith('b'):
mode = mode[:-1]
self.mode = mode
for attr in ('closed', 'read', 'write', 'seek', 'tell'):
setattr(self,attr, getattr(self.__file, attr))
@@ -117,7 +117,7 @@ class nodefd_file(nodes.node_descriptor):
filename = par.path
if isinstance(filename, (tuple, list)):
filename = '/'.join(filename)
try:
mime, icont = cntIndex.doIndex(None, filename=filename,
content_type=None, realfname=fname)
@@ -167,7 +167,7 @@ class nodefd_db(StringIO, nodes.node_descriptor):
nodes.node_descriptor.__init__(self, parent)
if mode.endswith('b'):
mode = mode[:-1]
if mode in ('r', 'r+'):
cr = ira_browse._cr # reuse the cursor of the browse object, just now
cr.execute('SELECT db_datas FROM ir_attachment WHERE id = %s',(ira_browse.id,))
@@ -198,7 +198,7 @@ class nodefd_db(StringIO, nodes.node_descriptor):
filename = par.path
if isinstance(filename, (tuple, list)):
filename = '/'.join(filename)
try:
mime, icont = cntIndex.doIndex(data, filename=filename,
content_type=None, realfname=None)
@@ -235,7 +235,7 @@ class nodefd_db(StringIO, nodes.node_descriptor):
class nodefd_db64(StringIO, nodes.node_descriptor):
""" A descriptor to db data, base64 (the old way)
It stores the data in base64 encoding at the db. Not optimal, but
the transparent compression of Postgres will save the day.
"""
@@ -243,7 +243,7 @@ class nodefd_db64(StringIO, nodes.node_descriptor):
nodes.node_descriptor.__init__(self, parent)
if mode.endswith('b'):
mode = mode[:-1]
if mode in ('r', 'r+'):
StringIO.__init__(self, base64.decodestring(ira_browse.db_datas))
elif mode in ('w', 'w+'):
@@ -271,7 +271,7 @@ class nodefd_db64(StringIO, nodes.node_descriptor):
filename = par.path
if isinstance(filename, (tuple, list)):
filename = '/'.join(filename)
try:
mime, icont = cntIndex.doIndex(data, filename=filename,
content_type=None, realfname=None)
@@ -312,7 +312,7 @@ class document_storage(osv.osv):
media.
The referring document.directory-ies will control the placement of data
into the storage.
It is a bad idea to have multiple document.storage objects pointing to
the same tree of filesystem storage.
"""
@@ -367,12 +367,12 @@ class document_storage(osv.osv):
def __prepare_realpath(self, cr, file_node, ira, store_path, do_create=True):
""" Cleanup path for realstore, create dirs if needed
@param file_node the node
@param ira ir.attachment browse of the file_node
@param store_path the path of the parent storage object, list
@param do_create create the directories, if needed
@return tuple(path "/var/filestore/real/dir/", npath ['dir','fname.ext'] )
"""
file_node.fix_ppath(cr, ira)
@@ -406,7 +406,7 @@ class document_storage(osv.osv):
boo = self.browse(cr, uid, id, context)
if not boo.online:
raise IOError(errno.EREMOTE, 'medium offline')
if fil_obj:
ira = fil_obj
else:
@@ -421,10 +421,10 @@ class document_storage(osv.osv):
boo = self.browse(cr, uid, id, context)
if not boo.online:
raise IOError(errno.EREMOTE, 'medium offline')
if boo.readonly and mode not in ('r', 'rb'):
raise IOError(errno.EPERM, "Readonly medium")
ira = self.pool.get('ir.attachment').browse(cr, uid, file_node.file_id, context=context)
if boo.type == 'filestore':
if not ira.store_fname:
@@ -464,7 +464,7 @@ class document_storage(osv.osv):
elif boo.type == 'virtual':
raise ValueError('Virtual storage does not support static files')
else:
raise TypeError("No %s storage" % boo.type)
@@ -529,7 +529,7 @@ class document_storage(osv.osv):
if not boo.online:
raise IOError(errno.EREMOTE, 'medium offline')
if boo.readonly:
raise IOError(errno.EPERM, "Readonly medium")
@@ -546,7 +546,7 @@ class document_storage(osv.osv):
fp.close()
self._doclog.debug( "Saved data to %s" % fname)
filesize = len(data) # os.stat(fname).st_size
# TODO Here, an old file would be left hanging.
except Exception, e:
@@ -623,7 +623,7 @@ class document_storage(osv.osv):
if not storage_bo.online:
raise IOError(errno.EREMOTE, 'medium offline')
if storage_bo.readonly:
raise IOError(errno.EPERM, "Readonly medium")
@@ -660,7 +660,7 @@ class document_storage(osv.osv):
""" A preparation for a file rename.
It will not affect the database, but merely check and perhaps
rename the realstore file.
@return the dict of values that can safely be be stored in the db.
"""
sbro = self.browse(cr, uid, file_node.storage_id, context=context)
@@ -668,7 +668,7 @@ class document_storage(osv.osv):
if not sbro.online:
raise IOError(errno.EREMOTE, 'medium offline')
if sbro.readonly:
raise IOError(errno.EPERM, "Readonly medium")
@@ -700,7 +700,7 @@ class document_storage(osv.osv):
""" A preparation for a file move.
It will not affect the database, but merely check and perhaps
move the realstore file.
@param ndir_bro a browse object of document.directory, where this
file should move to.
@return the dict of values that can safely be be stored in the db.
@@ -710,7 +710,7 @@ class document_storage(osv.osv):
if not sbro.online:
raise IOError(errno.EREMOTE, 'medium offline')
if sbro.readonly:
raise IOError(errno.EPERM, "Readonly medium")
@@ -735,11 +735,11 @@ class document_storage(osv.osv):
return ValueError("Tried to rename a non-stored file")
path = sbro.path
oldpath = os.path.join(path, fname)
for ch in ('*', '|', "\\", '/', ':', '"', '<', '>', '?', '..'):
if ch in new_name:
raise ValueError("Invalid char %s in name %s" %(ch, new_name))
file_node.fix_ppath(cr, ira)
npath = file_node.full_path() or []
dpath = [path,]
@@ -18,7 +18,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>
#
##############################################################################
from osv import osv, fields
from tools import config
@@ -27,7 +26,7 @@ class document_ftp_configuration(osv.osv_memory):
_name='document.ftp.configuration'
_description = 'Auto Directory Configuration'
_inherit = 'res.config'
_rec_name = 'host'
_columns = {
'host': fields.char('Address', size=64,
help="Server address or IP and port to which users should connect to for DMS access",
+11
View File
@@ -253,6 +253,17 @@ class DAVHandler(HttpOptions, FixSendError, DAVRequestHandler):
from service.http_server import reg_http_service,OpenERPAuthProvider
class DAVAuthProvider(OpenERPAuthProvider):
def authenticate(self, db, user, passwd, client_address):
""" authenticate, but also allow the False db, meaning to skip
authentication when no db is specified.
"""
if db is False:
return True
return OpenERPAuthProvider.authenticate(self, db, user, passwd, client_address)
from service.http_server import reg_http_service,OpenERPAuthProvider
class DAVAuthProvider(OpenERPAuthProvider):
def authenticate(self, db, user, passwd, client_address):
""" authenticate, but also allow the False db, meaning to skip
+1 -1
View File
@@ -267,7 +267,7 @@ This is useful for CRM leads for example"),
}
_sql_constraints = [
('name', 'unique (name)', _('The template name must be unique !'))
('name', 'unique (name)','The template name must be unique !')
]
def create_action(self, cr, uid, ids, context):
+44 -44
View File
@@ -1,17 +1,17 @@
- |
In order to test the "Event Organisation" in Association system.
In order to test the "Event Organisation" in Association system.
- |
I want to organize one conference event on "OpenERP Business".
- |
I'm creating new product "Ticket for Conference" to specify registration Cost of conference.
-
-
!record {model: product.product, id: product_product_ticketforconcert0}:
categ_id: product.cat1
list_price: 68.0
name: Ticket for Conference
name: Ticket for Conference
- |
I'm creating Event type "Conference".
-
-
!record {model: event.type, id: event_type_conference0}:
name: Conferences
- |
@@ -26,31 +26,31 @@
reply_to: 'info@customer.com'
- |
Check that the new conference event is "Draft" or not.
-
-
!assert {model: event.event, id: event_event_conference0}:
- state == 'draft', "Event should be in draft by default when first time created"
- |
Need Minimum 10 Registrations to confirm/start this Conference Event and does not allowed more than 100 Registrations.
- |
So I set Minimum and Maximum Registrations limit.
-
-
!python {model: event.event}: |
self.write(cr, uid, [ref('event_event_conference0')], {'register_max': 100, 'register_min': 10})
- |
I'm doing to confirm that conference event.
-
-
!python {model: event.event}: |
self.button_confirm(cr, uid, [ref("event_event_conference0")])
- |
But this conference event need minimum 10 Confirmed Registrations. so Check that Event is not "confirmed".
-
But this conference event need minimum 10 Confirmed Registrations. so Check that Event is not "confirmed".
-
!assert {model: event.event, id: event_event_conference0}:
- state != 'confirm', "Event should not confirmed if minimum registrations does not reached"
- |
"Mark Johnson" want to subscribe/join into "Conference on OpenERP Business" with 10 tickets.
- |
- |
I'm creating new partner "Mark Johnson" with his email "info@mycustomer.com".
-
-
!record {model: res.partner, id: res_partner_markjohnson0}:
address:
- city: Bruxelles
@@ -66,10 +66,10 @@
zip: '1000'
email: 'info@mycustomer.com'
name: Mark Johnson
- |
I'm creating Registration for "Mark Johnson" on "Conference on OpenERP Business" with 10 tickets.
-
I'm creating Registration for "Mark Johnson" on "Conference on OpenERP Business" with 10 tickets.
-
!record {model: event.registration, id: event_registration_registrationjacot0}:
contact_id: base_contact.res_partner_contact_jacot0
event_id: event.event_event_conference0
@@ -79,28 +79,28 @@
unit_price: 68.0
nb_register: 10
- |
I'm going to Open that Registration.
-
I'm going to Open that Registration.
-
!python {model: event.registration}: |
self.check_confirm(cr, uid, [ref("event_registration_registrationjacot0")])
- |
Check that Registration is in "Open" state or not.
-
!assert {model: event.registration, id: event_registration_registrationjacot0}:
-
!assert {model: event.registration, id: event_registration_registrationjacot0}:
- state == 'open', "Registration should be open here."
- |
I'm again trying to confirm that conference event.
-
-
!python {model: event.event}: |
self.button_confirm(cr, uid, [ref("event_event_conference0")])
- |
Now Minimum requirement of Registration is fulfil. so Check that Event is "confirmed" or not.
-
Now Minimum requirement of Registration is fulfil. so Check that Event is "confirmed" or not.
-
!assert {model: event.event, id: event_event_conference0}:
- state == 'confirm', "Event should be confirmed here."
- |
I'm creating invoice of Registration of "Mark Johnson" on "Conference on OpenERP Business".
-
@@ -108,22 +108,22 @@
self.action_invoice_create(cr, uid, [ref("event_registration_registrationjacot0")])
- |
Check Invoice of Registration of "Mark Johnson" is created or not.
-
Check Invoice of Registration of "Mark Johnson" is created or not.
-
!assert {model: event.registration, id: event_registration_registrationjacot0}:
- invoice_id != False, "Invoice should be generated"
- |
Check Registration of "Mark Johnson" is closed or not after invoice generated.
-
Check Registration of "Mark Johnson" is closed or not after invoice generated.
-
!assert {model: event.registration, id: event_registration_registrationjacot0}:
- state != 'done', "Registration should be closed after invoice generated"
- |
Now "Mark Johnson" want to another registration on "Conference on OpenERP Business" with 120 tickets.
- |
I'm creating new registration for "Mark Johnson" with 100 tickets.
-
-
!record {model: event.registration, id: event_registration_registrationzen0}:
event_id: event.event_event_conference0
partner_id: event.res_partner_markjohnson0
@@ -131,42 +131,42 @@
event_product: Ticket for Conference
unit_price: 68.0
nb_register: 100
- |
I'm going to open "Mark Johnson" registration.
-
I'm going to open "Mark Johnson" registration.
-
!python {model: event.registration}: |
self.check_confirm(cr, uid, [ref("event_registration_registrationzen0")])
- |
But conference event does not allow more than 100 Registrations. so Check that registration is not in "open" state.
-
But conference event does not allow more than 100 Registrations. so Check that registration is not in "open" state.
-
!assert {model: event.registration, id: event_registration_registrationzen0}:
- state == 'draft', "Registration should be in draft by default."
- |
Now I'm modifying number of tickets of "Mark Johnson"'s registration with 90 tickets.
-
Now I'm modifying number of tickets of "Mark Johnson"'s registration with 90 tickets.
-
!python {model: event.registration}: |
self.write(cr, uid, [ref("event_registration_registrationzen0")], {'nb_register': 90})
- |
I'm again try to open "Mark Johnson" registration.
-
I'm again try to open "Mark Johnson" registration.
-
!python {model: event.registration}: |
self.check_confirm(cr, uid, [ref("event_registration_registrationzen0")])
- |
Check that registration "open" or not.
-
Check that registration "open" or not.
-
!assert {model: event.registration, id: event_registration_registrationzen0}:
- state == 'open', "Registration should be open here."
- |
I'm closing "Conference on OpenERP Business" Conference event
-
-
!python {model: event.event}: |
self.button_done(cr, uid, [ref("event_event_conference0")])
- |
Check that conference is in "close" state or not.
-
Check that conference is in "close" state or not.
-
!assert {model: event.event, id: event_event_conference0}:
- state == 'done', "Registration should be Closed here."
+1 -1
View File
@@ -77,7 +77,7 @@
<field name="help">Time Tracking functionality aims to manage employee's attendances on the basis of the actions (Sign in/Sign out) performed by them. You can also link this to an attendance machine using OpenERP's webservices features.</field>
</record>
<menuitem id="menu_hr_time_tracking" name="Time Tracking" parent="hr.menu_hr_root" sequence="3"/>
<menuitem id="menu_hr_time_tracking" name="Time Tracking" parent="hr.menu_hr_root" sequence="3" />
<menuitem id="menu_hr_attendance" name="Attendances" parent="hr.menu_hr_root" sequence="4"/>
@@ -6,3 +6,4 @@
"access_product_template_hr_timesheet","product.template.hr.timesheet","product.model_product_template","base.group_hr_user",1,1,1,1
"access_product_uom_hr_timesheet","product.uom.hr.timesheet","product.model_product_uom","base.group_hr_user",1,1,1,1
"access_account_fiscalyear_hr_user","account.account.fiscalyear.user","account.model_account_fiscalyear","base.group_hr_user",1,1,1,1
"access_hr_analytic_timesheet","hr.analytic.timesheet","model_hr_analytic_timesheet","project.group_project_finance_user",1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
6 access_product_template_hr_timesheet product.template.hr.timesheet product.model_product_template base.group_hr_user 1 1 1 1
7 access_product_uom_hr_timesheet product.uom.hr.timesheet product.model_product_uom base.group_hr_user 1 1 1 1
8 access_account_fiscalyear_hr_user account.account.fiscalyear.user account.model_account_fiscalyear base.group_hr_user 1 1 1 1
9 access_hr_analytic_timesheet hr.analytic.timesheet model_hr_analytic_timesheet project.group_project_finance_user 1 0 0 0
@@ -14,3 +14,4 @@
"access_account_invoice_hr_user","account.invoice.hr.user","account.model_account_invoice","base.group_hr_user",1,1,1,1
"access_account_invoice_tax_hr_manager","account.invoice.tax.hr.manager","account.model_account_invoice_tax","base.group_hr_manager",1,1,1,1
"access_report_timesheet_line_employee","report.timesheet.line.employee","model_report_timesheet_line","base.group_hr_user",1,1,1,1
"access_hr_timesheet_invoice_factor","hr_timesheet_invoice.factor","model_hr_timesheet_invoice_factor","project.group_project_finance_user",1,1,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
14 access_account_invoice_hr_user account.invoice.hr.user account.model_account_invoice base.group_hr_user 1 1 1 1
15 access_account_invoice_tax_hr_manager account.invoice.tax.hr.manager account.model_account_invoice_tax base.group_hr_manager 1 1 1 1
16 access_report_timesheet_line_employee report.timesheet.line.employee model_report_timesheet_line base.group_hr_user 1 1 1 1
17 access_hr_timesheet_invoice_factor hr_timesheet_invoice.factor model_hr_timesheet_invoice_factor project.group_project_finance_user 1 1 0 0
@@ -181,8 +181,9 @@
<menuitem
id="base.menu_project_management_time_tracking"
name="Time Tracking"
parent="base.menu_main_pm" sequence="5"/>
parent="base.menu_main_pm" sequence="5" groups="project.group_project_finance_user"/>
<menuitem action="hr_timesheet_sheet.act_hr_timesheet_sheet_form" id="menu_act_project_management_timesheet_sheet_form" parent="base.menu_project_management_time_tracking"
sequence="5"/>
<menuitem action="act_hr_timesheet_sheet_form" id="menu_act_hr_timesheet_sheet_form" parent="hr_attendance.menu_hr_time_tracking"
sequence="2"/>
@@ -1,4 +1,5 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"access_hr_timesheet_report","hr.timesheet.report","model_hr_timesheet_report","base.group_hr_manager",1,0,0,0
"access_hr_timesheet_sheet_sheet_user","hr_timesheet_sheet.sheet.user","model_hr_timesheet_sheet_sheet","base.group_hr_user",1,1,1,1
"access_hr_timesheet_sheet_sheet_system_user","hr_timesheet_sheet.sheet.system.user","model_hr_timesheet_sheet_sheet","base.group_user",1,0,0,0
"access_hr_timesheet_sheet_sheet_day","hr_timesheet_sheet.sheet.day","model_hr_timesheet_sheet_sheet_day","base.group_hr_user",1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_hr_timesheet_report hr.timesheet.report model_hr_timesheet_report base.group_hr_manager 1 0 0 0
3 access_hr_timesheet_sheet_sheet_user hr_timesheet_sheet.sheet.user model_hr_timesheet_sheet_sheet base.group_hr_user 1 1 1 1
4 access_hr_timesheet_sheet_sheet_system_user hr_timesheet_sheet.sheet.system.user model_hr_timesheet_sheet_sheet base.group_user 1 0 0 0
5 access_hr_timesheet_sheet_sheet_day hr_timesheet_sheet.sheet.day model_hr_timesheet_sheet_sheet_day base.group_hr_user 1 1 1 1
+2
View File
@@ -33,6 +33,7 @@ class idea_category(osv.osv):
_name = "idea.category"
_description = "Idea Category"
_log_create=True
_columns = {
'name': fields.char('Category', size=64, required=True),
@@ -303,6 +304,7 @@ class idea_vote(osv.osv):
_name = 'idea.vote'
_description = 'Idea Vote'
_rec_name = 'score'
_log_create = True
_columns = {
'user_id': fields.many2one('res.users', 'User', readonly="True"),
+1
View File
@@ -109,6 +109,7 @@ class idea_post_vote(osv.osv_memory):
for do_vote_obj in self.read(cr, uid, ids):
score = str(do_vote_obj['vote'])
comment = do_vote_obj.get('note', False)
for vote_id in vote_ids:
vote = {
'idea_id': vote_id,
'user_id': uid,
-2
View File
@@ -396,7 +396,6 @@ class mailgate_tool(osv.osv_memory):
model_pool = self.pool.get(model)
res_id = False
# Create New Record into particular model
def create_record(msg):
att_ids = []
@@ -551,7 +550,6 @@ class mailgate_tool(osv.osv_memory):
if not len(res_ids):
new_res_id, attachment_ids = create_record(msg)
res_ids = [new_res_id]
# Store messages
context.update({'model' : model})
if hasattr(model_pool, 'history'):
@@ -257,7 +257,7 @@ class marketing_campaign_segment(osv.osv):
return True
_constraints = [
(_check_model, _('Model of filter must be same as resource model of Campaign '), ['ir_filter_id,campaign_id']),
(_check_model, 'Model of filter must be same as resource model of Campaign ', ['ir_filter_id,campaign_id']),
]
def onchange_campaign_id(self, cr, uid, ids, campaign_id):
@@ -309,7 +309,7 @@ class marketing_campaign_segment(osv.osv):
for segment in self.browse(cr, uid, segment_ids, context=context):
if segment.campaign_id.state != 'running':
continue
campaigns.add(segment.campaign_id.id)
act_ids = self.pool.get('marketing.campaign.activity').search(cr,
uid, [('start', '=', True), ('campaign_id', '=', segment.campaign_id.id)], context=context)
@@ -377,7 +377,7 @@ class marketing_campaign_activity(osv.osv):
help="Python expression to decide whether the activity can be executed, otherwise it will be deleted or cancelled."
"The expression may use the following [browsable] variables:\n"
" - activity: the campaign activity\n"
" - workitem: the campaign workitem\n"
" - workitem: the campaign workitem\n"
" - resource: the resource object this campaign item represents\n"
" - transitions: list of campaign transitions outgoing from this activity\n"
"...- re: Python regular expression module"),
@@ -539,9 +539,9 @@ class marketing_campaign_transition(osv.osv):
return True
_constraints = [
(_check_campaign, _('The To/From Activity of transition must be of the same Campaign '), ['activity_from_id,activity_to_id']),
(_check_campaign, 'The To/From Activity of transition must be of the same Campaign ', ['activity_from_id,activity_to_id']),
]
_sql_constraints = [
('interval_positive', 'CHECK(interval_nbr >= 0)', 'The interval must be positive or zero')
]
@@ -638,7 +638,7 @@ class marketing_campaign_workitem(osv.osv):
'activity': activity,
'workitem': workitem,
'object': object_id,
'resource': object_id,
'resource': object_id,
'transitions': activity.to_ids,
're': re,
}
+12 -12
View File
@@ -446,18 +446,18 @@ class mrp_production(osv.osv):
'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'mrp.production', context=c),
}
_order = 'priority desc, date_planned asc';
def _check_qty(self, cr, uid, ids):
orders = self.browse(cr, uid, ids)
for order in orders:
if order.product_qty <= 0:
return False
return True
_constraints = [
(_check_qty, 'Order quantity cannot be negative or zero !', ['product_qty']),
]
def unlink(self, cr, uid, ids, context=None):
productions = self.read(cr, uid, ids, ['state'])
unlink_ids = []
@@ -639,16 +639,16 @@ class mrp_production(osv.osv):
@param production_mode: specify production mode (consume/consume&produce).
@return: True
"""
stock_mov_obj = self.pool.get('stock.move')
production = self.browse(cr, uid, production_id)
final_product_todo = []
produced_qty = 0
if production_mode == 'consume_produce':
produced_qty = production_qty
for produced_product in production.move_created_ids2:
if (produced_product.scrapped) or (produced_product.product_id.id<>production.product_id.id):
continue
@@ -658,7 +658,7 @@ class mrp_production(osv.osv):
consumed_products = {}
check = {}
scrapped = map(lambda x:x.scrapped,production.move_lines2).count(True)
for consumed_product in production.move_lines2:
consumed = consumed_product.product_qty
if consumed_product.scrapped:
@@ -671,9 +671,9 @@ class mrp_production(osv.osv):
if (len(production.move_lines2) - scrapped) > len(production.product_lines):
check[consumed_product.product_id.id] += consumed_product.product_qty
consumed = check[consumed_product.product_id.id]
rest_consumed = produced_qty * f.product_qty / production.product_qty - consumed
rest_consumed = produced_qty * f.product_qty / production.product_qty - consumed
consumed_products[consumed_product.product_id.id] = rest_consumed
for raw_product in production.move_lines:
for f in production.product_lines:
if f.product_id.id == raw_product.product_id.id:
@@ -712,7 +712,7 @@ class mrp_production(osv.osv):
new_parent_ids.append(final_product.id)
for new_parent_id in new_parent_ids:
stock_mov_obj.write(cr, uid, [raw_product.id], {'move_history_ids': [(4,new_parent_id)]})
wf_service = netsvc.LocalService("workflow")
wf_service.trg_validate(uid, 'mrp.production', production_id, 'button_produce_done', cr)
return True
@@ -827,7 +827,7 @@ class mrp_production(osv.osv):
'company_id': production.company_id.id,
}
res_final_id = move_obj.create(cr, uid, data)
self.write(cr, uid, [production.id], {'move_created_ids': [(6, 0, [res_final_id])]})
moves = []
for line in production.product_lines:
@@ -879,7 +879,7 @@ class mrp_production(osv.osv):
'company_id': production.company_id.id,
})
wf_service.trg_validate(uid, 'procurement.order', proc_id, 'button_confirm', cr)
proc_ids.append(proc_id)
proc_ids.append(proc_id)
wf_service.trg_validate(uid, 'stock.picking', picking_id, 'button_confirm', cr)
self.write(cr, uid, [production.id], {'picking_id': picking_id, 'move_lines': [(6,0,moves)], 'state':'confirmed'})
message = _("Manufacturing order '%s' is scheduled for the %s.") % (
+9 -9
View File
@@ -129,9 +129,9 @@ class product_pricelist(osv.osv):
#def price_get_multi(self, cr, uid, product_ids, context=None):
def price_get_multi(self, cr, uid, pricelist_ids, products_by_qty_by_partner, context=None):
"""multi products 'price_get'.
@param pricelist_ids:
@param products_by_qty:
@param partner:
@param pricelist_ids:
@param products_by_qty:
@param partner:
@param context: {
'date': Date of the pricelist (%Y-%m-%d),}
@return: a dict of dict with product_id as key and a dict 'price by pricelist' as value
@@ -371,7 +371,7 @@ class product_pricelist(osv.osv):
'ORDER BY sequence',
(tmpl_id, prod_id, plversion['id'], qty))
res1 = cr.dictfetchall()
for res in res1:
item_id = 0
if res:
@@ -386,7 +386,7 @@ class product_pricelist(osv.osv):
res['base_pricelist_id']).currency_id.id
price = currency_obj.compute(cr, uid, ptype_src,
res['currency_id'], price_tmp, round=False)
break
break
elif res['base'] == -2:
where = []
if partner:
@@ -413,7 +413,7 @@ class product_pricelist(osv.osv):
if price:
price_limit = price
price = price * (1.0+(res['price_discount'] or 0.0))
price = rounding(price, res['price_round'])
price += (res['price_surcharge'] or 0.0)
@@ -422,14 +422,14 @@ class product_pricelist(osv.osv):
if res['price_max_margin']:
price = min(price, price_limit+res['price_max_margin'])
item_id = res['id']
break
break
else:
# False means no valid line found ! But we may not raise an
# exception here because it breaks the search
price = False
result[id] = price
result['item_id'] = {id: item_id}
result['item_id'] = {id: item_id}
if context and ('uom' in context):
product = product_obj.browse(cr, uid, prod_id)
uom = product.uos_id or product.uom_id
@@ -559,7 +559,7 @@ class product_pricelist_item(osv.osv):
}
_constraints = [
(_check_recursion, _('Error ! You cannot assign the Main Pricelist as Other Pricelist in PriceList Item!'), ['base_pricelist_id'])
(_check_recursion, 'Error ! You cannot assign the Main Pricelist as Other Pricelist in PriceList Item!', ['base_pricelist_id'])
]
def product_id_change(self, cr, uid, ids, product_id, context={}):
+2 -2
View File
@@ -86,7 +86,7 @@ class project(osv.osv):
cr.execute('''SELECT
project_id, sum(planned_hours), sum(total_hours), sum(effective_hours), SUM(remaining_hours)
FROM
project_task
project_task
WHERE
project_id in %s AND
state<>'cancelled'
@@ -475,7 +475,7 @@ class task(osv.osv):
return True
_constraints = [
(_check_recursion, _('Error ! You cannot create recursive tasks.'), ['parent_ids'])
(_check_recursion, 'Error ! You cannot create recursive tasks.', ['parent_ids'])
]
#
# Override view according to the company definition
+1
View File
@@ -546,6 +546,7 @@
</page>
</field>
</record>
<act_window context="{'search_default_user_id': [active_id]}" domain="[('state', '&lt;&gt;', 'cancelled'),('state', '&lt;&gt;', 'done')]" id="act_res_users_2_project_task_opened" name="Assigned tasks" res_model="project.task" src_model="res.users" view_mode="tree,form,gantt,calendar,graph" view_type="form"/>
<act_window context="{'search_default_user_id': [active_id]}" domain="[('date', '&gt;=', time.strftime('%Y-%m-01'))]" id="act_res_users_2_project_task_work_month" name="Month works" res_model="project.task.work" src_model="res.users" view_mode="tree,form" view_type="form"/>
</data>
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -16,7 +16,7 @@
# 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/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
@@ -4,5 +4,15 @@
<record id="group_project_supporter" model="res.groups">
<field name="name">Project / Support Manager</field>
</record>
<record model="ir.rule" id="project_issue_rule">
<field name="name" >Issues according to Users or Members</field>
<field name="model_id" ref="model_project_issue"/>
<field eval="1" name="perm_read"/>
<field eval="1" name="perm_create"/>
<field eval="1" name="perm_write"/>
<field name="groups" eval="[(6, 0, [ref('project.group_project_user')])]"/>
<field name="domain_force">['|',('members','in',[user.id]),('user_id','=',user.id)]</field>
</record>
</data>
</openerp>
@@ -0,0 +1,3 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"access_mailgate_message_project_manager","project.mailgate.message.manager","mail_gateway.model_mailgate_message","project.group_project_manager",1,1,1,0
"access_mailgate_message_project_user","project.mailgate.message.user","mail_gateway.model_mailgate_message","project.group_project_user",1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_mailgate_message_project_manager project.mailgate.message.manager mail_gateway.model_mailgate_message project.group_project_manager 1 1 1 0
3 access_mailgate_message_project_user project.mailgate.message.user mail_gateway.model_mailgate_message project.group_project_user 1 1 1 0
+5 -3
View File
@@ -34,7 +34,7 @@ from osv.orm import browse_record, browse_null
# Model definition
#
class purchase_order(osv.osv):
def _calc_amount(self, cr, uid, ids, prop, unknow_none, unknow_dict):
res = {}
for order in self.browse(cr, uid, ids):
@@ -42,7 +42,7 @@ class purchase_order(osv.osv):
for oline in order.order_line:
res[order.id] += oline.price_unit * oline.product_qty
return res
def _amount_all(self, cr, uid, ids, field_name, arg, context=None):
res = {}
cur_obj=self.pool.get('res.currency')
@@ -186,7 +186,7 @@ class purchase_order(osv.osv):
'invoice_method': fields.selection([('manual','Manual'),('order','From Order'),('picking','From Picking')], 'Invoicing Control', required=True,
help="From Order: a draft invoice will be pre-generated based on the purchase order. The accountant " \
"will just have to validate this invoice for control.\n" \
"From Picking: a draft invoice will be pre-generated based on validated receptions.\n" \
"From Picking: you manually have to generate the invoices based on the receptions.\n" \
"Manual: no invoice will be pre-generated. The accountant will have to encode manually."
),
'minimum_planned_date':fields.function(_minimum_planned_date, fnct_inv=_set_minimum_planned_date, method=True,store=True, string='Expected Date', type='date', help="This is computed as the minimum scheduled date of all purchase order lines' products."),
@@ -283,6 +283,8 @@ class purchase_order(osv.osv):
self.log(cr, uid, po.id, message)
current_name = self.name_get(cr, uid, ids)[0][1]
self.pool.get('purchase.order.line').action_confirm(cr, uid, todo, context)
message = _('confirm Order') + " ' " + po.name
self.log(cr,uid,po,message)
for id in ids:
self.write(cr, uid, [id], {'state' : 'confirmed', 'validator' : uid})
return True
@@ -1,27 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<!--Resource: purchase.requisition-->
<record id="order_purchase_requisition1" model="purchase.requisition">
<field name="name">TE0001</field>
<field name="user_id" model="res.users"/>
<field name="exclusive">multiple</field>
<field name="date_start">2010/09/16 15:56:14</field>
<field name="warehouse_id" model="stock.warehouse"/>
<field name="warehouse_id" ref="stock.stock_warehouse_shop0"/>
</record>
<!--Resource: purchase.requisition.line-->
<record id="line_purchase_requisition1" model="purchase.requisition.line">
<field name="requisition_id" ref="order_purchase_requisition1"/>
<field name="product_id" ref="product.product_product_pc3"/>
<field name="product_id" ref="product.product_product_pc3"/>
<field name="product_uom_id" model="product.uom" search="[]"/>
<field name="product_qty">5</field>
</record>
</data>
</openerp>
+1 -1
View File
@@ -1065,7 +1065,7 @@ class sale_order_line(osv.osv):
'title': _('Picking Information !'),
'message': warn_msg
}
result['product_uom_qty'] = qty
result['product_uom_qty'] = pack.qty
uom2 = False
if uom:
+23 -23
View File
@@ -24,13 +24,13 @@
picking_policy: direct
pricelist_id: product.list0
shop_id: sale.shop
-
-
I confirm the Sale Order.
-
-
!workflow {model: sale.order, action: order_confirm, ref: sale_order_so0}
-
I click on Create Invoice button to create the invoice.
-
-
!workflow {model: sale.order, action: manual_invoice, ref: sale_order_so0}
-
@@ -38,7 +38,7 @@
-
!python {model: sale.order}: |
so = self.browse(cr, uid, ref("sale_order_so0"))
assert so.invoice_ids, "Invoices has not been generated for sale_order_so0"
assert so.invoice_ids, "Invoices has not been generated for sale_order_so0"
-
I open the Invoice for the SO.
-
@@ -69,7 +69,7 @@
assert inv_brw.move_id, "Journal Entries has not been created"
-
Assign analytic journal into bank journal
-
-
!record {model: account.journal, id: sale.account_journal_bankjournal0}:
analytic_journal_id: account.cose_journal_sale
-
@@ -85,7 +85,7 @@
ref('account.period_8'), ref('sale.account_journal_bankjournal0'),
name='test')
-
I verify the invoice is in done state.
I verify the invoice is in done state.
-
!python {model: account.invoice}: |
sale_order_obj = self.pool.get('sale.order')
@@ -98,9 +98,9 @@
!python {model: sale.order}: |
sale_id=self.browse(cr, uid, ref("sale_order_so0"))
assert(sale_id.invoiced == True), "Paid has not been set to true"
-
-
I verify that the picking has been generated for the sale order
-
-
!python {model: sale.order}: |
so = self.browse(cr, uid, ref("sale_order_so0"))
assert so.picking_ids,"Picking has not been generated for sale_order_so0"
@@ -111,7 +111,7 @@
sale_order_obj = self.pool.get('sale.order')
so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
picking_id = self.search(cr, uid, [('origin','=',so.name)])
assert (picking_id),"Delivery order has not been generated"
assert(picking_id),"Delivery order has not been generated"
-
I verify that a procurement has been generated for so
-
@@ -120,7 +120,7 @@
sale_order_obj = self.pool.get('sale.order')
so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
proc_ids = self.search(cr, uid, [('origin','=',so.name)])
assert proc_ids, _('No Procurements!')
assert(proc_ids),"No Procurements!"
-
Then I click on the "Run Procurement" button
-
@@ -144,7 +144,7 @@
sale_order_obj = self.pool.get('sale.order')
so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
proc_ids = self.search(cr, uid, [('origin','=',so.name),('state','=','running')])
assert proc_ids, _('Procurement is not in the running state!')
assert(proc_ids),"Procurement is not in the running state!"
-
I verify that a purchase order has been generated
-
@@ -157,8 +157,8 @@
so = self.browse(cr, uid, ref("sale_order_so0"))
pur_obj=self.pool.get('purchase.order')
pur_id=pur_obj.search(cr, uid, [('origin','=',so.name)])
assert pur_id, _('Purchase order has not been generated')
assert(pur_id),"Purchase order has not been generated"
-
I click on the "Confirm" button to confirm the purchase order
-
@@ -175,7 +175,7 @@
pur_ids = pur_obj.search(cr, uid, [('origin','=',so.name)])
for pur in pur_ids:
wf_service.trg_validate(uid, 'purchase.order',pur,'purchase_confirm', cr)
-
-
I click on the "Approved by supplier" button to approve the purchase order
-
!python {model: sale.order}: |
@@ -192,7 +192,7 @@
for pur in pur_ids:
wf_service.trg_validate(uid, 'purchase.order',pur,'purchase_approve', cr)
-
I verify that a picking related to purchase order has been generated.
I verify that a picking related to purchase order has been generated.
-
!python {model: sale.order}: |
modules = self.pool.get('ir.module.module')
@@ -204,7 +204,7 @@
pur_id = pur_obj.search(cr, uid, [('origin','=',so.name)])
po = pur_obj.browse(cr, uid, pur_id)[0]
assert(po.picking_ids),"Picking for purchase order has not been generated"
-
-
Then I click on the "Products Received" button of Incoming Shipments
-
!record {model: stock.partial.picking, id: stock_partial_picking_0}:
@@ -242,10 +242,10 @@
po = pur_obj.browse(cr, uid, pur_id)[0]
picking_obj = self.pool.get('stock.picking')
ids = picking_obj.search(cr, uid, [('purchase_id', '=', po.id ),('state', '=', 'done')])
assert ids, _('Picking is not in the done state!')
assert(ids),"Picking is not in the done state!"
-
Then I done the picking
-
-
!python {model: stock.picking }: |
import time
sale_order_obj = self.pool.get('sale.order')
@@ -264,7 +264,7 @@
'product_id': move.product_id.id,
'product_qty': move.product_qty,
'product_uom': move.product_uom.id,
}
}
self.do_partial(cr, uid, [pick.id],partial_datas)
-
I verify that picking for sale order is in done state.
@@ -274,7 +274,7 @@
so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
picking_id = self.search(cr, uid, [('origin','=',so.name),('type','=','out')])
pick = self.browse(cr,uid,picking_id[0])
assert (pick.state) =='done', "Picking for SO is not in done state."
assert (pick.state) =='done', "Picking for SO is not in done state."
-
Then I done the delivery order
-
@@ -296,8 +296,8 @@
'product_id': move.product_id.id,
'product_qty': move.product_qty,
'product_uom': move.product_uom.id,
}
self.do_partial(cr, uid, [pick.id],partial_datas)
}
self.do_partial(cr, uid, [pick.id],partial_datas)
-
I verify that delivery state is done
-
@@ -308,7 +308,7 @@
pick = self.browse(cr,uid,picking_id[0])
assert (pick.state) =='done', "Picking for SO is not in done state."
-
I verify that a "Picked" has been set to true
I verify that a "Picked" has been set to true
-
!python {model: sale.order}: |
so = self.browse(cr, uid, ref("sale_order_so0"))
-1
View File
@@ -154,5 +154,4 @@ class crm_make_sale(osv.osv_memory):
'close': True,
'partner_id': _selectPartner,
}
crm_make_sale()
+23 -23
View File
@@ -356,7 +356,7 @@ class stock_location(osv.osv):
Attempt to find a quantity ``product_qty`` (in the product's default uom or the uom passed in ``context``) of product ``product_id``
in locations with id ``ids`` and their child locations. If ``lock`` is True, the stock.move lines
of product with id ``product_id`` in the searched location will be write-locked using Postgres's
"FOR UPDATE NOWAIT" option until the transaction is committed or rolled back, to prevent reservin
"FOR UPDATE NOWAIT" option until the transaction is committed or rolled back, to prevent reservin
twice the same products.
If ``lock`` is True and the lock cannot be obtained (because another transaction has locked some of
the same stock.move lines), a log line will be output and False will be returned, as if there was
@@ -501,14 +501,14 @@ class stock_tracking(osv.osv):
def unlink(self, cr, uid, ids, context=None):
raise osv.except_osv(_('Error'), _('You can not remove a lot line !'))
def action_traceability(self, cr, uid, ids, context={}):
""" It traces the information of a product
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param ids: List of IDs selected
@param context: A standard dictionary
@param ids: List of IDs selected
@param context: A standard dictionary
@return: A dictionary of values
"""
value={}
@@ -636,7 +636,7 @@ class stock_picking(osv.osv):
'invoice_state': fields.selection([
("invoiced", "Invoiced"),
("2binvoiced", "To Be Invoiced"),
("none", "Not from Picking")], "Invoice Control",
("none", "Not Applicable")], "Invoice Control",
select=True, required=True, readonly=True, states={'draft': [('readonly', False)]}),
'company_id': fields.many2one('res.company', 'Company', required=True, select=True),
}
@@ -682,7 +682,7 @@ class stock_picking(osv.osv):
picking_obj = self.browse(cr, uid, [res], context)[0]
for move in picking_obj.move_lines:
move_obj.write(cr, uid, [move.id], {'tracking_id': False,'prodlot_id':False})
return res
return res
def onchange_partner_in(self, cr, uid, context=None, partner_id=None):
return {}
@@ -1087,14 +1087,14 @@ class stock_picking(osv.osv):
if move.state not in ('cancel',):
return False
return True
def allow_cancel(self, cr, uid, ids, context={}):
for pick in self.browse(cr, uid, ids, context=context):
if not pick.move_lines:
return True
for move in pick.move_lines:
if move.state == 'done':
raise osv.except_osv(_('Error'), _('You cannot cancel picking because stock move is in done state !'))
raise osv.except_osv(_('Error'), _('You cannot cancel picking because stock move is in done state !'))
return True
def unlink(self, cr, uid, ids, context=None):
move_obj = self.pool.get('stock.move')
@@ -1182,7 +1182,7 @@ class stock_picking(osv.osv):
# Record the values that were chosen in the wizard, so they can be
# used for inventory valuation if real-time valuation is enabled.
move_obj.write(cr, uid, [move.id],
move_obj.write(cr, uid, [move.id],
{'price_unit': product_price,
'price_currency_id': product_currency})
@@ -1355,7 +1355,7 @@ class stock_production_lot(osv.osv):
'prefix': fields.char('Prefix', size=64, help="Optional prefix to prepend when displaying this serial number: PREFIX/SERIAL [INT_REF]"),
'product_id': fields.many2one('product.product', 'Product', required=True),
'date': fields.datetime('Creation Date', required=True),
'stock_available': fields.function(_get_stock, fnct_search=_stock_search, method=True, type="float", string="Available", select=True,
'stock_available': fields.function(_get_stock, fnct_search=_stock_search, method=True, type="float", string="Available", select=True,
help="Current quantity of products with this Production Lot Number available in company warehouses",
digits_compute=dp.get_precision('Product UoM')),
'revisions': fields.one2many('stock.production.lot.revision', 'lot_id', 'Revisions'),
@@ -1368,15 +1368,15 @@ class stock_production_lot(osv.osv):
'product_id': lambda x, y, z, c: c.get('product_id', False),
}
_sql_constraints = [
('name_ref_uniq', 'unique (name, ref)', _('The combination of serial number and internal reference must be unique !')),
('name_ref_uniq', 'unique (name, ref)', 'The combination of serial number and internal reference must be unique !'),
]
def action_traceability(self, cr, uid, ids, context={}):
""" It traces the information of a product
@param self: The object pointer.
@param cr: A database cursor
@param uid: ID of the user currently logged in
@param ids: List of IDs selected
@param context: A standard dictionary
@param ids: List of IDs selected
@param context: A standard dictionary
@return: A dictionary of values
"""
value=self.pool.get('action.traceability').action_traceability(cr,uid,ids,context)
@@ -1510,7 +1510,7 @@ class stock_move(osv.osv):
if context.get('move_line', []):
if context['move_line'][0]:
if isinstance(context['move_line'][0], (tuple, list)):
return context['move_line'][0][2] and context['move_line'][0][2].get('location_dest_id',False)
return context['move_line'][0][2] and context['move_line'][0][2].get('location_dest_id',False)
else:
move_list = self.pool.get('stock.move').read(cr, uid, context['move_line'][0], ['location_dest_id'])
return move_list and move_list['location_dest_id'][0] or False
@@ -1871,7 +1871,7 @@ class stock_move(osv.osv):
"""
Return the accounts and journal to use to post Journal Entries for the real-time
valuation of the move.
:param context: context dictionary that can explicitly mention the company to consider via the 'force_company' key
:raise: osv.except_osv() is any mandatory account or journal is not defined.
"""
@@ -1911,13 +1911,13 @@ class stock_move(osv.osv):
default_uom = move.product_id.uom_id.id
qty = product_uom_obj._compute_qty(cr, uid, move.product_uom.id, move.product_qty, default_uom)
# if product is set to average price and a specific value was entered in the picking wizard,
# if product is set to average price and a specific value was entered in the picking wizard,
# we use it
if move.product_id.cost_method == 'average' and move.price_unit:
reference_amount = qty * move.price_unit
reference_currency_id = move.price_currency_id.id or reference_currency_id
# Otherwise we default to the company's valuation price type, considering that the values of the
# Otherwise we default to the company's valuation price type, considering that the values of the
# valuation field are expressed in the default currency of the move's company.
else:
if context is None:
@@ -1959,7 +1959,7 @@ class stock_move(osv.osv):
move_obj = self.pool.get('account.move')
for j_id, move_lines in account_moves:
move_obj.create(cr, uid,
move_obj.create(cr, uid,
{'name': move.name,
'journal_id': j_id,
'line_id': move_lines,
@@ -2016,10 +2016,10 @@ class stock_move(osv.osv):
def _create_account_move_line(self, cr, uid, move, src_account_id, dest_account_id, reference_amount, reference_currency_id, context=None):
"""
Generate the account.move.line values to post to track the stock valuation difference due to the
Generate the account.move.line values to post to track the stock valuation difference due to the
processing of the given stock move.
"""
# prepare default values considering that the destination accounts have the reference_currency_id as their main currency
# prepare default values considering that the destination accounts have the reference_currency_id as their main currency
partner_id = (move.picking_id.address_id and move.picking_id.address_id.partner_id and move.picking_id.address_id.partner_id.id) or False
debit_line_vals = {
'name': move.name,
@@ -2043,7 +2043,7 @@ class stock_move(osv.osv):
}
# if we are posting to accounts in a different currency, provide correct values in both currencies correctly
# when compatible with the optional secondary currency on the account.
# when compatible with the optional secondary currency on the account.
# Financial Accounts only accept amounts in secondary currencies if there's no secondary currency on the account
# or if it's the same as that of the secondary amount being posted.
account_obj = self.pool.get('account.account')
@@ -2311,7 +2311,7 @@ class stock_move(osv.osv):
# Record the values that were chosen in the wizard, so they can be
# used for inventory valuation if real-time valuation is enabled.
self.write(cr, uid, [move.id],
self.write(cr, uid, [move.id],
{'price_unit': product_price,
'price_currency_id': product_currency,
})
@@ -2384,7 +2384,7 @@ class stock_inventory(osv.osv):
'state': 'draft',
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.inventory', context=c)
}
def _inventory_line_hook(self, cr, uid, inventory_line, move_vals):
""" Creates a stock move from an inventory line
@param inventory_line:
+6 -2
View File
@@ -304,7 +304,7 @@
<page string="Stock Moves">
<field colspan="2" name="move_ids" nolabel="1" widget="one2many_list">
<tree string="Stock Moves">
<field name="picking_id" string="Reference"/>
<field name="picking_id" string="Reference"/>
<field name="origin"/>
<field name="partner_id"/>
<field name="product_id"/>
@@ -317,7 +317,7 @@
<field name="location_dest_id"/>
<field name="state"/>
</tree>
</field>
</field>
</page>
</notebook>
</form>
@@ -658,6 +658,10 @@
groups="base.group_extended"
icon="terp-stock_effects-object-colorize"
states="draft,assigned,confirmed,done"/>
<button name="%(split_into)d" string="Put in a new pack" type="action"
groups="base.group_extended"
icon="terp-stock_effects-object-colorize"
states="draft,assigned,confirmed,done"/>
<field name="location_id"/>
<field name="location_dest_id"/>
<field name="date_expected" string="Date Expected"/>
+2 -2
View File
@@ -38,7 +38,7 @@ class stock_location_path(osv.osv):
'invoice_state': fields.selection([
("invoiced", "Invoiced"),
("2binvoiced", "To Be Invoiced"),
("none", "Not from Picking")], "Invoice Status",
("none", "Not Applicable")], "Invoice Status",
required=True,),
'picking_type': fields.selection([('out','Sending Goods'),('in','Getting Goods'),('internal','Internal')], 'Shipping Type', required=True, select=True, help="Depending on the company, choose whatever you want to receive or send products"),
'auto': fields.selection(
@@ -77,7 +77,7 @@ class product_pulled_flow(osv.osv):
'invoice_state': fields.selection([
("invoiced", "Invoiced"),
("2binvoiced", "To Be Invoiced"),
("none", "Not from Picking")], "Invoice Status",
("none", "Not Applicable")], "Invoice Status",
required=True,),
}
_defaults = {