diff --git a/addons/account/__openerp__.py b/addons/account/__openerp__.py
index d3a58272b89..09e51486ad2 100644
--- a/addons/account/__openerp__.py
+++ b/addons/account/__openerp__.py
@@ -127,6 +127,7 @@ module named account_vouchers
'board_account_demo.xml',
],
'test': [
+ 'test/account_sequence_test.yml',
'test/account_customer_invoice.yml',
'test/account_supplier_invoice.yml',
'test/account_change_currency.yml',
diff --git a/addons/account/account.py b/addons/account/account.py
index 6aa47551a98..45d3cb4377c 100644
--- a/addons/account/account.py
+++ b/addons/account/account.py
@@ -2684,6 +2684,15 @@ class wizard_multi_charts_accounts(osv.osv_memory):
'position_id' : new_fp,
}
obj_ac_fp.create(cr, uid, vals_acc)
+
+ #fially inactive the demo chart of accounts
+ data_id = data_pool.search(cr, uid, [('model','=','account.account'), ('name','=','chart0')])
+ if data_id:
+ data = data_pool.browse(cr, uid, data_id[0])
+ account_id = data.res_id
+ if account_id:
+ cr.execute("update account_account set active='f' where id=%s" % (account_id))
+
wizard_multi_charts_accounts()
class account_bank_accounts_wizard(osv.osv_memory):
diff --git a/addons/account/account_bank_statement.py b/addons/account/account_bank_statement.py
index e0d31b9cf18..d0d8a8e9458 100644
--- a/addons/account/account_bank_statement.py
+++ b/addons/account/account_bank_statement.py
@@ -25,6 +25,7 @@ from osv import fields, osv
from tools.misc import currency
from tools.translate import _
+import decimal_precision as dp
class account_bank_statement(osv.osv):
@@ -130,9 +131,9 @@ class account_bank_statement(osv.osv):
states={'confirm': [('readonly', True)]}, domain=[('type', '=', 'cash')]),
'period_id': fields.many2one('account.period', 'Period', required=True,
states={'confirm':[('readonly', True)]}),
- 'balance_start': fields.float('Starting Balance', digits=(16,2),
+ 'balance_start': fields.float('Starting Balance', digits_compute=dp.get_precision('Account'),
states={'confirm':[('readonly',True)]}),
- 'balance_end_real': fields.float('Ending Balance', digits=(16,2),
+ 'balance_end_real': fields.float('Ending Balance', digits_compute=dp.get_precision('Account'),
states={'confirm':[('readonly', True)]}),
'balance_end': fields.function(_end_balance, method=True, string='Balance'),
'line_ids': fields.one2many('account.bank.statement.line',
diff --git a/addons/account/account_cash_statement.py b/addons/account/account_cash_statement.py
index 1a0727e626f..b6c36dd3337 100644
--- a/addons/account/account_cash_statement.py
+++ b/addons/account/account_cash_statement.py
@@ -25,6 +25,7 @@ import time
from mx import DateTime
from decimal import Decimal
from tools.translate import _
+import decimal_precision as dp
class account_cashbox_line(osv.osv):
@@ -55,9 +56,9 @@ class account_cashbox_line(osv.osv):
return {'value':{'subtotal': sub or 0.0}}
_columns = {
- 'pieces': fields.float('Values', digits=(16,2)),
+ 'pieces': fields.float('Values', digits_compute=dp.get_precision('Account')),
'number': fields.integer('Number'),
- 'subtotal': fields.function(_sub_total, method=True, string='Sub Total', type='float',digits=(16,2)),
+ 'subtotal': fields.function(_sub_total, method=True, string='Sub Total', type='float', digits_compute=dp.get_precision('Account')),
'starting_id': fields.many2one('account.bank.statement',ondelete='cascade'),
'ending_id': fields.many2one('account.bank.statement',ondelete='cascade'),
}
@@ -176,7 +177,7 @@ class account_cash_statement(osv.osv):
_columns = {
'company_id':fields.many2one('res.company', 'Company', required=False),
'journal_id': fields.many2one('account.journal', 'Journal', required=True),
- 'balance_end_real': fields.float('Closing Balance', digits=(16,2), states={'confirm':[('readonly', True)]}, help="closing balance entered by the cashbox verifier"),
+ 'balance_end_real': fields.float('Closing Balance', digits_compute=dp.get_precision('Account'), states={'confirm':[('readonly', True)]}, help="closing balance entered by the cashbox verifier"),
'state': fields.selection(
[('draft', 'Draft'),
('confirm', 'Confirm'),
diff --git a/addons/account/account_invoice_view.xml b/addons/account/account_invoice_view.xml
index 6fe0182b584..6e770864799 100644
--- a/addons/account/account_invoice_view.xml
+++ b/addons/account/account_invoice_view.xml
@@ -201,13 +201,13 @@
-
+
+
-
@@ -295,14 +295,14 @@
-
+
+
-
diff --git a/addons/account/account_view.xml b/addons/account/account_view.xml
index 1eb238fa04f..cbcc714ff0f 100644
--- a/addons/account/account_view.xml
+++ b/addons/account/account_view.xml
@@ -196,7 +196,7 @@
-
+
account.account.listaccount.account
@@ -206,6 +206,7 @@
+
@@ -365,7 +366,7 @@
-
+
@@ -1213,13 +1214,13 @@
[('to_check','=',True), ('state','=','draft')]
-
-
-
+
diff --git a/addons/account/board_account_view.xml b/addons/account/board_account_view.xml
index 6738c7a7d37..4cf8cd89ec5 100644
--- a/addons/account/board_account_view.xml
+++ b/addons/account/board_account_view.xml
@@ -27,15 +27,19 @@
form
diff --git a/addons/account/i18n/zh_CN.po b/addons/account/i18n/zh_CN.po
index 58fbb3b1ac4..169283ae387 100644
--- a/addons/account/i18n/zh_CN.po
+++ b/addons/account/i18n/zh_CN.po
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.6\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
-"PO-Revision-Date: 2010-07-13 03:12+0000\n"
+"PO-Revision-Date: 2010-07-16 01:13+0000\n"
"Last-Translator: Black Jack \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"X-Launchpad-Export-Date: 2010-07-14 03:37+0000\n"
+"X-Launchpad-Export-Date: 2010-07-16 03:39+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: account
@@ -1182,7 +1182,7 @@ msgstr "银行收据"
#. module: account
#: view:res.partner:0
msgid "Bank account"
-msgstr "银行账号"
+msgstr "银行帐号"
#. module: account
#: field:account.chart.template,tax_template_ids:0
@@ -4555,7 +4555,7 @@ msgstr "辅助核算项统计"
msgid ""
"This will automatically configure your chart of accounts, bank accounts, "
"taxes and journals according to the selected template"
-msgstr "将根据选择的模板自动设置你的科目一览表、银行帐号、税和记录集合"
+msgstr "将根据选择的模板自动设置你的科目一览表、银行科目、税和记录集合"
#. module: account
#: view:account.bank.statement:0
@@ -5463,7 +5463,7 @@ msgstr "科目.税.模板"
#. module: account
#: field:wizard.multi.charts.accounts,bank_accounts_id:0
msgid "Bank Accounts"
-msgstr "银行帐号"
+msgstr "银行科目"
#. module: account
#: constraint:account.period:0
@@ -5739,7 +5739,7 @@ msgstr "打印记录集合 -"
#: field:account.chart.template,bank_account_view_id:0
#: field:account.invoice,partner_bank:0
msgid "Bank Account"
-msgstr "银行帐号"
+msgstr "银行科目"
#. module: account
#: model:ir.actions.act_window,name:account.action_model_form
diff --git a/addons/account/invoice.py b/addons/account/invoice.py
index e2700a4e4b1..f3b62f0fd27 100644
--- a/addons/account/invoice.py
+++ b/addons/account/invoice.py
@@ -924,12 +924,20 @@ class account_invoice(osv.osv):
move_id = obj_inv.move_id and obj_inv.move_id.id or False
reference = obj_inv.reference
if not number:
- if obj_inv.journal_id.invoice_sequence_id:
- sid = obj_inv.journal_id.invoice_sequence_id.id
- number = self.pool.get('ir.sequence').get_id(cr, uid, sid, 'id', {'fiscalyear_id': obj_inv.period_id.fiscalyear_id.id})
+ tmp_context = {
+ 'fiscalyear_id': inv.period_id.fiscalyear_id.id
+ }
+ if inv.journal_id.invoice_sequence_id:
+ sequence_id = inv.journal_id.invoice_sequence_id.id
+ number = self.pool.get('ir.sequence').get_id(cr, uid,
+ sequence_id,
+ 'id',
+ context=tmp_context)
else:
- number = self.pool.get('ir.sequence').get(cr, uid,
- 'account.invoice.' + invtype)
+ number = self.pool.get('ir.sequence').get_id(cr, uid,
+ 'account.invoice.%s' % invtype,
+ 'code',
+ context=tmp_context)
if invtype in ('in_invoice', 'in_refund'):
ref = reference
else:
diff --git a/addons/account/sequence.py b/addons/account/sequence.py
index c90e9ef93c7..b75e7f3e34e 100644
--- a/addons/account/sequence.py
+++ b/addons/account/sequence.py
@@ -19,19 +19,23 @@
#
##############################################################################
-from osv import fields,osv
+from osv import fields, osv
class ir_sequence_fiscalyear(osv.osv):
_name = 'account.sequence.fiscalyear'
_rec_name = "sequence_main_id"
_columns = {
- "sequence_id": fields.many2one("ir.sequence", 'Sequence', required=True, ondelete='cascade'),
- "sequence_main_id": fields.many2one("ir.sequence", 'Main Sequence', required=True, ondelete='cascade'),
- "fiscalyear_id": fields.many2one('account.fiscalyear', 'Fiscal Year', required=True, ondelete='cascade')
+ "sequence_id": fields.many2one("ir.sequence", 'Sequence', required=True,
+ ondelete='cascade'),
+ "sequence_main_id": fields.many2one("ir.sequence", 'Main Sequence',
+ required=True, ondelete='cascade'),
+ "fiscalyear_id": fields.many2one('account.fiscalyear', 'Fiscal Year',
+ required=True, ondelete='cascade')
}
_sql_constraints = [
- ('main_id', 'CHECK (sequence_main_id != sequence_id)', 'Main Sequence must be different from current !'),
+ ('main_id', 'CHECK (sequence_main_id != sequence_id)',
+ 'Main Sequence must be different from current !'),
]
ir_sequence_fiscalyear()
@@ -39,17 +43,25 @@ ir_sequence_fiscalyear()
class ir_sequence(osv.osv):
_inherit = 'ir.sequence'
_columns = {
- 'fiscal_ids' : fields.one2many('account.sequence.fiscalyear', 'sequence_main_id', 'Sequences')
+ 'fiscal_ids' : fields.one2many('account.sequence.fiscalyear',
+ 'sequence_main_id', 'Sequences')
}
- def get_id(self, cr, uid, sequence_id, test='id', context={}):
- cr.execute('select id from ir_sequence where '+test+'=%s and active=%s', (sequence_id, True,))
+ def get_id(self, cr, uid, sequence_id, test='id', context=None):
+ if context is None:
+ context = {}
+ cr.execute('select id from ir_sequence where '
+ + test + '=%s and active=%s', (sequence_id, True,))
res = cr.dictfetchone()
if res:
- for line in self.browse(cr, uid, res['id'], context=context).fiscal_ids:
- if line.fiscalyear_id.id==context.get('fiscalyear_id', False):
- return super(ir_sequence, self).get_id(cr, uid, line.sequence_id.id, test="id", context=context)
- return super(ir_sequence, self).get_id(cr, uid, sequence_id, test, context)
+ for line in self.browse(cr, uid, res['id'],
+ context=context).fiscal_ids:
+ if line.fiscalyear_id.id == context.get('fiscalyear_id', False):
+ return super(ir_sequence, self).get_id(cr, uid,
+ line.sequence_id.id,
+ test="id",
+ context=context)
+ return super(ir_sequence, self).get_id(cr, uid, sequence_id, test,
+ context=context)
ir_sequence()
-
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/account/sequence_view.xml b/addons/account/sequence_view.xml
index 2d4d159cb41..565725d5d71 100644
--- a/addons/account/sequence_view.xml
+++ b/addons/account/sequence_view.xml
@@ -14,6 +14,10 @@
+
diff --git a/addons/account/test/account_sequence_test.yml b/addons/account/test/account_sequence_test.yml
new file mode 100644
index 00000000000..3be824d2ca0
--- /dev/null
+++ b/addons/account/test/account_sequence_test.yml
@@ -0,0 +1,45 @@
+- In order to test the invoice numbering, I create a sequence for out invoices.
+- !record {model: ir.sequence, id: seq_out_invoice_test}:
+ name: Account Invoice Out for the demonstration Fiscal Year # XXX indicate the name of the fiscal year
+ code: account.invoice.out_invoice
+ padding: 3
+ prefix: FY-
+ suffix: -TEST
+ number_next: 42
+
+- I link the new sequence to the demo sequence and the demo fiscal years.
+- !record {model: account.sequence.fiscalyear, id: seq_out_invoice_test_fy}:
+ sequence_id: seq_out_invoice_test
+ sequence_main_id: seq_out_invoice
+ fiscalyear_id: data_fiscalyear
+
+- I create a draft customer invoice in a period of the demo fiscal year
+- !record {model: account.invoice, id: invoice_seq_test}:
+ account_id: account.a_recv
+ address_contact_id: base.res_partner_address_zen
+ address_invoice_id: base.res_partner_address_zen
+ company_id: base.main_company
+ currency_id: base.EUR
+ invoice_line:
+ - account_id: account.a_sale
+ name: '[PC3] Medium PC'
+ price_unit: 900.0
+ quantity: 10.0
+ product_id: product.product_product_pc3
+ uos_id: product.product_uom_unit
+ journal_id: account.sales_journal
+ partner_id: base.res_partner_3
+ reference_type: none
+ period_id: period_1
+
+- I create the invoice, as is I clicked on the "Create" button
+- !workflow {model: account.invoice, action: invoice_open, ref: invoice_seq_test}
+
+- I check that the invoice state is "Open"
+- !assert {model: account.invoice, id: invoice_seq_test}:
+ - state == 'open'
+
+- I check that the invoice got the right number using our sequence
+ # This used to fail because of bug #602188
+- !assert {model: account.invoice, id: invoice_seq_test}:
+ - number == 'FY-042-TEST'
diff --git a/addons/account/wizard/account_journal_select.py b/addons/account/wizard/account_journal_select.py
index f13958ed90f..e11660a42af 100644
--- a/addons/account/wizard/account_journal_select.py
+++ b/addons/account/wizard/account_journal_select.py
@@ -38,10 +38,11 @@ class account_journal_select(osv.osv_memory):
id = mod_obj.read(cr, uid, [result], ['res_id'])[0]['res_id']
result = act_obj.read(cr, uid, [id])[0]
cr.execute('select journal_id, period_id from account_journal_period where id=%s', (context['active_id'],))
- journal_id, period_id = cr.fetchone()
-
- result['domain'] = str([('journal_id', '=', journal_id), ('period_id', '=', period_id)])
- result['context'] = str({'journal_id': journal_id, 'period_id': period_id})
+ res = cr.fetchone()
+ if res:
+ journal_id, period_id = res
+ result['domain'] = str([('journal_id', '=', journal_id), ('period_id', '=', period_id)])
+ result['context'] = str({'journal_id': journal_id, 'period_id': period_id})
return result
diff --git a/addons/account/wizard/account_pl_report.py b/addons/account/wizard/account_pl_report.py
index f507226fefd..79b701b6fb9 100644
--- a/addons/account/wizard/account_pl_report.py
+++ b/addons/account/wizard/account_pl_report.py
@@ -68,7 +68,7 @@ class account_pl_report(osv.osv_memory):
'fiscalyear' : False,
'display_account': 'bal_all',
'display_type': True,
- }
+ }
def next_view(self, cr, uid, ids, context=None):
obj_model = self.pool.get('ir.model.data')
diff --git a/addons/account/wizard/account_pl_report_view.xml b/addons/account/wizard/account_pl_report_view.xml
index b1104df8d25..47ad83a235e 100644
--- a/addons/account/wizard/account_pl_report_view.xml
+++ b/addons/account/wizard/account_pl_report_view.xml
@@ -55,6 +55,8 @@
form
+
+ crm_lead_forward_to_partner1
+ crm.lead.forward.to.partner
+ form
+
+
+
+
+ Forward to Partnercrm.lead.forward.to.partnerformform
+ new
diff --git a/addons/crm/wizard/crm_lead_to_opportunity.py b/addons/crm/wizard/crm_lead_to_opportunity.py
index 7f47e27a4ff..acb259718f1 100644
--- a/addons/crm/wizard/crm_lead_to_opportunity.py
+++ b/addons/crm/wizard/crm_lead_to_opportunity.py
@@ -126,9 +126,9 @@ class crm_lead2opportunity(osv.osv_memory):
if lead.state in ['done', 'cancel']:
raise osv.except_osv(_("Warning !"), _("Closed/Cancelled \
Leads Could not convert into Opportunity"))
- if lead.state != 'open':
+ if lead.state not in ('open', 'pending'):
raise osv.except_osv(_('Warning !'), _('Lead should be in \
-\'Open\' state before converting to Opportunity.'))
+\'Open\' or \'Pending\' state before converting to Opportunity.'))
return False
def default_get(self, cr, uid, fields, context=None):
@@ -289,9 +289,9 @@ class crm_lead2opportunity_partner(osv.osv_memory):
if lead.state in ['done', 'cancel']:
raise osv.except_osv(_("Warning !"), _("Closed/Cancelled \
Leads Could not convert into Opportunity"))
- if lead.state != 'open':
+ if lead.state not in ('open', 'pending'):
raise osv.except_osv(_('Warning !'), _('Lead should be in \
-\'Open\' state before converting to Opportunity.'))
+\'Open\' or \'Pending\' state before converting to Opportunity.'))
return False
crm_lead2opportunity_partner()
diff --git a/addons/crm/wizard/crm_send_email.py b/addons/crm/wizard/crm_send_email.py
index bc2b5357c15..3f1c1916585 100644
--- a/addons/crm/wizard/crm_send_email.py
+++ b/addons/crm/wizard/crm_send_email.py
@@ -20,11 +20,13 @@
#
##############################################################################
+from crm import crm
from osv import osv, fields
from tools.translate import _
import base64
+import itertools
import tools
-from crm import crm
+import re
class crm_send_new_email_attachment(osv.osv_memory):
_name = 'crm.send.mail.attachment'
@@ -46,32 +48,25 @@ class crm_send_new_email(osv.osv_memory):
'email_to' : fields.char('To', size=512, required=True),
'email_from' : fields.char('From', size=128, required=True),
'reply_to' : fields.char('Reply To', size=128, required=True, help="Reply-to of the Sales team defined on this case"),
- 'email_cc' : fields.char('CC', size=512, help="Carbon Copy: list of recipients that will receive"\
- " a copy of this mail, and future communication related to this case"),
+ 'email_cc' : fields.char('CC', size=512, help="Carbon Copy: list of recipients that will receive a copy of this mail"),
'subject': fields.char('Subject', size=512, required=True),
- 'text': fields.text('Message', required=True),
+ 'body': fields.text('Message Body', required=True),
'state': fields.selection(crm.AVAILABLE_STATES, string='Set New State To', required=True),
'attachment_ids' : fields.one2many('crm.send.mail.attachment', 'wizard_id'),
}
- def action_cancel(self, cr, uid, ids, context=None):
- """ Closes Phonecall to Opportunity form
- """
- return {'type':'ir.actions.act_window_close'}
-
def action_send(self, cr, uid, ids, context=None):
""" This sends an email to ALL the addresses of the selected partners.
"""
-
hist_obj = self.pool.get('mailgate.message')
if not context:
context = {}
- if not context.get('model'):
+ if not context.get('active_model'):
raise osv.except_osv(_('Error'), _('Can not send mail!'))
- model = context.get('model')
+ model = context.get('active_model')
case_pool = self.pool.get(model)
res_id = context and context.get('active_id', False) or False
@@ -83,24 +78,38 @@ class crm_send_new_email(osv.osv_memory):
message_id = None
ref_id = None
- case = case_pool.browse(cr, uid, res_id)
+ case = case_pool.browse(cr, uid, res_id, context=context)
if context.get('mail', 'new') == 'new':
if case.message_ids:
message_id = case.message_ids[0].message_id
+ elif context.get('mail') == 'forward':
+ # extract attachements from case and emails according to mode
+ attachments = []
+ attach_pool = self.pool.get('ir.attachment')
+ direct_attachments = attach_pool.search(cr, uid, [('res_model', '=', 'crm.lead'), ('res_id', '=', res_id)], context=context)
+ attachments += attach_pool.browse(cr, uid, direct_attachments, context=context)
+ if obj.history in ['latest', 'whole'] and case.message_ids:
+ msgs = case.message_ids
+ if obj.history == 'latest':
+ msgs = msgs[:1]
+ attachments.extend(itertools.chain(*[m.attachment_ids for m in msgs]))
+ attach_all = [(a.datas_fname or a.name, base64.decodestring(a.datas)) for a in attachments if a.datas]
+ attach += attach_all
+
else:
- hist = hist_obj.browse(cr, uid, res_id)
+ hist = hist_obj.browse(cr, uid, res_id, context=context)
message_id = hist.message_id
model = hist.model
- model_pool = self.pool.get(model)
+ case_pool = self.pool.get(model)
res_id = hist.res_id
ref_id = hist.ref_id
- case = model_pool.browse(cr, uid, res_id)
+ case = case_pool.browse(cr, uid, res_id, context=context)
emails = [obj.email_to]
- email_cc = obj.email_cc and obj.email_cc.split(',') or ''
+ email_cc = re.findall(r'([^ ,<@]+@[^> ,]+)', obj.email_cc)
emails = filter(None, emails)
- body = obj.text
+ body = obj.body
- body = case_pool.format_body(body)
+ body = body and tools.ustr(body) or ''
email_from = getattr(obj, 'email_from', False)
x_headers = {}
if message_id:
@@ -121,10 +130,11 @@ class crm_send_new_email(osv.osv_memory):
if not flag:
raise osv.except_osv(_('Error!'), _('Unable to send mail. Please check SMTP is configured properly.'))
- case_pool.history(cr, uid, [case], _('Send'), history=True, \
+ msg_dict = {'new': 'Send', 'reply': 'Reply', 'forward': 'Forward'}
+ case_pool.history(cr, uid, [case], _(msg_dict[context.get('mail', 'new')]), history=True, \
email=obj.email_to, details=body, \
subject=obj.subject, email_from=email_from, \
- email_cc=email_cc, message_id=message_id, \
+ email_cc=', '.join(email_cc), message_id=message_id, \
references=ref_id or message_id, attach=attach)
if obj.state == 'unchanged':
pass
@@ -145,7 +155,7 @@ class crm_send_new_email(osv.osv_memory):
if not context:
context = {}
- if not context.get('model'):
+ if not context.get('active_model'):
raise osv.except_osv(_('Error'), _('Can not send mail!'))
res = super(crm_send_new_email, self).default_get(cr, uid, fields, context=context)
@@ -154,7 +164,7 @@ class crm_send_new_email(osv.osv_memory):
res.update(self.get_reply_defaults(cr, uid, fields, context=context))
return res
- model = context.get('model')
+ model = context.get('active_model')
mod_obj = self.pool.get(model)
res_id = context and context.get('active_ids', []) or []
@@ -172,8 +182,8 @@ class crm_send_new_email(osv.osv_memory):
res.update({'subject': tools.ustr(context.get('subject', case.name) or '')})
if 'email_cc' in fields:
res.update({'email_cc': tools.ustr(case.email_cc or '')})
- if 'text' in fields:
- res.update({'text': u'\n'+(tools.ustr(case.user_id.signature or ''))})
+ if 'body' in fields:
+ res.update({'body': u'\n'+(tools.ustr(case.user_id.signature or ''))})
if 'state' in fields:
res.update({'state': u'pending'})
@@ -209,7 +219,7 @@ class crm_send_new_email(osv.osv_memory):
signature = u'\n' + (tools.ustr(case.user_id.signature or '')) + u'\n'
original = [signature]
- if include_original == True and 'text' in fields:
+ if include_original == True and 'body' in fields:
header = u'-------- Original Message --------'
sender = u'From: %s' %(tools.ustr(hist.email_from or ''))
to = u'To: %s' % (tools.ustr(hist.email_to or ''))
@@ -218,10 +228,14 @@ class crm_send_new_email(osv.osv_memory):
original = [signature, header, sender, to, sentdate, desc]
- res['text']= u'\n' + u'\n'.join(original)
+ res['body']= u'\n' + u'\n'.join(original)
if 'subject' in fields:
res.update({u'subject': u'Re: %s' %(tools.ustr(hist.name or ''))})
+ if 'email_cc' in fields:
+ res.update({'email_cc': case.email_cc and tools.ustr(case.email_cc) or False})
+ if 'reply_to' in fields:
+ res.update({'reply_to': case.section_id.reply_to})
if 'state' in fields:
res['state'] = u'pending'
return res
@@ -239,7 +253,7 @@ class crm_send_new_email(osv.osv_memory):
if not context:
context = {}
- if not context.get('model'):
+ if not context.get('active_model'):
raise osv.except_osv(_('Error'), _('Can not send mail!'))
return True
diff --git a/addons/crm/wizard/crm_send_email_view.xml b/addons/crm/wizard/crm_send_email_view.xml
index df7218cbc02..77202a19f6c 100644
--- a/addons/crm/wizard/crm_send_email_view.xml
+++ b/addons/crm/wizard/crm_send_email_view.xml
@@ -9,7 +9,7 @@
crm.send.mailform
-
+
@@ -19,7 +19,7 @@
-
+
@@ -36,7 +36,7 @@
-
+
@@ -46,7 +46,7 @@
- Send New Mail
+ Send Mailcrm.send.mailformform
@@ -77,7 +77,7 @@
-
+
diff --git a/addons/crm_claim/crm_claim.py b/addons/crm_claim/crm_claim.py
index 85dfc8b9dd0..1625cc2ae8b 100644
--- a/addons/crm_claim/crm_claim.py
+++ b/addons/crm_claim/crm_claim.py
@@ -74,7 +74,7 @@ class crm_claim(osv.osv, crm.crm_case):
'partner_address_id': fields.many2one('res.partner.address', 'Partner Contact', \
# domain="[('partner_id','=',partner_id)]"
),
- 'email_cc': fields.text('Watchers Emails', size=252, help="These people will receive a copy of the future communication between partner and users by email"),
+ 'email_cc': fields.text('Watchers Emails', size=252, help="These addresses(Comma-separated) will receive a copy of the future communication between partner and users"),
'email_from': fields.char('Email', size=128, help="These people will receive email."),
'partner_name': fields.char("Employee's Name", size=64),
'partner_mobile': fields.char('Mobile', size=32),
diff --git a/addons/crm_fundraising/crm_fundraising.py b/addons/crm_fundraising/crm_fundraising.py
index 2fd7f4c6f52..1dd6211e915 100644
--- a/addons/crm_fundraising/crm_fundraising.py
+++ b/addons/crm_fundraising/crm_fundraising.py
@@ -46,7 +46,7 @@ class crm_fundraising(osv.osv, crm.crm_case):
'partner_id': fields.many2one('res.partner', 'Partner'),
'partner_address_id': fields.many2one('res.partner.address', 'Partner Contact', \
domain="[('partner_id','=',partner_id)]"),
- 'email_cc': fields.text('Watchers Emails', size=252 , help="These people will receive a copy of the future communication between partner and users by email"),
+ 'email_cc': fields.text('Watchers Emails', size=252 , help="These addresses(Comma-separated) will receive a copy of the future communication between partner and users"),
'email_from': fields.char('Email', size=128, help="These people will receive email."),
'date_closed': fields.datetime('Closed', readonly=True),
'date': fields.datetime('Date'),
diff --git a/addons/crm_helpdesk/crm_helpdesk.py b/addons/crm_helpdesk/crm_helpdesk.py
index 38352691db0..8d9985e5cb1 100644
--- a/addons/crm_helpdesk/crm_helpdesk.py
+++ b/addons/crm_helpdesk/crm_helpdesk.py
@@ -49,9 +49,7 @@ class crm_helpdesk(osv.osv, crm.crm_case):
'partner_id': fields.many2one('res.partner', 'Partner'),
'partner_address_id': fields.many2one('res.partner.address', 'Partner Contact', \
domain="[('partner_id','=',partner_id)]"),
- 'email_cc': fields.text('Watchers Emails', size=252 , help="These people\
- will receive a copy of the future" \
-" communication between partner and users by email"),
+ 'email_cc': fields.text('Watchers Emails', size=252 , help="These addresses(Comma-separated) will receive a copy of the future communication between partner and users"),
'email_from': fields.char('Email', size=128, help="These people will receive email."),
'date': fields.datetime('Date'),
'ref' : fields.reference('Reference', selection=crm._links_get, size=128),
diff --git a/addons/document_ics/document_ics_config_wizard.xml b/addons/document_ics/document_ics_config_wizard.xml
index ea7e5926868..39ec392d3f9 100644
--- a/addons/document_ics/document_ics_config_wizard.xml
+++ b/addons/document_ics/document_ics_config_wizard.xml
@@ -11,12 +11,19 @@
Configure Calendars for CRM Sections
-
-
-
-
+
+ Create Pre-Configured Calendars
+
+
+ OpenERP can create and pre-configure a series of integrated calendar for you.
+ 200
+
+
+ 15
+
+
+
@@ -27,8 +34,6 @@
-
@@ -43,7 +48,7 @@
new
-
+ register configuration wizard
diff --git a/addons/event/__openerp__.py b/addons/event/__openerp__.py
index 634484deecb..452e6577e73 100644
--- a/addons/event/__openerp__.py
+++ b/addons/event/__openerp__.py
@@ -45,6 +45,7 @@
'init_xml': ['event_data.xml'],
'update_xml': [
'wizard/event_confirm_registration_view.xml',
+ 'wizard/event_confirm_view.xml',
'event_view.xml',
'report/report_event_registration_view.xml',
'event_sequence.xml',
diff --git a/addons/event/event.py b/addons/event/event.py
index d7daca5552a..a26960639db 100644
--- a/addons/event/event.py
+++ b/addons/event/event.py
@@ -26,7 +26,7 @@ import netsvc
import pooler
import time
import tools
-
+import decimal_precision as dp
class event_type(osv.osv):
""" Event Type """
@@ -41,16 +41,8 @@ class event_event(osv.osv):
"""Event"""
_name = 'event.event'
_description = __doc__
- _inherit = 'crm.case.section'
_order = 'date_begin'
- def _get_currency(self, cr, uid, context):
- user = self.pool.get('res.users').browse(cr, uid, [uid])[0]
- if user.company_id:
- return user.company_id.currency_id.id
- else:
- return self.pool.get('res.currency').search(cr, uid, [('rate','=',1.0)])[0]
-
def copy(self, cr, uid, id, default=None, context=None):
""" Copy record of Given id
@param id: Id of Event record.
@@ -87,14 +79,9 @@ class event_event(osv.osv):
def button_done(self, cr, uid, ids, context=None):
return self.write(cr, uid, ids, {'state': 'done'}, context=context)
- def button_confirm(self, cr, uid, ids, context=None):
- """This Funtion send reminder who had already confirmed their event registration.
- @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 Event IDs
- @param return: True
- """
+ def do_confirm(self, cr, uid, ids, context=None):
+ """ Confirm Event and send confirmation email to all register peoples
+ """
register_pool = self.pool.get('event.registration')
for event in self.browse(cr, uid, ids, context=context):
if event.mail_auto_confirm:
@@ -106,6 +93,39 @@ class event_event(osv.osv):
return self.write(cr, uid, ids, {'state': 'confirm'})
+ def button_confirm(self, cr, uid, ids, context=None):
+ """This Function Confirm Event.
+ @param ids: List of Event IDs
+ @param context: A standard dictionary for contextual values
+ @return: True
+ """
+ data_pool = self.pool.get('ir.model.data')
+ unconfirmed_ids = []
+ for event in self.browse(cr, uid, ids, context=context):
+ total_confirmed = event.register_current
+ if total_confirmed >= event.register_min or event.register_max == 0:
+ self.do_confirm(cr, uid, [event.id], context=context)
+ else:
+ unconfirmed_ids.append(event.id)
+ if unconfirmed_ids:
+ view_id = data_pool._get_id(cr, uid, 'event', 'view_event_confirm')
+ view_data = data_pool.browse(cr, uid, view_id)
+ view_id = view_data.res_id
+ context['event_ids'] = unconfirmed_ids
+ return {
+ 'name': _('Confirm Event'),
+ 'context': context,
+ 'view_type': 'form',
+ 'view_mode': 'tree,form',
+ 'res_model': 'event.confirm',
+ 'views': [(view_id, 'form')],
+ 'type': 'ir.actions.act_window',
+ 'target': 'new',
+ 'context': context,
+ 'nodestroy': True
+ }
+ return True
+
def _get_register(self, cr, uid, ids, fields, args, context=None):
"""Get Confirm or uncofirm register value.
@@ -122,7 +142,7 @@ class event_event(osv.osv):
res[event.id][field] = False
state = []
if 'register_current' in fields:
- state.append('open')
+ state += ['open', 'done']
if 'register_prospect' in fields:
state.append('draft')
@@ -169,77 +189,134 @@ class event_event(osv.osv):
return res
_columns = {
- 'type': fields.many2one('event.type', 'Type', help="Type of Event like Seminar, Exhibition, Conference, Training."),
- 'register_max': fields.integer('Maximum Registrations', help="Provide Maximun Number of Registrations"),
- 'register_min': fields.integer('Minimum Registrations', help="Providee Minimum Number of Registrations"),
- 'register_current': fields.function(_get_register, method=True, string='Confirmed Registrations', multi='register_current', help="Total of Open Registrations"),
- 'register_prospect': fields.function(_get_register, method=True, string='Unconfirmed Registrations', multi='register_prospect', help="Total of Prospect Registrations"),
- 'date_begin': fields.datetime('Beginning date', required=True, help="Beginning Date of Event"),
- 'date_end': fields.datetime('Closing date', required=True, help="Closing Date of Event"),
- 'state': fields.selection([('draft', 'Draft'), ('confirm', 'Confirmed'), ('done', 'Done'), ('cancel', 'Cancelled')], 'State', readonly=True, required=True, help='If event is created, the state is \'Draft\'.\n If event is confirmed for the particular dates the state is set to \'Confirmed\'.\
- \nIf the event is over, the state is set to \'Done\'.\n If event is cancelled the state is set to \'Cancelled\'.'),
- 'mail_auto_registr': fields.boolean('Mail Auto Register', help='Check this box if you want to use the automatic mailing for new registration'),
- 'mail_auto_confirm': fields.boolean('Mail Auto Confirm', help='Check this box if you want ot use the automatic confirmation emailing or the reminder'),
- 'mail_registr': fields.text('Registration Email', help='This email will be sent when someone subscribes to the event.'),
- 'mail_confirm': fields.text('Confirmation Email', help="This email will be sent when the event gets confimed or when someone subscribes to a confirmed event. This is also the email sent to remind someone about the event."),
- 'product_id': fields.many2one('product.product', 'Product', required=True, help="Product which is provided cost of event. Invoice of event will be created with this Product."),
- 'note': fields.text('Notes', help="Description or Summary of Event"),
- 'currency_id': fields.many2one('res.currency', 'Currency', required=True, readonly=True, states={'draft':[('readonly',False)]}),
- "unit_price": fields.float('Cost'),
- 'main_speaker_id': fields.many2one('res.partner','Main Speaker'),
- 'speaker_ids':fields.many2many('res.partner', 'event_speaker_rel', 'speaker_id', 'partner_id', 'Other Speakers'),
- 'address_id': fields.many2one('res.partner.address','Location Room'),
- 'speaker_confirmed': fields.boolean('Speaker Confirmed'),
+ 'name': fields.char('Name', size=64, required=True, translate=True, readonly=False, states={'done': [('readonly', True)]}),
+ 'user_id': fields.many2one('res.users', 'Responsible User', readonly=False, states={'done': [('readonly', True)]}),
+ 'parent_id': fields.many2one('event.event', 'Parent Event', readonly=False, states={'done': [('readonly', True)]}),
+ 'section_id': fields.many2one('crm.case.section', 'Sale Team', readonly=False, states={'done': [('readonly', True)]}),
+ 'child_ids': fields.one2many('event.event', 'parent_id', 'Child Events', readonly=False, states={'done': [('readonly', True)]}),
+ 'reply_to': fields.char('Reply-To', size=64, readonly=False, states={'done': [('readonly', True)]}, help="The email address put in the 'Reply-To' of all emails sent by Open ERP"),
+ 'type': fields.many2one('event.type', 'Type', help="Type of Event like Seminar, Exhibition, Conference, Training.", readonly=False, states={'done': [('readonly', True)]}),
+ 'register_max': fields.integer('Maximum Registrations', help="Provide Maximun Number of Registrations", readonly=True, states={'draft': [('readonly', False)]}),
+ 'register_min': fields.integer('Minimum Registrations', help="Providee Minimum Number of Registrations", readonly=True, states={'draft': [('readonly', False)]}),
+ 'register_current': fields.function(_get_register, method=True, string='Confirmed Registrations', multi='register_current',
+ help="Total of Open and Done Registrations"),
+ 'register_prospect': fields.function(_get_register, method=True, string='Unconfirmed Registrations', multi='register_prospect',
+ help="Total of Prospect Registrations"),
+ 'registration_ids': fields.one2many('event.registration', 'event_id', 'Registrations', readonly=False, states={'done': [('readonly', True)]}),
+ 'date_begin': fields.datetime('Beginning date', required=True, help="Beginning Date of Event", readonly=True, states={'draft': [('readonly', False)]}),
+ 'date_end': fields.datetime('Closing date', required=True, help="Closing Date of Event", readonly=True, states={'draft': [('readonly', False)]}),
+ 'state': fields.selection([
+ ('draft', 'Draft'),
+ ('confirm', 'Confirmed'),
+ ('done', 'Done'),
+ ('cancel', 'Cancelled')],
+ 'State', readonly=True, required=True,
+ help='If event is created, the state is \'Draft\'.If event is confirmed for the particular dates the state is set to \'Confirmed\'. If the event is over, the state is set to \'Done\'.If event is cancelled the state is set to \'Cancelled\'.'),
+ 'mail_auto_registr': fields.boolean('Mail Auto Register', readonly=False, states={'done': [('readonly', True)]}, help='Check this box if you want to use the automatic mailing for new registration'),
+ 'mail_auto_confirm': fields.boolean('Mail Auto Confirm', readonly=False, states={'done': [('readonly', True)]}, help='Check this box if you want ot use the automatic confirmation emailing or the reminder'),
+ 'mail_registr': fields.text('Registration Email', readonly=False, states={'done': [('readonly', True)]}, help='This email will be sent when someone subscribes to the event.'),
+ 'mail_confirm': fields.text('Confirmation Email', readonly=False, states={'done': [('readonly', True)]}, help="This email will be sent when the event gets confimed or when someone subscribes to a confirmed event. This is also the email sent to remind someone about the event."),
+ 'product_id': fields.many2one('product.product', 'Product', required=True, readonly=True, states={'draft': [('readonly', False)]}, help="Product which is provided cost of event. Invoice of event will be created with this Product."),
+ 'note': fields.text('Notes', help="Description or Summary of Event", readonly=False, states={'done': [('readonly', True)]}),
+ 'pricelist_id': fields.many2one('product.pricelist', 'Pricelist', readonly=True, states={'draft': [('readonly', False)]}, help="Pricelist version for current event."),
+ "unit_price": fields.float('Registration Cost', digits_compute= dp.get_precision('Event Price'), readonly=True, states={'draft': [('readonly', False)]}),
+ 'main_speaker_id': fields.many2one('res.partner','Main Speaker', readonly=False, states={'done': [('readonly', True)]}),
+ 'speaker_ids':fields.many2many('res.partner', 'event_speaker_rel', 'speaker_id', 'partner_id', 'Other Speakers', readonly=False, states={'done': [('readonly', True)]}),
+ 'address_id': fields.many2one('res.partner.address','Location Address', readonly=False, states={'done': [('readonly', True)]}),
+ 'speaker_confirmed': fields.boolean('Speaker Confirmed', readonly=False, states={'done': [('readonly', True)]}),
'country_id': fields.related('address_id', 'country_id',
- type='many2one', relation='res.country', string='Country'),
- 'language': fields.char('Language',size=64),
+ type='many2one', relation='res.country', string='Country', readonly=False, states={'done': [('readonly', True)]}),
+ 'language': fields.char('Language',size=64, readonly=False, states={'done': [('readonly', True)]}),
+ 'note': fields.text('Description', readonly=False, states={'done': [('readonly', True)]}),
+ 'company_id': fields.many2one('res.company', 'Company', required=True, change_default=True, readonly=False, states={'done': [('readonly', True)]}),
}
_defaults = {
'state': 'draft',
- # 'code': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'event.event'),
+ 'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'event.event', context=c),
'user_id': lambda obj, cr, uid, context: uid,
- 'currency_id': _get_currency,
}
+ def _check_recursion(self, cr, uid, ids):
+ """
+ Checks for recursion level for event
+ """
+ level = 100
+
+ while len(ids):
+ cr.execute('select distinct parent_id from event_event where id IN %s', (tuple(ids),))
+ ids = filter(None, map(lambda x: x[0], cr.fetchall()))
+ if not level:
+ return False
+ level -= 1
+
+ return True
+
+ _constraints = [
+ (_check_recursion, 'Error ! You cannot create recursive event.', ['parent_id'])
+ ]
+
+ def do_team_change(self, cr, uid, ids, team_id, context=None):
+ """
+ On Change Callback: when team change, this is call.
+ on this function, take value of reply_to from selected team.
+ """
+ if not team_id:
+ return {}
+ if context is None:
+ context = {}
+ team_pool = self.pool.get('crm.case.section')
+ team = team_pool.browse(cr, uid, team_id, context=context)
+ res = {}
+ if team.reply_to:
+ res = {'value': {'reply_to': team.reply_to}}
+ return res
event_event()
class event_registration(osv.osv):
- """Event Registration"""
-
+ """Event Registration"""
_name= 'event.registration'
_description = __doc__
_inherit = 'crm.meeting'
+ def _amount_line(self, cr, uid, ids, field_name, arg, context=None):
+ cur_obj = self.pool.get('res.currency')
+ res = {}
+ context = context or {}
+ for line in self.browse(cr, uid, ids, context=context):
+ price = line.unit_price * line.nb_register
+ pricelist = line.event_id.pricelist_id or line.partner_invoice_id.property_product_pricelist
+ cur = pricelist and pricelist.currency_id or False
+ res[line.id] = cur and cur_obj.round(cr, uid, cur, price) or price
+ return res
+
_columns = {
- 'email_cc': fields.text('CC', size=252 , help="These \
-people will receive a copy of the future communication between partner \
-and users by email"),
- 'nb_register': fields.integer('Number of Registration', readonly=True, states={'draft': [('readonly', False)]}),
- 'event_id': fields.many2one('event.event', 'Event Related', required=True),
- "partner_invoice_id": fields.many2one('res.partner', 'Partner Invoiced'),
- "contact_id": fields.many2one('res.partner.contact', 'Partner Contact'), #TODO: filter only the contacts that have a function into the selected partner_id
- "unit_price": fields.float('Unit Price'),
- "badge_title": fields.char('Badge Title', size=128),
- "badge_name": fields.char('Badge Name', size=128),
- "badge_partner": fields.char('Badge Partner', size=128),
- "event_product": fields.char("Product Name", size=128, required=True),
- "tobe_invoiced": fields.boolean("To be Invoiced"),
+ 'name': fields.char('Summary', size=124, readonly=True, states={'draft': [('readonly', False)]}),
+ 'email_cc': fields.text('CC', size=252 , readonly=False, states={'done': [('readonly', True)]}, help="These people will receive a copy of the future communication between partner and users by email"),
+ 'nb_register': fields.integer('Quantity', required=True, readonly=True, states={'draft': [('readonly', False)]}, help="Number of Registrations or Tickets"),
+ 'event_id': fields.many2one('event.event', 'Event Related', required=True, readonly=True, states={'draft': [('readonly', False)]}),
+ "partner_invoice_id": fields.many2one('res.partner', 'Partner Invoiced', readonly=True, states={'draft': [('readonly', False)]}),
+ "contact_id": fields.many2one('res.partner.contact', 'Partner Contact', readonly=False, states={'done': [('readonly', True)]}), #TODO: filter only the contacts that have a function into the selected partner_id
+ "unit_price": fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Event Price'), readonly=True, states={'draft': [('readonly', False)]}),
+ 'price_subtotal': fields.function(_amount_line, method=True, string='Subtotal', digits_compute= dp.get_precision('Event Price')),
+ "badge_ids": fields.one2many('event.registration.badge', 'registration_id', 'Badges', readonly=False, states={'done': [('readonly', True)]}),
+ "event_product": fields.char("Invoice Name", size=128, required=True, readonly=True, states={'draft': [('readonly', False)]}),
+ "tobe_invoiced": fields.boolean("To be Invoiced", readonly=True, states={'draft': [('readonly', False)]}),
"invoice_id": fields.many2one("account.invoice", "Invoice", readonly=True),
'date_closed': fields.datetime('Closed', readonly=True),
'ref': fields.reference('Reference', selection=crm._links_get, size=128),
'ref2': fields.reference('Reference 2', selection=crm._links_get, size=128),
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('history', '=', True),('model','=',_name)]),
'log_ids': fields.one2many('mailgate.message', 'res_id', 'Logs', domain=[('history', '=', False),('model','=',_name)]),
- 'currency_id': fields.many2one('res.currency', 'Currency', readonly=True),
+ 'section_id': fields.related('event_id', 'section_id', type='many2one', relation='crm.case.section', string='Sale Team', store=True, readonly=True, states={'draft':[('readonly',False)]}),
+ 'company_id': fields.related('event_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True, states={'draft':[('readonly',False)]}),
}
_defaults = {
'nb_register': 1,
'tobe_invoiced': True,
- 'name': 'Registration',
- # 'currency_id': _get_currency,
+ 'date': time.strftime('%Y-%m-%d %H:%M:%S')
}
def _make_invoice(self, cr, uid, reg, lines, context=None):
@@ -323,16 +400,38 @@ and users by email"),
res = self._make_invoice(cr, uid, val[0][0], [v for k , v in val], context=context)
for k , v in val:
- self.write(cr, uid, [k.id], {'state': 'done', 'invoice_id': res}, context=context)
+ self.do_close(cr, uid, [k.id], context={'invoice_id': res})
else:
for k , v in val:
res = self._make_invoice(cr, uid, k, [v], context=context)
- self.write(cr, uid, [k.id], {'state': 'done', 'invoice_id': res}, context=context)
+ self.do_close(cr, uid, [k.id], context={'invoice_id': res})
if res: new_invoice_ids.append(res)
return new_invoice_ids
+ def do_open(self, cr, uid, ids, context=None):
+ """ Open Registration
+ """
+ res = self.write(cr, uid, ids, {'state': 'open'}, context=context)
+ self.mail_user(cr, uid, ids)
+ self._history(cr, uid, ids, _('Open'))
+ return res
+
+ def do_close(self, cr, uid, ids, context=None):
+ """ Close Registration
+ """
+ if not context:
+ context = {}
+ invoice_id = context.get('invoice_id', False)
+ values = {'state': 'done', 'date_closed': time.strftime('%Y-%m-%d %H:%M:%S')}
+ msg = _('Done')
+ if invoice_id:
+ values['invoice_id'] = invoice_id
+ res = self.write(cr, uid, ids, values)
+ self._history(cr, uid, ids, msg)
+ return res
+
def check_confirm(self, cr, uid, ids, context=None):
"""This Function Open Event Registration and send email to user.
@param ids: List of Event registration's IDs
@@ -344,9 +443,7 @@ and users by email"),
for registration in self.browse(cr, uid, ids, context=context):
total_confirmed = registration.event_id.register_current + registration.nb_register
if total_confirmed <= registration.event_id.register_max or registration.event_id.register_max == 0:
- self.write(cr, uid, [registration.id], {'state': 'open'}, context=context)
- self.mail_user(cr, uid, [registration.id])
- self._history(cr, uid, [registration], _('Open'))
+ self.do_open(cr, uid, [registration.id], context)
else:
unconfirmed_ids.append(registration.id)
if unconfirmed_ids:
@@ -368,12 +465,35 @@ and users by email"),
}
return True
- def button_reg_close(self, cr, uid, ids, *args):
+ def button_reg_close(self, cr, uid, ids, context=None):
"""This Function Close Event Registration.
"""
- registrations = self.browse(cr, uid, ids)
- self._history(cr, uid, registrations, _('Done'))
- self.write(cr, uid, ids, {'state': 'done', 'date_closed': time.strftime('%Y-%m-%d %H:%M:%S')})
+ if not context:
+ context = {}
+ data_pool = self.pool.get('ir.model.data')
+ unclosed_ids = []
+ for registration in self.browse(cr, uid, ids, context=context):
+ if registration.tobe_invoiced and not registration.invoice_id:
+ unclosed_ids.append(registration.id)
+ else:
+ self.do_close(cr, uid, [registration.id])
+ if unclosed_ids:
+ view_id = data_pool._get_id(cr, uid, 'event', 'view_event_make_invoice')
+ view_data = data_pool.browse(cr, uid, view_id)
+ view_id = view_data.res_id
+ context['active_ids'] = unclosed_ids
+ return {
+ 'name': _('Close Registration'),
+ 'context': context,
+ 'view_type': 'form',
+ 'view_mode': 'tree,form',
+ 'res_model': 'event.make.invoice',
+ 'views': [(view_id, 'form')],
+ 'type': 'ir.actions.act_window',
+ 'target': 'new',
+ 'context': context,
+ 'nodestroy': True
+ }
return True
def button_reg_cancel(self, cr, uid, ids, *args):
@@ -391,7 +511,6 @@ and users by email"),
event = event_obj.browse(cr, uid, values['event_id'], context=context)
values['date_deadline']= event.date_begin
values['description']= event.mail_confirm
- values['currency_id'] = event.currency_id.id
res = super(event_registration, self).create(cr, uid, values, context=context)
registrations = self.browse(cr, uid, [res], context=context)
self._history(cr, uid, registrations, _('Created'))
@@ -414,32 +533,35 @@ and users by email"),
if not context:
context = {}
- for reg_id in self.browse(cr, uid, ids):
- src = reg_id.event_id.reply_to or False
- dest = []
- if reg_id.email_from:
- dest += [reg_id.email_from]
- if reg_id.email_cc:
- dest += [reg_id.email_cc]
- if dest and src:
- if confirm:
- tools.email_send(src, dest,
- _('Auto Confirmation: [%s] %s') %(reg_id.id, reg_id.name),
- reg_id.event_id.mail_confirm,
- openobject_id = reg_id.id)
- elif reg_id.event_id.mail_auto_confirm or reg_id.event_id.mail_auto_registr:
- if reg_id.event_id.state in ['draft', 'fixed', 'open', 'confirm', 'running'] and reg_id.event_id.mail_auto_registr:
- tools.email_send(src, dest,
- _('Auto Registration: [%s] %s') %(reg_id.id, reg_id.name),
- reg_id.event_id.mail_registr, openobject_id = reg_id.id)
- if (reg_id.event_id.state in ['confirm', 'running']) and reg_id.event_id.mail_auto_confirm:
- tools.email_send(src, dest,
- _('Auto Confirmation: [%s] %s') %(reg_id.id, reg_id.name),
- reg_id.event_id.mail_confirm, openobject_id = reg_id.id)
-
- if not src:
- raise osv.except_osv(_('Error!'), _('You must define a reply-to address in order to mail the participant. You can do this in the Mailing tab of your event. Note that this is also the place where you can configure your event to not send emails automaticly while registering'))
-
+ for regestration in self.browse(cr, uid, ids, context=context):
+ src = regestration.event_id.reply_to or False
+ email_to = []
+ email_cc = []
+ if regestration.email_from:
+ email_to = regestration.email_from
+ if regestration.email_cc:
+ email_cc += [regestration.email_cc]
+ if not (email_to and email_cc):
+ continue
+ subject = ""
+ body = ""
+ if confirm:
+ subject = _('Auto Confirmation: [%s] %s') %(regestration.id, regestration.name)
+ body = regestration.event_id.mail_confirm
+ elif regestration.event_id.mail_auto_confirm or regestration.event_id.mail_auto_registr:
+ if regestration.event_id.state in ['draft', 'fixed', 'open', 'confirm', 'running'] and regestration.event_id.mail_auto_registr:
+ subject = _('Auto Registration: [%s] %s') %(regestration.id, regestration.name)
+ body = regestration.event_id.mail_registr
+ if (regestration.event_id.state in ['confirm', 'running']) and regestration.event_id.mail_auto_confirm:
+ subject = _('Auto Confirmation: [%s] %s') %(regestration.id, regestration.name)
+ body = regestration.event_id.mail_confirm
+ if subject or body:
+ tools.email_send(src, email_to, subject, body, email_cc = email_cc, openobject_id = regestration.id)
+ self.history(cr, uid, [regestration], subject, history=True, \
+ email=email_to, details=body, \
+ subject=subject, email_from=src, \
+ email_cc=', '.join(email_cc))
+
return True
def mail_user_confirm(self, cr, uid, ids, context=None):
@@ -451,22 +573,7 @@ and users by email"),
def _create_invoice_lines(self, cr, uid, ids, vals):
""" Create account Invoice line for Registration Id.
"""
- return self.pool.get('account.invoice.line').create(cr, uid, vals)
-
- def onchange_badge_name(self, cr, uid, ids, badge_name):
- """This function returns value of Registration Name based on Partner Badge Name.
- @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 Registration IDs
- @param badge_name: Badge Name
- """
-
- data ={}
- if not badge_name:
- return data
- data['name'] = 'Registration: ' + badge_name
- return {'value': data}
+ return self.pool.get('account.invoice.line').create(cr, uid, vals)
def onchange_contact_id(self, cr, uid, ids, contact, partner):
@@ -486,15 +593,11 @@ and users by email"),
job_obj = self.pool.get('res.partner.job')
contact_id = contact_obj.browse(cr, uid, contact)
- data['badge_name'] = contact_id.name
- data['badge_title'] = contact_id.title.name
if partner:
partner_addresses = addr_obj.search(cr, uid, [('partner_id', '=', partner)])
job_ids = job_obj.search(cr, uid, [('contact_id', '=', contact), ('address_id', 'in', partner_addresses)])
if job_ids:
data['email_from'] = job_obj.browse(cr, uid, job_ids[0]).email
- d = self.onchange_badge_name(cr, uid, ids, data['badge_name'])
- data.update(d['value'])
return {'value': data}
def onchange_event(self, cr, uid, ids, event_id, partner_invoice_id):
@@ -515,20 +618,17 @@ and users by email"),
res_obj = self.pool.get('res.partner')
data_event = event_obj.browse(cr, uid, event_id)
- context['currency_id'] = data_event.currency_id.id
+ res = {'value': {'unit_price': False, 'event_product': False, 'user_id': False}}
if data_event.user_id.id:
- return {'value': {'user_id':data_event.user_id.id}}
-
+ res['value'].update({'user_id':data_event.user_id.id})
if data_event.product_id:
- if not partner_invoice_id:
- unit_price=prod_obj.price_get(cr, uid, [data_event.product_id.id], context=context)[data_event.product_id.id]
- return {'value': {'unit_price': unit_price, 'event_product': data_event.product_id.name, 'currency_id': data_event.currency_id.id}}
- data_partner = res_obj.browse(cr, uid, partner_invoice_id)
- context.update({'partner_id': data_partner})
- unit_price = prod_obj._product_price(cr, uid, [data_event.product_id.id], False, False, {'pricelist': data_partner.property_product_pricelist.id})[data_event.product_id.id]
- return {'value': {'unit_price': unit_price, 'event_product': data_event.product_id.name, 'currency_id': data_event.currency_id.id}}
-
- return {'value': {'unit_price': False, 'event_product': False}}
+ pricelist_id = data_event.pricelist_id and data_event.pricelist_id.id or False
+ if partner_invoice_id:
+ partner = res_obj.browse(cr, uid, partner_invoice_id, context=context)
+ pricelist_id = pricelist_id or partner.property_product_pricelist.id
+ unit_price = prod_obj._product_price(cr, uid, [data_event.product_id.id], False, False, {'pricelist': pricelist_id})[data_event.product_id.id]
+ res['value'].update({'unit_price': unit_price, 'event_product': data_event.product_id.name})
+ return res
def onchange_partner_id(self, cr, uid, ids, part, event_id, email=False):
"""This function returns value of Patner Invoice id, Unit Price, badget title based on partner and Event.
@@ -542,8 +642,8 @@ and users by email"),
job_obj = self.pool.get('res.partner.job')
res_obj = self.pool.get('res.partner')
- data={}
- data['badge_partner'] = data['contact_id'] = data['partner_invoice_id'] = data['email_from'] = data['badge_title'] = data['badge_name'] = False
+ data = {}
+ data['contact_id'], data['partner_invoice_id'], data['email_from'] = (False, False, False)
if not part:
return {'value': data}
data['partner_invoice_id']=part
@@ -559,9 +659,7 @@ and users by email"),
data['contact_id'] = job_obj.browse(cr, uid, job_ids[0]).contact_id.id
d = self.onchange_contact_id(cr, uid, ids, data['contact_id'], part)
data.update(d['value'])
- partner_data = res_obj.browse(cr, uid, part)
- data['badge_partner'] = partner_data.name
-
+ partner_data = res_obj.browse(cr, uid, part)
return {'value': data}
def onchange_partner_invoice_id(self, cr, uid, ids, event_id, partner_invoice_id):
@@ -584,17 +682,26 @@ and users by email"),
return {'value': data}
data_event = event_obj.browse(cr, uid, event_id)
if data_event.product_id:
- data['event_product']=data_event.product_id.name
- if not partner_invoice_id:
- data['unit_price']=prod_obj.price_get(cr, uid, [data_event.product_id.id], context=context)[data_event.product_id.id]
- return {'value': data}
- data_partner = res_obj.browse(cr, uid, partner_invoice_id)
- context.update({'partner_id': data_partner})
- data['unit_price'] = prod_obj._product_price(cr, uid, [data_event.product_id.id], False, False, {'pricelist': data_partner.property_product_pricelist.id})[data_event.product_id.id]
- return {'value': data}
+ data['event_product'] = data_event.product_id.name
+ pricelist_id = data_event.pricelist_id and data_event.pricelist_id.id or False
+ if partner_invoice_id:
+ partner = res_obj.browse(cr, uid, partner_invoice_id, context=context)
+ pricelist_id = pricelist_id or partner.property_product_pricelist.id
+ data['unit_price'] = prod_obj._product_price(cr, uid, [data_event.product_id.id], False, False, {'pricelist': pricelist_id})[data_event.product_id.id]
return {'value': data}
event_registration()
+class event_registration_badge(osv.osv):
+ _name = 'event.registration.badge'
+ _description = __doc__
+ _columns = {
+ 'registration_id': fields.many2one('event.registration', 'Registration', required=True),
+ "title": fields.char('Title', size=128),
+ "name": fields.char('Name', size=128, required=True),
+ "address_id": fields.many2one('res.partner.address', 'Address'),
+ }
+event_registration_badge()
+
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/event/event_demo.xml b/addons/event/event_demo.xml
index 88927cd0f25..d390708b58c 100644
--- a/addons/event/event_demo.xml
+++ b/addons/event/event_demo.xml
@@ -55,8 +55,8 @@
Concert of Bon Jovi
- 2008-01-01 19:00:00
- 2008-01-01 23:00:00
+
+ 68.00
@@ -64,33 +64,11 @@
draft
-
Opera of Verdi
- 2008-03-05 18:00:00
- 2008-03-05 21:00:00
+
+ 24.00
@@ -101,8 +79,8 @@
Conference on ERP Buisness
- 2008-09-09 14:00:00
- 2008-09-09 16:30:00
+
+ 15.50
diff --git a/addons/event/event_view.xml b/addons/event/event_view.xml
index 9caaae6e722..f7586c31f1d 100644
--- a/addons/event/event_view.xml
+++ b/addons/event/event_view.xml
@@ -45,31 +45,33 @@
diff --git a/addons/event/security/ir.model.access.csv b/addons/event/security/ir.model.access.csv
index a59748aa534..b8db28fbef2 100644
--- a/addons/event/security/ir.model.access.csv
+++ b/addons/event/security/ir.model.access.csv
@@ -9,3 +9,5 @@
"access_crm_case_section_manager","crm.case.section manager","crm.model_crm_case_section","event.group_event_manager",1,1,1,1
"access_product_product","product.product.product manager","product.model_product_product","event.group_event_manager",1,1,1,1
"access_report_event_registration","report.event.registration","model_report_event_registration","event.group_event_manager",1,1,1,1
+"access_event_registration_badge","event.registration.badge","model_event_registration_badge","event.group_event_subscriber",1,1,1,1
+"access_event_registration_badge","event.registration.badge","model_event_registration_badge","event.group_event_manager",1,1,1,1
diff --git a/addons/event/test/test_event.yml b/addons/event/test/test_event.yml
index 32fe487762d..c3d89ebd5cb 100644
--- a/addons/event/test/test_event.yml
+++ b/addons/event/test/test_event.yml
@@ -54,7 +54,6 @@
we create it with a "Conference on OpenERP Offshore Business" event and provide "Beginning date", "Ending Date" and "Product" as Concert Ticket.
-
!record {model: event.event, id: event_event_conference0}:
- code: C/004
date_begin: '2010-06-07 13:39:00'
date_end: '2010-06-10 13:39:00'
name: Conference on OpenERP Offshore Business.
@@ -94,8 +93,6 @@
I create New Registration for "Conference on OpenERP Offshore Business.
-
!record {model: event.registration, id: event_registration_registrationjacot0}:
- badge_name: Jacot
- badge_partner: Mark Johnson
contact_id: base_contact.res_partner_contact_jacot0
date_deadline: '2010-06-07 13:39:00'
event_id: event.event_event_conference0
@@ -128,8 +125,6 @@
They create New registraion for This event.
-
!record {model: event.registration, id: event_registration_registrationzen0}:
- badge_name: Zen
- badge_partner: China Export
contact_id: base_contact.res_partner_contact_zen0
date_deadline: '2010-06-07 13:39:00'
event_id: event.event_event_conference0
@@ -149,8 +144,6 @@
Third person create New Registration for "Conference on OpenERP Offshore Business" event.
-
!record {model: event.registration, id: event_registration_registrationpassot0}:
- badge_name: Passot
- badge_partner: Mediapole SPRL
contact_id: base_contact.res_partner_contact_passot0
date_deadline: '2010-06-07 13:39:00'
email_from: info@mediapole.net
diff --git a/addons/event/wizard/__init__.py b/addons/event/wizard/__init__.py
index 945e5f84607..fbc44f417f4 100644
--- a/addons/event/wizard/__init__.py
+++ b/addons/event/wizard/__init__.py
@@ -21,5 +21,6 @@
import event_make_invoice
import event_confirm_registration
+import event_confirm
import partner_event_registration
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/event/wizard/event_confirm.py b/addons/event/wizard/event_confirm.py
new file mode 100644
index 00000000000..936d5dc8d72
--- /dev/null
+++ b/addons/event/wizard/event_confirm.py
@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL ().
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+##############################################################################
+
+from osv import fields, osv
+from tools.translate import _
+
+class event_confirm(osv.osv_memory):
+ """
+ Confirm Event
+ """
+ _name = "event.confirm"
+ _description = "Event Confirmation"
+
+ _columns = {
+ 'msg': fields.text('Message', readonly=True),
+ }
+ _defaults = {
+ 'msg': _('Total Registrations of this Event could not reached Minimum Registration Limit. What do you want to do?')
+ }
+
+ def confirm(self, cr, uid, ids, context):
+ event_pool = self.pool.get('event.event')
+ event_ids = context.get('event_ids', [])
+ event_pool.do_confirm(cr, uid, event_ids, context=context)
+ return {}
+
+event_confirm()
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/event/wizard/event_confirm_registration.py b/addons/event/wizard/event_confirm_registration.py
index 0e175979084..f115c630bc4 100644
--- a/addons/event/wizard/event_confirm_registration.py
+++ b/addons/event/wizard/event_confirm_registration.py
@@ -50,8 +50,8 @@ class event_confirm_registration(osv.osv_memory):
register_max = registration.event_id.register_max
if registration.event_id.id not in overlimit_event_ids:
overlimit_event_ids.append(registration.event_id.id)
- msg += _("The Event '%s' is reached Maximum Limit(%s). It has %s Confirmed registration\n") \
- %(registration.event_id.name, register_max, total_confirmed)
+ msg += _("The Event '%s' is reached Maximum Limit(%s).") \
+ %(registration.event_id.name, register_max)
if 'msg' in fields:
res.update({'msg': msg})
@@ -60,10 +60,7 @@ class event_confirm_registration(osv.osv_memory):
def confirm(self, cr, uid, ids, context):
registration_pool = self.pool.get('event.registration')
registration_ids = context.get('registration_ids', [])
- for reg_id in registration_ids:
- registration_pool.write(cr, uid, [reg_id], {'state':'open', })
- registration_pool._history(cr, uid, [reg_id], _('Open'))
- registration_pool.mail_user(cr, uid, [reg_id])
+ registration_pool.do_open(cr, uid, registration_ids, context=context)
return {}
event_confirm_registration()
diff --git a/addons/event/wizard/event_confirm_view.xml b/addons/event/wizard/event_confirm_view.xml
new file mode 100644
index 00000000000..fa3e8e73ef2
--- /dev/null
+++ b/addons/event/wizard/event_confirm_view.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+ Event Confirmation
+ event.confirm
+ form
+
+