[MERGE]:Merge with lp:~openerp-dev/openobject-addons/trunk-dev-addons1
bzr revid: sbh@tinyerp.com-20100609045848-ysb4bhc8l8zd2fjm
This commit is contained in:
commit
64d9c8b104
|
@ -183,7 +183,7 @@ class account_account(osv.osv):
|
|||
temp.append(x)
|
||||
ids2 += self._get_children_and_consol(cr, uid, temp, context)
|
||||
return ids2
|
||||
|
||||
|
||||
def search(self, cr, uid, args, offset=0, limit=None, order=None,
|
||||
context=None, count=False):
|
||||
if context is None:
|
||||
|
@ -320,7 +320,7 @@ class account_account(osv.osv):
|
|||
level = obj.level + 1
|
||||
res[account.id] = level
|
||||
return res
|
||||
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Name', size=128, required=True, select=True),
|
||||
'currency_id': fields.many2one('res.currency', 'Secondary Currency', help="Forces all moves for this account to have this secondary currency."),
|
||||
|
@ -477,7 +477,7 @@ class account_account(osv.osv):
|
|||
def _check_moves(self, cr, uid, ids, method, context):
|
||||
line_obj = self.pool.get('account.move.line')
|
||||
account_ids = self.search(cr, uid, [('id', 'child_of', ids)])
|
||||
|
||||
|
||||
if line_obj.search(cr, uid, [('account_id', 'in', account_ids)]):
|
||||
if method == 'write':
|
||||
raise osv.except_osv(_('Error !'), _('You cannot deactivate an account that contains account moves.'))
|
||||
|
@ -511,7 +511,7 @@ class account_account(osv.osv):
|
|||
context = {}
|
||||
if 'active' in vals and not vals['active']:
|
||||
self._check_moves(cr, uid, ids, "write", context)
|
||||
if 'type' in vals.keys():
|
||||
if 'type' in vals.keys():
|
||||
self._check_allow_type_change(cr, uid, ids, vals['type'], context=context)
|
||||
return super(account_account, self).write(cr, uid, ids, vals, context=context)
|
||||
|
||||
|
@ -559,7 +559,7 @@ class account_journal(osv.osv):
|
|||
_columns = {
|
||||
'name': fields.char('Journal Name', size=64, required=True, translate=True),
|
||||
'code': fields.char('Code', size=16),
|
||||
'type': fields.selection([('sale', 'Sale'), ('purchase', 'Purchase'), ('expanse', 'Expanse'), ('cash', 'Cash'), ('bank', 'Bank'), ('general', 'General'), ('situation', 'Situation')], 'Type', size=32, required=True,
|
||||
'type': fields.selection([('sale', 'Sale'), ('purchase', 'Purchase'), ('expense', 'Expense'), ('cash', 'Cash'), ('bank', 'Bank'), ('general', 'General'), ('situation', 'Situation')], 'Type', size=32, required=True,
|
||||
help="Select 'Sale' for Sale journal to be used at the time of making invoice."\
|
||||
" Select 'Purchase' for Purchase Journal to be used at the time of approving purchase order."\
|
||||
" Select 'Cash' to be used at the time of making payment."\
|
||||
|
@ -683,7 +683,7 @@ class account_fiscalyear(osv.osv):
|
|||
else:
|
||||
return False
|
||||
return ids[0]
|
||||
|
||||
|
||||
def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=80):
|
||||
if args is None:
|
||||
args = []
|
||||
|
@ -695,7 +695,7 @@ class account_fiscalyear(osv.osv):
|
|||
if not ids:
|
||||
ids = self.search(cr, user, [('name',operator,name)]+ args, limit=limit)
|
||||
return self.name_get(cr, user, ids, context=context)
|
||||
|
||||
|
||||
account_fiscalyear()
|
||||
|
||||
class account_period(osv.osv):
|
||||
|
@ -771,7 +771,7 @@ class account_period(osv.osv):
|
|||
cr.execute('update account_journal_period set state=%s where period_id=%s', (mode, id))
|
||||
cr.execute('update account_period set state=%s where id=%s', (mode, id))
|
||||
return True
|
||||
|
||||
|
||||
def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=80):
|
||||
if args is None:
|
||||
args = []
|
||||
|
@ -1375,7 +1375,7 @@ class account_tax_code(osv.osv):
|
|||
return False
|
||||
level -= 1
|
||||
return True
|
||||
|
||||
|
||||
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
if default is None:
|
||||
|
@ -1383,7 +1383,7 @@ class account_tax_code(osv.osv):
|
|||
default = default.copy()
|
||||
default.update({'line_ids': []})
|
||||
return super(account_tax_code, self).copy(cr, uid, id, default, context)
|
||||
|
||||
|
||||
_constraints = [
|
||||
(_check_recursion, 'Error ! You can not create recursive accounts.', ['parent_id'])
|
||||
]
|
||||
|
@ -1441,6 +1441,7 @@ class account_tax(osv.osv):
|
|||
'include_base_amount': fields.boolean('Included in base amount', help="Indicates if the amount of tax must be included in the base amount for the computation of the next taxes"),
|
||||
'company_id': fields.many2one('res.company', 'Company', required=True),
|
||||
'description': fields.char('Tax Code',size=32),
|
||||
'price_include': fields.boolean('Tax Included in Price', help="Check this if the price you use on the product and invoices includes this tax."),
|
||||
'type_tax_use': fields.selection([('sale','Sale'),('purchase','Purchase'),('all','All')], 'Tax Application', required=True)
|
||||
|
||||
}
|
||||
|
@ -1473,6 +1474,7 @@ class account_tax(osv.osv):
|
|||
'applicable_type': lambda *a: 'true',
|
||||
'type': lambda *a: 'percent',
|
||||
'amount': lambda *a: 0,
|
||||
'price_include': lambda *a: 0,
|
||||
'active': lambda *a: 1,
|
||||
'type_tax_use': lambda *a: 'all',
|
||||
'sequence': lambda *a: 1,
|
||||
|
@ -1963,13 +1965,12 @@ class account_add_tmpl_wizard(osv.osv_memory):
|
|||
if not tids or not tids[0]['parent_id']:
|
||||
return False
|
||||
ptids = tmpl_obj.read(cr, uid, [tids[0]['parent_id'][0]],['code'])
|
||||
res = None
|
||||
if not ptids or not ptids[0]['code']:
|
||||
raise osv.except_osv(_('Error !'), _('Cannot locate parent code for template account!'))
|
||||
res = acc_obj.search(cr,uid,[('code','=',ptids[0]['code'])])
|
||||
if res:
|
||||
return res[0]
|
||||
else:
|
||||
return False
|
||||
|
||||
return res and res[0] or False
|
||||
|
||||
_columns = {
|
||||
'cparent_id':fields.many2one('account.account', 'Parent target', help="Creates an account with the selected template under this existing parent.", required=True),
|
||||
|
|
|
@ -530,9 +530,8 @@ class account_move_line(osv.osv):
|
|||
date = datetime.now().strftime('%Y-%m-%d')
|
||||
part = self.pool.get('res.partner').browse(cr, uid, partner_id)
|
||||
|
||||
if part.property_payment_term and part.property_payment_term.line_ids:
|
||||
payterm = part.property_payment_term.line_ids[0]
|
||||
res = self.pool.get('account.payment.term').compute(cr, uid, payterm.id, 100, date)
|
||||
if part.property_payment_term:
|
||||
res = self.pool.get('account.payment.term').compute(cr, uid, part.property_payment_term.id, 100, date)
|
||||
if res:
|
||||
val['date_maturity'] = res[0][0]
|
||||
if not account_id:
|
||||
|
@ -540,10 +539,10 @@ class account_move_line(osv.osv):
|
|||
id2 = part.property_account_receivable.id
|
||||
if journal:
|
||||
jt = self.pool.get('account.journal').browse(cr, uid, journal).type
|
||||
if jt=='sale':
|
||||
if jt == 'sale':
|
||||
val['account_id'] = self.pool.get('account.fiscal.position').map_account(cr, uid, part and part.property_account_position or False, id2)
|
||||
|
||||
elif jt=='purchase':
|
||||
elif jt == 'purchase':
|
||||
val['account_id'] = self.pool.get('account.fiscal.position').map_account(cr, uid, part and part.property_account_position or False, id1)
|
||||
if val.get('account_id', False):
|
||||
d = self.onchange_account_id(cr, uid, ids, val['account_id'])
|
||||
|
|
|
@ -283,32 +283,32 @@
|
|||
<separator string="Journal View" colspan="4"/>
|
||||
<field name="view_id"/>
|
||||
</group>
|
||||
|
||||
|
||||
<group colspan="2" col="2">
|
||||
<separator string="Sequence" colspan="4"/>
|
||||
<field name="sequence_id"/>
|
||||
<field name="invoice_sequence_id"/>
|
||||
</group>
|
||||
|
||||
|
||||
<group colspan="2" col="2">
|
||||
<separator string="Accounts" colspan="4"/>
|
||||
<field name="default_debit_account_id" attrs="{'required':[('type','=','cash')]}" domain="[('type','<>','view'),('type','<>','consolidation')]"/>
|
||||
<field name="default_credit_account_id" attrs="{'required':[('type','=','cash')]}" domain="[('type','<>','view'),('type','<>','consolidation')]"/>
|
||||
</group>
|
||||
|
||||
|
||||
<group colspan="2" col="2">
|
||||
<separator string="Validations" colspan="4"/>
|
||||
<separator string="Validations" colspan="4"/>
|
||||
<field name="allow_date" groups="base.group_extended"/>
|
||||
</group>
|
||||
|
||||
|
||||
<group colspan="2" col="2">
|
||||
<separator string="Company" colspan="4"/>
|
||||
<separator string="Company" colspan="4"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="user_id" groups="base.group_extended"/>
|
||||
<field name="currency"/>
|
||||
</group>
|
||||
<group colspan="2" col="2">
|
||||
<separator string="Other Configuration" colspan="4"/>
|
||||
<separator string="Other Configuration" colspan="4"/>
|
||||
<field name="centralisation"/>
|
||||
<field name="group_invoice_lines"/>
|
||||
<field name="update_posted"/>
|
||||
|
@ -623,6 +623,7 @@
|
|||
<field name="arch" type="xml">
|
||||
<tree string="Account Tax">
|
||||
<field name="name"/>
|
||||
<field name="price_include"/>
|
||||
<field name="description"/>
|
||||
</tree>
|
||||
</field>
|
||||
|
@ -654,6 +655,7 @@
|
|||
<label colspan="2" nolabel="1" string="Keep empty to use the expense account"/>
|
||||
<field groups="base.group_extended" name="child_depend"/>
|
||||
<field groups="base.group_extended" name="sequence"/>
|
||||
<field groups="base.group_extended" name="price_include"/>
|
||||
<field name="type_tax_use"/>
|
||||
<newline/>
|
||||
<field colspan="4" groups="base.group_extended" name="child_ids"/>
|
||||
|
@ -1493,7 +1495,7 @@
|
|||
<act_window domain="[('partner_id', '=', active_id), ('account_id.type', 'in', ['receivable', 'payable']), ('reconcile_id','=',False)]" id="act_account_partner_account_move_unreconciled" name="Unreconciled Receivables & Payables" res_model="account.move.line" src_model="res.partner"/>
|
||||
|
||||
<act_window domain="[('partner_id', '=', active_id), ('account_id.type', 'in', ['receivable', 'payable'])]" id="act_account_partner_account_move_all" name="Receivables & Payables" res_model="account.move.line" src_model="res.partner"/>
|
||||
|
||||
|
||||
<act_window domain="[('partner_id', '=', active_id)]" id="act_account_partner_account_move" name="All Account Entries" res_model="account.move.line" src_model="res.partner"/>
|
||||
|
||||
<record id="view_account_addtmpl_wizard_form" model="ir.ui.view">
|
||||
|
|
|
@ -7,30 +7,30 @@ msgstr ""
|
|||
"Project-Id-Version: OpenERP Server 5.0.0\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
|
||||
"PO-Revision-Date: 2009-04-24 15:00+0000\n"
|
||||
"Last-Translator: Fabien (Open ERP) <fp@tinyerp.com>\n"
|
||||
"PO-Revision-Date: 2010-06-02 08:19+0000\n"
|
||||
"Last-Translator: jan@synkronized.be <Unknown>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2010-04-17 04:08+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-06-03 03:33+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. module: account
|
||||
#: field:account.tax.template,description:0
|
||||
msgid "Internal Name"
|
||||
msgstr ""
|
||||
msgstr "Interne naam"
|
||||
|
||||
#. module: account
|
||||
#: view:account.tax.code:0
|
||||
msgid "Account Tax Code"
|
||||
msgstr ""
|
||||
msgstr "Belasting code"
|
||||
|
||||
#. module: account
|
||||
#: model:ir.actions.act_window,name:account.action_invoice_tree9
|
||||
#: model:ir.ui.menu,name:account.menu_action_invoice_tree9
|
||||
msgid "Unpaid Supplier Invoices"
|
||||
msgstr ""
|
||||
msgstr "Onbetaalde inkoopfacturen"
|
||||
|
||||
#. module: account
|
||||
#: model:ir.ui.menu,name:account.menu_finance_entries
|
||||
|
@ -50,12 +50,12 @@ msgstr ""
|
|||
#. module: account
|
||||
#: model:account.account.type,name:account.account_type_asset
|
||||
msgid "Asset"
|
||||
msgstr ""
|
||||
msgstr "Activa"
|
||||
|
||||
#. module: account
|
||||
#: constraint:ir.actions.act_window:0
|
||||
msgid "Invalid model name in the action definition."
|
||||
msgstr ""
|
||||
msgstr "Ongeldige modelnaam in de actie-definitie."
|
||||
|
||||
#. module: account
|
||||
#: help:account.journal,currency:0
|
||||
|
@ -65,7 +65,7 @@ msgstr ""
|
|||
#. module: account
|
||||
#: wizard_view:account_use_models,init_form:0
|
||||
msgid "Select Message"
|
||||
msgstr ""
|
||||
msgstr "Kies bericht"
|
||||
|
||||
#. module: account
|
||||
#: help:product.category,property_account_income_categ:0
|
||||
|
@ -82,19 +82,19 @@ msgstr ""
|
|||
#. module: account
|
||||
#: wizard_view:account.automatic.reconcile,reconcile:0
|
||||
msgid "Reconciliation result"
|
||||
msgstr ""
|
||||
msgstr "Afletterresultaat"
|
||||
|
||||
#. module: account
|
||||
#: model:ir.actions.act_window,name:account.act_account_acount_move_line_open_unreconciled
|
||||
msgid "Unreconciled entries"
|
||||
msgstr ""
|
||||
msgstr "Niet afgeletterde boekingen"
|
||||
|
||||
#. module: account
|
||||
#: field:account.invoice.tax,base_code_id:0
|
||||
#: field:account.tax,base_code_id:0
|
||||
#: field:account.tax.template,base_code_id:0
|
||||
msgid "Base Code"
|
||||
msgstr ""
|
||||
msgstr "Basiscode"
|
||||
|
||||
#. module: account
|
||||
#: view:account.account:0
|
||||
|
@ -2132,7 +2132,8 @@ msgid "Analytic Entry"
|
|||
msgstr ""
|
||||
|
||||
#. module: account
|
||||
#: view:res.company:0 field:res.company,overdue_msg:0
|
||||
#: view:res.company:0
|
||||
#: field:res.company,overdue_msg:0
|
||||
msgid "Overdue Payments Message"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -951,23 +951,8 @@ class account_invoice(osv.osv):
|
|||
return taxes.values()
|
||||
|
||||
def _log_event(self, cr, uid, ids, factor=1.0, name='Open Invoice'):
|
||||
invs = self.read(cr, uid, ids, ['type','partner_id','amount_untaxed'])
|
||||
for inv in invs:
|
||||
part=inv['partner_id'] and inv['partner_id'][0]
|
||||
pc = pr = 0.0
|
||||
cr.execute('select sum(quantity*price_unit) from account_invoice_line where invoice_id=%s', (inv['id'],))
|
||||
total = inv['amount_untaxed']
|
||||
if inv['type'] in ('in_invoice','in_refund'):
|
||||
partnertype='supplier'
|
||||
eventtype = 'purchase'
|
||||
pc = total*factor
|
||||
else:
|
||||
partnertype = 'customer'
|
||||
eventtype = 'sale'
|
||||
pr = total*factor
|
||||
if self.pool.get('res.partner.event.type').check(cr, uid, 'invoice_open'):
|
||||
self.pool.get('res.partner.event').create(cr, uid, {'name':'Invoice: '+name, 'som':False, 'description':name+' '+str(inv['id']), 'document':name, 'partner_id':part, 'date':time.strftime('%Y-%m-%d %H:%M:%S'), 'canal_id':False, 'user_id':uid, 'partner_type':partnertype, 'probability':1.0, 'planned_revenue':pr, 'planned_cost':pc, 'type':eventtype})
|
||||
return len(invs)
|
||||
#TODO: implement messages system
|
||||
return True
|
||||
|
||||
def name_get(self, cr, uid, ids, context=None):
|
||||
if not len(ids):
|
||||
|
|
|
@ -74,13 +74,13 @@
|
|||
<page string="Accounting" position="inside">
|
||||
<group col="2" colspan="2">
|
||||
<separator string="Customer Accounting Properties" colspan="2"/>
|
||||
<field name="property_account_receivable" />
|
||||
<field name="property_account_receivable" groups="account.group_account_user" />
|
||||
<field name="property_account_position" widget="selection"/>
|
||||
<field name="property_payment_term" widget="selection"/>
|
||||
</group>
|
||||
<group col="2" colspan="2">
|
||||
<separator string="Supplier Accounting Properties" colspan="2"/>
|
||||
<field name="property_account_payable"/>
|
||||
<field name="property_account_payable" groups="account.group_account_user"/>
|
||||
</group>
|
||||
<group col="2" colspan="2">
|
||||
<separator string="Customer Credit" colspan="2"/>
|
||||
|
@ -132,11 +132,13 @@
|
|||
<field name="type">form</field>
|
||||
<field name="inherit_id" ref="base.view_partner_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<notebook position="inside">
|
||||
<page string="Project">
|
||||
<field name="contract_ids" colspan="4" nolabel="1" />
|
||||
</page>
|
||||
</notebook>
|
||||
<xpath expr="//notebook[last()]" position="after">
|
||||
<notebook colspan="4">
|
||||
<page string="Project">
|
||||
<field name="contract_ids" colspan="4" nolabel="1" />
|
||||
</page>
|
||||
</notebook>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
|
|
@ -22,9 +22,15 @@
|
|||
import xml
|
||||
import copy
|
||||
from operator import itemgetter
|
||||
import time
|
||||
import datetime
|
||||
from report import report_sxw
|
||||
import xml.dom.minidom
|
||||
import os, time
|
||||
import osv
|
||||
import re
|
||||
import tools
|
||||
import pooler
|
||||
import sys
|
||||
|
||||
class account_balance(report_sxw.rml_parse):
|
||||
_name = 'report.account.account.balance'
|
||||
|
@ -44,6 +50,10 @@ class account_balance(report_sxw.rml_parse):
|
|||
})
|
||||
self.context = context
|
||||
|
||||
def _add_header(self, node, header=1):
|
||||
if header==0:
|
||||
self.rml_header = ""
|
||||
return True
|
||||
def get_fiscalyear(self, form):
|
||||
res=[]
|
||||
if form.has_key('fiscalyear'):
|
||||
|
@ -56,16 +66,14 @@ class account_balance(report_sxw.rml_parse):
|
|||
|
||||
def get_periods(self, form):
|
||||
result=''
|
||||
if form.has_key('periods') and form['periods'][0][2]:
|
||||
period_ids = form['periods'][0][2]
|
||||
self.cr.execute("select name from account_period where id =ANY(%s)" ,(period_ids))
|
||||
res = self.cr.fetchall()
|
||||
len_res = len(res)
|
||||
for r in res:
|
||||
if (r == res[len_res-1]):
|
||||
result+=r[0]+". "
|
||||
if form.has_key('periods') and form['periods']:
|
||||
period_ids = form['periods']
|
||||
per_ids = self.pool.get('account.period').browse(self.cr,self.uid,form['periods'])
|
||||
for r in per_ids:
|
||||
if r == per_ids[len(per_ids)-1]:
|
||||
result+=r.name+". "
|
||||
else:
|
||||
result+=r[0]+", "
|
||||
result+=r.name+", "
|
||||
else:
|
||||
fy_obj = self.pool.get('account.fiscalyear').browse(self.cr,self.uid,form['fiscalyear'])
|
||||
res = fy_obj.period_ids
|
||||
|
@ -172,5 +180,8 @@ class account_balance(report_sxw.rml_parse):
|
|||
def _sum_debit(self):
|
||||
return self.sum_debit
|
||||
|
||||
report_sxw.report_sxw('report.account.account.balance', 'account.account', 'addons/account/report/account_balance.rml', parser=account_balance, header=False)
|
||||
|
||||
|
||||
|
||||
report_sxw.report_sxw('report.account.account.balance', 'account.account', 'addons/account/report/account_balance.rml', parser=account_balance, header=0)
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -66,6 +66,27 @@
|
|||
<blockAlignment value="LEFT"/>
|
||||
<blockValign value="TOP"/>
|
||||
</blockTableStyle>
|
||||
<blockTableStyle id="Table3a">
|
||||
<blockAlignment value="LEFT"/>
|
||||
<blockValign value="TOP"/>
|
||||
<lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="0,0" stop="0,-1"/>
|
||||
<lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="0,0" stop="0,0"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,-1" stop="0,-1"/>
|
||||
<lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="1,0" stop="1,-1"/>
|
||||
<lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="1,0" stop="1,0"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="1,-1" stop="1,-1"/>
|
||||
<lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="2,0" stop="2,-1"/>
|
||||
<lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="2,0" stop="2,0"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="2,-1" stop="2,-1"/>
|
||||
<lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="3,0" stop="3,-1"/>
|
||||
<lineStyle kind="LINEAFTER" colorName="#e6e6e6" start="3,0" stop="3,-1"/>
|
||||
<lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="3,0" stop="3,0"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="3,-1" stop="3,-1"/>
|
||||
<lineStyle kind="LINEAFTER" colorName="#e6e6e6" start="4,0" stop="4,-1"/>
|
||||
<lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="4,0" stop="4,0"/>
|
||||
<lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="4,-1" stop="4,-1"/>
|
||||
</blockTableStyle>
|
||||
|
||||
<blockTableStyle id="Table4">
|
||||
<blockAlignment value="LEFT"/>
|
||||
<blockValign value="TOP"/>
|
||||
|
@ -95,6 +116,8 @@
|
|||
<paraStyle name="P9b" fontName="Helvetica" fontSize="9" leftIndent="0.0" alignment="LEFT"/>
|
||||
<paraStyle name="P9b" fontName="Helvetica" fontSize="8" leftIndent="-5.0" alignment="LEFT"/>
|
||||
<paraStyle name="P12" fontName="Helvetica-Bold" fontSize="8.0" leading="14" alignment="CENTER" spaceBefore="0.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="terp_default_Centre_8" fontName="Helvetica" fontSize="8.0" leading="10" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/>
|
||||
<paraStyle name="terp_tblheader_General_Centre" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="CENTER" spaceBefore="6.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="P12a" fontName="Helvetica-Bold" fontSize="8.0" leading="14" alignment="LEFT" spaceBefore="0.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="P12b" fontName="Helvetica-Bold" fontSize="8.0" leading="14" alignment="CENTER" spaceBefore="0.0" spaceAfter="6.0"/>
|
||||
<paraStyle name="P14" rightIndent="17.0" leftIndent="-0.0" fontName="Helvetica-Bold" fontSize="8.0" leading="10" spaceBefore="0.0" spaceAfter="6.0"/>
|
||||
|
@ -141,14 +164,46 @@
|
|||
<para style="P2">
|
||||
<font color="white"> </font>
|
||||
</para>
|
||||
<blockTable colWidths="527.00" style="Table4" repeatRows="1">
|
||||
|
||||
<blockTable colWidths="78.0,108.0,108.0,108.0,138" style="Table3a">
|
||||
<tr>
|
||||
<td>
|
||||
<para style="P9a">[[ get_fiscalyear(data['form']) or removeParentNode('para') ]]:</para>
|
||||
<para style="P9b"><i> [[ get_periods(data['form']) or removeParentNode('para') ]]</i></para>
|
||||
<para style="terp_tblheader_General_Centre">Fiscal Year</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="terp_tblheader_General_Centre">End Date</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="terp_tblheader_General_Centre">Start Date</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="terp_tblheader_General_Centre">Display Account</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="terp_tblheader_General_Centre">Periods</para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
</blockTable>
|
||||
<blockTable colWidths="78.0,108.0,108.0,108.0,138" style="Table3a">
|
||||
<tr>
|
||||
<td>
|
||||
<para style="terp_default_Centre_8">[[ get_fiscalyear(data['form']) ]]</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="terp_default_Centre_8">[[ data['form']['date_from'] ]]</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="terp_default_Centre_8">[[ data['form']['date_to'] ]]</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="terp_default_Centre_8">[[ (data['form']['display_account']=='bal_all' and 'All') or (data['form']['display_account']=='bal_mouvement' and 'With movements') or 'With balance is not equal to 0']]</para>
|
||||
</td>
|
||||
<td>
|
||||
<para style="terp_default_Centre_8"> [[data['form']['periods'] and get_periods(data['form']) or '']]</para>
|
||||
</td>
|
||||
</tr>
|
||||
</blockTable>
|
||||
|
||||
|
||||
<para style="P2">
|
||||
<font color="white"> </font>
|
||||
|
|
|
@ -153,14 +153,11 @@ class rml_parse(report_sxw.rml_parse):
|
|||
return Stringer
|
||||
|
||||
def _add_header(self, node, header=1):
|
||||
if self.name == 'account.account.balance.landscape':
|
||||
if header==2:
|
||||
rml_head = self.rml_header2
|
||||
else:
|
||||
rml_head = self.rml_header
|
||||
rml_head = rml_head.replace('<pageGraphics>','''<pageGraphics> <image x="10" y="26cm" height="770.0" width="1120.0" >[[company.logo]] </image> ''')
|
||||
if header==2:
|
||||
rml_head = self.rml_header2
|
||||
else:
|
||||
return super(rml_parse, self)._add_header(node, header)
|
||||
rml_head = self.rml_header
|
||||
rml_head = rml_head.replace('<pageGraphics>','''<pageGraphics> <image x="10" y="26cm" height="770.0" width="1120.0" >[[company.logo]] </image> ''')
|
||||
return True
|
||||
|
||||
# def _add_header(self, node):
|
||||
|
|
|
@ -1,166 +0,0 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2008 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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from report import report_sxw
|
||||
import xml.dom.minidom
|
||||
import os, time
|
||||
import osv
|
||||
import re
|
||||
import tools
|
||||
import pooler
|
||||
import re
|
||||
import sys
|
||||
|
||||
class rml_parse(report_sxw.rml_parse):
|
||||
def __init__(self, cr, uid, name, context):
|
||||
super(rml_parse, self).__init__(cr, uid, name, context=None)
|
||||
self.localcontext.update({
|
||||
'comma_me': self.comma_me,
|
||||
'format_date': self._get_and_change_date_format_for_swiss,
|
||||
'strip_name' : self._strip_name,
|
||||
'explode_name' : self._explode_name,
|
||||
})
|
||||
|
||||
def comma_me(self,amount):
|
||||
#print "#" + str(amount) + "#"
|
||||
if not amount:
|
||||
amount = 0.0
|
||||
if type(amount) is float :
|
||||
amount = str('%.2f'%amount)
|
||||
else :
|
||||
amount = str(amount)
|
||||
if (amount == '0'):
|
||||
return ' '
|
||||
orig = amount
|
||||
new = re.sub("^(-?\d+)(\d{3})", "\g<1>'\g<2>", amount)
|
||||
if orig == new:
|
||||
return new
|
||||
else:
|
||||
return self.comma_me(new)
|
||||
|
||||
def _ellipsis(self, string, maxlen=100, ellipsis = '...'):
|
||||
ellipsis = ellipsis or ''
|
||||
try:
|
||||
return string[:maxlen - len(ellipsis) ] + (ellipsis, '')[len(string) < maxlen]
|
||||
except Exception, e:
|
||||
return False
|
||||
|
||||
def _strip_name(self, name, maxlen=50):
|
||||
return self._ellipsis(name, maxlen, '...')
|
||||
|
||||
def _get_and_change_date_format_for_swiss (self,date_to_format):
|
||||
date_formatted=''
|
||||
if date_to_format:
|
||||
date_formatted = strptime (date_to_format,'%Y-%m-%d').strftime('%d.%m.%Y')
|
||||
return date_formatted
|
||||
|
||||
def _explode_name(self,chaine,length):
|
||||
# We will test if the size is less then account
|
||||
full_string = ''
|
||||
if (len(str(chaine)) <= length):
|
||||
return chaine
|
||||
#
|
||||
else:
|
||||
chaine = unicode(chaine,'utf8').encode('iso-8859-1')
|
||||
rup = 0
|
||||
for carac in chaine:
|
||||
rup = rup + 1
|
||||
if rup == length:
|
||||
full_string = full_string + '\n'
|
||||
full_string = full_string + carac
|
||||
rup = 0
|
||||
else:
|
||||
full_string = full_string + carac
|
||||
|
||||
return full_string
|
||||
|
||||
def makeAscii(self,str):
|
||||
try:
|
||||
Stringer = str.encode("utf-8")
|
||||
except UnicodeDecodeError:
|
||||
try:
|
||||
Stringer = str.encode("utf-16")
|
||||
except UnicodeDecodeError:
|
||||
print "UTF_16 Error"
|
||||
Stringer = str
|
||||
else:
|
||||
return Stringer
|
||||
else:
|
||||
return Stringer
|
||||
return Stringer
|
||||
|
||||
def explode_this(self,chaine,length):
|
||||
#chaine = self.repair_string(chaine)
|
||||
chaine = rstrip(chaine)
|
||||
ast = list(chaine)
|
||||
i = length
|
||||
while i <= len(ast):
|
||||
ast.insert(i,'\n')
|
||||
i = i + length
|
||||
chaine = str("".join(ast))
|
||||
return chaine
|
||||
|
||||
def repair_string(self,chaine):
|
||||
ast = list(chaine)
|
||||
UnicodeAst = []
|
||||
_previouslyfound = False
|
||||
i = 0
|
||||
#print str(ast)
|
||||
while i < len(ast):
|
||||
elem = ast[i]
|
||||
try:
|
||||
Stringer = elem.encode("utf-8")
|
||||
except UnicodeDecodeError:
|
||||
to_reencode = elem + ast[i+1]
|
||||
print str(to_reencode)
|
||||
Good_char = to_reencode.decode('utf-8')
|
||||
UnicodeAst.append(Good_char)
|
||||
i += i +2
|
||||
else:
|
||||
UnicodeAst.append(elem)
|
||||
i += i + 1
|
||||
return "".join(UnicodeAst)
|
||||
|
||||
def ReencodeAscii(self,str):
|
||||
print sys.stdin.encoding
|
||||
try:
|
||||
Stringer = str.decode("ascii")
|
||||
except UnicodeEncodeError:
|
||||
print "REENCODING ERROR"
|
||||
return str.encode("ascii")
|
||||
except UnicodeDecodeError:
|
||||
print "DECODING ERROR"
|
||||
return str.encode("ascii")
|
||||
else:
|
||||
print Stringer
|
||||
return Stringer
|
||||
|
||||
def _add_header(self, node, header=1):
|
||||
if header==2:
|
||||
rml_head = self.rml_header2
|
||||
else:
|
||||
rml_head = self.rml_header
|
||||
rml_head = rml_head.replace('<pageGraphics>','''<pageGraphics> <image x="10" y="26cm" height="770.0" width="1120.0" >[[company.logo]] </image> ''')
|
||||
return True
|
||||
|
||||
|
||||
|
|
@ -30,15 +30,6 @@
|
|||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
<!-- <record model="ir.values" id="account_change_currency">
|
||||
<field name="model_id" ref="account.model_account_invoice" />
|
||||
<field name="object" eval="1" />
|
||||
<field name="name">Change Currency</field>
|
||||
<field name="key2">client_action_multi</field>
|
||||
<field name="value" eval="'ir.actions.act_window,' + str(ref('action_account_change_currency'))"/>
|
||||
<field name="key">action</field>
|
||||
<field name="model">account.invoice</field>
|
||||
</record>-->
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
</openerp>
|
||||
|
|
|
@ -37,10 +37,6 @@
|
|||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
<!-- <act_window id="action_account_invoice_refund"
|
||||
key2 = "client_action_multi" name="Credit Note"
|
||||
res_model="account.invoice.refund" src_model="account.invoice"
|
||||
view_mode="form" target="new" view_type="form" /> -->
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
</openerp>
|
||||
|
|
|
@ -58,7 +58,7 @@ class account_invoice_pay(osv.osv_memory):
|
|||
'amount': fields.float('Amount paid', required=True, digits_compute = dp.get_precision('Account')),
|
||||
'name': fields.char('Entry Name', size=64, required=True),
|
||||
'date': fields.date('Date payment', required=True),
|
||||
'journal_id': fields.many2one('account.journal', 'Journal/Payment Mode', required=True),
|
||||
'journal_id': fields.many2one('account.journal', 'Journal/Payment Mode', required=True, domain=[('type','=','cash')]),
|
||||
'period_id': fields.many2one('account.period', 'Period', required=True),
|
||||
}
|
||||
|
||||
|
@ -188,4 +188,4 @@ class account_invoice_pay(osv.osv_memory):
|
|||
|
||||
account_invoice_pay()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -37,14 +37,6 @@
|
|||
</record>
|
||||
|
||||
|
||||
<!-- <act_window name="Pay Invoice"
|
||||
res_model="account.invoice.pay"
|
||||
src_model="account.invoice"
|
||||
view_mode="form"
|
||||
target="new"
|
||||
key2="client_action_multi"
|
||||
id="action_view_account_invoice_pay"/> -->
|
||||
|
||||
<record id="view_account_invoice_pay_writeoff" model="ir.ui.view">
|
||||
<field name="name">account.invoice.pay.writeoff.form</field>
|
||||
<field name="model">account.invoice.pay.writeoff</field>
|
||||
|
@ -70,4 +62,4 @@
|
|||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
</openerp>
|
||||
|
|
|
@ -7,13 +7,13 @@ msgstr ""
|
|||
"Project-Id-Version: OpenERP Server 5.0.0\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
|
||||
"PO-Revision-Date: 2009-11-28 23:14+0000\n"
|
||||
"Last-Translator: Paulino <Unknown>\n"
|
||||
"PO-Revision-Date: 2010-06-01 10:22+0000\n"
|
||||
"Last-Translator: cmsa <Unknown>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2010-04-17 04:11+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-06-02 03:33+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
|
@ -38,12 +38,12 @@ msgstr "Data da última factura"
|
|||
#: help:account.analytic.account,remaining_ca:0
|
||||
msgid "Computed using the formula: Max Invoice Price - Invoiced Amount."
|
||||
msgstr ""
|
||||
"Processado usando a formula: Preço máximo da factura - Montante facturado"
|
||||
"Processado usando a fórmula: Preço Máximo da Factura - Montante Facturado"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: help:account.analytic.account,remaining_hours:0
|
||||
msgid "Computed using the formula: Maximum Quantity - Hours Tot."
|
||||
msgstr "Processado usando a formula: Quantidade máxima - Horas totais."
|
||||
msgstr "Processado usando a fórmula: Quantidade Máxima - Horas Totais."
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: model:ir.ui.menu,name:account_analytic_analysis.menu_action_account_analytic_all
|
||||
|
@ -54,32 +54,32 @@ msgstr "Todas as contas de contabilidade analítica"
|
|||
#: model:ir.actions.act_window,name:account_analytic_analysis.action_account_analytic_managed_open
|
||||
#: model:ir.ui.menu,name:account_analytic_analysis.menu_analytic_account_to_valid_open
|
||||
msgid "My Current Accounts"
|
||||
msgstr "Minhas contas correntes"
|
||||
msgstr "As minhas contas correntes"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: constraint:ir.ui.view:0
|
||||
msgid "Invalid XML for View Architecture!"
|
||||
msgstr "XML inválido para a arquitectura de vista"
|
||||
msgstr "XML inválido para a arquitectura de vista!"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: help:account.analytic.account,last_invoice_date:0
|
||||
msgid "Date of the last invoice created for this analytic account."
|
||||
msgstr "Data da última factura criada por esta conta analítica."
|
||||
msgstr "Data da última factura criada para esta conta analítica."
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: field:account.analytic.account,ca_theorical:0
|
||||
msgid "Theorical Revenue"
|
||||
msgstr "Rendimento teórico"
|
||||
msgstr "Rendimento Teórico"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: constraint:ir.actions.act_window:0
|
||||
msgid "Invalid model name in the action definition."
|
||||
msgstr "Nome de modelo invalido na definição da acção"
|
||||
msgstr "Nome de modelo inválido na definição da acção."
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: help:account.analytic.account,theorical_margin:0
|
||||
msgid "Computed using the formula: Theorial Revenue - Total Costs"
|
||||
msgstr "Processado usando a formula: Rendimento teórico - Custo total"
|
||||
msgstr "Processado usando a fórmula: Rendimento Teórico - Custo Total"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: constraint:ir.model:0
|
||||
|
@ -113,7 +113,7 @@ msgstr "Conta analíticas correntes"
|
|||
#. module: account_analytic_analysis
|
||||
#: help:account.analytic.account,last_worked_date:0
|
||||
msgid "Date of the latest work done on this account."
|
||||
msgstr "Data do ultimo trabalho feito nesta conta"
|
||||
msgstr "Data do último trabalho feito nesta conta"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: help:account.analytic.account,last_worked_invoiced_date:0
|
||||
|
@ -121,8 +121,8 @@ msgid ""
|
|||
"If invoice from the costs, this is the date of the latest work or cost that "
|
||||
"have been invoiced."
|
||||
msgstr ""
|
||||
"Se facturado dos custos, esta é a data do ultimo trabalho ou custo que foi "
|
||||
"facturado."
|
||||
"Se facturado sobre os custos, esta é a data do ultimo trabalho ou custo que "
|
||||
"foi facturado."
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: model:ir.ui.menu,name:account_analytic_analysis.menu_invoicing
|
||||
|
@ -137,7 +137,7 @@ msgstr "Data do ultimo custo/trabalho"
|
|||
#. module: account_analytic_analysis
|
||||
#: field:account.analytic.account,total_cost:0
|
||||
msgid "Total Costs"
|
||||
msgstr "Custo total"
|
||||
msgstr "Custos totais"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: help:account.analytic.account,hours_quantity:0
|
||||
|
@ -145,13 +145,13 @@ msgid ""
|
|||
"Number of hours you spent on the analytic account (from timesheet). It "
|
||||
"computes on all journal of type 'general'."
|
||||
msgstr ""
|
||||
"Número de horas que você passou no conta analítica (do horário). É "
|
||||
"Número de horas que você passou no conta analítica (da folha de horas). É "
|
||||
"processado em todo o jornal do tipo 'general'."
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: field:account.analytic.account,remaining_hours:0
|
||||
msgid "Remaining Hours"
|
||||
msgstr "Horas restantes"
|
||||
msgstr "Horas Restantes"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: help:account.analytic.account,ca_theorical:0
|
||||
|
@ -161,8 +161,8 @@ msgid ""
|
|||
"the pricelist."
|
||||
msgstr ""
|
||||
"Baseado nos custos você teve no projecto, o que seria o rendimento se todos "
|
||||
"estes custos forem facturados a preço normal da venda fornecido pela lista "
|
||||
"de preço."
|
||||
"estes custos fossem facturados ao preço normal da venda fornecidos pela "
|
||||
"tabela de preço."
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: field:account.analytic.account,user_ids:0
|
||||
|
@ -174,24 +174,24 @@ msgstr "Utilizador"
|
|||
#: model:ir.actions.act_window,name:account_analytic_analysis.action_account_analytic_managed_pending
|
||||
#: model:ir.ui.menu,name:account_analytic_analysis.menu_analytic_account_to_valid_pending
|
||||
msgid "My Pending Accounts"
|
||||
msgstr "Minhas contas pendentes"
|
||||
msgstr "As minhas contas pendentes"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: model:ir.actions.act_window,name:account_analytic_analysis.action_hr_tree_invoiced_my
|
||||
#: model:ir.ui.menu,name:account_analytic_analysis.menu_action_hr_tree_invoiced_my
|
||||
msgid "My Uninvoiced Entries"
|
||||
msgstr "Minhas entradas não facturadas"
|
||||
msgstr "As minhas entradas não facturadas"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: help:account.analytic.account,real_margin:0
|
||||
msgid "Computed using the formula: Invoiced Amount - Total Costs."
|
||||
msgstr "Processado usando a formula: Montante facturado - Custo total."
|
||||
msgstr "Processado usando a fórmula: Montante Facturado - Custo Total."
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: model:ir.actions.act_window,name:account_analytic_analysis.action_account_analytic_managed
|
||||
#: model:ir.ui.menu,name:account_analytic_analysis.menu_analytic_account_managed
|
||||
msgid "My Accounts"
|
||||
msgstr "Minhas contas"
|
||||
msgstr "As minhas contas"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: model:ir.module.module,description:account_analytic_analysis.module_meta_information
|
||||
|
@ -200,6 +200,9 @@ msgid ""
|
|||
"important data for project manager of services companies.\n"
|
||||
"Add menu to show relevant information for each manager."
|
||||
msgstr ""
|
||||
"Modificar a vista da conta analítica para mostrar\n"
|
||||
"dados importantes para o gestor de projecto das empresas de serviços.\n"
|
||||
"Adicione menu para mostrar as informações relevantes para cada gerente."
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: field:account.analytic.account,hours_qtt_non_invoiced:0
|
||||
|
@ -219,43 +222,43 @@ msgstr "Contas da contabilidade analítica"
|
|||
#. module: account_analytic_analysis
|
||||
#: model:ir.module.module,shortdesc:account_analytic_analysis.module_meta_information
|
||||
msgid "report_account_analytic"
|
||||
msgstr ""
|
||||
msgstr "report_account_analytic"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: field:account.analytic.account,ca_invoiced:0
|
||||
msgid "Invoiced Amount"
|
||||
msgstr "Montante facturado"
|
||||
msgstr "Montante Facturado"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: model:ir.ui.menu,name:account_analytic_analysis.next_id_71
|
||||
msgid "Financial Project Management"
|
||||
msgstr "Gestão do projecto financeiro"
|
||||
msgstr "Gestão do Projecto Financeiro"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: field:account.analytic.account,last_worked_invoiced_date:0
|
||||
msgid "Date of Last Invoiced Cost"
|
||||
msgstr "Data do ultimo custo de facturado"
|
||||
msgstr "Data do último custo facturado"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: field:account.analytic.account,ca_to_invoice:0
|
||||
msgid "Uninvoiced Amount"
|
||||
msgstr "Montante facturado"
|
||||
msgstr "Montante Facturado"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: model:ir.actions.act_window,name:account_analytic_analysis.action_account_analytic_all_pending
|
||||
#: model:ir.ui.menu,name:account_analytic_analysis.menu_action_account_analytic_all_pending
|
||||
msgid "Pending Analytic Accounts"
|
||||
msgstr "Contas da contabilidade analítica pendentes"
|
||||
msgstr "Contabilidade analítica contas pendentes"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: field:account.analytic.account,hours_qtt_invoiced:0
|
||||
msgid "Invoiced Hours"
|
||||
msgstr "Horas facturadas"
|
||||
msgstr "Horas Facturadas"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: field:account.analytic.account,real_margin:0
|
||||
msgid "Real Margin"
|
||||
msgstr "Margem real"
|
||||
msgstr "Margem Real"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: help:account.analytic.account,ca_invoiced:0
|
||||
|
@ -265,12 +268,12 @@ msgstr "Montante da facturação total do cliente para esta conta"
|
|||
#. module: account_analytic_analysis
|
||||
#: model:ir.model,name:account_analytic_analysis.model_account_analytic_analysis_summary_month
|
||||
msgid "Hours summary by month"
|
||||
msgstr "Sumário de horas por mês"
|
||||
msgstr "Resumo de horas por mês"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: help:account.analytic.account,real_margin_rate:0
|
||||
msgid "Computes using the formula: (Real Margin / Total Costs) * 100."
|
||||
msgstr "Processado usando a formula: (Margem real / Custos total) * 100."
|
||||
msgstr "Processado usando a fórmula: (Margem Real / Custos Total) * 100."
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: help:account.analytic.account,hours_qtt_non_invoiced:0
|
||||
|
@ -279,17 +282,17 @@ msgid ""
|
|||
"invoice based on analytic account."
|
||||
msgstr ""
|
||||
"Número de horas (do diário de tipo 'geral') que pode ser facturado se você "
|
||||
"factura baseado na conta analítica."
|
||||
"factura baseado em conta analítica."
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: view:account.analytic.account:0
|
||||
msgid "Analytic accounts"
|
||||
msgstr "Conta da Contabilidade analítica"
|
||||
msgstr "Contas da Contabilidade Analítica"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: field:account.analytic.account,remaining_ca:0
|
||||
msgid "Remaining Revenue"
|
||||
msgstr "Lucro restante"
|
||||
msgstr "Receita Restante"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: help:account.analytic.account,ca_to_invoice:0
|
||||
|
@ -297,18 +300,18 @@ msgid ""
|
|||
"If invoice from analytic account, the remaining amount you can invoice to "
|
||||
"the customer based on the total costs."
|
||||
msgstr ""
|
||||
"Se facturado da conta analítica, a quantidade restante que você pode "
|
||||
"Se facturado por conta analítica, a quantidade restante que você pode "
|
||||
"facturar ao cliente baseado nos custos totais."
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: help:account.analytic.account,revenue_per_hour:0
|
||||
msgid "Computed using the formula: Invoiced Amount / Hours Tot."
|
||||
msgstr "Processado usando a formula: Montante facturado / Horas totais."
|
||||
msgstr "Processado usando a fórmula: Montante Facturado / Horas Totais."
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: field:account.analytic.account,revenue_per_hour:0
|
||||
msgid "Revenue per Hours (real)"
|
||||
msgstr "Lucro por hora (real)"
|
||||
msgstr "Receitas por hora (real)"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: field:account_analytic_analysis.summary.month,unit_amount:0
|
||||
|
@ -332,7 +335,7 @@ msgstr "Conta da Contabilidade Analítica"
|
|||
#: model:ir.actions.act_window,name:account_analytic_analysis.action_account_analytic_managed_overpassed
|
||||
#: model:ir.ui.menu,name:account_analytic_analysis.menu_action_account_analytic_managed_overpassed
|
||||
msgid "Overpassed Accounts"
|
||||
msgstr "Contas ultrapassadas"
|
||||
msgstr "Contas Excedidas"
|
||||
|
||||
#. module: account_analytic_analysis
|
||||
#: model:ir.actions.act_window,name:account_analytic_analysis.action_hr_tree_invoiced_all
|
||||
|
@ -347,4 +350,4 @@ msgid ""
|
|||
"indirect costs, like time spent on timesheets."
|
||||
msgstr ""
|
||||
"Total de custos para esta conta. Inclui custos reais (das facturas) e custos "
|
||||
"indirectos, como o tempo passado em folha de presença."
|
||||
"indirectos, como o tempo passado em folha de horas."
|
||||
|
|
|
@ -7,13 +7,13 @@ msgstr ""
|
|||
"Project-Id-Version: OpenERP Server 5.0.4\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
|
||||
"PO-Revision-Date: 2009-11-28 23:17+0000\n"
|
||||
"Last-Translator: Paulino <Unknown>\n"
|
||||
"PO-Revision-Date: 2010-06-01 10:24+0000\n"
|
||||
"Last-Translator: cmsa <Unknown>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2010-04-17 04:11+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-06-02 03:33+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. module: account_analytic_plans
|
||||
|
@ -26,8 +26,7 @@ msgstr "Identificação da conta4"
|
|||
msgid ""
|
||||
"The Object name must start with x_ and not contain any special character !"
|
||||
msgstr ""
|
||||
"O nome do Objecto deve começar com x_ e não pode conter nenhum caractere "
|
||||
"especial !"
|
||||
"O nome do objecto deve começar com x_ e não pode conter um carácter especial!"
|
||||
|
||||
#. module: account_analytic_plans
|
||||
#: model:ir.actions.report.xml,name:account_analytic_plans.account_analytic_account_crossovered_analytic
|
||||
|
|
|
@ -178,12 +178,33 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_crossovered_budget_search" model="ir.ui.view">
|
||||
<field name="name">crossovered.budget.search</field>
|
||||
<field name="model">crossovered.budget</field>
|
||||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Budget">
|
||||
<group col="20" colspan="4">
|
||||
<filter string="Draft" domain="[('state','=','draft')]" help="Draft Budgets" default="1"/>
|
||||
<filter string="To Validate" domain="[('state','=','validate')]" help="To Validate Budgets" />
|
||||
<separator orientation="vertical"/>
|
||||
<field name="name" select="1"/>
|
||||
<field name="code" select="1" />
|
||||
<field name="state"/>
|
||||
<field name="date_from"/>
|
||||
<field name="date_to"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="act_crossovered_budget_view">
|
||||
<field name="name">Budget</field>
|
||||
<field name="res_model">crossovered.budget</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="crossovered_budget_view_tree"/>
|
||||
<field name="search_view_id" ref="view_crossovered_budget_search"/>
|
||||
</record>
|
||||
<menuitem parent="next_id_31"
|
||||
id="menu_act_crossovered_budget_view"
|
||||
|
|
|
@ -170,6 +170,7 @@ class account_invoice_line(osv.osv):
|
|||
|
||||
_defaults = {
|
||||
'state': lambda *a: 'article',
|
||||
'sequence': lambda *a : 0,
|
||||
# 'account_id': _default_account
|
||||
}
|
||||
account_invoice_line()
|
||||
|
|
|
@ -7,19 +7,19 @@ msgstr ""
|
|||
"Project-Id-Version: OpenERP Server 5.0.0\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
|
||||
"PO-Revision-Date: 2009-11-28 23:25+0000\n"
|
||||
"Last-Translator: Paulino <Unknown>\n"
|
||||
"PO-Revision-Date: 2010-06-01 09:55+0000\n"
|
||||
"Last-Translator: cmsa <Unknown>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2010-04-17 04:12+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-06-02 03:33+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. module: account_invoice_layout
|
||||
#: selection:account.invoice.line,state:0
|
||||
msgid "Sub Total"
|
||||
msgstr "Sub Total"
|
||||
msgstr "Sub-total"
|
||||
|
||||
#. module: account_invoice_layout
|
||||
#: rml:account.invoice.layout:0
|
||||
|
@ -48,7 +48,7 @@ msgstr "Título"
|
|||
#. module: account_invoice_layout
|
||||
#: model:ir.actions.wizard,name:account_invoice_layout.wizard_notify_message
|
||||
msgid "Invoices with Layout and Message"
|
||||
msgstr "Facturas com layout e mensagem"
|
||||
msgstr "Facturas com Layout e Mensagem"
|
||||
|
||||
#. module: account_invoice_layout
|
||||
#: rml:account.invoice.layout:0
|
||||
|
@ -84,7 +84,7 @@ msgstr "Preço Unitário"
|
|||
#. module: account_invoice_layout
|
||||
#: constraint:ir.actions.act_window:0
|
||||
msgid "Invalid model name in the action definition."
|
||||
msgstr ""
|
||||
msgstr "Nome do modelo inválido na definição da acção."
|
||||
|
||||
#. module: account_invoice_layout
|
||||
#: model:ir.model,name:account_invoice_layout.model_notify_message
|
||||
|
@ -119,7 +119,7 @@ msgstr "Referençia do cliente:"
|
|||
#. module: account_invoice_layout
|
||||
#: rml:account.invoice.layout:0
|
||||
msgid ")"
|
||||
msgstr ""
|
||||
msgstr ")"
|
||||
|
||||
#. module: account_invoice_layout
|
||||
#: field:account.invoice.line,state:0
|
||||
|
@ -134,7 +134,7 @@ msgstr "Preço"
|
|||
#. module: account_invoice_layout
|
||||
#: rml:account.invoice.layout:0
|
||||
msgid "/ ("
|
||||
msgstr ""
|
||||
msgstr "/("
|
||||
|
||||
#. module: account_invoice_layout
|
||||
#: rml:account.invoice.layout:0
|
||||
|
@ -149,7 +149,7 @@ msgstr "Conta de Origem"
|
|||
#. module: account_invoice_layout
|
||||
#: model:ir.actions.act_window,name:account_invoice_layout.notify_mesage_tree_form
|
||||
msgid "Write Messages"
|
||||
msgstr ""
|
||||
msgstr "Escrever mensagens"
|
||||
|
||||
#. module: account_invoice_layout
|
||||
#: rml:account.invoice.layout:0
|
||||
|
@ -189,7 +189,7 @@ msgstr "Quebra de Página"
|
|||
#. module: account_invoice_layout
|
||||
#: rml:account.invoice.layout:0
|
||||
msgid "Document:"
|
||||
msgstr ""
|
||||
msgstr "Documento:"
|
||||
|
||||
#. module: account_invoice_layout
|
||||
#: wizard_view:wizard.notify_message,init:0
|
||||
|
@ -214,7 +214,7 @@ msgstr "Facturas com disposição"
|
|||
#. module: account_invoice_layout
|
||||
#: rml:account.invoice.layout:0
|
||||
msgid "Description / Taxes"
|
||||
msgstr ""
|
||||
msgstr "Descrição / Impostos"
|
||||
|
||||
#. module: account_invoice_layout
|
||||
#: rml:account.invoice.layout:0
|
||||
|
@ -224,7 +224,7 @@ msgstr "Montante"
|
|||
#. module: account_invoice_layout
|
||||
#: rml:account.invoice.layout:0
|
||||
msgid "Description/Taxes"
|
||||
msgstr ""
|
||||
msgstr "Descrição/Impostos"
|
||||
|
||||
#. module: account_invoice_layout
|
||||
#: rml:account.invoice.layout:0
|
||||
|
@ -264,7 +264,7 @@ msgstr "Factura do fornecedor"
|
|||
#. module: account_invoice_layout
|
||||
#: rml:account.invoice.layout:0
|
||||
msgid "Note :"
|
||||
msgstr ""
|
||||
msgstr "Nota:"
|
||||
|
||||
#. module: account_invoice_layout
|
||||
#: rml:account.invoice.layout:0
|
||||
|
@ -274,12 +274,12 @@ msgstr "Taxa"
|
|||
#. module: account_invoice_layout
|
||||
#: model:ir.module.module,shortdesc:account_invoice_layout.module_meta_information
|
||||
msgid "account_invoice_layout"
|
||||
msgstr ""
|
||||
msgstr "account_invoice_layout"
|
||||
|
||||
#. module: account_invoice_layout
|
||||
#: rml:account.invoice.layout:0
|
||||
msgid "Total (Excl. taxes):"
|
||||
msgstr ""
|
||||
msgstr "Total (Antes de Impostos):"
|
||||
|
||||
#. module: account_invoice_layout
|
||||
#: rml:account.invoice.layout:0
|
||||
|
|
|
@ -7,13 +7,13 @@ msgstr ""
|
|||
"Project-Id-Version: OpenERP Server 5.0.0\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
|
||||
"PO-Revision-Date: 2009-11-28 23:58+0000\n"
|
||||
"Last-Translator: Paulino <Unknown>\n"
|
||||
"PO-Revision-Date: 2010-06-01 09:52+0000\n"
|
||||
"Last-Translator: cmsa <Unknown>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2010-04-17 04:16+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-06-02 03:33+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. module: account_reporting
|
||||
|
@ -46,13 +46,13 @@ msgstr "Nota"
|
|||
#. module: account_reporting
|
||||
#: field:account.report.bs,report_type:0
|
||||
msgid "Report Type"
|
||||
msgstr "Tipo de relatório"
|
||||
msgstr "Tipo de Relatório"
|
||||
|
||||
#. module: account_reporting
|
||||
#: model:ir.ui.menu,name:account_reporting.action_account_report_bs_form
|
||||
#: model:ir.ui.menu,name:account_reporting.menu_finan_config_BSheet
|
||||
msgid "Balance Sheet Report"
|
||||
msgstr "Relatório do balancete"
|
||||
msgstr "Relatório Balancete"
|
||||
|
||||
#. module: account_reporting
|
||||
#: constraint:ir.actions.act_window:0
|
||||
|
@ -62,7 +62,7 @@ msgstr "Nome de modelo inválido na definição da acção"
|
|||
#. module: account_reporting
|
||||
#: selection:account.report.bs,font_style:0
|
||||
msgid "Courier"
|
||||
msgstr "Correio"
|
||||
msgstr "Courier"
|
||||
|
||||
#. module: account_reporting
|
||||
#: selection:account.report.bs,font_style:0
|
||||
|
@ -167,7 +167,7 @@ msgstr "Cores rml"
|
|||
#. module: account_reporting
|
||||
#: model:ir.module.module,shortdesc:account_reporting.module_meta_information
|
||||
msgid "Reporting of Balancesheet for accounting"
|
||||
msgstr ""
|
||||
msgstr "Relatório do balancete para a contabilidade."
|
||||
|
||||
#. module: account_reporting
|
||||
#: field:account.report.bs,code:0
|
||||
|
|
|
@ -23,18 +23,6 @@ import time
|
|||
from osv import fields, osv
|
||||
import decimal_precision as dp
|
||||
|
||||
class account_tax(osv.osv):
|
||||
_inherit = 'account.tax'
|
||||
_description = 'Account Tax'
|
||||
_columns = {
|
||||
'price_include': fields.boolean('Tax Included in Price', help="Check this if the price you use on the product and invoices includes this tax."),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'price_include': 0,
|
||||
}
|
||||
account_tax()
|
||||
|
||||
class account_invoice(osv.osv):
|
||||
_inherit = "account.invoice"
|
||||
_columns = {
|
||||
|
|
|
@ -2,32 +2,6 @@
|
|||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Add price include (boolean) on tax form/tree view -->
|
||||
<record id="view_tax_tree_inherit" model="ir.ui.view">
|
||||
<field name="name">account.tax.tree.inherit.tree</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="model">account.tax</field>
|
||||
<field name="inherit_id" ref="account.view_tax_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="name" position="after">
|
||||
<field name="price_include"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_tax_form_inherit" model="ir.ui.view">
|
||||
<field name="name">account.tax.tree.inherit.form</field>
|
||||
<field name="type">form</field>
|
||||
<field name="model">account.tax</field>
|
||||
<field name="inherit_id" ref="account.view_tax_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="sequence" position="after">
|
||||
<field groups="base.group_extended" name="price_include"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
<!-- End -->
|
||||
|
||||
<record id="account_tax_view_price" model="ir.ui.view">
|
||||
<field name="name">account.tax.exlcuded.view.form</field>
|
||||
<field name="type">form</field>
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
</group>
|
||||
<separator colspan="4" string="Note"/>
|
||||
<label align="0.0" colspan="4" width="900"
|
||||
string="The rule use a AND operator. The model must match all non empty fields so that the rule execute the action described in the 'Actions' tab." />
|
||||
string="The rule uses the AND operator. The model must match all non-empty fields so that the rule executes the action described in the 'Actions' tab." />
|
||||
</page>
|
||||
<page string="Actions">
|
||||
<separator colspan="4" string="Fields to Change"/>
|
||||
|
@ -56,15 +56,15 @@
|
|||
<field name="server_action_id"/>
|
||||
<field name="filter_id"/>
|
||||
</page>
|
||||
<page string="E-Mail Actions">
|
||||
<page string="Email Actions">
|
||||
<!-- <group col="4" colspan="2">-->
|
||||
<separator colspan="4" string="Template of Email to Send"/>
|
||||
<separator colspan="4" string="Email Information"/>
|
||||
<field name="act_mail_to_watchers"/>
|
||||
<field name="act_mail_to_user"/>
|
||||
<field colspan="4" name="act_mail_to_email"/>
|
||||
<!-- </group>-->
|
||||
<!-- <group col="4" colspan="2">-->
|
||||
<separator colspan="4" string="E-Mail Reminders (includes the content of the object)"/>
|
||||
<separator colspan="4" string="Email Reminders"/>
|
||||
<field name="act_remind_partner"/>
|
||||
<field name="act_remind_attach"/>
|
||||
<field name="act_remind_user"/>
|
||||
|
@ -73,7 +73,7 @@
|
|||
</group>
|
||||
<field colspan="4" name="act_email_cc"/>
|
||||
<!-- </group>-->
|
||||
<separator colspan="4" string="Mail Body"/>
|
||||
<separator colspan="4" string="Email Body"/>
|
||||
<field colspan="4" name="act_mail_body" height="250"
|
||||
nolabel="1" attrs="{'required':[('act_remind_user','=',True)]}" />
|
||||
<separator colspan="4" string="Special Keywords to Be Used in The Body"/>
|
||||
|
@ -82,9 +82,9 @@
|
|||
<label align="0.0" string="%%(object_description)s = Object description" colspan="2"/>
|
||||
<label align="0.0" string="%%(object_date)s = Creation date" colspan="2"/>
|
||||
<label align="0.0" string="%%(partner)s = Partner name" colspan="2"/>
|
||||
<label align="0.0" string="%%(partner_email)s = Partner email" colspan="2"/>
|
||||
<label align="0.0" string="%%(partner_email)s = Partner Email" colspan="2"/>
|
||||
<label align="0.0" string="%%(object_user)s = Responsible name" colspan="2"/>
|
||||
<label align="0.0" string="%%(object_user_email)s = Responsible email" colspan="2"/>
|
||||
<label align="0.0" string="%%(object_user_email)s = Responsible Email" colspan="2"/>
|
||||
<label align="0.0" string="%%(object_user_phone)s = Responsible phone" colspan="2"/>
|
||||
</page>
|
||||
</notebook>
|
||||
|
|
|
@ -410,7 +410,10 @@ property or property parameter."),
|
|||
event.add('location').value = event_obj.location
|
||||
if event_obj.rrule:
|
||||
event.add('rrule').value = event_obj.rrule
|
||||
|
||||
if event_obj.user_id:
|
||||
event_org = event.add('organizer')
|
||||
event_org.params['CN'] = [event_obj.user_id.name]
|
||||
event_org.value = 'MAILTO:' + (event_obj.user_id.user_email or event_obj.user_id.name)
|
||||
if event_obj.alarm_id:
|
||||
# computes alarm data
|
||||
valarm = event.add('valarm')
|
||||
|
@ -440,7 +443,7 @@ property or property parameter."),
|
|||
attendee_add.params['CUTYPE'] = [str(attendee.cutype)]
|
||||
attendee_add.params['ROLE'] = [str(attendee.role)]
|
||||
attendee_add.params['RSVP'] = [str(attendee.rsvp)]
|
||||
attendee_add.value = 'MAILTO:' + attendee.email
|
||||
attendee_add.value = 'MAILTO:' + (attendee.email or '')
|
||||
res = cal.serialize()
|
||||
return res
|
||||
|
||||
|
@ -480,8 +483,8 @@ property or property parameter."),
|
|||
'company': company
|
||||
}
|
||||
body = html_invitation % body_vals
|
||||
attach = self.get_ics_file(cr, uid, res_obj, context=context)
|
||||
if mail_to and email_from:
|
||||
attach = self.get_ics_file(cr, uid, res_obj, context=context)
|
||||
tools.email_send(
|
||||
email_from,
|
||||
mail_to,
|
||||
|
|
|
@ -137,15 +137,14 @@
|
|||
</record>
|
||||
|
||||
<!-- Calenadar's menu -->
|
||||
|
||||
<menuitem id="base.menu_calendar_configuration" name="Calendar"
|
||||
parent="base.menu_base_config" sequence="10" />
|
||||
<menuitem id="base.menu_calendar_configuration" name="Calendar"
|
||||
parent="base.menu_config_address_book" sequence="15" />
|
||||
|
||||
<!-- Invitation menu -->
|
||||
|
||||
<menuitem id="menu_attendee_invitations"
|
||||
name="Event Invitations" parent="base.menu_calendar_configuration"
|
||||
sequence="10" action="action_view_attendee_form" />
|
||||
<menuitem id="menu_attendee_invitations"
|
||||
name="Event Invitations" parent="base.menu_calendar_configuration"
|
||||
sequence="10" action="action_view_attendee_form" />
|
||||
|
||||
<!-- ALARM FORM VIEW-->
|
||||
|
||||
|
@ -192,11 +191,10 @@
|
|||
|
||||
<!-- Menu for Alarms-->
|
||||
|
||||
<menuitem id="menu_crm_meeting_avail_alarm"
|
||||
<menuitem id="menu_crm_meeting_avail_alarm"
|
||||
groups="base.group_extended"
|
||||
action="base_calendar.action_res_alarm_view"
|
||||
parent="base.menu_calendar_configuration" />
|
||||
|
||||
<!-- Event Form View-->
|
||||
|
||||
<record model="ir.ui.view" id="event_form_view">
|
||||
|
@ -427,9 +425,9 @@
|
|||
|
||||
<!-- Event menu -->
|
||||
|
||||
<menuitem id="menu_events"
|
||||
name="Events" parent="base.menu_calendar_configuration"
|
||||
sequence="5" action="action_view_event" />
|
||||
<menuitem id="menu_events"
|
||||
name="Events" parent="base.menu_calendar_configuration"
|
||||
sequence="5" action="action_view_event" />
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -7,13 +7,13 @@ msgstr ""
|
|||
"Project-Id-Version: OpenERP Server 5.0.4\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
|
||||
"PO-Revision-Date: 2009-11-09 13:47+0000\n"
|
||||
"Last-Translator: <>\n"
|
||||
"PO-Revision-Date: 2010-06-03 01:30+0000\n"
|
||||
"Last-Translator: Abdul Munif Hanafi <Unknown>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2010-04-17 04:03+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-06-03 03:33+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. module: base_vat
|
||||
|
@ -25,7 +25,7 @@ msgstr ""
|
|||
#. module: base_vat
|
||||
#: constraint:ir.ui.view:0
|
||||
msgid "Invalid XML for View Architecture!"
|
||||
msgstr ""
|
||||
msgstr "XML tidak sah untuk Menampilkan Arsitektur!"
|
||||
|
||||
#. module: base_vat
|
||||
#: field:res.partner,vat_subjected:0
|
||||
|
@ -35,4 +35,4 @@ msgstr ""
|
|||
#. module: base_vat
|
||||
#: model:ir.module.module,shortdesc:base_vat.module_meta_information
|
||||
msgid "VAT"
|
||||
msgstr ""
|
||||
msgstr "VAT"
|
||||
|
|
|
@ -7,13 +7,13 @@ msgstr ""
|
|||
"Project-Id-Version: OpenERP Server 5.0.0\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
|
||||
"PO-Revision-Date: 2009-09-08 13:29+0000\n"
|
||||
"Last-Translator: Madalena_prime <madalena.barreto@prime.cv>\n"
|
||||
"PO-Revision-Date: 2010-06-01 10:02+0000\n"
|
||||
"Last-Translator: cmsa <Unknown>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2010-04-17 04:15+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-06-02 03:33+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. module: board
|
||||
|
@ -26,7 +26,7 @@ msgstr ""
|
|||
#. module: board
|
||||
#: model:ir.model,name:board.model_board_board
|
||||
msgid "board.board"
|
||||
msgstr ""
|
||||
msgstr "board.board"
|
||||
|
||||
#. module: board
|
||||
#: field:board.note,user_id:0
|
||||
|
@ -36,7 +36,7 @@ msgstr "Autor"
|
|||
#. module: board
|
||||
#: model:ir.module.module,shortdesc:board.module_meta_information
|
||||
msgid "Dashboard main module"
|
||||
msgstr ""
|
||||
msgstr "Módulo Principal do Painel"
|
||||
|
||||
#. module: board
|
||||
#: view:board.note:0
|
||||
|
@ -52,7 +52,7 @@ msgstr "Largura"
|
|||
#. module: board
|
||||
#: constraint:ir.actions.act_window:0
|
||||
msgid "Invalid model name in the action definition."
|
||||
msgstr ""
|
||||
msgstr "Nome de modelo inválido na definição da aclção."
|
||||
|
||||
#. module: board
|
||||
#: field:board.board.line,name:0
|
||||
|
@ -84,7 +84,7 @@ msgstr "Vista de acções"
|
|||
#. module: board
|
||||
#: model:ir.model,name:board.model_board_note
|
||||
msgid "board.note"
|
||||
msgstr ""
|
||||
msgstr "board.note"
|
||||
|
||||
#. module: board
|
||||
#: field:board.note,date:0
|
||||
|
@ -124,7 +124,7 @@ msgstr "Notas"
|
|||
#. module: board
|
||||
#: model:ir.model,name:board.model_board_note_type
|
||||
msgid "board.note.type"
|
||||
msgstr ""
|
||||
msgstr "board.note.type"
|
||||
|
||||
#. module: board
|
||||
#: view:board.board:0
|
||||
|
@ -136,7 +136,7 @@ msgstr "Painel"
|
|||
#. module: board
|
||||
#: model:ir.module.module,description:board.module_meta_information
|
||||
msgid "Base module for all dashboards."
|
||||
msgstr ""
|
||||
msgstr "Módulo base para todos os painéis."
|
||||
|
||||
#. module: board
|
||||
#: field:board.board.line,position:0
|
||||
|
@ -212,7 +212,7 @@ msgstr "Vista de painel"
|
|||
#. module: board
|
||||
#: model:ir.model,name:board.model_board_board_line
|
||||
msgid "board.board.line"
|
||||
msgstr ""
|
||||
msgstr "board.board.line"
|
||||
|
||||
#. module: board
|
||||
#: field:board.note,name:0
|
||||
|
|
|
@ -10,3 +10,4 @@
|
|||
"access_calendar_event_export","calendar.event.export","model_calendar_event_export","base.group_user",1,1,1,1
|
||||
"access_calendar_event_import","calendar.event.import","model_calendar_event_import","base.group_user",1,1,1,1
|
||||
"access_calendar_event_subscribe","calendar.event.subscribe","model_calendar_event_subscribe","base.group_user",1,1,1,1
|
||||
"access_basic_calendar","basic.calendar","model_basic_calendar","base.group_user",1,1,1,1
|
||||
|
|
|
|
@ -108,13 +108,13 @@ between mails and Open ERP.""",
|
|||
'crm_phonecall_demo.xml'
|
||||
],
|
||||
'test': [
|
||||
# 'test/test_crm_lead.yml',
|
||||
# 'test/test_crm_meeting.yml',
|
||||
# 'test/test_crm_opportunity.yml',
|
||||
# 'test/test_crm_phonecall.yml',
|
||||
],
|
||||
'installable': True,
|
||||
'active': False,
|
||||
'test/test_crm_lead.yml',
|
||||
'test/test_crm_meeting.yml',
|
||||
'test/test_crm_opportunity.yml',
|
||||
'test/test_crm_phonecall.yml',
|
||||
],
|
||||
'installable': True,
|
||||
'active': False,
|
||||
'certificate': '0079056041421',
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -203,9 +203,13 @@ class crm_case(object):
|
|||
address = self.pool.get('res.partner.address').browse(cr, uid, add)
|
||||
return {'value': {'email_from': address.email}}
|
||||
|
||||
def _history(self, cr, uid, cases, keyword, history=False, email=False, details=None, email_from=False, message_id=False, context={}):
|
||||
def _history(self, cr, uid, cases, keyword, history=False, subject=None, email=False, details=None, email_from=False, message_id=False, attach=[], context={}):
|
||||
mailgate_pool = self.pool.get('mailgate.thread')
|
||||
return mailgate_pool._history(cr, uid, cases, keyword, history=history, email=email, details=details, email_from=email_from, message_id=message_id, context=context)
|
||||
return mailgate_pool._history(cr, uid, cases, keyword, history=history,\
|
||||
subject=subject, email=email, \
|
||||
details=details, email_from=email_from,\
|
||||
message_id=message_id, attach=attach, \
|
||||
context=context)
|
||||
|
||||
def case_open(self, cr, uid, ids, *args):
|
||||
"""Opens Case
|
||||
|
@ -438,6 +442,7 @@ class crm_case_section(osv.osv):
|
|||
'child_ids': fields.one2many('crm.case.section', 'parent_id', 'Child Teams'),
|
||||
'resource_calendar_id': fields.many2one('resource.calendar', "Resource's Calendar"),
|
||||
'note': fields.text('Description'),
|
||||
'working_hours': fields.float('Working Hours', digits=(16,2 )),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
|
|
|
@ -82,23 +82,9 @@ this if you want the rule to send an email to the partner."),
|
|||
if hasattr(obj, 'categ_id'):
|
||||
ok = ok and (not action.trg_categ_id or action.trg_categ_id.id==obj.categ_id.id)
|
||||
|
||||
# TODO: history_line is removed
|
||||
# if hasattr(obj, 'history_line'):
|
||||
# ok = ok and (not action.trg_max_history or action.trg_max_history<=(len(obj.history_line)+1))
|
||||
# reg_history = action.regex_history
|
||||
# result_history = True
|
||||
# if reg_history:
|
||||
# ptrn = re.compile(str(reg_history))
|
||||
# if obj.history_line:
|
||||
# _result = ptrn.search(str(obj.history_line[0].description))
|
||||
# if not _result:
|
||||
# result_history = False
|
||||
regex_h = not reg_history or result_history
|
||||
ok = ok and regex_h
|
||||
return ok
|
||||
|
||||
def do_action(self, cr, uid, action, model_obj, obj, context={}):
|
||||
|
||||
""" @param self: The object pointer
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
|
@ -118,7 +104,7 @@ this if you want the rule to send an email to the partner."),
|
|||
write['email_cc'] = obj.email_cc+','+obj.act_email_cc
|
||||
else:
|
||||
write['email_cc'] = obj.act_email_cc
|
||||
|
||||
|
||||
model_obj.write(cr, uid, [obj.id], write, context)
|
||||
emails = []
|
||||
|
||||
|
|
|
@ -1,59 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="event_type_case_create" model="res.partner.event.type">
|
||||
<field name="name">CRM: Create Case</field>
|
||||
<field name="key">crm_case_draft</field>
|
||||
</record>
|
||||
|
||||
<record id="event_type_case_open" model="res.partner.event.type">
|
||||
<field name="name">CRM: Open Case</field>
|
||||
<field name="key">crm_case_open</field>
|
||||
</record>
|
||||
|
||||
<record id="event_type_case_pending" model="res.partner.event.type">
|
||||
<field name="name">CRM: Pending Case</field>
|
||||
<field name="key">crm_case_pending</field>
|
||||
</record>
|
||||
|
||||
<record id="event_type_case_cancel" model="res.partner.event.type">
|
||||
<field name="name">CRM: Cancel Case</field>
|
||||
<field name="key">crm_case_cancel</field>
|
||||
</record>
|
||||
|
||||
<record id="event_type_case_close" model="res.partner.event.type">
|
||||
<field name="name">CRM: Close Case</field>
|
||||
<field name="key">crm_case_done</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
|
||||
<data noupdate="1">
|
||||
<record model="crm.case.section" id="section_sales_department">
|
||||
<field name="name">Sales Department</field>
|
||||
<field name="code">Sales</field>
|
||||
</record>
|
||||
|
||||
<record id="event_type_case_create" model="res.partner.event.type">
|
||||
<field eval="False" name="active"/>
|
||||
</record>
|
||||
|
||||
<record id="event_type_case_open" model="res.partner.event.type">
|
||||
<field eval="True" name="active"/>
|
||||
</record>
|
||||
|
||||
<record id="event_type_case_pending" model="res.partner.event.type">
|
||||
<field eval="False" name="active"/>
|
||||
</record>
|
||||
|
||||
<record id="event_type_case_close" model="res.partner.event.type">
|
||||
<field eval="True" name="active"/>
|
||||
</record>
|
||||
|
||||
<record id="event_type_case_cancel" model="res.partner.event.type">
|
||||
<field eval="False" name="active"/>
|
||||
</record>
|
||||
|
||||
<record id="ir_cron_crm_action" model="ir.cron">
|
||||
<field name="name">Check cases rules</field>
|
||||
|
|
|
@ -39,7 +39,8 @@ class crm_installer(osv.osv_memory):
|
|||
'crm_caldav': fields.boolean('Calendar Synchronizing', help="Help you to synchronize the meetings with other calender clients(e.g.: Sunbird)."),
|
||||
'sale_crm': fields.boolean('Create Quotation from Opportunity', help="This module relates sale to opportunity cases in the CRM."),
|
||||
'fetchmail': fields.boolean('Fetch Emails', help="Fetchmail Server."),
|
||||
'thunderbird': fields.boolean('Thunderbird', help="Thunderbird Interface."),
|
||||
'thunderbird': fields.boolean('Thunderbird', help="Thunderbird Interface."),
|
||||
'wiki_sale_faq': fields.boolean('Sale FAQ', help="Sale FAQ."),
|
||||
}
|
||||
|
||||
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
|
||||
|
|
|
@ -35,7 +35,8 @@
|
|||
<field name="crm_claim" />
|
||||
<field name="crm_helpdesk" />
|
||||
<field name="crm_fundraising" />
|
||||
<field name="sale_crm" invisible="1"/>
|
||||
<field name="wiki_sale_faq"/>
|
||||
<field name="sale_crm" invisible="1"/>
|
||||
</group>
|
||||
</group>
|
||||
</data>
|
||||
|
|
|
@ -108,8 +108,8 @@ class crm_lead(osv.osv, crm_case):
|
|||
'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"),
|
||||
'description': fields.text('Description'),
|
||||
'write_date': fields.datetime('Update Date' , readonly=True),
|
||||
'description': fields.text('Notes'),
|
||||
'write_date': fields.datetime('Update Date' , readonly=True),
|
||||
|
||||
# Lead fields
|
||||
'thread_id': fields.many2one('mailgate.thread', 'Thread', required=False),
|
||||
|
@ -137,7 +137,6 @@ and users by email"),
|
|||
method=True, multi='day_open', type="float", store=True),
|
||||
'day_close': fields.function(_compute_day, string='Days to Close', \
|
||||
method=True, multi='day_close', type="float", store=True),
|
||||
'function_name': fields.char('Function', size=64),
|
||||
'state': fields.selection(crm.AVAILABLE_STATES, 'State', size=16, readonly=True,
|
||||
help='The state is set to \'Draft\', when a case is created.\
|
||||
\nIf the case is in progress the state is set to \'Open\'.\
|
||||
|
|
|
@ -12,9 +12,11 @@
|
|||
<field name="domain">[('object_id.model', '=', 'crm.lead')]</field>
|
||||
<field name="context">{'object_id':'crm.lead'}</field>
|
||||
</record>
|
||||
<menuitem action="crm_lead_stage_act" id="menu_crm_lead_stage_act"
|
||||
groups="base.group_extended"
|
||||
parent="crm.menu_crm_case_stage" />
|
||||
|
||||
<menuitem action="crm_lead_stage_act" id="menu_crm_lead_stage_act" name="Stages"
|
||||
groups="base.group_extended" sequence="0"
|
||||
parent="menu_crm_config_lead" />
|
||||
|
||||
|
||||
<!-- Resource Type Form View -->
|
||||
|
||||
|
@ -26,10 +28,11 @@
|
|||
<field name="domain">[('object_id.model', '=', 'crm.lead')]</field>
|
||||
<field name="context">{'object_id':'crm.lead'}</field>
|
||||
</record>
|
||||
<menuitem action="crm_lead_resource_act"
|
||||
id="menu_crm_lead_resource_act"
|
||||
groups="base.group_extended"
|
||||
parent="crm.menu_crm_case_resource_type" />
|
||||
|
||||
<menuitem action="crm_lead_resource_act"
|
||||
id="menu_crm_lead_resource_act" name="Resource Type"
|
||||
groups="base.group_extended" sequence="2"
|
||||
parent="menu_crm_config_lead" />
|
||||
|
||||
<!-- CRM Lead Form View -->
|
||||
|
||||
|
@ -47,7 +50,7 @@
|
|||
name="convert_opportunity"
|
||||
string="Convert"
|
||||
help="Convert to Opportunity"
|
||||
icon="gtk-index"
|
||||
icon="gtk-index"
|
||||
type="object"/>
|
||||
<newline />
|
||||
<field name="section_id" colspan="1"
|
||||
|
@ -71,7 +74,7 @@
|
|||
<field name="partner_name" string="Partner Name" colspan="4"/>
|
||||
<newline/>
|
||||
<field domain="[('domain', '=', 'contact')]" name="title"/>
|
||||
<field name="function_name" />
|
||||
<field name="function" />
|
||||
<field name="street" colspan="4"/>
|
||||
<field name="street2" colspan="4"/>
|
||||
<field name="zip"/>
|
||||
|
@ -160,16 +163,21 @@
|
|||
<field name="email_to"/>
|
||||
<field name="email_from"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<field name="description" colspan="4" nolabel="1"/>
|
||||
<notebook colspan="4">
|
||||
<page string="Details">
|
||||
<field name="description" colspan="4" nolabel="1"/>
|
||||
</page>
|
||||
<page string="Attachments">
|
||||
<field name="attachment_ids" colspan="4" readonly="1" nolabel="1"/>
|
||||
</page>
|
||||
</notebook>
|
||||
<button colspan="4"
|
||||
string="Reply to Last Email"
|
||||
name="%(action_crm_send_mail)d"
|
||||
context="{'mail':'reply', 'model': 'crm.lead', 'include_original' : True}"
|
||||
icon="gtk-undo" type="action" />
|
||||
string="Reply to Last Email"
|
||||
name="%(crm.action_crm_send_mail)d"
|
||||
context="{'mail':'reply', 'model': 'crm.lead', 'include_original' : True}"
|
||||
icon="gtk-undo" type="action" />
|
||||
</form>
|
||||
<tree string="Communication history">
|
||||
<field name="name" />
|
||||
<field name="date"/>
|
||||
<field name="email_from" />
|
||||
<field name="email_to"/>
|
||||
|
@ -177,7 +185,7 @@
|
|||
</tree>
|
||||
</field>
|
||||
<button colspan="2" string="Send New Email"
|
||||
name="%(action_crm_send_mail)d"
|
||||
name="%(crm.action_crm_send_mail)d"
|
||||
context="{'mail':'new', 'model': 'crm.lead'}"
|
||||
icon="gtk-go-forward" type="action" />
|
||||
<button colspan="2" string="Forward to Partner"
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
<field name="context">{'object_id':'crm.meeting'}</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="crm_meeting_categ_action"
|
||||
id="menu_crm_case_meeting-act" parent="crm.menu_crm_case_categ" />
|
||||
<menuitem action="crm_meeting_categ_action" name="Categories"
|
||||
id="menu_crm_case_meeting-act" parent="menu_crm_config_meeting" />
|
||||
|
||||
<!-- CRM Meetings Form View -->
|
||||
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<data>
|
||||
|
||||
<!-- Opportunity Categories Form View -->
|
||||
<!-- Opportunity Categories Form View -->
|
||||
|
||||
<record id="crm_opportunity_categ_action" model="ir.actions.act_window">
|
||||
<field name="name">Opportunity Categories</field>
|
||||
<field name="res_model">crm.case.categ</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="crm.crm_case_categ_tree-view"/>
|
||||
<field name="domain">[('object_id.model', '=', 'crm.lead')]</field>
|
||||
<field name="context">{'object_id':'crm.lead'}</field>
|
||||
</record>
|
||||
<record id="crm_opportunity_categ_action" model="ir.actions.act_window">
|
||||
<field name="name">Opportunity Categories</field>
|
||||
<field name="res_model">crm.case.categ</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="crm.crm_case_categ_tree-view"/>
|
||||
<field name="domain">[('object_id.model', '=', 'crm.lead')]</field>
|
||||
<field name="context">{'object_id':'crm.lead'}</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="crm_opportunity_categ_action"
|
||||
id="menu_crm_case_opportunity-act"
|
||||
parent="crm.menu_crm_case_categ" />
|
||||
<menuitem action="crm_opportunity_categ_action"
|
||||
id="menu_crm_case_opportunity-act" name="Categories"
|
||||
parent="menu_crm_config_opportunity" />
|
||||
|
||||
<!-- Opportunity Stages Form View-->
|
||||
<!-- Opportunity Stages Form View-->
|
||||
|
||||
<record id="crm_opportunity_stage_act" model="ir.actions.act_window">
|
||||
<field name="name">Opportunity Stages</field>
|
||||
|
@ -29,8 +29,8 @@
|
|||
</record>
|
||||
|
||||
<menuitem action="crm_opportunity_stage_act"
|
||||
id="menu_crm_opportunity_stage_act"
|
||||
parent="crm.menu_crm_case_stage" />
|
||||
id="menu_crm_opportunity_stage_act" name="Stages"
|
||||
parent="menu_crm_config_opportunity" />
|
||||
|
||||
<!-- Opportunity Resource Type Form View -->
|
||||
|
||||
|
@ -44,288 +44,307 @@
|
|||
</record>
|
||||
|
||||
<menuitem action="crm_opportunity_resource_act"
|
||||
id="menu_crm_opportunity_resource_act"
|
||||
parent="crm.menu_crm_case_resource_type" />
|
||||
id="menu_crm_opportunity_resource_act" name="Resource"
|
||||
parent="menu_crm_config_opportunity" />
|
||||
|
||||
<!-- Opportunities Form View -->
|
||||
<!-- Opportunities Form View -->
|
||||
|
||||
<record model="ir.ui.view" id="crm_case_form_view_oppor">
|
||||
<field name="name">Opportunities</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Opportunities">
|
||||
<group colspan="4" col="7">
|
||||
<field name="name" required="1" string="Opportunity"/>
|
||||
<label string="Stage:" align="1.0"/>
|
||||
<group colspan="1" col="4">
|
||||
<field name="stage_id" nolabel="1"
|
||||
on_change="onchange_stage_id(stage_id)"
|
||||
widget="selection"
|
||||
domain="[('object_id.model', '=', 'crm.lead')]" />
|
||||
<button name="stage_previous"
|
||||
<record model="ir.ui.view" id="crm_case_form_view_oppor">
|
||||
<field name="name">Opportunities</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Opportunities">
|
||||
<group colspan="4" col="7">
|
||||
<field name="name" required="1" string="Opportunity"/>
|
||||
<label string="Stage:" align="1.0"/>
|
||||
<group colspan="1" col="4">
|
||||
<field name="stage_id" nolabel="1"
|
||||
on_change="onchange_stage_id(stage_id)"
|
||||
widget="selection"
|
||||
domain="[('object_id.model', '=', 'crm.lead')]" />
|
||||
<button name="stage_previous"
|
||||
states="open,pending" type="object"
|
||||
icon="gtk-go-back" string="" />
|
||||
<button name="stage_next" states="open,pending"
|
||||
type="object" icon="gtk-go-forward" string="" />
|
||||
</group>
|
||||
<field name="user_id"/>
|
||||
|
||||
<button name="action_makeMeeting" type="object"
|
||||
string="Schedule Meeting" icon="gtk-redo" />
|
||||
|
||||
<field name="planned_revenue"/>
|
||||
<field name="probability"/>
|
||||
<field name="date_deadline" string="Expected Closing"/>
|
||||
<button string="Schedule Call"
|
||||
name="%(opportunity2phonecall_act)d" icon="gtk-redo" type="action" />
|
||||
<newline/>
|
||||
<field name="date_action"/>
|
||||
<field name="priority" string="Priority"/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page string="Opportunity">
|
||||
<group col="4" colspan="2">
|
||||
<separator colspan="4" string="Contacts"/>
|
||||
<field name="partner_id" select="1"
|
||||
on_change="onchange_partner_id(partner_id, email_from)"
|
||||
colspan="2" />
|
||||
<field name="partner_address_id"
|
||||
string="Contact"
|
||||
on_change="onchange_partner_address_id(partner_address_id, email_from)"
|
||||
colspan="1" />
|
||||
<field name="email_from" string="Email" />
|
||||
<field name="phone"/>
|
||||
</group>
|
||||
<group col="2" colspan="2">
|
||||
<separator colspan="2" string="Categorization"/>
|
||||
<field name="section_id" colspan="1" widget="selection"/>
|
||||
<field name="categ_id" select="1" groups="base.group_extended"
|
||||
string="Category" widget="selection"
|
||||
domain="[('object_id.model', '=', 'crm.lead')]" />
|
||||
</group>
|
||||
|
||||
<separator colspan="4" string="Details"/>
|
||||
<field name="description" nolabel="1" colspan="4"/>
|
||||
|
||||
<separator colspan="4"/>
|
||||
<group col="8" colspan="4">
|
||||
<field name="state"/>
|
||||
<button name="case_open" string="Open"
|
||||
states="draft,pending" type="object"
|
||||
icon="gtk-go-forward" />
|
||||
<button name="case_pending" string="Pending"
|
||||
states="draft,open" type="object"
|
||||
icon="gtk-media-pause" />
|
||||
<button name="case_escalate" string="Escalate"
|
||||
states="open,draft,pending" type="object"
|
||||
groups="base.group_extended"
|
||||
icon="gtk-go-up" />
|
||||
<button name="case_cancel" string="Mark Lost"
|
||||
states="draft,open,pending" type="object"
|
||||
icon="gtk-close" />
|
||||
<button name="case_close" string="Mark Won"
|
||||
states="open,draft,pending" type="object"
|
||||
icon="gtk-apply" />
|
||||
<button name="case_reset" string="Reset to New"
|
||||
states="done,cancel" type="object"
|
||||
icon="gtk-convert" />
|
||||
</group>
|
||||
</page>
|
||||
|
||||
<page string="Emails" groups="base.group_extended">
|
||||
<group colspan="4">
|
||||
<field colspan="4" name="email_cc" string="CC"/>
|
||||
</group>
|
||||
<field name="message_ids" colspan="4" nolabel="1" mode="form,tree" height="280">
|
||||
<form string="Communication history">
|
||||
<group col="6" colspan="4">
|
||||
<field name="date"/>
|
||||
<field name="email_to"/>
|
||||
<field name="email_from"/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page string="Details">
|
||||
<field name="description" colspan="4" nolabel="1"/>
|
||||
</page>
|
||||
<page string="Attachments">
|
||||
<field name="attachment_ids" colspan="4" readonly="1" nolabel="1"/>
|
||||
</page>
|
||||
</notebook>
|
||||
<button colspan="4"
|
||||
string="Reply to Last Email"
|
||||
name="%(crm.action_crm_send_mail)d"
|
||||
context="{'mail':'reply', 'model': 'crm.lead', 'include_original' : True}"
|
||||
icon="gtk-undo" type="action" />
|
||||
</form>
|
||||
<tree string="Communication history">
|
||||
<field name="date"/>
|
||||
<field name="email_from" />
|
||||
<field name="email_to"/>
|
||||
<field name="description"/>
|
||||
</tree>
|
||||
</field>
|
||||
<button colspan="2" string="Send New Email"
|
||||
name="%(crm.action_crm_send_mail)d"
|
||||
context="{'mail':'new', 'model': 'crm.lead'}"
|
||||
icon="gtk-go-forward" type="action" />
|
||||
<button colspan="2" string="Forward to Partner"
|
||||
name="%(crm_lead_forward_to_partner_act)d"
|
||||
icon="gtk-go-forward" type="action" />
|
||||
</page>
|
||||
<page string="History" groups="base.group_extended">
|
||||
<group col="2" colspan="2">
|
||||
<separator string="Dates" colspan="2"/>
|
||||
<field name="create_date"/>
|
||||
<field name="write_date"/>
|
||||
<field name="date_closed"/>
|
||||
<field name="date_open"/>
|
||||
</group>
|
||||
<group col="2" colspan="2">
|
||||
<separator string="Misc" colspan="2"/>
|
||||
<field name="active"/>
|
||||
<field name="day_open"/>
|
||||
<field name="day_close"/>
|
||||
<field name="referred"/>
|
||||
</group>
|
||||
<separator colspan="4" string="References"/>
|
||||
<field name="ref"/>
|
||||
<field name="ref2"/>
|
||||
<field name="log_ids" nolabel="1" colspan="4">
|
||||
<tree string="Logs">
|
||||
<field name="name" colspan="4"/>
|
||||
<field name="date"/>
|
||||
<field name="user_id"/>
|
||||
</tree>
|
||||
<form string="Logs">
|
||||
<separator string="Action Information" colspan="4"/>
|
||||
<field name="name" colspan="4"/>
|
||||
<field name="date"/>
|
||||
<field name="user_id"/>
|
||||
</form>
|
||||
</field>
|
||||
</page>
|
||||
</notebook>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Opportunities Tree View -->
|
||||
|
||||
<record model="ir.ui.view" id="crm_case_tree_view_oppor">
|
||||
<field name="name">Opportunities Tree</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Opportunities" colors="blue:state=='pending';grey:state in ('cancel', 'done');red:date_deadline < current_date">
|
||||
<field name="date_deadline" invisible="1"/>
|
||||
<field name="create_date"/>
|
||||
<field name="name" string="Opportunity"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="stage_id"/>
|
||||
<field name="categ_id" invisible="1" groups="base.group_extended"/>
|
||||
<button name="stage_previous" string="Previous"
|
||||
states="open,pending" type="object" icon="gtk-go-back" />
|
||||
<button name="stage_next" string="Next"
|
||||
states="open,pending" type="object"
|
||||
icon="gtk-go-back" string="" />
|
||||
<button name="stage_next" states="open,pending"
|
||||
type="object" icon="gtk-go-forward" string="" />
|
||||
</group>
|
||||
<field name="user_id"/>
|
||||
|
||||
<button name="action_makeMeeting" type="object"
|
||||
string="Schedule Meeting" icon="gtk-redo" />
|
||||
|
||||
<field name="planned_revenue"/>
|
||||
<field name="probability"/>
|
||||
<field name="date_deadline" string="Expected Closing"/>
|
||||
<button string="Schedule Call"
|
||||
name="%(opportunity2phonecall_act)d" icon="gtk-redo" type="action" />
|
||||
|
||||
<newline/>
|
||||
<field name="date_action"/>
|
||||
<field name="priority" string="Priority"/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page string="Opportunity">
|
||||
<group col="4" colspan="2">
|
||||
<separator colspan="4" string="Contacts"/>
|
||||
<field name="partner_id" select="1"
|
||||
on_change="onchange_partner_id(partner_id, email_from)"
|
||||
colspan="2" />
|
||||
<field name="partner_address_id"
|
||||
string="Contact"
|
||||
on_change="onchange_partner_address_id(partner_address_id, email_from)"
|
||||
colspan="1" />
|
||||
<field name="email_from" string="Email" />
|
||||
<field name="phone"/>
|
||||
</group>
|
||||
<group col="2" colspan="2">
|
||||
<separator colspan="2" string="Categorization"/>
|
||||
<field name="section_id" colspan="1" widget="selection"/>
|
||||
<field name="categ_id" select="1" groups="base.group_extended"
|
||||
string="Category" widget="selection"
|
||||
domain="[('object_id.model', '=', 'crm.lead')]" />
|
||||
</group>
|
||||
|
||||
<separator colspan="4" string="Details"/>
|
||||
<field name="description" nolabel="1" colspan="4"/>
|
||||
|
||||
<separator colspan="4"/>
|
||||
<group col="8" colspan="4">
|
||||
icon="gtk-go-forward" />
|
||||
<field name="planned_revenue" sum="Total of Planned Revenue"/>
|
||||
<field name="probability" widget="progressbar" avg="Avg. of Probability"/>
|
||||
<field name="date_action"/>
|
||||
<field name="section_id" groups="base.group_extended"/>
|
||||
<field name="user_id"/>
|
||||
<field name="priority"/>
|
||||
<field name="state"/>
|
||||
<button name="case_open" string="Open"
|
||||
states="draft,pending" type="object"
|
||||
icon="gtk-go-forward" />
|
||||
<button name="case_pending" string="Pending"
|
||||
states="draft,open" type="object"
|
||||
icon="gtk-media-pause" />
|
||||
<button name="case_escalate" string="Escalate"
|
||||
states="open,draft,pending" type="object"
|
||||
groups="base.group_extended"
|
||||
icon="gtk-go-up" />
|
||||
<button name="case_cancel" string="Mark Lost"
|
||||
states="draft,open,pending" type="object"
|
||||
icon="gtk-close" />
|
||||
<button name="case_close" string="Mark Won"
|
||||
<button name="case_close" string="Won"
|
||||
states="open,draft,pending" type="object"
|
||||
icon="gtk-apply" />
|
||||
<button name="case_reset" string="Reset to New"
|
||||
states="done,cancel" type="object"
|
||||
icon="gtk-convert" />
|
||||
</group>
|
||||
</page>
|
||||
|
||||
<page string="Emails" groups="base.group_extended">
|
||||
<group colspan="4">
|
||||
<field colspan="4" name="email_cc" string="CC"/>
|
||||
</group>
|
||||
<field name="message_ids" colspan="4" nolabel="1" mode="form,tree">
|
||||
<form string="Communication history">
|
||||
<group col="6" colspan="4">
|
||||
<field name="date"/>
|
||||
<field name="email_to"/>
|
||||
<field name="email_from"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<field name="description" colspan="4" nolabel="1"/>
|
||||
<button colspan="4"
|
||||
string="Reply to Last Email"
|
||||
name="%(action_crm_send_mail)d"
|
||||
context="{'mail':'reply', 'model': 'crm.lead'}"
|
||||
icon="gtk-undo" type="action" />
|
||||
</form>
|
||||
<tree string="Communication history">
|
||||
<field name="description"/>
|
||||
<field name="email_to"/>
|
||||
<field name="date"/>
|
||||
</tree>
|
||||
</field>
|
||||
<button colspan="2" string="Send New Email"
|
||||
name="%(action_crm_send_mail)d"
|
||||
context="{'mail':'new', 'model': 'crm.lead'}"
|
||||
icon="gtk-go-forward" type="action" />
|
||||
<button colspan="2" string="Forward to Partner"
|
||||
name="%(crm_lead_forward_to_partner_act)d"
|
||||
icon="gtk-go-forward" type="action" />
|
||||
</page>
|
||||
<page string="History" groups="base.group_extended">
|
||||
<group col="2" colspan="2">
|
||||
<separator string="Dates" colspan="2"/>
|
||||
<field name="create_date"/>
|
||||
<field name="write_date"/>
|
||||
<field name="date_closed"/>
|
||||
<field name="date_open"/>
|
||||
</group>
|
||||
<group col="2" colspan="2">
|
||||
<separator string="Misc" colspan="2"/>
|
||||
<field name="active"/>
|
||||
<field name="day_open"/>
|
||||
<field name="day_close"/>
|
||||
<field name="referred"/>
|
||||
</group>
|
||||
<separator colspan="4" string="References"/>
|
||||
<field name="ref"/>
|
||||
<field name="ref2"/>
|
||||
<field name="log_ids" nolabel="1" colspan="4">
|
||||
<tree string="Logs">
|
||||
<field name="name" colspan="4"/>
|
||||
<field name="date"/>
|
||||
<field name="user_id"/>
|
||||
</tree>
|
||||
<form string="Logs">
|
||||
<separator string="Action Information" colspan="4"/>
|
||||
<field name="name" colspan="4"/>
|
||||
<field name="date"/>
|
||||
<field name="user_id"/>
|
||||
</form>
|
||||
</field>
|
||||
</page>
|
||||
</notebook>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Opportunities Tree View -->
|
||||
|
||||
<record model="ir.ui.view" id="crm_case_tree_view_oppor">
|
||||
<field name="name">Opportunities Tree</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Opportunities" colors="blue:state=='pending';grey:state in ('cancel', 'done');red:date_deadline < current_date">
|
||||
<field name="date_deadline" invisible="1"/>
|
||||
<field name="create_date"/>
|
||||
<field name="name" string="Opportunity"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="stage_id"/>
|
||||
<field name="categ_id" invisible="1" groups="base.group_extended"/>
|
||||
<button name="stage_previous" string="Previous"
|
||||
states="open,pending" type="object" icon="gtk-go-back" />
|
||||
<button name="stage_next" string="Next"
|
||||
states="open,pending" type="object"
|
||||
icon="gtk-go-forward" />
|
||||
<field name="planned_revenue" sum="Total of Planned Revenue"/>
|
||||
<field name="probability" widget="progressbar" avg="Avg. of Probability"/>
|
||||
<field name="date_action"/>
|
||||
<field name="section_id" groups="base.group_extended"/>
|
||||
<field name="user_id"/>
|
||||
<field name="priority"/>
|
||||
<field name="state"/>
|
||||
<button name="case_open" string="Open"
|
||||
states="draft,pending" type="object"
|
||||
icon="gtk-go-forward" />
|
||||
<button name="case_close" string="Won"
|
||||
states="open,draft,pending" type="object"
|
||||
icon="gtk-apply" />
|
||||
<button name="case_pending" string="Pending"
|
||||
states="open,draft" type="object"
|
||||
icon="gtk-media-pause" />
|
||||
<button name="case_cancel" string="Lost"
|
||||
states="draft,open,pending" type="object"
|
||||
icon="gtk-cancel" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Opportunities Graph View -->
|
||||
|
||||
<record model="ir.ui.view" id="crm_case_graph_view_opportunity">
|
||||
<field name="name">CRM - Opportunity Graph</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Opportunity by Categories" type="bar" orientation="horizontal">
|
||||
<field name="categ_id"/>
|
||||
<field name="planned_revenue" operator="+"/>
|
||||
<field name="state" group="True"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Opportunities Search View -->
|
||||
|
||||
<record id="view_crm_case_opportunities_filter" model="ir.ui.view">
|
||||
<field name="name">CRM - Opportunities Search</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Opportunities">
|
||||
<filter icon="terp-project"
|
||||
string="Current"
|
||||
name="current"
|
||||
domain="[('state','in',('draft','open'))]"/>
|
||||
<filter icon="terp-project"
|
||||
string="Open"
|
||||
domain="[('state','=','open')]"/>
|
||||
<filter icon="terp-project"
|
||||
string="Pending"
|
||||
domain="[('state','=','pending')]"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter icon="gtk-home" string="Today"
|
||||
domain="[('create_date','<', time.strftime('%%Y-%%m-%%d 23:59:59')), ('create_date','>=', time.strftime('%%Y-%%m-%%d 23:59:59'))]"
|
||||
help="Todays' Opportunities" />
|
||||
<filter icon="gtk-media-rewind" string="7 Days"
|
||||
help="Opportunities during last 7 days"
|
||||
domain="[('create_date','<', time.strftime('%%Y-%%m-%%d')),\
|
||||
('create_date','>=',(datetime.date.today()-datetime.timedelta(days=7)).strftime('%%Y-%%m-%%d'))]"
|
||||
/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="name" string="Opportunity"/>
|
||||
<field name="user_id" widget="selection">
|
||||
<filter icon="terp-partner"
|
||||
domain="[('user_id','=',uid)]"
|
||||
help="My Opportunities" default="1"/>
|
||||
<filter icon="terp-partner"
|
||||
domain="[('user_id','=', uid)]"
|
||||
help="Unassigned Opportunities"/>
|
||||
<button name="case_pending" string="Pending"
|
||||
states="open,draft" type="object"
|
||||
icon="gtk-media-pause" />
|
||||
<button name="case_cancel" string="Lost"
|
||||
states="draft,open,pending" type="object"
|
||||
icon="gtk-cancel" />
|
||||
</tree>
|
||||
</field>
|
||||
<field name="section_id"
|
||||
default="context.get('section_id', False)" select="1"
|
||||
widget="selection">
|
||||
<filter icon="terp-crm"
|
||||
domain="[('section_id','=',context.get('section_id',False))]"
|
||||
help="My Sale Team" />
|
||||
</field>
|
||||
<newline/>
|
||||
<group expand="1" string="Group By...">
|
||||
<filter string="Stage" icon="terp-crm" domain="[]"
|
||||
context="{'group_by':'stage_id'}"/>
|
||||
<filter string="Priority" icon="terp-crm" domain="[]"
|
||||
context="{'group_by':'priority'}"/>
|
||||
<filter string="Category" icon="terp-crm"
|
||||
domain="[]" context="{'group_by':'categ_id'}"/>
|
||||
</record>
|
||||
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Salesman" icon="terp-crm"
|
||||
domain="[('user_id','=',uid)]" context="{'group_by':'user_id'}"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Creation" icon="terp-project"
|
||||
domain="[]" context="{'group_by':'create_date'}"/>
|
||||
<filter string="Exp.Closing" icon="terp-project"
|
||||
domain="[]" context="{'group_by':'date_deadline'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
<!-- Opportunities Graph View -->
|
||||
|
||||
<record model="ir.ui.view" id="crm_case_graph_view_opportunity">
|
||||
<field name="name">CRM - Opportunity Graph</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Opportunity by Categories" type="bar" orientation="horizontal">
|
||||
<field name="categ_id"/>
|
||||
<field name="planned_revenue" operator="+"/>
|
||||
<field name="state" group="True"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Opportunities Search View -->
|
||||
|
||||
<record id="view_crm_case_opportunities_filter" model="ir.ui.view">
|
||||
<field name="name">CRM - Opportunities Search</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Opportunities">
|
||||
<filter icon="terp-project"
|
||||
string="Current"
|
||||
name="current"
|
||||
domain="[('state','in',('draft','open'))]"/>
|
||||
<filter icon="terp-project"
|
||||
string="Open"
|
||||
domain="[('state','=','open')]"/>
|
||||
<filter icon="terp-project"
|
||||
string="Pending"
|
||||
domain="[('state','=','pending')]"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter icon="gtk-home" string="Today"
|
||||
domain="[('create_date','<', time.strftime('%%Y-%%m-%%d 23:59:59')), ('create_date','>=', time.strftime('%%Y-%%m-%%d 23:59:59'))]"
|
||||
help="Todays' Opportunities" />
|
||||
<filter icon="gtk-media-rewind" string="7 Days"
|
||||
help="Opportunities during last 7 days"
|
||||
domain="[('create_date','<', time.strftime('%%Y-%%m-%%d')),\
|
||||
('create_date','>=',(datetime.date.today()-datetime.timedelta(days=7)).strftime('%%Y-%%m-%%d'))]"
|
||||
/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="name" string="Opportunity"/>
|
||||
<field name="user_id" widget="selection">
|
||||
<filter icon="terp-partner"
|
||||
domain="[('user_id','=', False)]"
|
||||
help="Unassigned Opportunities" />
|
||||
</field>
|
||||
<field name="section_id"
|
||||
default="context.get('section_id', False)" select="1"
|
||||
widget="selection">
|
||||
<filter icon="terp-crm"
|
||||
domain="[('section_id','=',context.get('section_id',False))]"
|
||||
help="My Sale Team" />
|
||||
</field>
|
||||
<newline/>
|
||||
<group expand="0" string="Group By..." colspan="16">
|
||||
<filter string="Stage" icon="terp-crm" domain="[]"
|
||||
context="{'group_by':'stage_id'}" />
|
||||
<filter string="Priority" icon="terp-crm" domain="[]"
|
||||
context="{'group_by':'priority'}" />
|
||||
<filter string="Category" icon="terp-crm"
|
||||
domain="[]" context="{'group_by':'categ_id'}" />
|
||||
|
||||
<separator orientation="vertical" />
|
||||
<filter string="Salesman" icon="terp-crm"
|
||||
domain="[('user_id','=',uid)]" context="{'group_by':'user_id'}" />
|
||||
<separator orientation="vertical" />
|
||||
<filter string="Creation" icon="terp-project"
|
||||
domain="[]" context="{'group_by':'create_date'}" />
|
||||
<filter string="Exp.Closing" icon="terp-project"
|
||||
domain="[]" context="{'group_by':'date_deadline'}" />
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<!-- Opportunities Graph View -->
|
||||
|
||||
<record model="ir.ui.view" id="crm_case_graph_view_opportunity">
|
||||
<field name="name">CRM - Opportunity Graph</field>
|
||||
<field name="model">crm.lead</field>
|
||||
<field name="type">graph</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Opportunity by Categories" type="bar" orientation="horizontal">
|
||||
<field name="categ_id"/>
|
||||
<field name="planned_revenue" operator="+"/>
|
||||
<field name="state" group="True"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -38,6 +38,9 @@ class crm_phonecall(osv.osv, crm_case):
|
|||
'name': fields.char('Name', size=64),
|
||||
'active': fields.boolean('Active', required=False),
|
||||
'thread_id': fields.many2one('mailgate.thread', 'Thread', required=False),
|
||||
'date_action_last': fields.datetime('Last Action', readonly=1),
|
||||
'date_action_next': fields.datetime('Next Action', readonly=1),
|
||||
'create_date': fields.datetime('Creation Date' , readonly=True),
|
||||
'section_id': fields.many2one('crm.case.section', 'Sales Team', \
|
||||
select=True, help='Sales team to which Case belongs to.\
|
||||
Define Responsible user and Email account for mail gateway.'),
|
||||
|
@ -87,6 +90,7 @@ class crm_phonecall(osv.osv, crm_case):
|
|||
'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0],
|
||||
'state': lambda *a: 'draft',
|
||||
'user_id': lambda self,cr,uid,ctx: uid,
|
||||
'active': lambda *a: 1,
|
||||
}
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
<field name="context">{'object_id':'crm.phonecall'}</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="crm_phonecall_categ_action"
|
||||
id="menu_crm_case_phonecall-act" parent="crm.menu_crm_case_categ" />
|
||||
<menuitem action="crm_phonecall_categ_action" name="Categories"
|
||||
id="menu_crm_case_phonecall-act" parent="menu_crm_config_phonecall" />
|
||||
|
||||
<!-- ResourceType Form View -->
|
||||
|
||||
|
@ -27,10 +27,9 @@
|
|||
<field name="context">{'object_id':'crm.phonecall'}</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="crm_phonecall_resource_act"
|
||||
id="menu_crm_phonecall_resource_act"
|
||||
parent="crm.menu_crm_case_resource_type" />
|
||||
|
||||
<menuitem action="crm_phonecall_resource_act"
|
||||
id="menu_crm_phonecall_resource_act" name="Resource Type"
|
||||
parent="menu_crm_config_phonecall" />
|
||||
|
||||
<!-- PhoneCalls Tree View -->
|
||||
|
||||
|
|
|
@ -1,8 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<menuitem id="base.menu_crm_configuration" name="Cases"
|
||||
parent="base.menu_base_config" sequence="0" groups="base.group_extended"/>
|
||||
<menuitem id="base.menu_crm_config_sales" name="Sales"
|
||||
parent="base.menu_base_config" sequence="1" groups="base.group_extended"/>
|
||||
|
||||
<menuitem id="menu_crm_config_lead" name="Lead"
|
||||
parent="base.menu_crm_config_sales" sequence="0" groups="base.group_extended"/>
|
||||
|
||||
<menuitem id="menu_crm_config_opportunity" name="Opportunity"
|
||||
parent="base.menu_crm_config_sales" sequence="1" groups="base.group_extended"/>
|
||||
|
||||
<menuitem id="menu_crm_config_meeting" name="Meeting"
|
||||
parent="base.menu_base_config" sequence="4" groups="base.group_extended"/>
|
||||
|
||||
<menuitem id="menu_crm_config_phonecall" name="Phone Call"
|
||||
parent="base.menu_base_config" sequence="5" groups="base.group_extended"/>
|
||||
|
||||
<menuitem id="base.next_id_64" name="Reporting"
|
||||
parent="base.menu_base_partner" sequence="8" />
|
||||
|
@ -117,9 +129,7 @@
|
|||
<field name="view_id" ref="crm_case_stage_tree"/>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_crm_case_stage" name="Stages" parent="base.menu_crm_configuration" groups="base.group_extended"/>
|
||||
|
||||
<!-- Case Categories Form View -->
|
||||
<!-- Case Categories Form View -->
|
||||
|
||||
<record id="crm_case_categ-view" model="ir.ui.view">
|
||||
<field name="name">crm.case.categ.form</field>
|
||||
|
@ -156,11 +166,11 @@
|
|||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="crm_case_categ_tree-view"/>
|
||||
</record>
|
||||
<menuitem id="menu_crm_case_categ" name="Categories" parent="base.menu_crm_configuration" groups="base.group_extended"/>
|
||||
|
||||
<menuitem action="crm_case_section_act"
|
||||
id="menu_crm_case_section_act"
|
||||
parent="base.menu_crm_configuration" />
|
||||
id="menu_crm_case_section_act" sequence="4"
|
||||
parent="base.menu_crm_config_sales" />
|
||||
|
||||
|
||||
|
||||
<!-- Resource Type of case Tree View -->
|
||||
|
@ -201,8 +211,6 @@
|
|||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="crm_case_resource_type_tree"/>
|
||||
</record>
|
||||
<menuitem id="menu_crm_case_resource_type" name="Resource Type"
|
||||
parent="base.menu_crm_configuration" groups="base.group_extended" />
|
||||
|
||||
<record id="crm_case_section_act_tree" model="ir.actions.act_window">
|
||||
<field name="name">Cases by section</field>
|
||||
|
@ -342,10 +350,11 @@
|
|||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
<menuitem action="crm_segmentation_tree-act"
|
||||
|
||||
<menuitem action="crm_segmentation_tree-act"
|
||||
id="menu_crm_segmentation-act"
|
||||
groups="base.group_extended"
|
||||
parent="base.menu_crm_configuration" />
|
||||
groups="base.group_extended" sequence="5"
|
||||
parent="base.menu_crm_config_sales" />
|
||||
|
||||
<record model="ir.ui.view" id="view_users_form_simple_modif_inherited1">
|
||||
<field name="name">view.users.form.crm.modif.inherited1</field>
|
||||
|
|
|
@ -13,7 +13,7 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2010-06-01 03:44+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-06-02 03:33+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. module: crm
|
||||
|
|
|
@ -7,13 +7,13 @@ msgstr ""
|
|||
"Project-Id-Version: OpenERP Server 5.0.0\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2010-01-05 05:59+0000\n"
|
||||
"PO-Revision-Date: 2010-01-22 23:56+0000\n"
|
||||
"Last-Translator: Paulino <Unknown>\n"
|
||||
"PO-Revision-Date: 2010-06-01 14:21+0000\n"
|
||||
"Last-Translator: cmsa <Unknown>\n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2010-04-17 04:02+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-06-02 03:33+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. module: crm
|
||||
|
@ -34,7 +34,7 @@ msgstr ""
|
|||
#: help:crm.case.rule,act_mail_to_user:0
|
||||
msgid ""
|
||||
"Check this if you want the rule to send an email to the responsible person."
|
||||
msgstr ""
|
||||
msgstr "Marque isto se quer que a regra envie um email ao responsável."
|
||||
|
||||
#. module: crm
|
||||
#: view:crm.meeting:0
|
||||
|
@ -57,7 +57,7 @@ msgstr "Fechar dica"
|
|||
#: view:crm.opportunity:0
|
||||
#: view:crm.phonecall:0
|
||||
msgid " 7 Days "
|
||||
msgstr ""
|
||||
msgstr " 7 Dias "
|
||||
|
||||
#. module: crm
|
||||
#: help:crm.menu.config_wizard,helpdesk:0
|
||||
|
@ -67,7 +67,7 @@ msgstr "Gere um serviço de Helpdesk"
|
|||
#. module: crm
|
||||
#: view:crm.job:0
|
||||
msgid "Pending Jobs"
|
||||
msgstr ""
|
||||
msgstr "Tarefas Pendentes"
|
||||
|
||||
#. module: crm
|
||||
#: field:crm.case.rule,trg_state_to:0
|
||||
|
@ -82,7 +82,7 @@ msgstr "Custos previstos"
|
|||
#. module: crm
|
||||
#: wizard_field:crm.job.partner_create,init,close:0
|
||||
msgid "Close job request"
|
||||
msgstr ""
|
||||
msgstr "Fechar tarefa requerida"
|
||||
|
||||
#. module: crm
|
||||
#: field:crm.case.stage,name:0
|
||||
|
@ -191,6 +191,8 @@ msgid ""
|
|||
"Describes the action name.eg:on which object which ation to be taken on "
|
||||
"basis of which condition"
|
||||
msgstr ""
|
||||
"Descreve o nome da acção . Ou seja, em que Objecto, que acção e em que "
|
||||
"condições"
|
||||
|
||||
#. module: crm
|
||||
#: help:crm.case,section_id:0
|
||||
|
@ -238,7 +240,7 @@ msgstr "Salário proposto"
|
|||
#. module: crm
|
||||
#: help:crm.case.section,sequence:0
|
||||
msgid "Gives the sequence order when displaying a list of case sections."
|
||||
msgstr ""
|
||||
msgstr "Devolve a ordem de sequência quando apresenta as secções de opções"
|
||||
|
||||
#. module: crm
|
||||
#: code:addons/crm/wizard/crm_job_wizard.py:0
|
||||
|
@ -3619,6 +3621,8 @@ msgstr ""
|
|||
msgid ""
|
||||
"Can not send mail with empty body,you should have description in the body"
|
||||
msgstr ""
|
||||
"Não pode enviar um email sem corpo de texto, deve inserir texto no corpo do "
|
||||
"email."
|
||||
|
||||
#. module: crm
|
||||
#: selection:report.crm.case.section.categ.categ2,month:0
|
||||
|
|
|
@ -35,7 +35,7 @@ class crm_lead_report(osv.osv):
|
|||
_name = "crm.lead.report"
|
||||
_auto = False
|
||||
_description = "CRM Lead Report"
|
||||
|
||||
|
||||
def _get_data(self, cr, uid, ids, field_name, arg, context={}):
|
||||
|
||||
""" @param cr: the current row, from the database cursor,
|
||||
|
@ -89,7 +89,10 @@ class crm_lead_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),
|
||||
'email': fields.integer('# of Emails', size=128, readonly=True),
|
||||
'expected_closing_days': fields.integer('# of Expected Closing Days', size=128, readonly=True),
|
||||
'delay_open': fields.float('Delay to open',digits=(16,2),readonly=True, group_operator="avg",help="Number of Days to open the case"),
|
||||
'delay_close': fields.float('Delay to close',digits=(16,2),readonly=True, group_operator="avg",help="Number of Days to close the case"),
|
||||
'categ_id': fields.many2one('crm.case.categ', 'Category',\
|
||||
domain="[('section_id','=',section_id),\
|
||||
|
@ -98,11 +101,10 @@ class crm_lead_report(osv.osv):
|
|||
domain="[('section_id','=',section_id),\
|
||||
('object_id.model', '=', 'crm.lead')]", readonly=True),
|
||||
'partner_id': fields.many2one('res.partner', 'Partner' , readonly=True),
|
||||
'company_id': fields.many2one('res.company', 'Company', readonly=True),
|
||||
'company_id': fields.many2one('res.company', 'Company', readonly=True),
|
||||
'type':fields.selection([
|
||||
('lead','Lead'),
|
||||
('opportunity','Opportunity'),
|
||||
|
||||
],'Type', help="Type is used to separate Leads and Opportunities"),
|
||||
}
|
||||
def init(self, cr):
|
||||
|
@ -132,13 +134,28 @@ class crm_lead_report(osv.osv):
|
|||
0 as avg_answers,
|
||||
0.0 as perc_done,
|
||||
0.0 as perc_cancel,
|
||||
(select count(id) from mailgate_message where thread_id=c.id) as email,
|
||||
date_trunc('day',c.create_date) as create_date,
|
||||
avg(extract('epoch' from (c.date_closed-c.create_date)))/(3600*24) as delay_close
|
||||
sum(cast(to_char(date_trunc('day',c.date_open) - date_trunc('day',c.date_deadline),'DD') as int)) as expected_closing_days,
|
||||
avg(extract('epoch' from (c.date_closed-c.create_date)))/(3600*24) as delay_close,
|
||||
avg(extract('epoch' from (c.date_open-c.create_date)))/(3600*24) as delay_open
|
||||
from
|
||||
crm_lead c
|
||||
group by to_char(c.create_date, 'YYYY'), to_char(c.create_date, 'MM'),\
|
||||
c.state, c.user_id,c.section_id,c.stage_id,categ_id,c.partner_id,c.company_id, c.type
|
||||
,c.create_date,to_char(c.create_date, 'YYYY-MM-DD')
|
||||
group by
|
||||
to_char(c.create_date, 'YYYY'),
|
||||
to_char(c.create_date, 'MM'),
|
||||
c.state,
|
||||
c.user_id,
|
||||
c.id,
|
||||
c.section_id,
|
||||
c.stage_id,
|
||||
categ_id,
|
||||
c.partner_id,
|
||||
c.company_id,
|
||||
c.type,
|
||||
c.create_date,
|
||||
to_char(c.create_date, 'YYYY-MM-DD')
|
||||
|
||||
)""")
|
||||
|
||||
crm_lead_report()
|
||||
|
|
|
@ -144,7 +144,7 @@
|
|||
<field name="model">crm.lead.report</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Opportunities">
|
||||
<tree string="Opportunities Analysis">
|
||||
<field name="name" invisible="1"/>
|
||||
<field name="month" invisible="1"/>
|
||||
<field name="section_id" invisible="1" groups="base.group_extended"/>
|
||||
|
@ -153,7 +153,10 @@
|
|||
<field name="partner_id" invisible="1"/>
|
||||
<field name="day" invisible="1"/>
|
||||
<field name="nbr" string="#Opportunities" sum="#Opportunities"/>
|
||||
<field name="delay_close" sum='Avg Closing Delay'/>
|
||||
<field name="email" sum="# of Emails"/>
|
||||
<field name="expected_closing_days" sum='# of Expected Closing Days'/>
|
||||
<field name="delay_open" sum='Delay to open'/>
|
||||
<field name="delay_close" sum='Delay to close'/>
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="stage_id" invisible="1"/>
|
||||
<field name="categ_id" invisible="1"/>
|
||||
|
@ -188,8 +191,8 @@
|
|||
<field name="act_window_id" ref="action_report_crm_lead"/>
|
||||
</record>
|
||||
|
||||
<record id="action_report_crm_opportunity" model="ir.actions.act_window">
|
||||
<field name="name">Opportunities</field>
|
||||
<record id="action_report_crm_opportunity" model="ir.actions.act_window">
|
||||
<field name="name">Opportunities Analysis</field>
|
||||
<field name="res_model">crm.lead.report</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="context">{"search_default_User":1,"search_default_This Month":1,'group_by_no_leaf':1,'group_by':[]}</field>
|
||||
|
@ -216,7 +219,7 @@
|
|||
groups="base.group_extended"
|
||||
parent="base.next_id_64" action="action_report_crm_lead" />
|
||||
|
||||
<menuitem name="Opportunities" id="menu_report_crm_opportunities_tree"
|
||||
<menuitem name="Opportunities Analysis" id="menu_report_crm_opportunities_tree"
|
||||
groups="base.group_extended"
|
||||
parent="base.next_id_64" action="action_report_crm_opportunity" />
|
||||
|
||||
|
|
|
@ -27,10 +27,12 @@ class res_partner(osv.osv):
|
|||
|
||||
_columns = {
|
||||
'opportunity_ids': fields.one2many('crm.lead', 'partner_id',\
|
||||
'Opportunities', domain=[('type', '=', 'opportunity')]),
|
||||
'Opportunities', readonly=True, \
|
||||
domain=[('type', '=', 'opportunity')]),
|
||||
'meeting_ids': fields.one2many('crm.meeting', 'partner_id',\
|
||||
'Meetings'),
|
||||
'phonecall_ids': fields.one2many('crm.phonecall', 'partner_id', 'Phonecalls'),
|
||||
'Meetings', readonly=True),
|
||||
'phonecall_ids': fields.one2many('crm.phonecall', 'partner_id',\
|
||||
'Phonecalls', readonly=True),
|
||||
}
|
||||
|
||||
res_partner()
|
||||
|
|
|
@ -10,52 +10,54 @@
|
|||
<field name="type">form</field>
|
||||
<field name="inherit_id" ref="base.view_partner_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<notebook position="inside">
|
||||
<page string="CRM">
|
||||
<field name="meeting_ids" colspan="4" nolabel="1" />
|
||||
<field name="phonecall_ids" colspan="4" nolabel="1" />
|
||||
<field name="opportunity_ids" colspan="4" nolabel="1" domain="[('type', '=', 'opportunity')]">
|
||||
<tree string="Opportunities" colors="blue:state=='pending';grey:state in ('cancel', 'done')">
|
||||
<field name="create_date"/>
|
||||
<field name="partner_name"/>
|
||||
<field name="name"/>
|
||||
<field name="email_from"/>
|
||||
<field name="phone"/>
|
||||
|
||||
<field name="categ_id" invisible="1"/>
|
||||
<field name="type_id" invisible="1"/>
|
||||
<field name="referred" invisible="1"/>
|
||||
|
||||
<field name="stage_id"/>
|
||||
<button name="stage_previous" string="Previous"
|
||||
states="open,pending" type="object" icon="gtk-go-back" />
|
||||
<button name="stage_next" string="Next"
|
||||
states="open,pending" type="object"
|
||||
icon="gtk-go-forward" />
|
||||
<field name="section_id"
|
||||
invisible="context.get('invisible_section', True)" />
|
||||
<field name="user_id" />
|
||||
<field name="state" />
|
||||
<button name="case_open" string="Open"
|
||||
states="draft,pending" type="object"
|
||||
icon="gtk-go-forward" />
|
||||
<button name="case_close" string="Close"
|
||||
states="open,draft,pending" type="object"
|
||||
icon="gtk-close" />
|
||||
<button string="Convert to Opportunity"
|
||||
name="convert_opportunity"
|
||||
states="draft,open,pending" icon="gtk-index"
|
||||
type="object" />
|
||||
<button name="case_escalate" string="Escalate"
|
||||
states="open,draft,pending" type="object"
|
||||
icon="gtk-go-up" />
|
||||
<button name="case_cancel" string="Cancel"
|
||||
states="draft,open,pending" type="object"
|
||||
icon="gtk-cancel" />
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
</notebook>
|
||||
<xpath expr="//notebook[last()]" position="after">
|
||||
<notebook colspan="4">
|
||||
<page string="CRM">
|
||||
<field name="meeting_ids" colspan="4" nolabel="1" />
|
||||
<field name="phonecall_ids" colspan="4" nolabel="1" />
|
||||
<field name="opportunity_ids" colspan="4" nolabel="1" domain="[('type', '=', 'opportunity')]">
|
||||
<tree string="Opportunities" colors="blue:state=='pending';grey:state in ('cancel', 'done')">
|
||||
<field name="create_date"/>
|
||||
<field name="partner_name"/>
|
||||
<field name="name"/>
|
||||
<field name="email_from"/>
|
||||
<field name="phone"/>
|
||||
|
||||
<field name="categ_id" invisible="1"/>
|
||||
<field name="type_id" invisible="1"/>
|
||||
<field name="referred" invisible="1"/>
|
||||
|
||||
<field name="stage_id"/>
|
||||
<button name="stage_previous" string="Previous"
|
||||
states="open,pending" type="object" icon="gtk-go-back" />
|
||||
<button name="stage_next" string="Next"
|
||||
states="open,pending" type="object"
|
||||
icon="gtk-go-forward" />
|
||||
<field name="section_id"
|
||||
invisible="context.get('invisible_section', True)" />
|
||||
<field name="user_id" />
|
||||
<field name="state" />
|
||||
<button name="case_open" string="Open"
|
||||
states="draft,pending" type="object"
|
||||
icon="gtk-go-forward" />
|
||||
<button name="case_close" string="Close"
|
||||
states="open,draft,pending" type="object"
|
||||
icon="gtk-close" />
|
||||
<button string="Convert to Opportunity"
|
||||
name="convert_opportunity"
|
||||
states="draft,open,pending" icon="gtk-index"
|
||||
type="object" />
|
||||
<button name="case_escalate" string="Escalate"
|
||||
states="open,draft,pending" type="object"
|
||||
icon="gtk-go-up" />
|
||||
<button name="case_cancel" string="Cancel"
|
||||
states="draft,open,pending" type="object"
|
||||
icon="gtk-cancel" />
|
||||
</tree>
|
||||
</field>
|
||||
</page>
|
||||
</notebook>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ class Contact
|
|||
"email_from" => new xmlrpcval($post['email'], "string"),
|
||||
"phone" => new xmlrpcval($post['phone'], "string"),
|
||||
"partner_name" => new xmlrpcval($post['name'], "string"),
|
||||
"function_name" => new xmlrpcval($post["jobtitle"], "string"),
|
||||
"function" => new xmlrpcval($post["jobtitle"], "string"),
|
||||
"zip" => new xmlrpcval($post['zip'], "string"),
|
||||
"stage_id" => new xmlrpcval(6, "int"),
|
||||
"city" => new xmlrpcval($post['city'], "string"),
|
||||
|
|
|
@ -26,3 +26,4 @@
|
|||
"access_crm_lead2opportunity_partner","crm.lead2opportunity.partner","model_crm_lead2opportunity_partner","crm.group_crm_user",1,1,1,1
|
||||
"access_crm_installer","crm.installer.rule","model_crm_installer","crm.group_crm_user",1,1,1,1
|
||||
"access_crm_lead_forward_to_partner","crm.lead.forward.to.partner","model_crm_lead_forward_to_partner","crm.group_crm_user",2,2,2,2
|
||||
"access_mailgate_thread","mailgate.thread","model_mailgate_thread","crm.group_crm_user",1,1,1,1
|
||||
|
|
|
|
@ -82,9 +82,9 @@
|
|||
- |
|
||||
I can check that a lead and a business opportunity is now assigned to this
|
||||
lead.
|
||||
-
|
||||
# !python {model: crm.lead, id: crm_lead_newcustomer0}:
|
||||
# - opportunity_id == False
|
||||
#-
|
||||
# !python {model: crm.lead, id: crm_lead_newcustomer0}:
|
||||
# - opportunity_id == False
|
||||
|
||||
- |
|
||||
I check that the partner associated to this lead as the same country, phone number
|
||||
|
@ -97,10 +97,11 @@
|
|||
opportunity = obj_opportunity.browse(cr, uid, ids)[0]
|
||||
assert lead.partner_name == opportunity.partner_id.name
|
||||
assert lead.phone == opportunity.phone
|
||||
-
|
||||
|
|
||||
# yaml is also not working smpt server and send new email.
|
||||
|
||||
|
||||
#-
|
||||
# |
|
||||
# yaml is also not working smpt server and send new email.
|
||||
|
||||
- |
|
||||
I configure with smtp server.
|
||||
- |
|
||||
|
@ -113,4 +114,4 @@
|
|||
- |
|
||||
I Reply to last Email to lead with some document attached.and check that communication history generated or not.
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -107,8 +107,8 @@ class crm_lead_forward_to_partner(osv.osv_memory):
|
|||
#TODO: ids and context are not comming
|
||||
res = False
|
||||
msg_val = ''
|
||||
res_id = False # Comes from context
|
||||
model = None # Comes from context
|
||||
res_id = context.get('active_id')
|
||||
model = context.get('active_model')
|
||||
model_pool = self.pool.get(model)
|
||||
if not res_id or not model:
|
||||
return res
|
||||
|
@ -212,7 +212,7 @@ class crm_lead_forward_to_partner(osv.osv_memory):
|
|||
lead = lead_proxy.browse(cr, uid, lead_id, context=context)
|
||||
if lead.type == 'lead':
|
||||
field_names = [
|
||||
'partner_name', 'title', 'function_name', 'street', 'street2',
|
||||
'partner_name', 'title', 'function', 'street', 'street2',
|
||||
'zip', 'city', 'country_id', 'state_id', 'email_from',
|
||||
'phone', 'fax', 'mobile'
|
||||
]
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<form string="Forward to Partner">
|
||||
<separator string="User" colspan="4" />
|
||||
<field name="email_from" colspan="2" />
|
||||
<field name="history" colspan="2" on_change="on_change_history(history)"/>
|
||||
<field name="history" colspan="2" on_change="on_change_history(history, context)"/>
|
||||
<separator string="Send to" colspan="4" />
|
||||
<field name="name" colspan="2" />
|
||||
<group col="2" colspan="2" attrs="{ 'invisible' : [('name','!=','user')]}">
|
||||
|
|
|
@ -155,7 +155,7 @@ class crm_lead2partner(osv.osv_memory):
|
|||
'email': lead.email_from,
|
||||
'fax': lead.fax,
|
||||
'title': lead.title,
|
||||
'function': lead.function_name,
|
||||
'function': lead.function,
|
||||
'street': lead.street,
|
||||
'street2': lead.street2,
|
||||
'zip': lead.zip,
|
||||
|
|
|
@ -99,7 +99,7 @@ class crm_send_new_email(osv.osv_memory):
|
|||
model = hist.model_id.model
|
||||
model_pool = self.pool.get(model)
|
||||
res_ids = model_pool.search(cr, uid, [('thread_id','=', hist.thread_id.id)])
|
||||
res_id = res_ids and res_ids[0] or False
|
||||
res_id = res_ids and res_ids[0] or False
|
||||
case = model_pool.browse(cr, uid, res_id)
|
||||
emails = [obj.email_to] + (obj.email_cc or '').split(',')
|
||||
emails = filter(None, emails)
|
||||
|
@ -107,7 +107,11 @@ class crm_send_new_email(osv.osv_memory):
|
|||
|
||||
body = case_pool.format_body(body)
|
||||
email_from = getattr(obj, 'email_from', False)
|
||||
case_pool._history(cr, uid, [case], _('Send'), history=True, email=obj.email_to, details=body, email_from=email_from, message_id=message_id)
|
||||
|
||||
case_pool._history(cr, uid, [case], _('Send'), history=True, \
|
||||
email=obj.email_to, details=body, \
|
||||
subject=obj.subject, email_from=email_from, \
|
||||
message_id=message_id, attach=attach)
|
||||
|
||||
x_headers = dict()
|
||||
#x_headers = {
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
<openerp>
|
||||
<data>
|
||||
|
||||
<menuitem id="menu_config_claim" name="Claim"
|
||||
groups="base.group_extended"
|
||||
parent="base.menu_base_config" sequence="8" />
|
||||
|
||||
<!-- Claims categories -->
|
||||
|
||||
<record id="crm_claim_categ_action" model="ir.actions.act_window">
|
||||
|
@ -13,8 +17,9 @@
|
|||
<field name="context">{'object_id':'crm.claim'}</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="crm_claim_categ_action"
|
||||
id="menu_crm_case_claim-act" parent="crm.menu_crm_case_categ" />
|
||||
<menuitem action="crm_claim_categ_action" name="Categories"
|
||||
id="menu_crm_case_claim-act" parent="menu_config_claim" />
|
||||
|
||||
|
||||
<!-- Claim Stages -->
|
||||
|
||||
|
@ -27,8 +32,8 @@
|
|||
<field name="context">{'object_id':'crm.claim'}</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="crm_claim_stage_act"
|
||||
id="menu_crm_claim_stage_act" parent="crm.menu_crm_case_stage" />
|
||||
<menuitem action="crm_claim_stage_act" name="Stages"
|
||||
id="menu_crm_claim_stage_act" parent="menu_config_claim" />
|
||||
|
||||
<!-- Claim Resource Type -->
|
||||
|
||||
|
@ -41,9 +46,9 @@
|
|||
<field name="context">{'object_id':'crm.claim'}</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="crm_claim_resource_act"
|
||||
<menuitem action="crm_claim_resource_act" name="Resource Type"
|
||||
id="menu_crm_claim_stage_act"
|
||||
parent="crm.menu_crm_case_resource_type" />
|
||||
parent="menu_config_claim" />
|
||||
|
||||
<!-- Claims -->
|
||||
|
||||
|
@ -174,31 +179,38 @@
|
|||
<group colspan="4">
|
||||
<field colspan="4" name="email_cc" string="CC"/>
|
||||
</group>
|
||||
<field name="message_ids" colspan="4" nolabel="1" mode="form,tree">
|
||||
<form string="Communication history">
|
||||
<group col="6" colspan="4">
|
||||
<field name="date"/>
|
||||
<field name="email_to"/>
|
||||
<field name="email_from"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<field name="description" colspan="4" nolabel="1"/>
|
||||
<button colspan="4"
|
||||
string="Reply to Last Email"
|
||||
name="%(crm.action_crm_send_mail)d"
|
||||
context="{'mail':'reply', 'model': 'crm.claim'}"
|
||||
icon="gtk-undo" type="action" />
|
||||
</form>
|
||||
<tree string="Communication history">
|
||||
<field name="description"/>
|
||||
<field name="email_to"/>
|
||||
<field name="date"/>
|
||||
</tree>
|
||||
</field>
|
||||
<button colspan="4" string="Send New Email"
|
||||
name="%(crm.action_crm_send_mail)d"
|
||||
context="{'mail':'new', 'model': 'crm.claim'}"
|
||||
icon="gtk-go-forward" type="action" />
|
||||
<field name="message_ids" colspan="4" nolabel="1" mode="form,tree" height="280">
|
||||
<form string="Communication history">
|
||||
<group col="6" colspan="4">
|
||||
<field name="date"/>
|
||||
<field name="email_to"/>
|
||||
<field name="email_from"/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page string="Details">
|
||||
<field name="description" colspan="4" nolabel="1"/>
|
||||
</page>
|
||||
<page string="Attachments">
|
||||
<field name="attachment_ids" colspan="4" readonly="1" nolabel="1"/>
|
||||
</page>
|
||||
</notebook>
|
||||
<button colspan="4"
|
||||
string="Reply to Last Email"
|
||||
name="%(crm.action_crm_send_mail)d"
|
||||
context="{'mail':'reply', 'model': 'crm.lead'}"
|
||||
icon="gtk-undo" type="action" />
|
||||
</form>
|
||||
<tree string="Communication history">
|
||||
<field name="date"/>
|
||||
<field name="email_from" />
|
||||
<field name="email_to"/>
|
||||
<field name="description"/>
|
||||
</tree>
|
||||
</field>
|
||||
<button colspan="4" string="Send New Email"
|
||||
name="%(crm.action_crm_send_mail)d"
|
||||
context="{'mail':'new', 'model': 'crm.claim'}"
|
||||
icon="gtk-go-forward" type="action" />
|
||||
</page>
|
||||
</notebook>
|
||||
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<!-- Fund Raising Configuration Menu -->
|
||||
<menuitem id="menu_config_fundrising" name="Fund Raising"
|
||||
groups="base.group_extended"
|
||||
parent="base.menu_base_config" sequence="7" />
|
||||
|
||||
<!-- Fund Raising Categories Form View -->
|
||||
|
||||
|
@ -13,9 +17,9 @@
|
|||
<field name="context">{'object_id':'crm.fundraising'}</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="crm_fund_categ_action"
|
||||
<menuitem action="crm_fund_categ_action" name="Categories"
|
||||
id="menu_crm_case_fundraising-act" groups="base.group_extended"
|
||||
parent="crm.menu_crm_case_categ" />
|
||||
parent="menu_config_fundrising" />
|
||||
|
||||
<!-- Fund Stage Form View -->
|
||||
|
||||
|
@ -28,10 +32,11 @@
|
|||
<field name="context">{'object_id':'crm.fundraising'}</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="crm_fundraising_stage_act"
|
||||
groups="base.group_extended"
|
||||
<menuitem action="crm_fundraising_stage_act"
|
||||
groups="base.group_extended" name="Stages"
|
||||
id="menu_crm_fundraising_stage_act"
|
||||
parent="crm.menu_crm_case_stage" />
|
||||
parent="menu_config_fundrising" />
|
||||
|
||||
|
||||
<!-- Fund Resource Type Form View -->
|
||||
|
||||
|
@ -44,10 +49,10 @@
|
|||
<field name="context">{'object_id':'crm.fundraising'}</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="crm_fundraising_resource_act"
|
||||
groups="base.group_extended"
|
||||
<menuitem action="crm_fundraising_resource_act"
|
||||
groups="base.group_extended" name="Resource Type"
|
||||
id="menu_crm_fundraising_resource_act"
|
||||
parent="crm.menu_crm_case_resource_type" />
|
||||
parent="menu_config_fundrising" />
|
||||
|
||||
|
||||
<!-- Fund Raising Tree View -->
|
||||
|
@ -195,18 +200,25 @@
|
|||
<field name="email_to"/>
|
||||
<field name="email_from"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<field name="description" colspan="4" nolabel="1"/>
|
||||
<notebook colspan="4">
|
||||
<page string="Details">
|
||||
<field name="description" colspan="4" nolabel="1"/>
|
||||
</page>
|
||||
<page string="Attachments">
|
||||
<field name="attachment_ids" colspan="4" readonly="1" nolabel="1"/>
|
||||
</page>
|
||||
</notebook>
|
||||
<button colspan="4"
|
||||
string="Reply to Last Email"
|
||||
name="%(crm.action_crm_send_mail)d"
|
||||
context="{'mail':'reply', 'model': 'crm.fundraising'}"
|
||||
icon="gtk-undo" type="action" />
|
||||
string="Reply to Last Email"
|
||||
name="%(crm.action_crm_send_mail)d"
|
||||
context="{'mail':'reply', 'model': 'crm.fundraising'}"
|
||||
icon="gtk-undo" type="action" />
|
||||
</form>
|
||||
<tree string="Communication history">
|
||||
<field name="description"/>
|
||||
<field name="email_to"/>
|
||||
<field name="date"/>
|
||||
<field name="email_from" />
|
||||
<field name="email_to"/>
|
||||
<field name="description"/>
|
||||
</tree>
|
||||
</field>
|
||||
<button colspan="4" string="Send New Email"
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<!-- Helpdesk Support Categories Configuration Menu-->
|
||||
<menuitem id="menu_config_helpdesk" name="Helpdesk"
|
||||
groups="base.group_extended"
|
||||
parent="base.menu_base_config" sequence="8" />
|
||||
|
||||
<!-- Helpdesk Support Categories Form View -->
|
||||
|
||||
|
@ -13,8 +17,8 @@
|
|||
<field name="context">{'object_id':'crm.helpdesk'}</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="crm_helpdesk_categ_action"
|
||||
id="menu_crm_case_helpdesk-act" parent="crm.menu_crm_case_categ" />
|
||||
<menuitem action="crm_helpdesk_categ_action" name="Categories"
|
||||
id="menu_crm_case_helpdesk-act" parent="menu_config_helpdesk" />
|
||||
|
||||
<!-- Helpdesk Support Form View -->
|
||||
|
||||
|
@ -135,18 +139,25 @@
|
|||
<field name="email_to"/>
|
||||
<field name="email_from"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<field name="description" colspan="4" nolabel="1"/>
|
||||
<notebook colspan="4">
|
||||
<page string="Details">
|
||||
<field name="description" colspan="4" nolabel="1"/>
|
||||
</page>
|
||||
<page string="Attachments">
|
||||
<field name="attachment_ids" colspan="4" readonly="1" nolabel="1"/>
|
||||
</page>
|
||||
</notebook>
|
||||
<button colspan="4"
|
||||
string="Reply to Last Email"
|
||||
name="%(crm.action_crm_send_mail)d"
|
||||
context="{'mail':'reply', 'model': 'crm.helpdesk'}"
|
||||
icon="gtk-undo" type="action" />
|
||||
string="Reply to Last Email"
|
||||
name="%(crm.action_crm_send_mail)d"
|
||||
context="{'mail':'reply', 'model': 'crm.helpdesk'}"
|
||||
icon="gtk-undo" type="action" />
|
||||
</form>
|
||||
<tree string="Communication history">
|
||||
<field name="description"/>
|
||||
<field name="email_to"/>
|
||||
<field name="date"/>
|
||||
<field name="email_from" />
|
||||
<field name="email_to"/>
|
||||
<field name="description"/>
|
||||
</tree>
|
||||
</field>
|
||||
<button colspan="4" string="Send New Email"
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
<menuitem parent="base.menu_crm_configuration" id="menu_segm_questionnaire"
|
||||
action="open_questionnaires" />
|
||||
|
||||
<menuitem parent="base.menu_crm_config_sales" id="menu_segm_questionnaire"
|
||||
action="open_questionnaires" />
|
||||
|
||||
<record model="ir.actions.act_window" id="open_questions">
|
||||
<field name="name">Questions</field>
|
||||
|
@ -25,7 +25,8 @@
|
|||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
<menuitem parent="base.menu_crm_configuration" id="menu_segm_answer"
|
||||
|
||||
<menuitem parent="base.menu_crm_config_sales" id="menu_segm_answer"
|
||||
action="open_questions" />
|
||||
|
||||
<!-- Profiling Questionnaire Tree view -->
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
'category': 'Generic Modules/Others',
|
||||
'description': """This is a complete document management system:
|
||||
* User Authentication
|
||||
* Document Indexation
|
||||
* Document Indexation :- .pptx and .docx files are not support in windows platform.
|
||||
|
||||
ATTENTION:
|
||||
- When you install this module in a running company that have already PDF files stored into the database,
|
||||
|
|
|
@ -75,7 +75,7 @@ class document_file(osv.osv):
|
|||
'user_id': fields.many2one('res.users', 'Owner', select=1),
|
||||
'group_ids': fields.many2many('res.groups', 'document_group_rel', 'item_id', 'group_id', 'Groups'),
|
||||
# the directory id now is mandatory. It can still be computed automatically.
|
||||
'parent_id': fields.many2one('document.directory', 'Directory', select=1, required=True),
|
||||
'parent_id': fields.many2one('document.directory', 'Directory', select=1),
|
||||
'file_size': fields.integer('File Size', required=True),
|
||||
'file_type': fields.char('Content Type', size=128),
|
||||
# If ir.attachment contained any data before document is installed, preserve
|
||||
|
@ -88,11 +88,16 @@ class document_file(osv.osv):
|
|||
'create_uid': fields.many2one('res.users', 'Creator', readonly=True),
|
||||
'store_method': fields.selection([('db', 'Database'), ('fs', 'Filesystem'), ('link', 'Link')], "Storing Method"),
|
||||
'datas': fields.function(_data_get, method=True, fnct_inv=_data_set, string='File Content', type="binary", nodrop=True),
|
||||
'url': fields.char('File URL',size=64),
|
||||
'store_fname': fields.char('Stored Filename', size=200),
|
||||
'res_model': fields.char('Attached Model', size=64), #res_model
|
||||
'res_id': fields.integer('Attached ID'), #res_id
|
||||
'partner_id':fields.many2one('res.partner', 'Partner', select=1),
|
||||
'title': fields.char('Resource Title', size=64),
|
||||
'type':fields.selection([
|
||||
('url','URL'),
|
||||
('binary','Binary'),
|
||||
|
||||
],'Type', help="Type is used to separate URL and binary File"),
|
||||
}
|
||||
|
||||
def __get_def_directory(self, cr, uid, context=None):
|
||||
|
@ -103,6 +108,7 @@ class document_file(osv.osv):
|
|||
'user_id': lambda self, cr, uid, ctx:uid,
|
||||
'file_size': lambda self, cr, uid, ctx:0,
|
||||
'store_method': lambda *args: 'db',
|
||||
'type': 'binary',
|
||||
'parent_id': __get_def_directory
|
||||
}
|
||||
_sql_constraints = [
|
||||
|
@ -155,7 +161,6 @@ class document_file(osv.osv):
|
|||
def create(self, cr, uid, vals, context=None):
|
||||
if not context:
|
||||
context = {}
|
||||
vals['title'] = vals['name']
|
||||
vals['parent_id'] = context.get('parent_id', False) or vals.get('parent_id', False)
|
||||
if not vals['parent_id']:
|
||||
vals['parent_id'] = self.pool.get('document.directory')._get_root_directory(cr,uid, context)
|
||||
|
@ -168,8 +173,6 @@ class document_file(osv.osv):
|
|||
result = obj_model.read(cr, uid, [vals['res_id']], ['name', 'partner_id', 'address_id'], context=context)
|
||||
if len(result):
|
||||
obj = result[0]
|
||||
if obj.get('name', False):
|
||||
vals['title'] = (obj.get('name', ''))[:60]
|
||||
if obj_model._name == 'res.partner':
|
||||
vals['partner_id'] = obj['id']
|
||||
elif obj.get('address_id', False):
|
||||
|
|
|
@ -104,11 +104,9 @@ class document_directory(osv.osv):
|
|||
]
|
||||
def name_get(self, cr, uid, ids, context={}):
|
||||
res = []
|
||||
all_ids = self.search(cr,uid,[])
|
||||
if not self.search(cr,uid,[('id','in',ids)]):
|
||||
ids = []
|
||||
for d in self.browse(cr, uid, ids, context=context):
|
||||
if d.id not in all_ids:
|
||||
continue
|
||||
|
||||
s = ''
|
||||
d2 = d
|
||||
while d2 and d2.parent_id:
|
||||
|
|
|
@ -118,7 +118,7 @@
|
|||
<record model="ir.ui.view" id="view_document_directory_tree">
|
||||
<field name="name">document.directory</field>
|
||||
<field name="model">document.directory</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Directories" toolbar="1">
|
||||
<field name="name"/>
|
||||
|
@ -179,71 +179,96 @@
|
|||
<form string="Documents">
|
||||
<group colspan="4" col="6">
|
||||
<field name="name" select="1" />
|
||||
<field name="title" select="1"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="user_id"/>
|
||||
<field name="parent_id"/>
|
||||
<field name="type"/>
|
||||
<field name="parent_id"/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page string="Attachment">
|
||||
<group col="2" colspan="2">
|
||||
<separator string="Data" colspan="2"/>
|
||||
<group col="2" colspan="2" attrs="{'invisible':[('type','=','url')]}">
|
||||
<field name="datas" filename="datas_fname"/>
|
||||
<field name="datas_fname" select="1"/>
|
||||
</group>
|
||||
<group col="2" colspan="2">
|
||||
<separator string="Attached To" colspan="2"/>
|
||||
<field name="res_model" readonly="1"/>
|
||||
<field name="res_id" readonly="1"/>
|
||||
</group>
|
||||
<separator string="Preview" colspan="4"/>
|
||||
<field
|
||||
name="preview"
|
||||
widget="image"
|
||||
readonly="1"
|
||||
nolabel="1"
|
||||
colspan="4"
|
||||
img_height="400"
|
||||
img_width="800"/>
|
||||
</group>
|
||||
<group col="2" colspan="2" attrs="{'invisible':[('type','=','binary')]}">
|
||||
<field name="url" widget="url"/>
|
||||
</group>
|
||||
|
||||
</page><page string="Indexed Content">
|
||||
<field name="index_content" nolabel="1" colspan="4" select="1"/>
|
||||
</page><page string="Security">
|
||||
<field name="group_ids" colspan="4" nolabel="1"/>
|
||||
</page><page string="Others Info">
|
||||
<group colspan="4" col="4">
|
||||
<separator string="File Information" colspan="4"/>
|
||||
<field name="file_size" readonly="1"/>
|
||||
<newline/>
|
||||
</group>
|
||||
|
||||
|
||||
<group col="2" colspan="2">
|
||||
<separator string="Relation" colspan="2"/>
|
||||
<field name="res_name" readonly="1"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="user_id"/>
|
||||
</group>
|
||||
<group col="4" colspan="4">
|
||||
<separator string="History" colspan="4"/>
|
||||
<group col="4" colspan="4">
|
||||
<field name="create_uid"/>
|
||||
<field name="create_date"/>
|
||||
</group>
|
||||
<group col="4" colspan="4">
|
||||
<field name="write_uid"/>
|
||||
<field name="write_date"/>
|
||||
</group>
|
||||
</group>
|
||||
|
||||
</page><page string="Notes">
|
||||
</page>
|
||||
<page string="Security">
|
||||
<field name="group_ids" colspan="4" nolabel="1"/>
|
||||
</page>
|
||||
|
||||
<page string="Notes">
|
||||
<field colspan="4" name="description" nolabel="1"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_attach_filter" model="ir.ui.view">
|
||||
<field name="name">IR Attachment</field>
|
||||
<field name="model">ir.attachment</field>
|
||||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="IR Attachment">
|
||||
<filter icon="gtk-media-rewind" string="Recent"
|
||||
help="less 1 month modified/created attachments"
|
||||
domain="[('create_date','<=', time.strftime('%%Y-%%m-%%d')),('create_date','>',(datetime.date.today()-datetime.timedelta(days=30)).strftime('%%Y-%%m-%%d'))]"
|
||||
/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="user_id" widget="selection">
|
||||
<filter icon="terp-partner"
|
||||
domain="[('user_id','=', False)]"
|
||||
help="Filter on my Attachment" />
|
||||
</field>
|
||||
<field name="partner_id" widget="selection"/>
|
||||
<newline/>
|
||||
<group expand="1" string="Group By...">
|
||||
<filter string="Partner" icon="terp-partner" domain="[]"
|
||||
context="{'group_by':'partner_id'}" />
|
||||
<filter string="Directory" icon="gtk-open" domain="[]" context="{'group_by':'parent_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="view_document_file_tree">
|
||||
<field name="name">ir.attachment</field>
|
||||
<field name="model">ir.attachment</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="priority" eval="1"/>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Documents">
|
||||
<tree colors="blue:type in ('url')" string="Documents">
|
||||
<field name="name"/>
|
||||
<field name="title" />
|
||||
<field name="partner_id"/>
|
||||
<field name="type"/>
|
||||
<field name="datas_fname"/>
|
||||
<field name="user_id"/>
|
||||
<field name="create_date"/>
|
||||
<field name="write_date"/>
|
||||
</tree>
|
||||
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
|
|
@ -44,7 +44,6 @@ class report_document_user(osv.osv):
|
|||
('07','July'), ('08','August'), ('09','September'), ('10','October'), ('11','November'), ('12','December')],'Month',readonly=True),
|
||||
'user_id':fields.integer('Owner', readonly=True),
|
||||
'user':fields.char('User',size=64,readonly=True),
|
||||
'file_title': fields.char('File Name',size=64,readonly=True),
|
||||
'directory': fields.char('Directory',size=64,readonly=True),
|
||||
'create_date': fields.datetime('Date Created', readonly=True),
|
||||
'change_date': fields.datetime('Modified Date', readonly=True),
|
||||
|
@ -66,7 +65,6 @@ class report_document_user(osv.osv):
|
|||
d.name as directory,
|
||||
f.create_date as create_date,
|
||||
f.file_size as file_size,
|
||||
min(f.title) as file_title,
|
||||
min(d.type) as type,
|
||||
f.write_date as change_date
|
||||
from ir_attachment f
|
||||
|
@ -83,7 +81,6 @@ class report_files_partner(osv.osv):
|
|||
_auto = False
|
||||
_columns = {
|
||||
'name': fields.char('Year',size=64,required=False, readonly=True),
|
||||
'file_title': fields.char('File Name',size=64,readonly=True),
|
||||
'directory': fields.char('Directory',size=64,readonly=True),
|
||||
'create_date': fields.datetime('Date Created', readonly=True),
|
||||
'change_date': fields.datetime('Modified Date', readonly=True),
|
||||
|
@ -101,7 +98,6 @@ class report_files_partner(osv.osv):
|
|||
select min(f.id) as id,count(*) as nbr,
|
||||
to_char(f.create_date,'YYYY') as name,
|
||||
min(to_char(f.create_date,'MM')) as month,
|
||||
min(f.title) as file_title,
|
||||
p.name as partner
|
||||
from ir_attachment f
|
||||
inner join res_partner p
|
||||
|
@ -145,7 +141,6 @@ class report_document_wall(osv.osv):
|
|||
'user_id':fields.many2one('res.users', 'Owner',readonly=True),
|
||||
'user':fields.char('User',size=64,readonly=True),
|
||||
'month': fields.char('Month', size=24,readonly=True),
|
||||
'file_name':fields.char('Last Posted File Name',size=64,readonly=True),
|
||||
'last':fields.datetime('Last Posted Time', readonly=True),
|
||||
}
|
||||
|
||||
|
@ -153,7 +148,6 @@ class report_document_wall(osv.osv):
|
|||
cr.execute("""
|
||||
create or replace view report_document_wall as (
|
||||
select max(f.id) as id,
|
||||
min(title) as file_name,
|
||||
to_char(min(f.create_date),'YYYY-MM-DD HH24:MI:SS') as last,
|
||||
f.user_id as user_id, f.user_id as user,
|
||||
to_char(f.create_date,'Month') as month
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
<field name="arch" type="xml">
|
||||
<form string="Files">
|
||||
<field name="name" select="1"/>
|
||||
<field name="file_title" select="1"/>
|
||||
<field name="user" select="1"/>
|
||||
<field name="directory" select="1"/>
|
||||
<field name="file_size"/>
|
||||
|
@ -26,7 +25,6 @@
|
|||
<tree string="Files">
|
||||
<field name="name" select="1"/>
|
||||
<field name="month" select="1"/>
|
||||
<field name="file_title"/>
|
||||
<field name="user" select="1"/>
|
||||
<field name="directory" select="1"/>
|
||||
<field name="file_size"/>
|
||||
|
@ -48,7 +46,6 @@
|
|||
<separator orientation="vertical"/>
|
||||
<field name="name" select="1"/>
|
||||
<field name="month" select="1"/>
|
||||
<field name="file_title" select="1"/>
|
||||
<field name="user" select="1"/>
|
||||
<field name="directory" select="1"/>
|
||||
</group>
|
||||
|
@ -79,13 +76,11 @@
|
|||
<form string="Wall of Shame">
|
||||
<field name="user_id" select="1"/>
|
||||
<field name="month" select="1"/>
|
||||
<field name="file_name" select="1"/>
|
||||
<field name="last"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<record model="ir.ui.view" id="view_document_wall_tree">
|
||||
<field name="name">report.document.wall.tree</field>
|
||||
<field name="model">report.document.wall</field>
|
||||
|
@ -94,7 +89,6 @@
|
|||
<tree string="Wall of Shame">
|
||||
<field name="user_id" select="1"/>
|
||||
<field name="month" select="1"/>
|
||||
<field name="file_name"/>
|
||||
<field name="last"/>
|
||||
</tree>
|
||||
</field>
|
||||
|
|
|
@ -57,6 +57,7 @@ class PptxIndex(indexer):
|
|||
return ['.pptx']
|
||||
|
||||
def _doIndexFile(self,fname):
|
||||
# pptx2txt.pl package not support in windows platform.
|
||||
# Download pptx2txt package from http://sourceforge.net/projects/pptx2txt/" link.
|
||||
# To install this tool, just copy pptx2txt.pl to appropriate place (e.g. /usr/bin directory)
|
||||
fp = Popen(['pptx2txt.pl', fname], shell=False, stdout=PIPE).stdout
|
||||
|
@ -88,6 +89,7 @@ class DocxIndex(indexer):
|
|||
return ['.docx']
|
||||
|
||||
def _doIndexFile(self,fname):
|
||||
# docx2txt.pl package not support in windows platform.
|
||||
# Download docx2txt package from "http://sourceforge.net/projects/docx2txt/" link.
|
||||
# In case, you don't want to use Makefile for installation, you can follow these steps for manual installation.
|
||||
# Copy docx2txt.pl, docx2txt.sh and docx2txt.config to appropriate place (e.g. /usr/bin directory) . used following command.
|
||||
|
|
|
@ -558,8 +558,7 @@ class abstracted_fs:
|
|||
|
||||
if dst_obj2:
|
||||
ressource_type_id = pool.get('ir.model').search(cr, uid, [('model','=',dst_obj2._name)])[0]
|
||||
ressource_id = dst_obj2.id
|
||||
title = dst_obj2.name
|
||||
ressource_id = dst_obj2.id
|
||||
ressource_model = dst_obj2._name
|
||||
if dst_obj2._name == 'res.partner':
|
||||
partner_id = dst_obj2.id
|
||||
|
@ -569,8 +568,7 @@ class abstracted_fs:
|
|||
ressource_type_id = False
|
||||
ressource_id = False
|
||||
ressource_model = False
|
||||
partner_id = False
|
||||
title = False
|
||||
partner_id = False
|
||||
pool.get('document.directory').write(cr, uid, result['directory'], {
|
||||
'name' : dst_basename,
|
||||
'ressource_id': ressource_id,
|
||||
|
@ -579,8 +577,7 @@ class abstracted_fs:
|
|||
})
|
||||
val = {
|
||||
'res_id': ressource_id,
|
||||
'res_model': ressource_model,
|
||||
'title': title,
|
||||
'res_model': ressource_model,
|
||||
'partner_id': partner_id
|
||||
}
|
||||
pool.get('ir.attachment').write(cr, uid, result['attachment'], val)
|
||||
|
@ -603,7 +600,6 @@ class abstracted_fs:
|
|||
'res_model': False,
|
||||
'name': dst_basename,
|
||||
'datas_fname': dst_basename,
|
||||
'title': dst_basename,
|
||||
}
|
||||
|
||||
if (dst_obj and (dst_obj.type in ('directory','ressource'))) or not dst_obj2:
|
||||
|
@ -613,8 +609,7 @@ class abstracted_fs:
|
|||
|
||||
if dst_obj2:
|
||||
val['res_model'] = dst_obj2._name
|
||||
val['res_id'] = dst_obj2.id
|
||||
val['title'] = dst_obj2.name
|
||||
val['res_id'] = dst_obj2.id
|
||||
if dst_obj2._name == 'res.partner':
|
||||
val['partner_id'] = dst_obj2.id
|
||||
else:
|
||||
|
|
|
@ -1975,7 +1975,7 @@ class FTPHandler(asynchat.async_chat):
|
|||
# which IPv6 address to use for binding the socket?
|
||||
# Unfortunately RFC-2428 does not provide satisfing information
|
||||
# on how to do that. The assumption is that we don't have any way
|
||||
# to know wich address to use, hence we just use the same address
|
||||
# to know which address to use, hence we just use the same address
|
||||
# family used on the control connection.
|
||||
if not line:
|
||||
self._make_epasv(extmode=True)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
|
@ -15,7 +15,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/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
import email_template_account
|
||||
import email_template
|
||||
import email_template_mailbox
|
||||
import wizard
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name" : "Email Template for Open ERP",
|
||||
"version" : "0.7 RC",
|
||||
"author" : "Open ERP",
|
||||
"website" : "http://openerp.com",
|
||||
"category" : "Added functionality",
|
||||
"depends" : ['base'],
|
||||
"description": """
|
||||
Email Template is extraction of Power Email basically just to send the emails.
|
||||
""",
|
||||
"init_xml": ['email_template_scheduler_data.xml'],
|
||||
"update_xml": [
|
||||
'security/email_template_security.xml',
|
||||
'email_template_workflow.xml',
|
||||
'email_template_account_view.xml',
|
||||
'email_template_view.xml',
|
||||
'email_template_mailbox_view.xml',
|
||||
'wizard/email_template_send_wizard_view.xml',
|
||||
],
|
||||
"installable": True,
|
||||
"active": False,
|
||||
}
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -0,0 +1,698 @@
|
|||
import base64
|
||||
import random
|
||||
import time
|
||||
import types
|
||||
import netsvc
|
||||
|
||||
LOGGER = netsvc.Logger()
|
||||
|
||||
TEMPLATE_ENGINES = []
|
||||
|
||||
from osv import osv, fields
|
||||
from tools.translate import _
|
||||
from mako.template import Template #For backward combatibility
|
||||
try:
|
||||
from mako.template import Template as MakoTemplate
|
||||
from mako import exceptions
|
||||
TEMPLATE_ENGINES.append(('mako', 'Mako Templates'))
|
||||
except:
|
||||
LOGGER.notifyChannel(
|
||||
_("Email Template"),
|
||||
netsvc.LOG_ERROR,
|
||||
_("Mako templates not installed")
|
||||
)
|
||||
try:
|
||||
from django.template import Context, Template as DjangoTemplate
|
||||
#Workaround for bug:
|
||||
#http://code.google.com/p/django-tagging/issues/detail?id=110
|
||||
from django.conf import settings
|
||||
settings.configure()
|
||||
#Workaround ends
|
||||
TEMPLATE_ENGINES.append(('django', 'Django Template'))
|
||||
except:
|
||||
LOGGER.notifyChannel(
|
||||
_("Email Template"),
|
||||
netsvc.LOG_ERROR,
|
||||
_("Django templates not installed")
|
||||
)
|
||||
|
||||
import email_template_engines
|
||||
import tools
|
||||
import report
|
||||
import pooler
|
||||
|
||||
|
||||
def get_value(cursor, user, recid, message=None, template=None, context=None):
|
||||
"""
|
||||
Evaluates an expression and returns its value
|
||||
@param cursor: Database Cursor
|
||||
@param user: ID of current user
|
||||
@param recid: ID of the target record under evaluation
|
||||
@param message: The expression to be evaluated
|
||||
@param template: BrowseRecord object of the current template
|
||||
@param context: Open ERP Context
|
||||
@return: Computed message (unicode) or u""
|
||||
"""
|
||||
pool = pooler.get_pool(cursor.dbname)
|
||||
if message is None:
|
||||
message = {}
|
||||
#Returns the computed expression
|
||||
if message:
|
||||
try:
|
||||
message = tools.ustr(message)
|
||||
object = pool.get(template.model_int_name).browse(cursor, user, recid, context)
|
||||
env = {
|
||||
'user':pool.get('res.users').browse(cursor, user, user, context),
|
||||
'db':cursor.dbname
|
||||
}
|
||||
if template.template_language == 'mako':
|
||||
templ = MakoTemplate(message, input_encoding='utf-8')
|
||||
reply = MakoTemplate(message).render_unicode(object=object,
|
||||
peobject=object,
|
||||
env=env,
|
||||
format_exceptions=True)
|
||||
elif template.template_language == 'django':
|
||||
templ = DjangoTemplate(message)
|
||||
env['object'] = object
|
||||
env['peobject'] = object
|
||||
reply = templ.render(Context(env))
|
||||
return reply or False
|
||||
except Exception:
|
||||
return u""
|
||||
else:
|
||||
return message
|
||||
|
||||
class email_template(osv.osv):
|
||||
"Templates for sending Email"
|
||||
|
||||
_name = "email.template"
|
||||
_description = 'Email Templates for Models'
|
||||
|
||||
def change_model(self, cursor, user, ids, object_name, context=None):
|
||||
if object_name:
|
||||
mod_name = self.pool.get('ir.model').read(
|
||||
cursor,
|
||||
user,
|
||||
object_name,
|
||||
['model'], context)['model']
|
||||
else:
|
||||
mod_name = False
|
||||
return {
|
||||
'value':{'model_int_name':mod_name}
|
||||
}
|
||||
|
||||
_columns = {
|
||||
'name' : fields.char('Name of Template', size=100, required=True),
|
||||
'object_name':fields.many2one('ir.model', 'Model'),
|
||||
'model_int_name':fields.char('Model Internal Name', size=200,),
|
||||
'def_to':fields.char(
|
||||
'Recepient (To)',
|
||||
size=250,
|
||||
help="The default recepient of email."
|
||||
"Placeholders can be used here."),
|
||||
'def_cc':fields.char(
|
||||
'Default CC',
|
||||
size=250,
|
||||
help="The default CC for the email."
|
||||
" Placeholders can be used here."),
|
||||
'def_bcc':fields.char(
|
||||
'Default BCC',
|
||||
size=250,
|
||||
help="The default BCC for the email."
|
||||
" Placeholders can be used here."),
|
||||
'lang':fields.char(
|
||||
'Language',
|
||||
size=250,
|
||||
help="The default language for the email."
|
||||
" Placeholders can be used here. "
|
||||
"eg. ${object.partner_id.lang}"),
|
||||
'def_subject':fields.char(
|
||||
'Default Subject',
|
||||
size=200,
|
||||
help="The default subject of email."
|
||||
" Placeholders can be used here.",
|
||||
translate=True),
|
||||
'def_body_text':fields.text(
|
||||
'Standard Body (Text)',
|
||||
help="The text version of the mail",
|
||||
translate=True),
|
||||
'def_body_html':fields.text(
|
||||
'Body (Text-Web Client Only)',
|
||||
help="The text version of the mail",
|
||||
translate=True),
|
||||
'use_sign':fields.boolean(
|
||||
'Use Signature',
|
||||
help="the signature from the User details"
|
||||
"will be appened to the mail"),
|
||||
'file_name':fields.char(
|
||||
'File Name Pattern',
|
||||
size=200,
|
||||
help="File name pattern can be specified with placeholders."
|
||||
"eg. 2009_SO003.pdf",
|
||||
translate=True),
|
||||
'report_template':fields.many2one(
|
||||
'ir.actions.report.xml',
|
||||
'Report to send'),
|
||||
'ref_ir_act_window':fields.many2one(
|
||||
'ir.actions.act_window',
|
||||
'Window Action',
|
||||
readonly=True),
|
||||
'ref_ir_value':fields.many2one(
|
||||
'ir.values',
|
||||
'Wizard Button',
|
||||
readonly=True),
|
||||
'allowed_groups':fields.many2many(
|
||||
'res.groups',
|
||||
'template_group_rel',
|
||||
'templ_id', 'group_id',
|
||||
string="Allowed User Groups",
|
||||
help="Only users from these groups will be"
|
||||
" allowed to send mails from this Template"),
|
||||
'enforce_from_account':fields.many2one(
|
||||
'email_template.account',
|
||||
string="Enforce From Account",
|
||||
help="Emails will be sent only from this account.",
|
||||
domain="[('company','=','yes')]"),
|
||||
'model_object_field':fields.many2one(
|
||||
'ir.model.fields',
|
||||
string="Field",
|
||||
help="Select the field from the model you want to use."
|
||||
"\nIf it is a relationship field you will be able to "
|
||||
"choose the nested values in the box below\n(Note:If "
|
||||
"there are no values make sure you have selected the"
|
||||
" correct model)",
|
||||
store=False),
|
||||
'sub_object':fields.many2one(
|
||||
'ir.model',
|
||||
'Sub-model',
|
||||
help='When a relation field is used this field'
|
||||
' will show you the type of field you have selected',
|
||||
store=False),
|
||||
'sub_model_object_field':fields.many2one(
|
||||
'ir.model.fields',
|
||||
'Sub Field',
|
||||
help="When you choose relationship fields "
|
||||
"this field will specify the sub value you can use.",
|
||||
store=False),
|
||||
'null_value':fields.char(
|
||||
'Null Value',
|
||||
help="This Value is used if the field is empty",
|
||||
size=50, store=False),
|
||||
'copyvalue':fields.char(
|
||||
'Expression',
|
||||
size=100,
|
||||
help="Copy and paste the value in the "
|
||||
"location you want to use a system value.",
|
||||
store=False),
|
||||
'table_html':fields.text(
|
||||
'HTML code',
|
||||
help="Copy this html code to your HTML message"
|
||||
" body for displaying the info in your mail.",
|
||||
store=False),
|
||||
#Template language(engine eg.Mako) specifics
|
||||
'template_language':fields.selection(
|
||||
TEMPLATE_ENGINES,
|
||||
'Templating Language',
|
||||
required=True
|
||||
)
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
|
||||
}
|
||||
_sql_constraints = [
|
||||
('name', 'unique (name)', _('The template name must be unique !'))
|
||||
]
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
id = super(email_template, self).create(cr, uid, vals, context)
|
||||
src_obj = self.pool.get('ir.model').read(cr, uid, vals['object_name'], ['model'], context)['model']
|
||||
vals['ref_ir_act_window'] = self.pool.get('ir.actions.act_window').create(cr, uid, {
|
||||
'name': _("%s Mail Form") % vals['name'],
|
||||
'type': 'ir.actions.act_window',
|
||||
'res_model': 'email_template.send.wizard',
|
||||
'src_model': src_obj,
|
||||
'view_type': 'form',
|
||||
'context': "{'src_model':'%s','template_id':'%d','src_rec_id':active_id,'src_rec_ids':active_ids}" % (src_obj, id),
|
||||
'view_mode':'form,tree',
|
||||
'view_id': self.pool.get('ir.ui.view').search(cr, uid, [('name', '=', 'email_template.send.wizard.form')], context=context)[0],
|
||||
'target': 'new',
|
||||
'auto_refresh':1
|
||||
}, context)
|
||||
vals['ref_ir_value'] = self.pool.get('ir.values').create(cr, uid, {
|
||||
'name': _('Send Mail (%s)') % vals['name'],
|
||||
'model': src_obj,
|
||||
'key2': 'client_action_multi',
|
||||
'value': "ir.actions.act_window," + str(vals['ref_ir_act_window']),
|
||||
'object': True,
|
||||
}, context)
|
||||
self.write(cr, uid, id, {
|
||||
'ref_ir_act_window': vals['ref_ir_act_window'],
|
||||
'ref_ir_value': vals['ref_ir_value'],
|
||||
}, context)
|
||||
return id
|
||||
|
||||
def unlink(self, cr, uid, ids, context=None):
|
||||
for template in self.browse(cr, uid, ids, context):
|
||||
obj = self.pool.get(template.object_name.model)
|
||||
try:
|
||||
if template.ref_ir_act_window:
|
||||
self.pool.get('ir.actions.act_window').unlink(cr, uid, template.ref_ir_act_window.id, context)
|
||||
if template.ref_ir_value:
|
||||
self.pool.get('ir.values').unlink(cr, uid, template.ref_ir_value.id, context)
|
||||
except:
|
||||
raise osv.except_osv(_("Warning"), _("Deletion of Record failed"))
|
||||
return super(email_template, self).unlink(cr, uid, ids, context)
|
||||
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
if default is None:
|
||||
default = {}
|
||||
default = default.copy()
|
||||
old = self.read(cr, uid, id, ['name'], context=context)
|
||||
new_name = _("Copy of template ") + old.get('name', 'No Name')
|
||||
check = self.search(cr, uid, [('name', '=', new_name)], context=context)
|
||||
if check:
|
||||
new_name = new_name + '_' + random.choice('abcdefghij') + random.choice('lmnopqrs') + random.choice('tuvwzyz')
|
||||
default.update({'name':new_name})
|
||||
return super(email_template, self).copy(cr, uid, id, default, context)
|
||||
|
||||
def compute_pl(self,
|
||||
model_object_field,
|
||||
sub_model_object_field,
|
||||
null_value, template_language='mako'):
|
||||
"""
|
||||
Returns the expression based on data provided
|
||||
@param model_object_field: First level field
|
||||
@param sub_model_object_field: Second level drilled down field (M2O)
|
||||
@param null_value: What has to be returned if the value is empty
|
||||
@param template_language: The language used for templating
|
||||
@return: computed expression
|
||||
"""
|
||||
#Configure for MAKO
|
||||
copy_val = ''
|
||||
if template_language == 'mako':
|
||||
if model_object_field:
|
||||
copy_val = "${object." + model_object_field
|
||||
if sub_model_object_field:
|
||||
copy_val += "." + sub_model_object_field
|
||||
if null_value:
|
||||
copy_val += " or '" + null_value + "'"
|
||||
if model_object_field:
|
||||
copy_val += "}"
|
||||
elif template_language == 'django':
|
||||
if model_object_field:
|
||||
copy_val = "{{object." + model_object_field
|
||||
if sub_model_object_field:
|
||||
copy_val += "." + sub_model_object_field
|
||||
if null_value:
|
||||
copy_val = copy_val + '|default:"' + null_value + '"'
|
||||
copy_val = copy_val + "}}"
|
||||
return copy_val
|
||||
|
||||
def onchange_model_object_field(self, cr, uid, ids, model_object_field, template_language, context=None):
|
||||
if not model_object_field:
|
||||
return {}
|
||||
result = {}
|
||||
field_obj = self.pool.get('ir.model.fields').browse(cr, uid, model_object_field, context)
|
||||
#Check if field is relational
|
||||
if field_obj.ttype in ['many2one', 'one2many', 'many2many']:
|
||||
res_ids = self.pool.get('ir.model').search(cr, uid, [('model', '=', field_obj.relation)], context=context)
|
||||
if res_ids:
|
||||
result['sub_object'] = res_ids[0]
|
||||
result['copyvalue'] = self.compute_pl(False,
|
||||
False,
|
||||
False,
|
||||
template_language)
|
||||
result['sub_model_object_field'] = False
|
||||
result['null_value'] = False
|
||||
else:
|
||||
#Its a simple field... just compute placeholder
|
||||
result['sub_object'] = False
|
||||
result['copyvalue'] = self.compute_pl(field_obj.name,
|
||||
False,
|
||||
False,
|
||||
template_language
|
||||
)
|
||||
result['sub_model_object_field'] = False
|
||||
result['null_value'] = False
|
||||
return {'value':result}
|
||||
|
||||
def onchange_sub_model_object_field(self, cr, uid, ids, model_object_field, sub_model_object_field, template_language, context=None):
|
||||
if not model_object_field or not sub_model_object_field:
|
||||
return {}
|
||||
result = {}
|
||||
field_obj = self.pool.get('ir.model.fields').browse(cr, uid, model_object_field, context)
|
||||
if field_obj.ttype in ['many2one', 'one2many', 'many2many']:
|
||||
res_ids = self.pool.get('ir.model').search(cr, uid, [('model', '=', field_obj.relation)], context=context)
|
||||
sub_field_obj = self.pool.get('ir.model.fields').browse(cr, uid, sub_model_object_field, context)
|
||||
if res_ids:
|
||||
result['sub_object'] = res_ids[0]
|
||||
result['copyvalue'] = self.compute_pl(field_obj.name,
|
||||
sub_field_obj.name,
|
||||
False,
|
||||
template_language
|
||||
)
|
||||
result['sub_model_object_field'] = sub_model_object_field
|
||||
result['null_value'] = False
|
||||
else:
|
||||
#Its a simple field... just compute placeholder
|
||||
result['sub_object'] = False
|
||||
result['copyvalue'] = self.compute_pl(field_obj.name,
|
||||
False,
|
||||
False,
|
||||
template_language
|
||||
)
|
||||
result['sub_model_object_field'] = False
|
||||
result['null_value'] = False
|
||||
return {'value':result}
|
||||
|
||||
def onchange_null_value(self, cr, uid, ids, model_object_field, sub_model_object_field, null_value, template_language, context=None):
|
||||
if not model_object_field and not null_value:
|
||||
return {}
|
||||
result = {}
|
||||
field_obj = self.pool.get('ir.model.fields').browse(cr, uid, model_object_field, context)
|
||||
if field_obj.ttype in ['many2one', 'one2many', 'many2many']:
|
||||
res_ids = self.pool.get('ir.model').search(cr, uid, [('model', '=', field_obj.relation)], context=context)
|
||||
sub_field_obj = self.pool.get('ir.model.fields').browse(cr, uid, sub_model_object_field, context)
|
||||
if res_ids:
|
||||
result['sub_object'] = res_ids[0]
|
||||
result['copyvalue'] = self.compute_pl(field_obj.name,
|
||||
sub_field_obj.name,
|
||||
null_value,
|
||||
template_language
|
||||
)
|
||||
result['sub_model_object_field'] = sub_model_object_field
|
||||
result['null_value'] = null_value
|
||||
else:
|
||||
#Its a simple field... just compute placeholder
|
||||
result['sub_object'] = False
|
||||
result['copyvalue'] = self.compute_pl(field_obj.name,
|
||||
False,
|
||||
null_value,
|
||||
template_language
|
||||
)
|
||||
result['sub_model_object_field'] = False
|
||||
result['null_value'] = null_value
|
||||
return {'value':result}
|
||||
|
||||
def generate_attach_reports(self,
|
||||
cursor,
|
||||
user,
|
||||
template,
|
||||
record_id,
|
||||
mail,
|
||||
context=None):
|
||||
"""
|
||||
Generate report to be attached and attach it
|
||||
to the email
|
||||
|
||||
@param cursor: Database Cursor
|
||||
@param user: ID of User
|
||||
@param template: Browse record of
|
||||
template
|
||||
@param record_id: ID of the target model
|
||||
for which this mail has
|
||||
to be generated
|
||||
@param mail: Browse record of email object
|
||||
@return: True
|
||||
"""
|
||||
reportname = 'report.' + \
|
||||
self.pool.get('ir.actions.report.xml').read(
|
||||
cursor,
|
||||
user,
|
||||
template.report_template.id,
|
||||
['report_name'],
|
||||
context)['report_name']
|
||||
service = netsvc.LocalService(reportname)
|
||||
data = {}
|
||||
data['model'] = template.model_int_name
|
||||
(result, format) = service.create(cursor,
|
||||
user,
|
||||
[record_id],
|
||||
data,
|
||||
context)
|
||||
attachment_obj = self.pool.get('ir.attachment')
|
||||
new_att_vals = {
|
||||
'name':mail.subject + ' (Email Attachment)',
|
||||
'datas':base64.b64encode(result),
|
||||
'datas_fname':tools.ustr(
|
||||
get_value(
|
||||
cursor,
|
||||
user,
|
||||
record_id,
|
||||
template.file_name,
|
||||
template,
|
||||
context
|
||||
) or 'Report') + "." + format,
|
||||
'description':mail.subject or "No Description",
|
||||
'res_model':'email_template.mailbox',
|
||||
'res_id':mail.id
|
||||
}
|
||||
attachment_id = attachment_obj.create(cursor,
|
||||
user,
|
||||
new_att_vals,
|
||||
context)
|
||||
if attachment_id:
|
||||
self.pool.get('email_template.mailbox').write(
|
||||
cursor,
|
||||
user,
|
||||
mail.id,
|
||||
{
|
||||
'attachments_ids':[
|
||||
[6, 0, [attachment_id]]
|
||||
],
|
||||
'mail_type':'multipart/mixed'
|
||||
},
|
||||
context)
|
||||
return True
|
||||
|
||||
def generate_mailbox_item_from_template(self,
|
||||
cursor,
|
||||
user,
|
||||
template,
|
||||
record_id,
|
||||
context=None):
|
||||
"""
|
||||
Generates an email from the template for
|
||||
record record_id of target object
|
||||
|
||||
@param cursor: Database Cursor
|
||||
@param user: ID of User
|
||||
@param template: Browse record of
|
||||
template
|
||||
@param record_id: ID of the target model
|
||||
for which this mail has
|
||||
to be generated
|
||||
@return: ID of created object
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
#If account to send from is in context select it, else use enforced account
|
||||
if 'account_id' in context.keys():
|
||||
from_account = self.pool.get('email_template.account').read(
|
||||
cursor,
|
||||
user,
|
||||
context.get('account_id'),
|
||||
['name', 'email_id'],
|
||||
context
|
||||
)
|
||||
else:
|
||||
from_account = {
|
||||
'id':template.enforce_from_account.id,
|
||||
'name':template.enforce_from_account.name,
|
||||
'email_id':template.enforce_from_account.email_id
|
||||
}
|
||||
lang = get_value(cursor,
|
||||
user,
|
||||
record_id,
|
||||
template.lang,
|
||||
template,
|
||||
context)
|
||||
if lang:
|
||||
ctx = context.copy()
|
||||
ctx.update({'lang':lang})
|
||||
template = self.browse(cursor, user, template_id, context=ctx)
|
||||
mailbox_values = {
|
||||
'email_from': tools.ustr(from_account['name']) + \
|
||||
"<" + tools.ustr(from_account['email_id']) + ">",
|
||||
'email_to':get_value(cursor,
|
||||
user,
|
||||
record_id,
|
||||
template.def_to,
|
||||
template,
|
||||
context),
|
||||
'email_cc':get_value(cursor,
|
||||
user,
|
||||
record_id,
|
||||
template.def_cc,
|
||||
template,
|
||||
context),
|
||||
'email_bcc':get_value(cursor,
|
||||
user,
|
||||
record_id,
|
||||
template.def_bcc,
|
||||
template,
|
||||
context),
|
||||
'subject':get_value(cursor,
|
||||
user,
|
||||
record_id,
|
||||
template.def_subject,
|
||||
template,
|
||||
context),
|
||||
'body_text':get_value(cursor,
|
||||
user,
|
||||
record_id,
|
||||
template.def_body_text,
|
||||
template,
|
||||
context),
|
||||
'body_html':get_value(cursor,
|
||||
user,
|
||||
record_id,
|
||||
template.def_body_html,
|
||||
template,
|
||||
context),
|
||||
'account_id' :from_account['id'],
|
||||
#This is a mandatory field when automatic emails are sent
|
||||
'state':'na',
|
||||
'folder':'drafts',
|
||||
'mail_type':'multipart/alternative'
|
||||
}
|
||||
#Use signatures if allowed
|
||||
if template.use_sign:
|
||||
sign = self.pool.get('res.users').read(cursor,
|
||||
user,
|
||||
user,
|
||||
['signature'],
|
||||
context)['signature']
|
||||
if mailbox_values['body_text']:
|
||||
mailbox_values['body_text'] += sign
|
||||
if mailbox_values['body_html']:
|
||||
mailbox_values['body_html'] += sign
|
||||
mailbox_id = self.pool.get('email_template.mailbox').create(
|
||||
cursor,
|
||||
user,
|
||||
mailbox_values,
|
||||
context)
|
||||
return mailbox_id
|
||||
|
||||
def generate_mail(self,
|
||||
cursor,
|
||||
user,
|
||||
template_id,
|
||||
record_ids,
|
||||
context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
template = self.browse(cursor, user, template_id, context=context)
|
||||
if not template:
|
||||
raise Exception("The requested template could not be loaded")
|
||||
for record_id in record_ids:
|
||||
mailbox_id = self._generate_mailbox_item_from_template(
|
||||
cursor,
|
||||
user,
|
||||
template,
|
||||
record_id,
|
||||
context)
|
||||
mail = self.pool.get('email_template.mailbox').browse(
|
||||
cursor,
|
||||
user,
|
||||
mailbox_id,
|
||||
context=context
|
||||
)
|
||||
if template.report_template:
|
||||
self._generate_attach_reports(
|
||||
cursor,
|
||||
user,
|
||||
template,
|
||||
record_id,
|
||||
mail,
|
||||
context
|
||||
)
|
||||
self.pool.get('email_template.mailbox').write(
|
||||
cursor,
|
||||
user,
|
||||
mailbox_id,
|
||||
{'folder':'outbox'},
|
||||
context=context
|
||||
)
|
||||
return True
|
||||
|
||||
email_template()
|
||||
|
||||
class email_template_preview(osv.osv_memory):
|
||||
_name = "email_template.preview"
|
||||
_description = "Email Template Preview"
|
||||
|
||||
def _get_model_recs(self, cr, uid, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
#Fills up the selection box which allows records from the selected object to be displayed
|
||||
self.context = context
|
||||
if 'active_id' in context.keys():
|
||||
# context['active_id'] = 5
|
||||
ref_obj_id = self.pool.get('email.template').read(cr, uid, context['active_id'], ['object_name'], context)
|
||||
ref_obj_name = self.pool.get('ir.model').read(cr, uid, ref_obj_id[0], ['model'], context)['model']
|
||||
ref_obj_ids = self.pool.get(ref_obj_name).search(cr, uid, [], context=context)
|
||||
ref_obj_recs = self.pool.get(ref_obj_name).name_get(cr, uid, ref_obj_ids, context)
|
||||
return ref_obj_recs
|
||||
|
||||
def _default_model(self, cursor, user, context=None):
|
||||
"""
|
||||
Returns the default value for model field
|
||||
@param cursor: Database Cursor
|
||||
@param user: ID of current user
|
||||
@param context: Open ERP Context
|
||||
"""
|
||||
return self.pool.get('email.template').read(
|
||||
cursor,
|
||||
user,
|
||||
context['active_id'],
|
||||
['object_name'],
|
||||
context)['object_name']
|
||||
|
||||
_columns = {
|
||||
'ref_template':fields.many2one(
|
||||
'email.template',
|
||||
'Template', readonly=True),
|
||||
'rel_model':fields.many2one('ir.model', 'Model', readonly=True),
|
||||
'rel_model_ref':fields.selection(_get_model_recs, 'Referred Document'),
|
||||
'to':fields.char('To', size=250, readonly=True),
|
||||
'cc':fields.char('CC', size=250, readonly=True),
|
||||
'bcc':fields.char('BCC', size=250, readonly=True),
|
||||
'subject':fields.char('Subject', size=200, readonly=True),
|
||||
'body_text':fields.text('Body', readonly=True),
|
||||
'body_html':fields.text('Body', readonly=True),
|
||||
'report':fields.char('Report Name', size=100, readonly=True),
|
||||
}
|
||||
_defaults = {
|
||||
'ref_template': lambda self, cr, uid, ctx:ctx['active_id'],
|
||||
'rel_model': _default_model
|
||||
}
|
||||
|
||||
def on_change_ref(self, cr, uid, ids, rel_model_ref, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
if not rel_model_ref:
|
||||
return {}
|
||||
vals = {}
|
||||
if context == {}:
|
||||
context = self.context
|
||||
template = self.pool.get('email.template').browse(cr, uid, context['active_id'], context)
|
||||
#Search translated template
|
||||
lang = get_value(cr, uid, rel_model_ref, template.lang, template, context)
|
||||
if lang:
|
||||
ctx = context.copy()
|
||||
ctx.update({'lang':lang})
|
||||
template = self.pool.get('email.template').browse(cr, uid, context['active_id'], ctx)
|
||||
vals['to'] = get_value(cr, uid, rel_model_ref, template.def_to, template, context)
|
||||
vals['cc'] = get_value(cr, uid, rel_model_ref, template.def_cc, template, context)
|
||||
vals['bcc'] = get_value(cr, uid, rel_model_ref, template.def_bcc, template, context)
|
||||
vals['subject'] = get_value(cr, uid, rel_model_ref, template.def_subject, template, context)
|
||||
vals['body_text'] = get_value(cr, uid, rel_model_ref, template.def_body_text, template, context)
|
||||
vals['body_html'] = get_value(cr, uid, rel_model_ref, template.def_body_html, template, context)
|
||||
vals['report'] = get_value(cr, uid, rel_model_ref, template.file_name, template, context)
|
||||
return {'value':vals}
|
||||
|
||||
email_template_preview()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -0,0 +1,440 @@
|
|||
from osv import osv, fields
|
||||
from html2text import html2text
|
||||
import re
|
||||
import smtplib
|
||||
import base64
|
||||
from email import Encoders
|
||||
from email.mime.base import MIMEBase
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
from email.mime.text import MIMEText
|
||||
from email.header import decode_header, Header
|
||||
from email.utils import formatdate
|
||||
import re
|
||||
import netsvc
|
||||
import string
|
||||
import email
|
||||
import time, datetime
|
||||
import email_template_engines
|
||||
from tools.translate import _
|
||||
import tools
|
||||
|
||||
class email_template_account(osv.osv):
|
||||
"""
|
||||
Object to store email account settings
|
||||
"""
|
||||
_name = "email_template.account"
|
||||
_known_content_types = ['multipart/mixed',
|
||||
'multipart/alternative',
|
||||
'multipart/related',
|
||||
'text/plain',
|
||||
'text/html'
|
||||
]
|
||||
_columns = {
|
||||
'name': fields.char('Email Account Desc',
|
||||
size=64, required=True,
|
||||
readonly=True, select=True,
|
||||
states={'draft':[('readonly', False)]}),
|
||||
'user':fields.many2one('res.users',
|
||||
'Related User', required=True,
|
||||
readonly=True, states={'draft':[('readonly', False)]}),
|
||||
'email_id': fields.char('Email ID',
|
||||
size=120, required=True,
|
||||
readonly=True, states={'draft':[('readonly', False)]} ,
|
||||
help=" eg:yourname@yourdomain.com "),
|
||||
'smtpserver': fields.char('Server',
|
||||
size=120, required=True,
|
||||
readonly=True, states={'draft':[('readonly', False)]},
|
||||
help="Enter name of outgoing server,eg:smtp.gmail.com "),
|
||||
'smtpport': fields.integer('SMTP Port ',
|
||||
size=64, required=True,
|
||||
readonly=True, states={'draft':[('readonly', False)]},
|
||||
help="Enter port number,eg:SMTP-587 "),
|
||||
'smtpuname': fields.char('User Name',
|
||||
size=120, required=False,
|
||||
readonly=True, states={'draft':[('readonly', False)]}),
|
||||
'smtppass': fields.char('Password',
|
||||
size=120, invisible=True,
|
||||
required=False, readonly=True,
|
||||
states={'draft':[('readonly', False)]}),
|
||||
'smtptls':fields.boolean('Use TLS',
|
||||
states={'draft':[('readonly', False)]}, readonly=True),
|
||||
|
||||
'smtpssl':fields.boolean('Use SSL/TLS (only in python 2.6)',
|
||||
states={'draft':[('readonly', False)]}, readonly=True),
|
||||
'send_pref':fields.selection([
|
||||
('html', 'HTML otherwise Text'),
|
||||
('text', 'Text otherwise HTML'),
|
||||
('both', 'Both HTML & Text')
|
||||
], 'Mail Format', required=True),
|
||||
'allowed_groups':fields.many2many(
|
||||
'res.groups',
|
||||
'account_group_rel', 'templ_id', 'group_id',
|
||||
string="Allowed User Groups",
|
||||
help="Only users from these groups will be" \
|
||||
"allowed to send mails from this ID"),
|
||||
'company':fields.selection([
|
||||
('yes', 'Yes'),
|
||||
('no', 'No')
|
||||
], 'Company Mail A/c',
|
||||
readonly=True,
|
||||
help="Select if this mail account does not belong" \
|
||||
"to specific user but the organisation as a whole." \
|
||||
"eg:info@somedomain.com",
|
||||
required=True, states={
|
||||
'draft':[('readonly', False)]
|
||||
}),
|
||||
|
||||
'state':fields.selection([
|
||||
('draft', 'Initiated'),
|
||||
('suspended', 'Suspended'),
|
||||
('approved', 'Approved')
|
||||
],
|
||||
'Account Status', required=True, readonly=True),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'name':lambda self, cursor, user, context:self.pool.get(
|
||||
'res.users'
|
||||
).read(
|
||||
cursor,
|
||||
user,
|
||||
user,
|
||||
['name'],
|
||||
context
|
||||
)['name'],
|
||||
'smtpssl':lambda * a:True,
|
||||
'state':lambda * a:'draft',
|
||||
'user':lambda self, cursor, user, context:user,
|
||||
'send_pref':lambda * a: 'html',
|
||||
'smtptls':lambda * a:True,
|
||||
}
|
||||
|
||||
_sql_constraints = [
|
||||
(
|
||||
'email_uniq',
|
||||
'unique (email_id)',
|
||||
'Another setting already exists with this email ID !')
|
||||
]
|
||||
|
||||
def _constraint_unique(self, cursor, user, ids):
|
||||
"""
|
||||
This makes sure that you dont give personal
|
||||
users two accounts with same ID (Validated in sql constaints)
|
||||
However this constraint exempts company accounts.
|
||||
Any no of co accounts for a user is allowed
|
||||
"""
|
||||
if self.read(cursor, user, ids, ['company'])[0]['company'] == 'no':
|
||||
accounts = self.search(cursor, user, [
|
||||
('user', '=', user),
|
||||
('company', '=', 'no')
|
||||
])
|
||||
if len(accounts) > 1 :
|
||||
return False
|
||||
else :
|
||||
return True
|
||||
else:
|
||||
return True
|
||||
|
||||
_constraints = [
|
||||
(_constraint_unique,
|
||||
'Error: You are not allowed to have more than 1 account.',
|
||||
[])
|
||||
]
|
||||
|
||||
def on_change_emailid(self, cursor, user, ids, name=None, email_id=None, context=None):
|
||||
"""
|
||||
Called when the email ID field changes.
|
||||
|
||||
UI enhancement
|
||||
Writes the same email value to the smtpusername
|
||||
and incoming username
|
||||
"""
|
||||
#TODO: Check and remove the write. Is it needed?
|
||||
self.write(cursor, user, ids, {'state':'draft'}, context=context)
|
||||
return {
|
||||
'value': {
|
||||
'state': 'draft',
|
||||
'smtpuname':email_id,
|
||||
'isuser':email_id
|
||||
}
|
||||
}
|
||||
|
||||
def get_outgoing_server(self, cursor, user, ids, context=None):
|
||||
"""
|
||||
Returns the Out Going Connection (SMTP) object
|
||||
|
||||
@attention: DO NOT USE except_osv IN THIS METHOD
|
||||
@param cursor: Database Cursor
|
||||
@param user: ID of current user
|
||||
@param ids: ID/list of ids of current object for
|
||||
which connection is required
|
||||
First ID will be chosen from lists
|
||||
@param context: Context
|
||||
|
||||
@return: SMTP server object or Exception
|
||||
"""
|
||||
#Type cast ids to integer
|
||||
if type(ids) == list:
|
||||
ids = ids[0]
|
||||
this_object = self.browse(cursor, user, ids, context)
|
||||
if this_object:
|
||||
if this_object.smtpserver and this_object.smtpport:
|
||||
try:
|
||||
if this_object.smtpssl:
|
||||
serv = smtplib.SMTP_SSL(this_object.smtpserver, this_object.smtpport)
|
||||
else:
|
||||
serv = smtplib.SMTP(this_object.smtpserver, this_object.smtpport)
|
||||
if this_object.smtptls:
|
||||
serv.ehlo()
|
||||
serv.starttls()
|
||||
serv.ehlo()
|
||||
except Exception, error:
|
||||
raise error
|
||||
try:
|
||||
if serv.has_extn('AUTH') or this_object.smtpuname or this_object.smtppass:
|
||||
serv.login(this_object.smtpuname, this_object.smtppass)
|
||||
except Exception, error:
|
||||
raise error
|
||||
return serv
|
||||
raise Exception(_("SMTP SERVER or PORT not specified"))
|
||||
raise Exception(_("Core connection for the given ID does not exist"))
|
||||
|
||||
def check_outgoing_connection(self, cursor, user, ids, context=None):
|
||||
"""
|
||||
checks SMTP credentials and confirms if outgoing connection works
|
||||
(Attached to button)
|
||||
@param cursor: Database Cursor
|
||||
@param user: ID of current user
|
||||
@param ids: list of ids of current object for
|
||||
which connection is required
|
||||
@param context: Context
|
||||
"""
|
||||
try:
|
||||
self.get_outgoing_server(cursor, user, ids, context)
|
||||
raise osv.except_osv(_("SMTP Test Connection Was Successful"), '')
|
||||
except osv.except_osv, success_message:
|
||||
raise success_message
|
||||
except Exception, error:
|
||||
raise osv.except_osv(
|
||||
_("Out going connection test failed"),
|
||||
_("Reason: %s") % error
|
||||
)
|
||||
|
||||
def do_approval(self, cr, uid, ids, context={}):
|
||||
#TODO: Check if user has rights
|
||||
self.write(cr, uid, ids, {'state':'approved'}, context=context)
|
||||
# wf_service = netsvc.LocalService("workflow")
|
||||
|
||||
def smtp_connection(self, cursor, user, id, context=None):
|
||||
"""
|
||||
This method should now wrap smtp_connection
|
||||
"""
|
||||
#This function returns a SMTP server object
|
||||
logger = netsvc.Logger()
|
||||
core_obj = self.browse(cursor, user, id, context)
|
||||
if core_obj.smtpserver and core_obj.smtpport and core_obj.state == 'approved':
|
||||
try:
|
||||
serv = self.get_outgoing_server(cursor, user, id, context)
|
||||
except Exception, error:
|
||||
logger.notifyChannel(_("Email Template"), netsvc.LOG_ERROR, _("Mail from Account %s failed on login. Probable Reason:Could not login to server\nError: %s") % (id, error))
|
||||
return False
|
||||
#Everything is complete, now return the connection
|
||||
return serv
|
||||
else:
|
||||
logger.notifyChannel(_("Email Template"), netsvc.LOG_ERROR, _("Mail from Account %s failed. Probable Reason:Account not approved") % id)
|
||||
return False
|
||||
|
||||
#**************************** MAIL SENDING FEATURES ***********************#
|
||||
def split_to_ids(self, ids_as_str):
|
||||
"""
|
||||
Identifies email IDs separated by separators
|
||||
and returns a list
|
||||
TODO: Doc this
|
||||
"a@b.com,c@bcom; d@b.com;e@b.com->['a@b.com',...]"
|
||||
"""
|
||||
email_sep_by_commas = ids_as_str \
|
||||
.replace('; ', ',') \
|
||||
.replace(';', ',') \
|
||||
.replace(', ', ',')
|
||||
return email_sep_by_commas.split(',')
|
||||
|
||||
def get_ids_from_dict(self, addresses={}):
|
||||
"""
|
||||
TODO: Doc this
|
||||
"""
|
||||
result = {'all':[]}
|
||||
keys = ['To', 'CC', 'BCC']
|
||||
for each in keys:
|
||||
ids_as_list = self.split_to_ids(addresses.get(each, u''))
|
||||
while u'' in ids_as_list:
|
||||
ids_as_list.remove(u'')
|
||||
result[each] = ids_as_list
|
||||
result['all'].extend(ids_as_list)
|
||||
return result
|
||||
|
||||
def send_mail(self, cr, uid, ids, addresses, subject='', body=None, payload=None, context=None):
|
||||
#TODO: Replace all this crap with a single email object
|
||||
if body is None:
|
||||
body = {}
|
||||
if payload is None:
|
||||
payload = {}
|
||||
if context is None:
|
||||
context = {}
|
||||
logger = netsvc.Logger()
|
||||
for id in ids:
|
||||
core_obj = self.browse(cr, uid, id, context)
|
||||
serv = self.smtp_connection(cr, uid, id)
|
||||
if serv:
|
||||
try:
|
||||
msg = MIMEMultipart()
|
||||
if subject:
|
||||
msg['Subject'] = subject
|
||||
sender_name = Header(core_obj.name, 'utf-8').encode()
|
||||
msg['From'] = sender_name + " <" + core_obj.email_id + ">"
|
||||
msg['Organization'] = tools.ustr(core_obj.user.company_id.name)
|
||||
msg['Date'] = formatdate()
|
||||
addresses_l = self.get_ids_from_dict(addresses)
|
||||
if addresses_l['To']:
|
||||
msg['To'] = u','.join(addresses_l['To'])
|
||||
if addresses_l['CC']:
|
||||
msg['CC'] = u','.join(addresses_l['CC'])
|
||||
# if addresses_l['BCC']:
|
||||
# msg['BCC'] = u','.join(addresses_l['BCC'])
|
||||
if body.get('text', False):
|
||||
temp_body_text = body.get('text', '')
|
||||
l = len(temp_body_text.replace(' ', '').replace('\r', '').replace('\n', ''))
|
||||
if l == 0:
|
||||
body['text'] = u'No Mail Message'
|
||||
# Attach parts into message container.
|
||||
# According to RFC 2046, the last part of a multipart message, in this case
|
||||
# the HTML message, is best and preferred.
|
||||
if core_obj.send_pref == 'text' or core_obj.send_pref == 'both':
|
||||
body_text = body.get('text', u'No Mail Message')
|
||||
body_text = tools.ustr(body_text)
|
||||
msg.attach(MIMEText(body_text.encode("utf-8"), _charset='UTF-8'))
|
||||
if core_obj.send_pref == 'html' or core_obj.send_pref == 'both':
|
||||
html_body = body.get('html', u'')
|
||||
if len(html_body) == 0 or html_body == u'':
|
||||
html_body = body.get('text', u'<p>No Mail Message</p>').replace('\n', '<br/>').replace('\r', '<br/>')
|
||||
html_body = tools.ustr(html_body)
|
||||
msg.attach(MIMEText(html_body.encode("utf-8"), _subtype='html', _charset='UTF-8'))
|
||||
#Now add attachments if any
|
||||
for file in payload.keys():
|
||||
part = MIMEBase('application', "octet-stream")
|
||||
part.set_payload(base64.decodestring(payload[file]))
|
||||
part.add_header('Content-Disposition', 'attachment; filename="%s"' % file)
|
||||
Encoders.encode_base64(part)
|
||||
msg.attach(part)
|
||||
except Exception, error:
|
||||
logger.notifyChannel(_("Email Template"), netsvc.LOG_ERROR, _("Mail from Account %s failed. Probable Reason:MIME Error\nDescription: %s") % (id, error))
|
||||
return error
|
||||
try:
|
||||
#print msg['From'],toadds
|
||||
serv.sendmail(msg['From'], addresses_l['all'], msg.as_string())
|
||||
except Exception, error:
|
||||
logger.notifyChannel(_("Email Template"), netsvc.LOG_ERROR, _("Mail from Account %s failed. Probable Reason:Server Send Error\nDescription: %s") % (id, error))
|
||||
return error
|
||||
#The mail sending is complete
|
||||
serv.close()
|
||||
logger.notifyChannel(_("Email Template"), netsvc.LOG_INFO, _("Mail from Account %s successfully Sent.") % (id))
|
||||
return True
|
||||
else:
|
||||
logger.notifyChannel(_("Email Template"), netsvc.LOG_ERROR, _("Mail from Account %s failed. Probable Reason:Account not approved") % id)
|
||||
|
||||
def extracttime(self, time_as_string):
|
||||
"""
|
||||
TODO: DOC THis
|
||||
"""
|
||||
logger = netsvc.Logger()
|
||||
#The standard email dates are of format similar to:
|
||||
#Thu, 8 Oct 2009 09:35:42 +0200
|
||||
#print time_as_string
|
||||
date_as_date = False
|
||||
convertor = {'+':1, '-':-1}
|
||||
try:
|
||||
time_as_string = time_as_string.replace(',', '')
|
||||
date_list = time_as_string.split(' ')
|
||||
date_temp_str = ' '.join(date_list[1:5])
|
||||
if len(date_list) >= 6:
|
||||
sign = convertor.get(date_list[5][0], False)
|
||||
else:
|
||||
sign = False
|
||||
try:
|
||||
dt = datetime.datetime.strptime(
|
||||
date_temp_str,
|
||||
"%d %b %Y %H:%M:%S")
|
||||
except:
|
||||
try:
|
||||
dt = datetime.datetime.strptime(
|
||||
date_temp_str,
|
||||
"%d %b %Y %H:%M")
|
||||
except:
|
||||
return False
|
||||
if sign:
|
||||
try:
|
||||
offset = datetime.timedelta(
|
||||
hours=sign * int(
|
||||
date_list[5][1:3]
|
||||
),
|
||||
minutes=sign * int(
|
||||
date_list[5][3:5]
|
||||
)
|
||||
)
|
||||
except Exception, e2:
|
||||
"""Looks like UT or GMT, just forget decoding"""
|
||||
return False
|
||||
else:
|
||||
offset = datetime.timedelta(hours=0)
|
||||
dt = dt + offset
|
||||
date_as_date = dt.strftime('%Y-%m-%d %H:%M:%S')
|
||||
#print date_as_date
|
||||
except Exception, e:
|
||||
logger.notifyChannel(
|
||||
_("Email Template"),
|
||||
netsvc.LOG_WARNING,
|
||||
_(
|
||||
"Datetime Extraction failed.Date:%s \
|
||||
\tError:%s") % (
|
||||
time_as_string,
|
||||
e)
|
||||
)
|
||||
return date_as_date
|
||||
|
||||
def send_receive(self, cr, uid, ids, context=None):
|
||||
self.get_mails(cr, uid, ids, context)
|
||||
for id in ids:
|
||||
ctx = context.copy()
|
||||
ctx['filters'] = [('account_id', '=', id)]
|
||||
self.pool.get('email_template.mailbox').send_all_mail(cr, uid, [], context=ctx)
|
||||
return True
|
||||
|
||||
def decode_header_text(self, text):
|
||||
""" Decode internationalized headers RFC2822.
|
||||
To, CC, BCC, Subject fields can contain
|
||||
text slices with different encodes, like:
|
||||
=?iso-8859-1?Q?Enric_Mart=ED?= <enricmarti@company.com>,
|
||||
=?Windows-1252?Q?David_G=F3mez?= <david@company.com>
|
||||
Sometimes they include extra " character at the beginning/
|
||||
end of the contact name, like:
|
||||
"=?iso-8859-1?Q?Enric_Mart=ED?=" <enricmarti@company.com>
|
||||
and decode_header() does not work well, so we use regular
|
||||
expressions (?= ? ? ?=) to split the text slices
|
||||
"""
|
||||
if not text:
|
||||
return text
|
||||
p = re.compile("(=\?.*?\?.\?.*?\?=)")
|
||||
text2 = ''
|
||||
try:
|
||||
for t2 in p.split(text):
|
||||
text2 += ''.join(
|
||||
[s.decode(
|
||||
t or 'ascii'
|
||||
) for (s, t) in decode_header(t2)]
|
||||
).encode('utf-8')
|
||||
except:
|
||||
return text
|
||||
return text2
|
||||
|
||||
email_template_account()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -0,0 +1,110 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<menuitem name="Tools" id="base.menu_tools" icon="STOCK_PREFERENCES" sequence="15"/>
|
||||
<menuitem name="Email Template" id="menu_email_template" parent="base.menu_tools"/>
|
||||
|
||||
<record model="ir.ui.view" id="email_template_account_form">
|
||||
<field name="name">email_template.account.form</field>
|
||||
<field name="model">email_template.account</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Email Account Configuration">
|
||||
<group colspan="2">
|
||||
<field name="name" select="1" />
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page string="Outgoing">
|
||||
<separator string="Server Information" colspan="4" />
|
||||
<group colspan="4">
|
||||
<field name="smtpserver" select="1" colspan="2" />
|
||||
<field name="smtpport" select="2" colspan="2" />
|
||||
<field name="smtpssl" select="2" colspan="2" />
|
||||
<field name="smtptls" select="2" colspan="2" />
|
||||
</group>
|
||||
<button name="check_outgoing_connection" type="object" string="Check Outgoing Connection" />
|
||||
<separator string="User Information" colspan="4" />
|
||||
<group col="2" colspan="2">
|
||||
<field name="email_id" select="1" on_change="on_change_emailid(name,email_id)" colspan="2" />
|
||||
<field name="smtppass" password="True" colspan="2" />
|
||||
<field name="company" select="2" colspan="2" />
|
||||
</group>
|
||||
<group col="2" colspan="2">
|
||||
<field name="smtpuname" select="1" colspan="2" />
|
||||
<field name="user" select="2" colspan="2" />
|
||||
<field name="send_pref" colspan="2" />
|
||||
</group>
|
||||
</page>
|
||||
<page string="security" attrs="{'invisible':[('company','!=','yes')]}">
|
||||
<field name="allowed_groups" attrs="{'required':[('company','=','yes')]}" nolabel="1"/>
|
||||
</page>
|
||||
</notebook>
|
||||
<group colspan="4" col="10">
|
||||
<field name="state" select="1"/>
|
||||
<button string="Approve Account" name="button_approval" states="draft" type="workflow"/>
|
||||
<button string="Suspend Account" name="button_suspended" states="approved" type="workflow" />
|
||||
<button string="Request Re-activation" name="get_reapprove" states="suspended" type="workflow" />
|
||||
<button string="Send/Receive" name="send_receive" states="approved" type="object" />
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="email_template_account_tree">
|
||||
<field name="name">email_template.account.tree</field>
|
||||
<field name="model">email_template.account</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="SMTP Server">
|
||||
<field name="name" select="2" />
|
||||
<field name="email_id" select="2" />
|
||||
<field name="smtpuname" select="2" />
|
||||
<field name="user" select="2" />
|
||||
<field name="smtpserver" select="2" />
|
||||
<field name="smtpport" select="2" />
|
||||
<field name="state" select="2" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_email_template_account_search" model="ir.ui.view">
|
||||
<field name="name">email_template.account.search</field>
|
||||
<field name="model">email_template.account</field>
|
||||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Accounts">
|
||||
<filter icon="terp-crm" string="My Accounts" name="my" domain="[('user','=',uid)]"/>
|
||||
<filter icon="terp-crm" string="Personal Accounts" domain="[('company','=','no')]"/>
|
||||
<filter icon="terp-crm" string="Company Accounts" domain="[('company','=','yes')]"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter icon="terp-crm" string="Draft" name="draft" domain="[('state','=','draft')]"/>
|
||||
<filter icon="terp-crm" string="Suspended" domain="[('state','=','suspended')]"/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="name" select="1"/>
|
||||
<field name="user" select="1"/>
|
||||
<field name="email_id" select="1"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_email_template_account_tree_all">
|
||||
<field name="name">Accounts</field>
|
||||
<field name="res_model">email_template.account</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form,tree</field>
|
||||
<field name="view_id" ref="email_template_account_tree" />
|
||||
<field name="context">{'group_by': [], 'search_default_draft': 1, 'search_default_my': 1}</field>
|
||||
<field name="search_view_id" ref="view_email_template_account_search"/>
|
||||
</record>
|
||||
|
||||
<menuitem name="Configuration" id="menu_email_template_configuration" parent="menu_email_template" />
|
||||
|
||||
<menuitem name="All Accounts" id="menu_email_template_account_all" parent="menu_email_template_configuration" action="action_email_template_account_tree_all" groups="res_groups_email_template_manager" />
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
# To change this template, choose Tools | Templates
|
||||
# and open the template in the editor.
|
||||
from osv import fields,osv
|
||||
import pooler
|
||||
import netsvc
|
||||
import re
|
||||
|
||||
class email_template_engines(osv.osv):
|
||||
_name = "email_template.engines"
|
||||
_description = "Email Template Engine"
|
||||
|
||||
# def __init__(self):
|
||||
# print "Started Engine"
|
||||
|
||||
def check(self):
|
||||
print "Start self check"
|
||||
|
||||
def strip_html(self,text):
|
||||
#Removes HTML, Have to check if still relevent
|
||||
if text:
|
||||
def fixup(m):
|
||||
text = m.group(0)
|
||||
if text[:1] == "<":
|
||||
return "" # ignore tags
|
||||
if text[:2] == "&#":
|
||||
try:
|
||||
if text[:3] == "&#x":
|
||||
return unichr(int(text[3:-1], 16))
|
||||
else:
|
||||
return unichr(int(text[2:-1]))
|
||||
except ValueError:
|
||||
pass
|
||||
elif text[:1] == "&":
|
||||
import htmlentitydefs
|
||||
entity = htmlentitydefs.entitydefs.get(text[1:-1])
|
||||
if entity:
|
||||
if entity[:2] == "&#":
|
||||
try:
|
||||
return unichr(int(entity[2:-1]))
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
return unicode(entity, "iso-8859-1")
|
||||
return text # leave as is
|
||||
return re.sub("(?s)<[^>]*>|&#?\w+;", fixup, text)
|
||||
|
||||
def parsevalue(self,cr,uid,id,message,templateid,context):
|
||||
#id: ID of the template's model's record to be used
|
||||
#message: the complete text including placeholders
|
||||
#templateid: the template id of the template
|
||||
#context: TODO
|
||||
#print cr,uid,id,message,templateid,context
|
||||
if message:
|
||||
logger = netsvc.Logger()
|
||||
def merge(match):
|
||||
template = self.pool.get("email.template").browse(cr,uid,templateid,context)
|
||||
obj_pool = self.pool.get(template.object_name.model)
|
||||
obj = obj_pool.browse(cr, uid, id, context)
|
||||
exp = str(match.group()[2:-2]).strip()
|
||||
#print "level 1:",exp
|
||||
exp_spl = exp.split('/')
|
||||
#print "level 2:",exp_spl
|
||||
try:
|
||||
result = eval(exp_spl[0], {'object':obj,})
|
||||
except:
|
||||
result = "Rendering Error"
|
||||
#print "result:",result
|
||||
try:
|
||||
if result in (None, False):
|
||||
if len(exp_spl)>1:
|
||||
return exp_spl[1]
|
||||
else:
|
||||
return 'Not Available'
|
||||
return str(result)
|
||||
except:
|
||||
return "Rendering Error"
|
||||
if message:
|
||||
com = re.compile('(\[\[.+?\]\])')
|
||||
retmessage = com.sub(merge, message)
|
||||
else:
|
||||
retmessage=""
|
||||
return retmessage
|
||||
|
||||
email_template_engines()
|
|
@ -0,0 +1,182 @@
|
|||
from osv import osv, fields
|
||||
import time
|
||||
import email_template_engines
|
||||
import netsvc
|
||||
from tools.translate import _
|
||||
import tools
|
||||
|
||||
LOGGER = netsvc.Logger()
|
||||
|
||||
class email_template_mailbox(osv.osv):
|
||||
_name = "email_template.mailbox"
|
||||
_description = 'Email Mailbox'
|
||||
_rec_name = "subject"
|
||||
_order = "date_mail desc"
|
||||
|
||||
def run_mail_scheduler(self, cursor, user, context=None):
|
||||
"""
|
||||
This method is called by Open ERP Scheduler
|
||||
to periodically send emails
|
||||
"""
|
||||
try:
|
||||
self.send_all_mail(cursor, user, context)
|
||||
except Exception, e:
|
||||
LOGGER.notifyChannel(
|
||||
_("Email Template"),
|
||||
netsvc.LOG_ERROR,
|
||||
_("Error sending mail: %s" % str(e)))
|
||||
|
||||
def send_all_mail(self, cr, uid, ids=None, context=None):
|
||||
if ids is None:
|
||||
ids = []
|
||||
if context is None:
|
||||
context = {}
|
||||
filters = [('folder', '=', 'outbox'), ('state', '!=', 'sending')]
|
||||
if 'filters' in context.keys():
|
||||
for each_filter in context['filters']:
|
||||
filters.append(each_filter)
|
||||
ids = self.search(cr, uid, filters, context=context)
|
||||
self.write(cr, uid, ids, {'state':'sending'}, context)
|
||||
self.send_this_mail(cr, uid, ids, context)
|
||||
return True
|
||||
|
||||
def send_this_mail(self, cr, uid, ids=None, context=None):
|
||||
if ids is None:
|
||||
ids = []
|
||||
for id in ids:
|
||||
try:
|
||||
account_obj = self.pool.get('email_template.account')
|
||||
values = self.read(cr, uid, id, [], context)
|
||||
payload = {}
|
||||
if values['attachments_ids']:
|
||||
for attid in values['attachments_ids']:
|
||||
attachment = self.pool.get('ir.attachment').browse(cr, uid, attid, context)#,['datas_fname','datas'])
|
||||
payload[attachment.datas_fname] = attachment.datas
|
||||
print "233333333333333"
|
||||
result = account_obj.send_mail(cr, uid,
|
||||
[values['account_id'][0]],
|
||||
{'To':values.get('email_to', u'') or u'', 'CC':values.get('email_cc', u'') or u'', 'BCC':values.get('email_bcc', u'') or u''},
|
||||
values['subject'] or u'',
|
||||
{'text':values.get('body_text', u'') or u'', 'html':values.get('body_html', u'') or u''},
|
||||
payload=payload, context=context)
|
||||
|
||||
if result == True:
|
||||
self.write(cr, uid, id, {'folder':'sent', 'state':'na', 'date_mail':time.strftime("%Y-%m-%d %H:%M:%S")}, context)
|
||||
self.historise(cr, uid, [id], "Email sent successfully", context)
|
||||
else:
|
||||
self.historise(cr, uid, [id], result, context)
|
||||
except Exception, error:
|
||||
logger = netsvc.Logger()
|
||||
logger.notifyChannel(_("Power Email"), netsvc.LOG_ERROR, _("Sending of Mail %s failed. Probable Reason:Could not login to server\nError: %s") % (id, error))
|
||||
self.historise(cr, uid, [id], error, context)
|
||||
self.write(cr, uid, id, {'state':'na'}, context)
|
||||
return True
|
||||
|
||||
def historise(self, cr, uid, ids, message='', context=None):
|
||||
for id in ids:
|
||||
history = self.read(cr, uid, id, ['history'], context).get('history', '')
|
||||
self.write(cr, uid, id, {'history':history or '' + "\n" + time.strftime("%Y-%m-%d %H:%M:%S") + ": " + tools.ustr(message)}, context)
|
||||
|
||||
_columns = {
|
||||
'email_from':fields.char(
|
||||
'From',
|
||||
size=64),
|
||||
'email_to':fields.char(
|
||||
'Recepient (To)',
|
||||
size=250,),
|
||||
'email_cc':fields.char(
|
||||
' CC',
|
||||
size=250),
|
||||
'email_bcc':fields.char(
|
||||
' BCC',
|
||||
size=250),
|
||||
'subject':fields.char(
|
||||
' Subject',
|
||||
size=200,),
|
||||
'body_text':fields.text(
|
||||
'Standard Body (Text)'),
|
||||
'body_html':fields.text(
|
||||
'Body (Text-Web Client Only)'),
|
||||
'attachments_ids':fields.many2many(
|
||||
'ir.attachment',
|
||||
'mail_attachments_rel',
|
||||
'mail_id',
|
||||
'att_id',
|
||||
'Attachments'),
|
||||
'account_id' :fields.many2one(
|
||||
'email_template.account',
|
||||
'User account',
|
||||
required=True),
|
||||
'user':fields.related(
|
||||
'account_id',
|
||||
'user',
|
||||
type="many2one",
|
||||
relation="res.users",
|
||||
string="User"),
|
||||
'server_ref':fields.integer(
|
||||
'Server Reference of mail',
|
||||
help="Applicable for inward items only"),
|
||||
'mail_type':fields.selection([
|
||||
('multipart/mixed',
|
||||
'Has Attachments'),
|
||||
('multipart/alternative',
|
||||
'Plain Text & HTML with no attachments'),
|
||||
('multipart/related',
|
||||
'Intermixed content'),
|
||||
('text/plain',
|
||||
'Plain Text'),
|
||||
('text/html',
|
||||
'HTML Body'),
|
||||
], 'Mail Contents'),
|
||||
#I like GMAIL which allows putting same mail in many folders
|
||||
#Lets plan it for 0.9
|
||||
'folder':fields.selection([
|
||||
('drafts', 'Drafts'),
|
||||
('outbox', 'Outbox'),
|
||||
('trash', 'Trash'),
|
||||
('sent', 'Sent Items'),
|
||||
], 'Folder', required=True),
|
||||
'state':fields.selection([
|
||||
('na', 'Not Applicable'),
|
||||
('sending', 'Sending'),
|
||||
], 'Status', required=True),
|
||||
'date_mail':fields.datetime(
|
||||
'Rec/Sent Date'),
|
||||
'history':fields.text(
|
||||
'History',
|
||||
readonly=True,
|
||||
store=True)
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'state': lambda * a: 'na',
|
||||
'folder': lambda * a: 'outbox',
|
||||
}
|
||||
|
||||
def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
|
||||
if context is None:
|
||||
context = {}
|
||||
if context.get('company', False):
|
||||
users_groups = self.pool.get('res.users').browse(cr, uid, uid, context).groups_id
|
||||
group_acc_rel = {}
|
||||
#get all accounts and get a table of {group1:[account1,account2],group2:[account1]}
|
||||
for each_account_id in self.pool.get('email_template.account').search(cr, uid, [('state', '=', 'approved'), ('company', '=', 'yes')], context=context):
|
||||
account = self.pool.get('email_template.account').browse(cr, uid, each_account_id, context)
|
||||
for each_group in account.allowed_groups:
|
||||
if not account.id in group_acc_rel.get(each_group, []):
|
||||
groups = group_acc_rel.get(each_group, [])
|
||||
groups.append(account.id)
|
||||
group_acc_rel[each_group] = groups
|
||||
users_company_accounts = []
|
||||
for each_group in group_acc_rel.keys():
|
||||
if each_group in users_groups:
|
||||
for each_account in group_acc_rel[each_group]:
|
||||
if not each_account in users_company_accounts:
|
||||
users_company_accounts.append(each_account)
|
||||
args.append(('account_id', 'in', users_company_accounts))
|
||||
return super(osv.osv, self).search(cr, uid, args, offset, limit,
|
||||
order, context=context, count=count)
|
||||
|
||||
email_template_mailbox()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -0,0 +1,170 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<!-- Email Template-->
|
||||
<record model="ir.ui.view" id="email_template_mailbox_form">
|
||||
<field name="name">email_template.mailbox.form</field>
|
||||
<field name="model">email_template.mailbox</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Outbox">
|
||||
<group col="4" colspan="2">
|
||||
<field name="email_from" colspan="4" select="1"/>
|
||||
<field name="email_cc" colspan="4" select="1"/>
|
||||
<field name="date_mail" colspan="4" select="2"/>
|
||||
</group>
|
||||
<group col="4" colspan="2">
|
||||
<field name="email_to" colspan="4" required="1" select="1" />
|
||||
<field name="email_bcc" colspan="4" select="2"/>
|
||||
<field name="subject" colspan="4" select="1"/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page string="Standard Body">
|
||||
<separator colspan="4" string="Standard Body" />
|
||||
<notebook colspan="4">
|
||||
<page string="Standard Body (Text)">
|
||||
<field name="body_text" nolabel="1" colspan="4" select="1"/>
|
||||
</page>
|
||||
<page string="Body (HTML-Web Client Only)">
|
||||
<field name="body_html" nolabel="1" colspan="4" />
|
||||
<!--<label string="Note: HTML body can't be edited with GTK desktop client." colspan="4"/>
|
||||
--></page>
|
||||
|
||||
</notebook>
|
||||
</page>
|
||||
|
||||
|
||||
<page string="Attachments">
|
||||
<group col="4">
|
||||
<separator colspan="4" string="Attachments" />
|
||||
<field name="attachments_ids" colspan="4" nolabel="1" />
|
||||
</group>
|
||||
</page>
|
||||
<page string="Advanced">
|
||||
<group col="4">
|
||||
<field name="account_id" colspan="2" />
|
||||
<field name="server_ref" colspan="2" />
|
||||
<field name="mail_type" colspan="2" />
|
||||
<field name="folder" colspan="2" select="2"/>
|
||||
<separator string="History" colspan="4" />
|
||||
<field name="history" nolabel="1" colspan="4"/>
|
||||
</group>
|
||||
</page>
|
||||
</notebook>
|
||||
<separator colspan="4" string="" />
|
||||
<group col="4" colspan="4">
|
||||
<field name="state" colspan="2" readonly="1" />
|
||||
<button name="complete_mail" type="object" string="Download Full Mail" colspan="2" states="read,unread" />
|
||||
<button name="send_this_mail" type="object" string="Send Mail" />
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!--============================================= TREE VIEWS =============================================-->
|
||||
<!--DRAFTS-->
|
||||
<record model="ir.ui.view" id="email_template_drafts_tree">
|
||||
<field name="name">email_template.mailbox.draftstree</field>
|
||||
<field name="model">email_template.mailbox</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Drafts">
|
||||
<field name="user" />
|
||||
<field name="email_from" select="1" />
|
||||
<field name="subject" select="1" />
|
||||
<field name="attachments_ids" select="2" />
|
||||
<field name="date_mail" select="2" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<!--OUTBOX-->
|
||||
<record model="ir.ui.view" id="email_template_outbox_tree">
|
||||
<field name="name">email_template.mailbox.outboxtree</field>
|
||||
<field name="model">email_template.mailbox</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Outbox">
|
||||
<field name="user" />
|
||||
<field name="email_from" select="1" />
|
||||
<field name="subject" select="1" />
|
||||
<field name="attachments_ids" select="2" />
|
||||
<field name="date_mail" select="2" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<!--SENT-->
|
||||
<record model="ir.ui.view" id="email_template_sentbox_tree">
|
||||
<field name="name">email_template.mailbox.sentboxtree</field>
|
||||
<field name="model">email_template.mailbox</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Sent">
|
||||
<field name="user" />
|
||||
<field name="email_from" select="1" />
|
||||
<field name="subject" select="1" />
|
||||
<field name="attachments_ids" select="2" />
|
||||
<field name="date_mail" select="2" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<!--TRASH-->
|
||||
<record model="ir.ui.view" id="email_template_trashbox_tree">
|
||||
<field name="name">email_template.mailbox.trashboxtree</field>
|
||||
<field name="model">email_template.mailbox</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Trash">
|
||||
<field name="user" />
|
||||
<field name="email_from" select="1" />
|
||||
<field name="subject" select="1" />
|
||||
<field name="attachments_ids" select="2" />
|
||||
<field name="date_mail" select="2" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_email_template_mailbox_search" model="ir.ui.view">
|
||||
<field name="name">email_template.mailbox.search</field>
|
||||
<field name="model">email_template.mailbox</field>
|
||||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Mailboxes">
|
||||
<filter icon="terp-crm" string="Drafts" name="draft" domain="[('folder','=','drafts']"/>
|
||||
<filter icon="terp-crm" string="Outbox" name="outbox" domain="[('folder','=','outbox')]"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter icon="terp-crm" string="Sent" domain="[('folder','=','sent')]"/>
|
||||
<filter icon="terp-crm" string="Trash" domain="[('folder','=','trash')]"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter icon="terp-crm" string="Not Applicable" domain="[('state','=','na')]"/>
|
||||
<filter icon="terp-crm" string="Sending" domain="[('state','=','sending')]"/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="email_from" select="1"/>
|
||||
<field name="email_to" select="1"/>
|
||||
<field name="subject" select="1"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_email_template_mailbox">
|
||||
<field name="name">Mailbox</field>
|
||||
<field name="res_model">email_template.mailbox</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form,tree</field>
|
||||
<field name="view_id" ref="email_template_outbox_tree" />
|
||||
<field name="context">{'group_by': [], 'search_default_draft': 1, 'search_default_outbox': 1}</field>
|
||||
<field name="search_view_id" ref="view_email_template_mailbox_search"/>
|
||||
</record>
|
||||
|
||||
<!--======================================== MENUS ========================================-->
|
||||
<menuitem name="MailBox" id="menu_email_template_mailbox_all_main2" parent="menu_email_template" />
|
||||
<menuitem name="Personal" id="menu_email_template_personal" parent="menu_email_template_mailbox_all_main2" />
|
||||
<menuitem name="Mails" id="menu_email_template_personal_mails" parent="menu_email_template_personal" action="action_email_template_mailbox"/>
|
||||
<menuitem name="Company" id="menu_email_template_company" parent="menu_email_template_mailbox_all_main2" />
|
||||
<menuitem name="Mails" id="menu_email_template_company_mails" parent="menu_email_template_company" action="action_email_template_mailbox"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
<record forcecreate="True" id="ir_cron_mail_scheduler_action" model="ir.cron">
|
||||
<field name="name">Email Template scheduler</field>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="interval_number">1</field>
|
||||
<field name="interval_type">hours</field>
|
||||
<field name="numbercall">12</field>
|
||||
<field eval="False" name="doall"/>
|
||||
<field eval="'email_template.mailbox'" name="model"/>
|
||||
<field eval="'run_mail_scheduler'" name="function"/>
|
||||
<field eval="'()'" name="args"/>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1,188 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<!-- Email Template PReview -->
|
||||
<record model="ir.ui.view" id="email_template_preview_form">
|
||||
<field name="name">email_template.preview.form</field>
|
||||
<field name="model">email_template.preview</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Email Preview">
|
||||
<field name="rel_model" />
|
||||
<newline />
|
||||
<field name="rel_model_ref" on_change="on_change_ref(rel_model_ref, context)" />
|
||||
<newline />
|
||||
<field name="to" />
|
||||
<newline />
|
||||
<field name="cc" />
|
||||
<newline />
|
||||
<field name="bcc" />
|
||||
<newline />
|
||||
<field name="subject" />
|
||||
<newline />
|
||||
<field name="body_text" />
|
||||
<newline />
|
||||
<!-- <field name="body_html" widget="text_html" />-->
|
||||
<!--
|
||||
Removed text_html because it doesnt work in GTK
|
||||
And TinyMCE messes up the HTML in Web Client
|
||||
-->
|
||||
<field name="body_html"/>
|
||||
<newline />
|
||||
<field name="report" />
|
||||
<group>
|
||||
<button icon="gtk-ok" special="cancel" string="OK" />
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="wizard_email_template_preview" model="ir.actions.act_window">
|
||||
<field name="name">Template Preview</field>
|
||||
<field name="res_model">email_template.preview</field>
|
||||
<field name="src_model">email_template.preview</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="auto_refresh" eval="1" />
|
||||
<field name="target">new</field>
|
||||
<field name="context">{'ids':active_id}</field>
|
||||
</record>
|
||||
<!--EMail client Form view -->
|
||||
|
||||
<record model="ir.ui.view" id="email_template_form">
|
||||
<field name="name">email.template.form</field>
|
||||
<field name="model">email.template</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Email Templates">
|
||||
<field name="name" />
|
||||
<field name="object_name" required="1"
|
||||
on_change="change_model(object_name)" />
|
||||
<field name="model_int_name" invisible="1" />
|
||||
<notebook colspan="4">
|
||||
<page string="Mail Details">
|
||||
<group col="4" colspan="2">
|
||||
<field name="def_to" colspan="4" required="1" />
|
||||
<field name="def_cc" colspan="4" />
|
||||
<field name="def_bcc" colspan="4" />
|
||||
</group>
|
||||
<group col="2" colspan="2">
|
||||
<field name="def_subject" colspan="4" required="1" />
|
||||
<field name="use_sign" colspan="4" />
|
||||
<field name="lang" colspan="4" />
|
||||
</group>
|
||||
<separator colspan="3" string="Standard Body" />
|
||||
<separator colspan="1" string="Expression Builder" />
|
||||
|
||||
<notebook>
|
||||
<page string="Body (Text)">
|
||||
<field name="def_body_text" colspan="4" nolabel="1" />
|
||||
</page>
|
||||
<page string="Body (Raw HTML)">
|
||||
<field name="def_body_html" colspan="4" nolabel="1" />
|
||||
<label string="Note: This is Raw HTML." colspan="4" />
|
||||
</page>
|
||||
</notebook>
|
||||
<group col="4">
|
||||
<field name="template_language"
|
||||
on_change="onchange_null_value(model_object_field,sub_model_object_field,null_value,template_language,context)" />
|
||||
<notebook>
|
||||
<page string="Insert Simple Field">
|
||||
|
||||
<field name="model_object_field"
|
||||
domain="[('model_id','=',object_name),('ttype','!=','one2many'),('ttype','!=','many2many')]"
|
||||
on_change="onchange_model_object_field(model_object_field, template_language,context)"
|
||||
colspan="4" />
|
||||
<field name="sub_object" readonly="1" colspan="4" />
|
||||
<field name="sub_model_object_field"
|
||||
domain="[('model_id','=',sub_object),('ttype','!=','one2many'),('ttype','!=','many2many')]"
|
||||
colspan="4"
|
||||
attrs="{'readonly':[('sub_object','=',False)],'required':[('sub_object','!=',False)]}"
|
||||
on_change="onchange_sub_model_object_field(model_object_field,sub_model_object_field,template_language,context)" />
|
||||
<field name="null_value" colspan="4"
|
||||
on_change="onchange_null_value(model_object_field,sub_model_object_field,null_value,template_language,context)" />
|
||||
<field name="copyvalue" colspan="4" />
|
||||
</page>
|
||||
</notebook>
|
||||
<button name="%(wizard_email_template_preview)d" string="Preview Template"
|
||||
type="action" colspan="4" target="new" />
|
||||
</group>
|
||||
</page>
|
||||
<page string="Security">
|
||||
<separator colspan="4" string="Allowed User Groups" />
|
||||
<field name="allowed_groups" string="Allowed User Groups"
|
||||
nolabel="1" />
|
||||
</page>
|
||||
<page string="Advanced">
|
||||
<separator string="Automatic Email" colspan="4" />
|
||||
<field name="enforce_from_account" attrs="{'required':[('auto_email','=',True)]}" />
|
||||
<newline/>
|
||||
<field name="ref_ir_act_window" />
|
||||
<field name="ref_ir_value" />
|
||||
<separator string="Attachments (Report to attach)" colspan="4"/>
|
||||
<field name="file_name" colspan="2" />
|
||||
<field name="report_template" colspan="2"
|
||||
domain="[('model','=',model_int_name)]" />
|
||||
</page>
|
||||
</notebook>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="email_template_tree">
|
||||
<field name="name">email.template.tree</field>
|
||||
<field name="model">email.template</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Email Templates">
|
||||
<field name="name" select="1" />
|
||||
<field name="object_name" required="1" select="1" />
|
||||
<field name="def_to" colspan="4" select="2" />
|
||||
<field name="def_cc" colspan="4" select="2" />
|
||||
<field name="def_bcc" colspan="4" select="2" />
|
||||
<field name="def_subject" colspan="4" select="2" />
|
||||
<field name="use_sign" colspan="4" select="2" />
|
||||
<field name="file_name" colspan="4" />
|
||||
<field name="enforce_from_account" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_email_template_search" model="ir.ui.view">
|
||||
<field name="name">email.template.search</field>
|
||||
<field name="model">email.template</field>
|
||||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Templates">
|
||||
<separator orientation="vertical"/>
|
||||
<field name="name" select="1"/>
|
||||
<field name="object_name" select="1"/>
|
||||
<field name="def_to" select="1"/>
|
||||
<separator orientation="vertical"/>
|
||||
<field name="lang" select="1"/>
|
||||
<field name="def_subject" select="1"/>
|
||||
<field name="file_name" select="1"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_email_template_tree_all">
|
||||
<field name="name">Email Templates</field>
|
||||
<field name="res_model">email.template</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form,tree</field>
|
||||
<field name="view_id" ref="email_template_tree" />
|
||||
<field name="search_view_id" ref="view_email_template_search"/>
|
||||
</record>
|
||||
|
||||
<menuitem name="E-MAIL Templates" id="menu_email_template_all"
|
||||
parent="menu_email_template_configuration" action="action_email_template_tree_all" />
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record id="PE_ADMIN" model="res.roles">
|
||||
<field name="name">Email Administrator</field>
|
||||
</record>
|
||||
|
||||
<record id="wkf_email_template_setting" model="workflow">
|
||||
<field name="name">Email Template Workflow</field>
|
||||
<field name="osv">email_template.account</field>
|
||||
<field name="on_create">True</field>
|
||||
</record>
|
||||
|
||||
<!--Activity -->
|
||||
|
||||
<record id="act_draft" model="workflow.activity">
|
||||
<field name="wkf_id" ref="wkf_email_template_setting"/>
|
||||
<field name="flow_start">True</field>
|
||||
<field name="name">draft</field>
|
||||
<field name="kind">function</field>
|
||||
<field name="action">write({'state':'draft'})</field>
|
||||
</record>
|
||||
|
||||
<record id="act_approved" model="workflow.activity">
|
||||
<field name="name">approval</field>
|
||||
<field name="wkf_id" ref="wkf_email_template_setting"/>
|
||||
<field name="kind">function</field>
|
||||
<field name="action">do_approval()</field>
|
||||
</record>
|
||||
|
||||
<record id="act_suspended" model="workflow.activity">
|
||||
<field name="name">suspended</field>
|
||||
<field name="wkf_id" ref="wkf_email_template_setting"/>
|
||||
<field name="kind">function</field>
|
||||
<field name="action">write({'state':'suspended'})</field>
|
||||
</record>
|
||||
<record id="act_dummy" model="workflow.activity">
|
||||
<field name="name">dummy</field>
|
||||
<field name="wkf_id" ref="wkf_email_template_setting"/>
|
||||
<field name="flow_stop">True</field>
|
||||
</record>
|
||||
|
||||
<!-- Transition -->
|
||||
|
||||
<record id="trans_awaiting_approved" model="workflow.transition">
|
||||
<field name="act_from" ref="act_draft"/>
|
||||
<field name="act_to" ref="act_approved"/>
|
||||
<field name="signal">button_approval</field>
|
||||
<field name="role_id" ref="PE_ADMIN"/>
|
||||
</record>
|
||||
|
||||
<record id="trans_approved_suspended" model="workflow.transition">
|
||||
<field name="act_from" ref="act_approved"/>
|
||||
<field name="act_to" ref="act_suspended"/>
|
||||
<field name="signal">button_suspended</field>
|
||||
<field name="role_id" ref="PE_ADMIN"/>
|
||||
</record>
|
||||
<record id="trans_suspended_reapproved" model="workflow.transition">
|
||||
<field name="act_from" ref="act_suspended"/>
|
||||
<field name="act_to" ref="act_draft"/>
|
||||
<field name="signal">get_reapprove</field>
|
||||
<field name="role_id" ref="PE_ADMIN"/>
|
||||
</record>
|
||||
<record id="trans_suspended_dummy" model="workflow.transition">
|
||||
<field name="act_from" ref="act_suspended"/>
|
||||
<field name="act_to" ref="act_dummy"/>
|
||||
<field name="signal">get_never</field>
|
||||
<field name="role_id" ref="PE_ADMIN"/>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1,455 @@
|
|||
#!/usr/bin/env python
|
||||
"""html2text: Turn HTML into equivalent Markdown-structured text."""
|
||||
__version__ = "2.36"
|
||||
__author__ = "Aaron Swartz (me@aaronsw.com)"
|
||||
__copyright__ = "(C) 2004-2008 Aaron Swartz. GNU GPL 3."
|
||||
__contributors__ = ["Martin 'Joey' Schulze", "Ricardo Reyes", "Kevin Jay North"]
|
||||
|
||||
# TODO:
|
||||
# Support decoded entities with unifiable.
|
||||
|
||||
if not hasattr(__builtins__, 'True'): True, False = 1, 0
|
||||
import re, sys, urllib, htmlentitydefs, codecs, StringIO, types
|
||||
import sgmllib
|
||||
import urlparse
|
||||
sgmllib.charref = re.compile('&#([xX]?[0-9a-fA-F]+)[^0-9a-fA-F]')
|
||||
|
||||
try: from textwrap import wrap
|
||||
except: pass
|
||||
|
||||
# Use Unicode characters instead of their ascii psuedo-replacements
|
||||
UNICODE_SNOB = 0
|
||||
|
||||
# Put the links after each paragraph instead of at the end.
|
||||
LINKS_EACH_PARAGRAPH = 0
|
||||
|
||||
# Wrap long lines at position. 0 for no wrapping. (Requires Python 2.3.)
|
||||
BODY_WIDTH = 78
|
||||
|
||||
# Don't show internal links (href="#local-anchor") -- corresponding link targets
|
||||
# won't be visible in the plain text file anyway.
|
||||
SKIP_INTERNAL_LINKS = False
|
||||
|
||||
### Entity Nonsense ###
|
||||
|
||||
def name2cp(k):
|
||||
if k == 'apos': return ord("'")
|
||||
if hasattr(htmlentitydefs, "name2codepoint"): # requires Python 2.3
|
||||
return htmlentitydefs.name2codepoint[k]
|
||||
else:
|
||||
k = htmlentitydefs.entitydefs[k]
|
||||
if k.startswith("&#") and k.endswith(";"): return int(k[2:-1]) # not in latin-1
|
||||
return ord(codecs.latin_1_decode(k)[0])
|
||||
|
||||
unifiable = {'rsquo':"'", 'lsquo':"'", 'rdquo':'"', 'ldquo':'"',
|
||||
'copy':'(C)', 'mdash':'--', 'nbsp':' ', 'rarr':'->', 'larr':'<-', 'middot':'*',
|
||||
'ndash':'-', 'oelig':'oe', 'aelig':'ae',
|
||||
'agrave':'a', 'aacute':'a', 'acirc':'a', 'atilde':'a', 'auml':'a', 'aring':'a',
|
||||
'egrave':'e', 'eacute':'e', 'ecirc':'e', 'euml':'e',
|
||||
'igrave':'i', 'iacute':'i', 'icirc':'i', 'iuml':'i',
|
||||
'ograve':'o', 'oacute':'o', 'ocirc':'o', 'otilde':'o', 'ouml':'o',
|
||||
'ugrave':'u', 'uacute':'u', 'ucirc':'u', 'uuml':'u'}
|
||||
|
||||
unifiable_n = {}
|
||||
|
||||
for k in unifiable.keys():
|
||||
unifiable_n[name2cp(k)] = unifiable[k]
|
||||
|
||||
def charref(name):
|
||||
if name[0] in ['x','X']:
|
||||
c = int(name[1:], 16)
|
||||
else:
|
||||
c = int(name)
|
||||
|
||||
if not UNICODE_SNOB and c in unifiable_n.keys():
|
||||
return unifiable_n[c]
|
||||
else:
|
||||
return unichr(c)
|
||||
|
||||
def entityref(c):
|
||||
if not UNICODE_SNOB and c in unifiable.keys():
|
||||
return unifiable[c]
|
||||
else:
|
||||
try: name2cp(c)
|
||||
except KeyError: return "&" + c
|
||||
else: return unichr(name2cp(c))
|
||||
|
||||
def replaceEntities(s):
|
||||
s = s.group(1)
|
||||
if s[0] == "#":
|
||||
return charref(s[1:])
|
||||
else: return entityref(s)
|
||||
|
||||
r_unescape = re.compile(r"&(#?[xX]?(?:[0-9a-fA-F]+|\w{1,8}));")
|
||||
def unescape(s):
|
||||
return r_unescape.sub(replaceEntities, s)
|
||||
|
||||
def fixattrs(attrs):
|
||||
# Fix bug in sgmllib.py
|
||||
if not attrs: return attrs
|
||||
newattrs = []
|
||||
for attr in attrs:
|
||||
newattrs.append((attr[0], unescape(attr[1])))
|
||||
return newattrs
|
||||
|
||||
### End Entity Nonsense ###
|
||||
|
||||
def onlywhite(line):
|
||||
"""Return true if the line does only consist of whitespace characters."""
|
||||
for c in line:
|
||||
if c is not ' ' and c is not ' ':
|
||||
return c is ' '
|
||||
return line
|
||||
|
||||
def optwrap(text):
|
||||
"""Wrap all paragraphs in the provided text."""
|
||||
if not BODY_WIDTH:
|
||||
return text
|
||||
|
||||
assert wrap, "Requires Python 2.3."
|
||||
result = ''
|
||||
newlines = 0
|
||||
for para in text.split("\n"):
|
||||
if len(para) > 0:
|
||||
if para[0] is not ' ' and para[0] is not '-' and para[0] is not '*':
|
||||
for line in wrap(para, BODY_WIDTH):
|
||||
result += line + "\n"
|
||||
result += "\n"
|
||||
newlines = 2
|
||||
else:
|
||||
if not onlywhite(para):
|
||||
result += para + "\n"
|
||||
newlines = 1
|
||||
else:
|
||||
if newlines < 2:
|
||||
result += "\n"
|
||||
newlines += 1
|
||||
return result
|
||||
|
||||
def hn(tag):
|
||||
if tag[0] == 'h' and len(tag) == 2:
|
||||
try:
|
||||
n = int(tag[1])
|
||||
if n in range(1, 10): return n
|
||||
except ValueError: return 0
|
||||
|
||||
class _html2text(sgmllib.SGMLParser):
|
||||
def __init__(self, out=sys.stdout.write, baseurl=''):
|
||||
sgmllib.SGMLParser.__init__(self)
|
||||
|
||||
if out is None: self.out = self.outtextf
|
||||
else: self.out = out
|
||||
self.outtext = u''
|
||||
self.quiet = 0
|
||||
self.p_p = 0
|
||||
self.outcount = 0
|
||||
self.start = 1
|
||||
self.space = 0
|
||||
self.a = []
|
||||
self.astack = []
|
||||
self.acount = 0
|
||||
self.list = []
|
||||
self.blockquote = 0
|
||||
self.pre = 0
|
||||
self.startpre = 0
|
||||
self.lastWasNL = 0
|
||||
self.abbr_title = None # current abbreviation definition
|
||||
self.abbr_data = None # last inner HTML (for abbr being defined)
|
||||
self.abbr_list = {} # stack of abbreviations to write later
|
||||
self.baseurl = baseurl
|
||||
|
||||
def outtextf(self, s):
|
||||
self.outtext += s
|
||||
|
||||
def close(self):
|
||||
sgmllib.SGMLParser.close(self)
|
||||
|
||||
self.pbr()
|
||||
self.o('', 0, 'end')
|
||||
|
||||
return self.outtext
|
||||
|
||||
def handle_charref(self, c):
|
||||
self.o(charref(c))
|
||||
|
||||
def handle_entityref(self, c):
|
||||
self.o(entityref(c))
|
||||
|
||||
def unknown_starttag(self, tag, attrs):
|
||||
self.handle_tag(tag, attrs, 1)
|
||||
|
||||
def unknown_endtag(self, tag):
|
||||
self.handle_tag(tag, None, 0)
|
||||
|
||||
def previousIndex(self, attrs):
|
||||
""" returns the index of certain set of attributes (of a link) in the
|
||||
self.a list
|
||||
|
||||
If the set of attributes is not found, returns None
|
||||
"""
|
||||
if not attrs.has_key('href'): return None
|
||||
|
||||
i = -1
|
||||
for a in self.a:
|
||||
i += 1
|
||||
match = 0
|
||||
|
||||
if a.has_key('href') and a['href'] == attrs['href']:
|
||||
if a.has_key('title') or attrs.has_key('title'):
|
||||
if (a.has_key('title') and attrs.has_key('title') and
|
||||
a['title'] == attrs['title']):
|
||||
match = True
|
||||
else:
|
||||
match = True
|
||||
|
||||
if match: return i
|
||||
|
||||
def handle_tag(self, tag, attrs, start):
|
||||
attrs = fixattrs(attrs)
|
||||
|
||||
if hn(tag):
|
||||
self.p()
|
||||
if start: self.o(hn(tag)*"#" + ' ')
|
||||
|
||||
if tag in ['p', 'div']: self.p()
|
||||
|
||||
if tag == "br" and start: self.o(" \n")
|
||||
|
||||
if tag == "hr" and start:
|
||||
self.p()
|
||||
self.o("* * *")
|
||||
self.p()
|
||||
|
||||
if tag in ["head", "style", 'script']:
|
||||
if start: self.quiet += 1
|
||||
else: self.quiet -= 1
|
||||
|
||||
if tag in ["body"]:
|
||||
self.quiet = 0 # sites like 9rules.com never close <head>
|
||||
|
||||
if tag == "blockquote":
|
||||
if start:
|
||||
self.p(); self.o('> ', 0, 1); self.start = 1
|
||||
self.blockquote += 1
|
||||
else:
|
||||
self.blockquote -= 1
|
||||
self.p()
|
||||
|
||||
if tag in ['em', 'i', 'u']: self.o("_")
|
||||
if tag in ['strong', 'b']: self.o("**")
|
||||
if tag == "code" and not self.pre: self.o('`') #TODO: `` `this` ``
|
||||
if tag == "abbr":
|
||||
if start:
|
||||
attrsD = {}
|
||||
for (x, y) in attrs: attrsD[x] = y
|
||||
attrs = attrsD
|
||||
|
||||
self.abbr_title = None
|
||||
self.abbr_data = ''
|
||||
if attrs.has_key('title'):
|
||||
self.abbr_title = attrs['title']
|
||||
else:
|
||||
if self.abbr_title != None:
|
||||
self.abbr_list[self.abbr_data] = self.abbr_title
|
||||
self.abbr_title = None
|
||||
self.abbr_data = ''
|
||||
|
||||
if tag == "a":
|
||||
if start:
|
||||
attrsD = {}
|
||||
for (x, y) in attrs: attrsD[x] = y
|
||||
attrs = attrsD
|
||||
if attrs.has_key('href') and not (SKIP_INTERNAL_LINKS and attrs['href'].startswith('#')):
|
||||
self.astack.append(attrs)
|
||||
self.o("[")
|
||||
else:
|
||||
self.astack.append(None)
|
||||
else:
|
||||
if self.astack:
|
||||
a = self.astack.pop()
|
||||
if a:
|
||||
i = self.previousIndex(a)
|
||||
if i is not None:
|
||||
a = self.a[i]
|
||||
else:
|
||||
self.acount += 1
|
||||
a['count'] = self.acount
|
||||
a['outcount'] = self.outcount
|
||||
self.a.append(a)
|
||||
self.o("][" + `a['count']` + "]")
|
||||
|
||||
if tag == "img" and start:
|
||||
attrsD = {}
|
||||
for (x, y) in attrs: attrsD[x] = y
|
||||
attrs = attrsD
|
||||
if attrs.has_key('src'):
|
||||
attrs['href'] = attrs['src']
|
||||
alt = attrs.get('alt', '')
|
||||
i = self.previousIndex(attrs)
|
||||
if i is not None:
|
||||
attrs = self.a[i]
|
||||
else:
|
||||
self.acount += 1
|
||||
attrs['count'] = self.acount
|
||||
attrs['outcount'] = self.outcount
|
||||
self.a.append(attrs)
|
||||
self.o("![")
|
||||
self.o(alt)
|
||||
self.o("]["+`attrs['count']`+"]")
|
||||
|
||||
if tag == 'dl' and start: self.p()
|
||||
if tag == 'dt' and not start: self.pbr()
|
||||
if tag == 'dd' and start: self.o(' ')
|
||||
if tag == 'dd' and not start: self.pbr()
|
||||
|
||||
if tag in ["ol", "ul"]:
|
||||
if start:
|
||||
self.list.append({'name':tag, 'num':0})
|
||||
else:
|
||||
if self.list: self.list.pop()
|
||||
|
||||
self.p()
|
||||
|
||||
if tag == 'li':
|
||||
if start:
|
||||
self.pbr()
|
||||
if self.list: li = self.list[-1]
|
||||
else: li = {'name':'ul', 'num':0}
|
||||
self.o(" "*len(self.list)) #TODO: line up <ol><li>s > 9 correctly.
|
||||
if li['name'] == "ul": self.o("* ")
|
||||
elif li['name'] == "ol":
|
||||
li['num'] += 1
|
||||
self.o(`li['num']`+". ")
|
||||
self.start = 1
|
||||
else:
|
||||
self.pbr()
|
||||
|
||||
if tag in ["table", "tr"] and start: self.p()
|
||||
if tag == 'td': self.pbr()
|
||||
|
||||
if tag == "pre":
|
||||
if start:
|
||||
self.startpre = 1
|
||||
self.pre = 1
|
||||
else:
|
||||
self.pre = 0
|
||||
self.p()
|
||||
|
||||
def pbr(self):
|
||||
if self.p_p == 0: self.p_p = 1
|
||||
|
||||
def p(self): self.p_p = 2
|
||||
|
||||
def o(self, data, puredata=0, force=0):
|
||||
if self.abbr_data is not None: self.abbr_data += data
|
||||
|
||||
if not self.quiet:
|
||||
if puredata and not self.pre:
|
||||
data = re.sub('\s+', ' ', data)
|
||||
if data and data[0] == ' ':
|
||||
self.space = 1
|
||||
data = data[1:]
|
||||
if not data and not force: return
|
||||
|
||||
if self.startpre:
|
||||
#self.out(" :") #TODO: not output when already one there
|
||||
self.startpre = 0
|
||||
|
||||
bq = (">" * self.blockquote)
|
||||
if not (force and data and data[0] == ">") and self.blockquote: bq += " "
|
||||
|
||||
if self.pre:
|
||||
bq += " "
|
||||
data = data.replace("\n", "\n"+bq)
|
||||
|
||||
if self.start:
|
||||
self.space = 0
|
||||
self.p_p = 0
|
||||
self.start = 0
|
||||
|
||||
if force == 'end':
|
||||
# It's the end.
|
||||
self.p_p = 0
|
||||
self.out("\n")
|
||||
self.space = 0
|
||||
|
||||
|
||||
if self.p_p:
|
||||
self.out(('\n'+bq)*self.p_p)
|
||||
self.space = 0
|
||||
|
||||
if self.space:
|
||||
if not self.lastWasNL: self.out(' ')
|
||||
self.space = 0
|
||||
|
||||
if self.a and ((self.p_p == 2 and LINKS_EACH_PARAGRAPH) or force == "end"):
|
||||
if force == "end": self.out("\n")
|
||||
|
||||
newa = []
|
||||
for link in self.a:
|
||||
if self.outcount > link['outcount']:
|
||||
self.out(" ["+`link['count']`+"]: " + urlparse.urljoin(self.baseurl, link['href']))
|
||||
if link.has_key('title'): self.out(" ("+link['title']+")")
|
||||
self.out("\n")
|
||||
else:
|
||||
newa.append(link)
|
||||
|
||||
if self.a != newa: self.out("\n") # Don't need an extra line when nothing was done.
|
||||
|
||||
self.a = newa
|
||||
|
||||
if self.abbr_list and force == "end":
|
||||
for abbr, definition in self.abbr_list.items():
|
||||
self.out(" *[" + abbr + "]: " + definition + "\n")
|
||||
|
||||
self.p_p = 0
|
||||
self.out(data)
|
||||
self.lastWasNL = data and data[-1] == '\n'
|
||||
self.outcount += 1
|
||||
|
||||
def handle_data(self, data):
|
||||
if r'\/script>' in data: self.quiet -= 1
|
||||
self.o(data, 1)
|
||||
|
||||
def unknown_decl(self, data): pass
|
||||
|
||||
def wrapwrite(text): sys.stdout.write(text.encode('utf8'))
|
||||
|
||||
def html2text_file(html, out=wrapwrite, baseurl=''):
|
||||
h = _html2text(out, baseurl)
|
||||
h.feed(html)
|
||||
h.feed("")
|
||||
return h.close()
|
||||
|
||||
def html2text(html, baseurl=''):
|
||||
return optwrap(html2text_file(html, None, baseurl))
|
||||
|
||||
if __name__ == "__main__":
|
||||
baseurl = ''
|
||||
if sys.argv[1:]:
|
||||
arg = sys.argv[1]
|
||||
if arg.startswith('http://'):
|
||||
baseurl = arg
|
||||
j = urllib.urlopen(baseurl)
|
||||
try:
|
||||
from feedparser import _getCharacterEncoding as enc
|
||||
except ImportError:
|
||||
enc = lambda x, y: ('utf-8', 1)
|
||||
text = j.read()
|
||||
encoding = enc(j.headers, text)[0]
|
||||
if encoding == 'us-ascii': encoding = 'utf-8'
|
||||
data = text.decode(encoding)
|
||||
|
||||
else:
|
||||
encoding = 'utf8'
|
||||
if len(sys.argv) > 2:
|
||||
encoding = sys.argv[2]
|
||||
f = open(arg, 'r')
|
||||
try:
|
||||
data = f.read().decode(encoding)
|
||||
finally:
|
||||
f.close()
|
||||
else:
|
||||
data = sys.stdin.read().decode('utf8')
|
||||
wrapwrite(html2text(data, baseurl))
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="0">
|
||||
|
||||
<record id="res_groups_email_template_manager" model="res.groups">
|
||||
<field name="name">Email Template / Settings_Manager</field>
|
||||
</record>
|
||||
|
||||
<record id="res_groups_email_template_userse" model="res.groups">
|
||||
<field name="name">Email Template / External_users</field>
|
||||
</record>
|
||||
|
||||
<record id="res_groups_email_template_usersi" model="res.groups">
|
||||
<field name="name">Email Template / Internal_users</field>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -0,0 +1 @@
|
|||
import email_template_send_wizard
|
|
@ -0,0 +1,235 @@
|
|||
from osv import osv, fields
|
||||
from mako.template import Template
|
||||
from mako import exceptions
|
||||
import netsvc
|
||||
import base64
|
||||
import time
|
||||
from tools.translate import _
|
||||
import tools
|
||||
from email_template.email_template import get_value
|
||||
|
||||
class email_template_send_wizard(osv.osv_memory):
|
||||
_name = 'email_template.send.wizard'
|
||||
_description = 'This is the wizard for sending mail'
|
||||
_rec_name = "subject"
|
||||
|
||||
def _get_accounts(self, cr, uid, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
template = self._get_template(cr, uid, context)
|
||||
if not template:
|
||||
return []
|
||||
|
||||
logger = netsvc.Logger()
|
||||
|
||||
if template.enforce_from_account:
|
||||
return [(template.enforce_from_account.id, '%s (%s)' % (template.enforce_from_account.name, template.enforce_from_account.email_id))]
|
||||
else:
|
||||
account_id = self.pool.get('email_template.account').search(cr,uid,[('company','=','no'),('user','=',uid)], context=context)
|
||||
if account_id:
|
||||
account = self.pool.get('email_template.account').browse(cr,uid,account_id, context)
|
||||
return [(r.id,r.name + " (" + r.email_id + ")") for r in account]
|
||||
else:
|
||||
logger.notifyChannel(_("Power Email"), netsvc.LOG_ERROR, _("No personal email accounts are configured for you. \nEither ask admin to enforce an account for this template or get yourself a personal power email account."))
|
||||
raise osv.except_osv(_("Power Email"),_("No personal email accounts are configured for you. \nEither ask admin to enforce an account for this template or get yourself a personal power email account."))
|
||||
|
||||
def get_value(self, cursor, user, template, message, context=None, id=None):
|
||||
"""Gets the value of the message parsed with the content of object id (or the first 'src_rec_ids' if id is not given)"""
|
||||
if not message:
|
||||
return ''
|
||||
if not id:
|
||||
id = context['src_rec_ids'][0]
|
||||
return get_value(cursor, user, id, message, template, context)
|
||||
|
||||
def _get_template(self, cr, uid, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
if not 'template' in context and not 'template_id' in context:
|
||||
return None
|
||||
if 'template_id' in context.keys():
|
||||
template_ids = self.pool.get('email.template').search(cr, uid, [('id','=',context['template_id'])], context=context)
|
||||
elif 'template' in context.keys():
|
||||
# Old versions of email_template used the name of the template. This caused
|
||||
# problems when the user changed the name of the template, but we keep the code
|
||||
# for compatibility with those versions.
|
||||
template_ids = self.pool.get('email.template').search(cr, uid, [('name','=',context['template'])], context=context)
|
||||
if not template_ids:
|
||||
return None
|
||||
|
||||
template = self.pool.get('email.template').browse(cr, uid, template_ids[0], context)
|
||||
|
||||
lang = self.get_value(cr, uid, template, template.lang, context)
|
||||
if lang:
|
||||
# Use translated template if necessary
|
||||
ctx = context.copy()
|
||||
ctx['lang'] = lang
|
||||
template = self.pool.get('email.template').browse(cr, uid, template.id, ctx)
|
||||
return template
|
||||
|
||||
def _get_template_value(self, cr, uid, field, context=None):
|
||||
template = self._get_template(cr, uid, context)
|
||||
if not template:
|
||||
return False
|
||||
if len(context['src_rec_ids']) > 1: # Multiple Mail: Gets original template values for multiple email change
|
||||
return getattr(template, field)
|
||||
else: # Simple Mail: Gets computed template values
|
||||
return self.get_value(cr, uid, template, getattr(template, field), context)
|
||||
|
||||
_columns = {
|
||||
'state':fields.selection([
|
||||
('single','Simple Mail Wizard Step 1'),
|
||||
('multi','Multiple Mail Wizard Step 1'),
|
||||
('done','Wizard Complete')
|
||||
],'Status',readonly=True),
|
||||
'ref_template':fields.many2one('email.template','Template',readonly=True),
|
||||
'rel_model':fields.many2one('ir.model','Model',readonly=True),
|
||||
'rel_model_ref':fields.integer('Referred Document',readonly=True),
|
||||
'from':fields.selection(_get_accounts,'From Account',select=True),
|
||||
'to':fields.char('To',size=250,required=True),
|
||||
'cc':fields.char('CC',size=250,),
|
||||
'bcc':fields.char('BCC',size=250,),
|
||||
'subject':fields.char('Subject',size=200),
|
||||
'body_text':fields.text('Body',),
|
||||
'body_html':fields.text('Body',),
|
||||
'report':fields.char('Report File Name',size=100,),
|
||||
'signature':fields.boolean('Attach my signature to mail'),
|
||||
#'filename':fields.text('File Name'),
|
||||
'requested':fields.integer('No of requested Mails',readonly=True),
|
||||
'generated':fields.integer('No of generated Mails',readonly=True),
|
||||
'full_success':fields.boolean('Complete Success',readonly=True),
|
||||
'attachment_ids': fields.many2many('ir.attachment','send_wizard_attachment_rel', 'wizard_id', 'attachment_id', 'Attachments'),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'state': lambda self,cr,uid,ctx: len(ctx['src_rec_ids']) > 1 and 'multi' or 'single',
|
||||
'rel_model': lambda self,cr,uid,ctx: self.pool.get('ir.model').search(cr,uid,[('model','=',ctx['src_model'])],context=ctx)[0],
|
||||
'rel_model_ref': lambda self,cr,uid,ctx: ctx['active_id'],
|
||||
'to': lambda self,cr,uid,ctx: self._get_template_value(cr, uid, 'def_to', ctx),
|
||||
'cc': lambda self,cr,uid,ctx: self._get_template_value(cr, uid, 'def_cc', ctx),
|
||||
'bcc': lambda self,cr,uid,ctx: self._get_template_value(cr, uid, 'def_bcc', ctx),
|
||||
'subject':lambda self,cr,uid,ctx: self._get_template_value(cr, uid, 'def_subject', ctx),
|
||||
'body_text':lambda self,cr,uid,ctx: self._get_template_value(cr, uid, 'def_body_text', ctx),
|
||||
'body_html':lambda self,cr,uid,ctx: self._get_template_value(cr, uid, 'def_body_html', ctx),
|
||||
'report': lambda self,cr,uid,ctx: self._get_template_value(cr, uid, 'file_name', ctx),
|
||||
'signature': lambda self,cr,uid,ctx: self._get_template(cr, uid, ctx).use_sign,
|
||||
'ref_template':lambda self,cr,uid,ctx: self._get_template(cr, uid, ctx).id,
|
||||
'requested':lambda self,cr,uid,ctx: len(ctx['src_rec_ids']),
|
||||
'full_success': lambda *a: False
|
||||
}
|
||||
|
||||
def fields_get(self, cr, uid, fields=None, context=None, read_access=True):
|
||||
result = super(email_template_send_wizard, self).fields_get(cr, uid, fields, context, read_access)
|
||||
if 'attachment_ids' in result and 'src_model' in context:
|
||||
result['attachment_ids']['domain'] = [('res_model','=',context['src_model']),('res_id','=',context['active_id'])]
|
||||
return result
|
||||
|
||||
def sav_to_drafts(self, cr, uid, ids, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
mailid = self.save_to_mailbox(cr, uid, ids, context)
|
||||
if self.pool.get('email_template.mailbox').write(cr, uid, mailid, {'folder':'drafts'}, context):
|
||||
return {'type':'ir.actions.act_window_close' }
|
||||
|
||||
def send_mail(self, cr, uid, ids, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
mailid = self.save_to_mailbox(cr, uid, ids, context)
|
||||
if self.pool.get('email_template.mailbox').write(cr, uid, mailid, {'folder':'outbox'}, context):
|
||||
return {'type':'ir.actions.act_window_close' }
|
||||
|
||||
def get_generated(self, cr, uid, ids=None, context=None):
|
||||
if ids is None:
|
||||
ids = []
|
||||
if context is None:
|
||||
context = {}
|
||||
logger = netsvc.Logger()
|
||||
if context['src_rec_ids'] and len(context['src_rec_ids'])>1:
|
||||
#Means there are multiple items selected for email.
|
||||
mail_ids = self.save_to_mailbox(cr, uid, ids, context)
|
||||
if mail_ids:
|
||||
self.pool.get('email_template.mailbox').write(cr, uid, mail_ids, {'folder':'outbox'}, context)
|
||||
logger.notifyChannel(_("Power Email"), netsvc.LOG_INFO, _("Emails for multiple items saved in outbox."))
|
||||
self.write(cr, uid, ids, {
|
||||
'generated':len(mail_ids),
|
||||
'state':'done'
|
||||
}, context)
|
||||
else:
|
||||
raise osv.except_osv(_("Power Email"),_("Email sending failed for one or more objects."))
|
||||
return True
|
||||
|
||||
def save_to_mailbox(self, cr, uid, ids, context=None):
|
||||
def get_end_value(id, value):
|
||||
if len(context['src_rec_ids']) > 1: # Multiple Mail: Gets value from the template
|
||||
return self.get_value(cr, uid, template, value, context, id)
|
||||
else:
|
||||
return value
|
||||
|
||||
mail_ids = []
|
||||
template = self._get_template(cr, uid, context)
|
||||
for id in context['src_rec_ids']:
|
||||
print "@22222222222222222222222",ids
|
||||
screen_vals = self.read(cr, uid, ids[0], [],context)
|
||||
account = self.pool.get('email_template.account').read(cr, uid, screen_vals['from'], context=context)
|
||||
vals = {
|
||||
'email_from': tools.ustr(account['name']) + "<" + tools.ustr(account['email_id']) + ">",
|
||||
'email_to': get_end_value(id, screen_vals['to']),
|
||||
'email_cc': get_end_value(id, screen_vals['cc']),
|
||||
'email_bcc': get_end_value(id, screen_vals['bcc']),
|
||||
'subject': get_end_value(id, screen_vals['subject']),
|
||||
'body_text': get_end_value(id, screen_vals['body_text']),
|
||||
'body_html': get_end_value(id, screen_vals['body_html']),
|
||||
'account_id': screen_vals['from'],
|
||||
'state':'na',
|
||||
'mail_type':'multipart/alternative' #Options:'multipart/mixed','multipart/alternative','text/plain','text/html'
|
||||
}
|
||||
if screen_vals['signature']:
|
||||
signature = self.pool.get('res.users').read(cr, uid, uid, ['signature'], context)['signature']
|
||||
if signature:
|
||||
vals['body_text'] = tools.ustr(vals['body_text'] or '') + signature
|
||||
vals['body_html'] = tools.ustr(vals['body_html'] or '') + signature
|
||||
|
||||
attachment_ids = []
|
||||
|
||||
#Create partly the mail and later update attachments
|
||||
mail_id = self.pool.get('email_template.mailbox').create(cr, uid, vals, context)
|
||||
mail_ids.append(mail_id)
|
||||
if template.report_template:
|
||||
reportname = 'report.' + self.pool.get('ir.actions.report.xml').read(cr, uid, template.report_template.id, ['report_name'], context)['report_name']
|
||||
data = {}
|
||||
data['model'] = self.pool.get('ir.model').browse(cr, uid, screen_vals['rel_model'], context).model
|
||||
|
||||
# Ensure report is rendered using template's language
|
||||
ctx = context.copy()
|
||||
if template.lang:
|
||||
ctx['lang'] = self.get_value(cr, uid, template, template.lang, context, id)
|
||||
service = netsvc.LocalService(reportname)
|
||||
(result, format) = service.create(cr, uid, [id], data, ctx)
|
||||
attachment_id = self.pool.get('ir.attachment').create(cr, uid, {
|
||||
'name': _('%s (Email Attachment)') % tools.ustr(vals['subject']),
|
||||
'datas': base64.b64encode(result),
|
||||
'datas_fname': tools.ustr(get_end_value(id, screen_vals['report']) or _('Report')) + "." + format,
|
||||
'description': vals['body_text'] or _("No Description"),
|
||||
'res_model': 'email_template.mailbox',
|
||||
'res_id': mail_id
|
||||
}, context)
|
||||
attachment_ids.append( attachment_id )
|
||||
|
||||
# Add document attachments
|
||||
for attachment_id in screen_vals.get('attachment_ids',[]):
|
||||
new_id = self.pool.get('ir.attachment').copy(cr, uid, attachment_id, {
|
||||
'res_model': 'email_template.mailbox',
|
||||
'res_id': mail_id,
|
||||
}, context)
|
||||
attachment_ids.append( new_id )
|
||||
|
||||
if attachment_ids:
|
||||
self.pool.get('email_template.mailbox').write(cr, uid, mail_id, {
|
||||
'attachments_ids': [[6, 0, attachment_ids]],
|
||||
'mail_type': 'multipart/mixed'
|
||||
}, context)
|
||||
|
||||
return mail_ids
|
||||
email_template_send_wizard()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
|
@ -0,0 +1,64 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<record model="ir.ui.view" id="email_template_send_wizard_form">
|
||||
<field name="name">email_template.send.wizard.form</field>
|
||||
<field name="model">email_template.send.wizard</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Send mail Wizard">
|
||||
<group col="4" colspan="4">
|
||||
<field name="rel_model" colspan="2" />
|
||||
<field name="from" required="1" colspan="2" />
|
||||
</group>
|
||||
<group col="4" colspan="4">
|
||||
<group col="6" colspan="4">
|
||||
<field name="to" select="1" colspan="4" />
|
||||
<newline />
|
||||
<field name="cc" select="2" colspan="4" />
|
||||
<newline />
|
||||
<field name="bcc" select="2" colspan="4" />
|
||||
<newline />
|
||||
<field name="subject" select="2" colspan="4" attrs="{'required':[('state','=','single')]}" />
|
||||
<newline />
|
||||
<field name="report" colspan="4" />
|
||||
</group>
|
||||
<separator string="" colspan="4" />
|
||||
<notebook colspan="4">
|
||||
<page string="Body (Plain Text)">
|
||||
<field name="body_text" select="2" colspan="4" nolabel="1" />
|
||||
</page>
|
||||
<page string="Body (HTML)">
|
||||
<field name="body_html" select="2" colspan="4" nolabel="1" />
|
||||
<!--<label string="Note: HTML body can't be edited with GTK desktop client." colspan="4"/>
|
||||
--></page>
|
||||
<page string="Attachments">
|
||||
<label string="Add here all attachments of the current document you want to include in the e-mail." colspan="4"/>
|
||||
<field name="attachment_ids" colspan="4" nolabel="1"/>
|
||||
</page>
|
||||
</notebook>
|
||||
<field name="signature" colspan="4" />
|
||||
</group>
|
||||
<group col="4" colspan="4" attrs="{'invisible':[('state','!=','single')]}">
|
||||
<button icon="gtk-apply" name="sav_to_drafts" string="Save in Drafts" type="object" />
|
||||
<button icon="gtk-ok" name="send_mail" string="Send now" type="object" />
|
||||
<button icon="gtk-cancel" special="cancel" string="Discard Mail" />
|
||||
</group>
|
||||
<group col="4" colspan="4" attrs="{'invisible':[('state','=','single')]}">
|
||||
<label string="Tip: Multiple emails are sent in the same language (the first one is proposed). We suggest you send emails in groups according to language." colspan="4"/>
|
||||
<field name="requested" />
|
||||
<field name="generated" />
|
||||
<button icon="gtk-ok" name="get_generated" string="Send all mails" type="object" states="multi" colspan="2" />
|
||||
<button icon="gtk-cancel" special="cancel" string="Discard Mail" colspan="2" states="multi" />
|
||||
</group>
|
||||
<button icon="gtk-ok" special="cancel" string="Close" colspan="4" states="done" />
|
||||
<field name="state" />
|
||||
<newline />
|
||||
<label string="After clicking send all mails, mails will be sent to outbox and cleared in next Send/Recieve" colspan="4"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
@ -223,25 +223,32 @@
|
|||
<page string="History">
|
||||
<field name="message_ids" colspan="4" nolabel="1" mode="tree,form">
|
||||
<form string="Communication history">
|
||||
<group col="6" colspan="4">
|
||||
<field name="date"/>
|
||||
<field name="email_to"/>
|
||||
<field name="email_from"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<field name="description" colspan="4" nolabel="1"/>
|
||||
<button colspan="4"
|
||||
string="Reply to Last Email"
|
||||
name="%(crm.action_crm_send_mail)d"
|
||||
context="{'mail':'reply', 'model': 'crm.lead'}"
|
||||
icon="gtk-undo" type="action" />
|
||||
</form>
|
||||
<tree string="Communication history">
|
||||
<field name="description"/>
|
||||
<field name="email_to"/>
|
||||
<field name="date"/>
|
||||
</tree>
|
||||
</field>
|
||||
<group col="6" colspan="4">
|
||||
<field name="date"/>
|
||||
<field name="email_to"/>
|
||||
<field name="email_from"/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page string="Details">
|
||||
<field name="description" colspan="4" nolabel="1"/>
|
||||
</page>
|
||||
<page string="Attachments">
|
||||
<field name="attachment_ids" colspan="4" readonly="1" nolabel="1"/>
|
||||
</page>
|
||||
</notebook>
|
||||
<button colspan="4"
|
||||
string="Reply to Last Email"
|
||||
name="%(crm.action_crm_send_mail)d"
|
||||
context="{'mail':'reply', 'model': 'event.registration'}"
|
||||
icon="gtk-undo" type="action" />
|
||||
</form>
|
||||
<tree string="Communication history">
|
||||
<field name="date"/>
|
||||
<field name="email_from" />
|
||||
<field name="email_to"/>
|
||||
<field name="description"/>
|
||||
</tree>
|
||||
</field>
|
||||
<field name="log_ids" nolabel="1" colspan="4" mode="tree,form" readonly="1">
|
||||
<tree string="Actions">
|
||||
<separator string="Action Information" colspan="4"/>
|
||||
|
|
|
@ -69,7 +69,7 @@ class event_make_invoice(osv.osv_memory):
|
|||
inv_rej_reason += "ID "+str(reg.id)+": Registration doesn't have any partner to invoice. \n"
|
||||
continue
|
||||
else:
|
||||
val_invoice = pool_obj.get('account.invoice').onchange_partner_id(cr, uid, [], 'out_invoice', reg.partner_invoice_id.id, False, False)
|
||||
val_invoice = inv_obj.onchange_partner_id(cr, uid, [], 'out_invoice', reg.partner_invoice_id.id, False, False)
|
||||
val_invoice['value'].update({'partner_id': reg.partner_invoice_id.id})
|
||||
partner_address_id = val_invoice['value']['address_invoice_id']
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
<field eval="[(6,0,[])]" name="users"/>
|
||||
<field name="type" ref="survey.survey_type1"/>
|
||||
<field name="responsible_id" ref="base.user_demo"/>
|
||||
<field name="response_user">5</field>
|
||||
</record>
|
||||
</data>
|
||||
<data>
|
||||
|
@ -16,6 +17,7 @@
|
|||
<field eval="[(6,0,[])]" name="users"/>
|
||||
<field name="type" ref="survey.survey_type1"/>
|
||||
<field name="responsible_id" ref="base.user_root"/>
|
||||
<field name="response_user">5</field>
|
||||
</record>
|
||||
</data>
|
||||
<data>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<openerp>
|
||||
<data noupdate="1">
|
||||
|
||||
<record id="product_product_expense_0" model="product.product">
|
||||
<record id="product_product_expense_air" model="product.product">
|
||||
<field name="list_price">1.0</field>
|
||||
<field name="standard_price">1.0</field>
|
||||
<field name="uom_id" ref="product.product_uom_unit"/>
|
||||
|
@ -10,11 +10,11 @@
|
|||
<field name="type">service</field>
|
||||
<field name="name">Air Ticket</field>
|
||||
<field name="default_code">AT</field>
|
||||
<field name="categ_id" ref="product.product_category_7"/>
|
||||
<field name="categ_id" ref="product.cat2"/>
|
||||
<field name="hr_expense_ok" eval="True" />
|
||||
</record>
|
||||
|
||||
<record id="product_product_expense_2" model="product.product">
|
||||
<record id="product_product_expense_hotel" model="product.product">
|
||||
<field name="list_price">1.0</field>
|
||||
<field name="standard_price">1.0</field>
|
||||
<field name="uom_id" ref="product.product_uom_unit"/>
|
||||
|
@ -22,7 +22,19 @@
|
|||
<field name="type">service</field>
|
||||
<field name="name">Hotel Accommodation</field>
|
||||
<field name="default_code">HA0</field>
|
||||
<field name="categ_id" ref="product.product_category_7"/>
|
||||
<field name="categ_id" ref="product.cat2"/>
|
||||
<field name="hr_expense_ok" eval="True" />
|
||||
</record>
|
||||
|
||||
<record id="product_product_expense_car" model="product.product">
|
||||
<field name="list_price">0.30</field>
|
||||
<field name="standard_price">0.30</field>
|
||||
<field name="uom_id" ref="product.product_uom_km"/>
|
||||
<field name="uom_po_id" ref="product.product_uom_km"/>
|
||||
<field name="type">consu</field>
|
||||
<field name="name">Car Travel</field>
|
||||
<field name="default_code">CAR</field>
|
||||
<field name="categ_id" ref="product.cat2"/>
|
||||
<field name="hr_expense_ok" eval="True" />
|
||||
</record>
|
||||
|
||||
|
@ -30,29 +42,29 @@
|
|||
<field name="currency_id" ref="base.EUR"/>
|
||||
<field name="employee_id" ref="hr.employee1"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="name">September Expenses</field>
|
||||
<field name="name">May Expenses</field>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<field name="date">2010-05-03</field>
|
||||
<field name="state">draft</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_expense_line_travelbycarcustomerseagatedouble0" model="hr.expense.line">
|
||||
<field name="name">Travel by Air - Customer Seagate 2 - Double</field>
|
||||
<field name="name">Travel by Air</field>
|
||||
<field name="date_value">2010-05-03</field>
|
||||
<field name="analytic_account" ref="account.analytic_thymbra"/>
|
||||
<field name="product_id" ref="product_product_expense_0"/>
|
||||
<field model="hr.expense.expense" name="expense_id" search="[('name', '=', u'September Expenses')]"/>
|
||||
<field name="analytic_account" ref="account.analytic_consultancy"/>
|
||||
<field name="product_id" ref="product_product_expense_air"/>
|
||||
<field model="hr.expense.expense" name="expense_id" search="[('name', '=', u'May Expenses')]"/>
|
||||
<field eval="700.0" name="unit_amount"/>
|
||||
<field name="uom_id" ref="product.product_uom_unit"/>
|
||||
<field eval="200.0" name="unit_quantity"/>
|
||||
<field eval="1.0" name="unit_quantity"/>
|
||||
</record>
|
||||
<record id="hr_expense_line_basicpcserverforseagate0" model="hr.expense.line">
|
||||
<field name="name">Basic PC - Server for Seagate</field>
|
||||
<field name="date_value">2010-05-03</field>
|
||||
<field name="analytic_account" ref="account.analytic_seagate_p2"/>
|
||||
<field name="product_id" ref="product.product_product_25"/>
|
||||
<field model="hr.expense.expense" name="expense_id" search="[('name', '=', u'September Expenses')]"/>
|
||||
<field eval="35.5" name="unit_amount"/>
|
||||
<field name="product_id" ref="product.product_product_pc4"/>
|
||||
<field model="hr.expense.expense" name="expense_id" search="[('name', '=', u'May Expenses')]"/>
|
||||
<field eval="1200.0" name="unit_amount"/>
|
||||
<field name="uom_id" ref="product.product_uom_unit"/>
|
||||
<field eval="1.0" name="unit_quantity"/>
|
||||
</record>
|
||||
|
@ -62,7 +74,7 @@
|
|||
<field name="currency_id" ref="base.EUR"/>
|
||||
<field name="employee_id" ref="hr.employee1"/>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="name">Hotel Expenses</field>
|
||||
<field name="name">Travel Expenses</field>
|
||||
<field name="company_id" ref="base.main_company"/>
|
||||
<field name="date">2010-04-20</field>
|
||||
<field name="state">draft</field>
|
||||
|
@ -71,12 +83,23 @@
|
|||
<field name="name">Hotel Expenses - Thymbra</field>
|
||||
<field name="date_value">2010-05-03</field>
|
||||
<field name="analytic_account" ref="account.analytic_thymbra"/>
|
||||
<field name="product_id" ref="product_product_expense_2"/>
|
||||
<field model="hr.expense.expense" name="expense_id" search="[('name', '=', u'Hotel Expenses')]"/>
|
||||
<field name="product_id" ref="product_product_expense_hotel"/>
|
||||
<field model="hr.expense.expense" name="expense_id" search="[('name', '=', u'Travel Expenses')]"/>
|
||||
<field eval="400.0" name="unit_amount"/>
|
||||
<field name="uom_id" ref="product.product_uom_unit"/>
|
||||
<field eval="5.0" name="unit_quantity"/>
|
||||
</record>
|
||||
<record id="hr_expense_line_car_travel" model="hr.expense.line">
|
||||
<field name="name">Bruxelles - Paris</field>
|
||||
<field name="date_value">2010-05-03</field>
|
||||
<field name="analytic_account" ref="account.analytic_thymbra"/>
|
||||
<field name="product_id" ref="product_product_expense_car"/>
|
||||
<field model="hr.expense.expense" name="expense_id" search="[('name', '=', u'Travel Expenses')]"/>
|
||||
<field eval="0.30" name="unit_amount"/>
|
||||
<field name="uom_id" ref="product.product_uom_km"/>
|
||||
<field eval="622.0" name="unit_quantity"/>
|
||||
</record>
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
</openerp>
|
||||
|
|
|
@ -148,6 +148,7 @@
|
|||
<field eval="[(6,0,[])]" name="users"/>
|
||||
<field name="type" ref="survey.survey_type1"/>
|
||||
<field name="responsible_id" ref="base.user_root"/>
|
||||
<field name="response_user">5</field>
|
||||
</record>
|
||||
</data>
|
||||
<data>
|
||||
|
|
|
@ -2,6 +2,12 @@
|
|||
<openerp>
|
||||
<data>
|
||||
|
||||
<menuitem
|
||||
id="menu_hr_config_applicant"
|
||||
name="Applicant"
|
||||
parent="hr.menu_hr_configuration"
|
||||
/>
|
||||
|
||||
# ------------------------------------------------------
|
||||
# Job Categories
|
||||
# ------------------------------------------------------
|
||||
|
@ -25,7 +31,8 @@
|
|||
<field name="domain">[('object_id.model', '=', 'hr.applicant')]</field>
|
||||
<field name="context">{'object_id':'hr.applicant'}</field>
|
||||
</record>
|
||||
<menuitem action="hr_job_stage_act" id="menu_hr_job_stage_act" parent="crm.menu_crm_case_stage"/>
|
||||
|
||||
<menuitem action="hr_job_stage_act" id="menu_hr_job_stage_act" name="Stages" parent="menu_hr_config_applicant"/>
|
||||
|
||||
# ------------------------------------------------------
|
||||
# Jobs
|
||||
|
@ -152,26 +159,33 @@
|
|||
<field colspan="4" name="email_cc" string="CC"/>
|
||||
</group>
|
||||
<field name="message_ids" colspan="4" nolabel="1" mode="form,tree">
|
||||
<form string="Communication history">
|
||||
<group col="6" colspan="4">
|
||||
<field name="date"/>
|
||||
<field name="email_to"/>
|
||||
<field name="email_from"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<field name="description" colspan="4" nolabel="1"/>
|
||||
<button colspan="4"
|
||||
string="Reply to Last Email"
|
||||
name="%(crm.action_crm_send_mail)d"
|
||||
context="{'mail':'reply', 'model': 'hr.applicant'}"
|
||||
icon="gtk-undo" type="action" />
|
||||
</form>
|
||||
<tree string="Communication history">
|
||||
<field name="description"/>
|
||||
<field name="email_to"/>
|
||||
<field name="date"/>
|
||||
</tree>
|
||||
</field>
|
||||
<form string="Communication history">
|
||||
<group col="6" colspan="4">
|
||||
<field name="date"/>
|
||||
<field name="email_to"/>
|
||||
<field name="email_from"/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page string="Details">
|
||||
<field name="description" colspan="4" nolabel="1"/>
|
||||
</page>
|
||||
<page string="Attachments">
|
||||
<field name="attachment_ids" colspan="4" readonly="1" nolabel="1"/>
|
||||
</page>
|
||||
</notebook>
|
||||
<button colspan="4"
|
||||
string="Reply to Last Email"
|
||||
name="%(crm.action_crm_send_mail)d"
|
||||
context="{'mail':'reply', 'model': 'hr.applicant'}"
|
||||
icon="gtk-undo" type="action" />
|
||||
</form>
|
||||
<tree string="Communication history">
|
||||
<field name="date"/>
|
||||
<field name="email_from" />
|
||||
<field name="email_to"/>
|
||||
<field name="description"/>
|
||||
</tree>
|
||||
</field>
|
||||
<button colspan="4" string="Send New Email"
|
||||
name="%(crm.action_crm_send_mail)d"
|
||||
context="{'mail':'new', 'model': 'hr.applicant'}"
|
||||
|
|
|
@ -57,8 +57,7 @@ class hr_analytic_timesheet(osv.osv):
|
|||
|
||||
def on_change_unit_amount(self, cr, uid, id, prod_id, unit_amount, unit, context={}):
|
||||
res = {}
|
||||
# if prod_id and unit_amount:
|
||||
if prod_id:
|
||||
if prod_id and unit_amount:
|
||||
# find company
|
||||
company_id = self.pool.get('res.company')._company_default_get(cr, uid, 'account.analytic.line', context=context)
|
||||
res = self.pool.get('account.analytic.line').on_change_unit_amount(cr, uid, id, prod_id, unit_amount, company_id, unit, context=context)
|
||||
|
|
|
@ -115,31 +115,19 @@ class hr_si_project(osv.osv_memory):
|
|||
# get the latest action (sign_in or out) for this employee
|
||||
cr.execute('select action from hr_attendance where employee_id=%s and action in (\'sign_in\',\'sign_out\') order by name desc limit 1', (emp_id,))
|
||||
res = (cr.fetchone() or ('sign_out',))[0]
|
||||
in_out = res == 'sign_out' and 'out' or 'in'
|
||||
#TODO: invert sign_in et sign_out
|
||||
if res == 'sign_out':
|
||||
model_data_ids = obj_model.search(cr,uid,[('model','=','ir.ui.view'),('name','=','view_hr_timesheet_sign_in')])
|
||||
resource_id = obj_model.read(cr,uid,model_data_ids,fields=['res_id'])[0]['res_id']
|
||||
return {
|
||||
'name': 'Sign in / Sign out',
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree,form',
|
||||
'res_model': 'hr.sign.in.project',
|
||||
'views': [(False,'tree'), (resource_id,'form')],
|
||||
'type': 'ir.actions.act_window',
|
||||
'target': 'new'
|
||||
}
|
||||
else:
|
||||
model_data_ids = obj_model.search(cr,uid,[('model','=','ir.ui.view'),('name','=','view_hr_timesheet_sign_out')])
|
||||
resource_id = obj_model.read(cr,uid,model_data_ids,fields=['res_id'])[0]['res_id']
|
||||
return {
|
||||
'name': 'Sign in / Sign out',
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree,form',
|
||||
'res_model': 'hr.sign.out.project',
|
||||
'views': [(False,'tree'), (resource_id,'form')],
|
||||
'type': 'ir.actions.act_window',
|
||||
'target': 'new'
|
||||
}
|
||||
model_data_ids = obj_model.search(cr,uid,[('model','=','ir.ui.view'),('name','=','view_hr_timesheet_sign_%s' % in_out)])
|
||||
resource_id = obj_model.read(cr,uid,model_data_ids,fields=['res_id'])[0]['res_id']
|
||||
return {
|
||||
'name': 'Sign in / Sign out',
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree,form',
|
||||
'res_model': 'hr.sign.%s.project' % in_out,
|
||||
'views': [(False,'tree'), (resource_id,'form')],
|
||||
'type': 'ir.actions.act_window',
|
||||
'target': 'new'
|
||||
}
|
||||
|
||||
def _get_empid(self, cr, uid, context=None):
|
||||
emp_obj = self.pool.get('hr.employee')
|
||||
|
@ -153,10 +141,7 @@ class hr_si_project(osv.osv_memory):
|
|||
emp_obj = self.pool.get('hr.employee')
|
||||
data = self.read(cr, uid, ids, [], context)[0]
|
||||
emp_id = data['emp_id']
|
||||
try:
|
||||
success = emp_obj.attendance_action_change(cr, uid, [emp_id], type = 'sign_in' ,dt=data['date'] or False)
|
||||
except except_osv, e:
|
||||
raise osv.except_osv(e.name, e.value)
|
||||
success = emp_obj.attendance_action_change(cr, uid, [emp_id], type = 'sign_in' ,dt=data['date'] or False)
|
||||
return {}
|
||||
|
||||
def default_get(self, cr, uid, fields_list, context=None):
|
||||
|
@ -166,4 +151,4 @@ class hr_si_project(osv.osv_memory):
|
|||
|
||||
hr_si_project()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -462,6 +462,7 @@
|
|||
<newline/>
|
||||
<group expand="1" string="Group By...">
|
||||
<filter string="User" icon="terp-project" domain="[]" context="{'group_by':'user_id'}"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Product" icon="terp-project" domain="[]" context="{'group_by':'product_id'}"/>
|
||||
<filter string="Analytic Account" icon="terp-project" domain="[]" context="{'group_by':'analytic_account_id'}"/>
|
||||
<filter string="General Account" icon="terp-project" domain="[]" context="{'group_by':'general_account_id'}"/>
|
||||
|
|
|
@ -74,12 +74,12 @@
|
|||
domain="[('user_id','=',False)]"/>
|
||||
</field>
|
||||
<field name="company_id" widget="selection" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
<newline/>
|
||||
</group>
|
||||
<newline/>
|
||||
<group expand="1" string="Group By...">
|
||||
<filter string="User" name="User" icon="terp-hr" context="{'group_by':'user_id'}"/>
|
||||
<filter string="Product" icon="terp-hr" context="{'group_by':'product_id'}"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Product" icon="terp-hr" context="{'group_by':'product_id'}"/>
|
||||
<filter string="Type of Invoicing" icon="terp-hr" context="{'group_by':'to_invoice'}"/>
|
||||
<filter string="Analytic Account" icon="terp-hr" context="{'group_by':'account_id'}"/>
|
||||
<filter string="General Account" icon="terp-hr" context="{'group_by':'general_account_id'}"/>
|
||||
|
@ -111,7 +111,7 @@
|
|||
<separator orientation="vertical"/>
|
||||
<field name="general_account_id"/>
|
||||
<field name="to_invoice" widget="selection"/>
|
||||
</group>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
|
|
@ -13,7 +13,7 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2010-06-01 03:44+0000\n"
|
||||
"X-Launchpad-Export-Date: 2010-06-02 03:33+0000\n"
|
||||
"X-Generator: Launchpad (build Unknown)\n"
|
||||
|
||||
#. module: idea
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
from osv import osv
|
||||
from osv import fields
|
||||
from tools.translate import _
|
||||
import time
|
||||
|
||||
VoteValues = [('-1', 'Not Voted'), ('0', 'Very Bad'), ('25', 'Bad'), \
|
||||
('50', 'Normal'), ('75', 'Good'), ('100', 'Very Good') ]
|
||||
|
@ -29,7 +30,7 @@ DefaultVoteValue = '50'
|
|||
|
||||
class idea_category(osv.osv):
|
||||
""" Category of Idea """
|
||||
|
||||
|
||||
_name = "idea.category"
|
||||
_description = "Idea Category"
|
||||
|
||||
|
@ -155,16 +156,16 @@ class idea_idea(osv.osv):
|
|||
'title': fields.char('Idea Summary', size=64, required=True, readonly=True, states={'draft':[('readonly',False)]}),
|
||||
'description': fields.text('Description', help='Content of the idea', readonly=True, states={'draft':[('readonly',False)]}),
|
||||
'comment_ids': fields.one2many('idea.comment', 'idea_id', 'Comments'),
|
||||
'create_date': fields.datetime('Creation date', readonly=True),
|
||||
'created_date': fields.datetime('Creation date', readonly=True),
|
||||
'vote_ids': fields.one2many('idea.vote', 'idea_id', 'Vote'),
|
||||
'my_vote': fields.function(_vote_read, fnct_inv = _vote_save, string="My Vote", method=True, type="selection", selection=VoteValues),
|
||||
'vote_avg': fields.function(_vote_avg_compute, method=True, string="Average Score", type="float"),
|
||||
'count_votes': fields.function(_vote_count, method=True, string="Count of votes", type="integer"),
|
||||
'count_comments': fields.function(_comment_count, method=True, string="Count of comments", type="integer"),
|
||||
'category_id': fields.many2one('idea.category', 'Category', required=True, readonly=True, states={'draft':[('readonly',False)]}),
|
||||
'state': fields.selection([('draft', 'Draft'),
|
||||
'state': fields.selection([('draft', 'Draft'),
|
||||
('open', 'Opened'),
|
||||
('close', 'Accepted'),
|
||||
('close', 'Accepted'),
|
||||
('cancel', 'Cancelled')],
|
||||
'State', readonly=True,
|
||||
help='When the Idea is created the state is \'Draft\'.\n It is \
|
||||
|
@ -173,12 +174,16 @@ class idea_idea(osv.osv):
|
|||
),
|
||||
'visibility':fields.boolean('Open Idea?', required=False),
|
||||
'stat_vote_ids': fields.one2many('idea.vote.stat', 'idea_id', 'Statistics', readonly=True),
|
||||
'vote_limit': fields.integer('Maximum Vote per User',
|
||||
help="Set to one if you require only one Vote per user"),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'user_id': lambda self,cr,uid,context: uid,
|
||||
'my_vote': lambda *a: '-1',
|
||||
'state': lambda *a: 'draft',
|
||||
'vote_limit': lambda * a: 1,
|
||||
'created_date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'visibility': lambda *a: True,
|
||||
}
|
||||
_order = 'id desc'
|
||||
|
@ -190,11 +195,11 @@ class idea_idea(osv.osv):
|
|||
@param user: ID of the user currently logged in
|
||||
@param vals: provides data for new record
|
||||
@param context: context arguments, like lang, time zone
|
||||
|
||||
|
||||
@return: Returns an id of the new record
|
||||
"""
|
||||
visibility = False
|
||||
|
||||
|
||||
if vals.get('category_id', False):
|
||||
category_pool = self.pool.get('idea.category')
|
||||
category = category_pool.browse(cr, user, vals.get('category_id'), context)
|
||||
|
@ -215,41 +220,41 @@ class idea_idea(osv.osv):
|
|||
@param id: list of record ids on which copy method executes
|
||||
@param default: dict type contains the values to be overridden during copy of object
|
||||
@param context: context arguments, like lang, time zone
|
||||
|
||||
|
||||
@return: Returns the id of the new record
|
||||
"""
|
||||
|
||||
|
||||
default.update({
|
||||
'comment_ids':False,
|
||||
'vote_ids':False,
|
||||
'stat_vote_ids':False
|
||||
|
||||
|
||||
})
|
||||
res_id = super(idea_idea, self).copy(cr, uid, id, default, context)
|
||||
return res_id
|
||||
|
||||
|
||||
def write(self, cr, user, ids, vals, context=None):
|
||||
"""
|
||||
Update redord(s) exist in {ids}, with new value provided in {vals}
|
||||
|
||||
|
||||
@param cr: A database cursor
|
||||
@param user: ID of the user currently logged in
|
||||
@param ids: list of record ids to update
|
||||
@param vals: dict of new values to be set
|
||||
@param context: context arguments, like lang, time zone
|
||||
|
||||
|
||||
@return: Returns True on success, False otherwise
|
||||
"""
|
||||
|
||||
|
||||
state = self.browse(cr, user, ids[0]).state
|
||||
|
||||
|
||||
if vals.get('my_vote', False):
|
||||
if vals.get('state', state) != 'open':
|
||||
raise osv.except_osv(_("Warning !"), _("Draft/Accepted/Cancelled ideas Could not be voted"))
|
||||
|
||||
|
||||
res = super(idea_idea, self).write(cr, user, ids, vals, context)
|
||||
return res
|
||||
|
||||
|
||||
def idea_cancel(self, cr, uid, ids):
|
||||
self.write(cr, uid, ids, { 'state': 'cancel' })
|
||||
return True
|
||||
|
@ -261,7 +266,7 @@ class idea_idea(osv.osv):
|
|||
def idea_close(self, cr, uid, ids):
|
||||
self.write(cr, uid, ids, { 'state': 'close' })
|
||||
return True
|
||||
|
||||
|
||||
def idea_draft(self, cr, uid, ids):
|
||||
self.write(cr, uid, ids, { 'state': 'draft' })
|
||||
return True
|
||||
|
@ -299,12 +304,15 @@ class idea_vote(osv.osv):
|
|||
_rec_name = 'score'
|
||||
|
||||
_columns = {
|
||||
'user_id': fields.many2one('res.users', 'User'),
|
||||
'idea_id': fields.many2one('idea.idea', 'Idea', required=True, ondelete='cascade'),
|
||||
'score': fields.selection(VoteValues, 'Score', required=True)
|
||||
'user_id': fields.many2one('res.users', 'By user', readonly="True"),
|
||||
'idea_id': fields.many2one('idea.idea', 'Idea', readonly="True", ondelete='cascade'),
|
||||
'score': fields.selection(VoteValues, 'Vote Status', readonly="True"),
|
||||
'date': fields.datetime('Date', readonly="True"),
|
||||
'comment': fields.text('Comment', readonly="True"),
|
||||
}
|
||||
_defaults = {
|
||||
'score': lambda *a: DefaultVoteValue,
|
||||
'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
}
|
||||
|
||||
idea_vote()
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
|
||||
<menuitem name="Categories" parent="menu_ideas" id="menu_idea_category" action="action_idea_category" />
|
||||
|
||||
|
||||
<!-- Idea Category Action -->
|
||||
|
||||
<record model="ir.actions.act_window" id="action_idea_category_tree">
|
||||
|
@ -60,8 +61,18 @@
|
|||
</record>
|
||||
|
||||
<menuitem name="Ideas" parent="base.menu_tools" id="menu_ideas1" sequence="4"/>
|
||||
|
||||
<menuitem
|
||||
name="Ideas by Categories" parent="menu_ideas1"
|
||||
id="menu_idea_category_tree"
|
||||
action="action_idea_category_tree"/>
|
||||
|
||||
<menuitem name="Give Vote" parent="menu_ideas1"
|
||||
id="menu_give_vote"
|
||||
action="action_idea_select"/>
|
||||
|
||||
<!-- Oepn Ideas Action -->
|
||||
|
||||
<!-- Open Ideas Action -->
|
||||
|
||||
<record model="ir.actions.act_window" id="action_idea_idea_categ_open">
|
||||
<field name="name">Open Ideas</field>
|
||||
|
@ -102,9 +113,9 @@
|
|||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Votes">
|
||||
<field name="idea_id"/>
|
||||
<field name="user_id"/>
|
||||
<field name="score" />
|
||||
<field name="user_id" />
|
||||
<field name="score"/>
|
||||
<field name="date"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
@ -117,12 +128,39 @@
|
|||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Votes">
|
||||
<field name="idea_id" select="1" />
|
||||
<field name="user_id" select="1" />
|
||||
<field name="score"/>
|
||||
<group colspan="4">
|
||||
<field name="user_id" select="1" />
|
||||
<field name="date"/>
|
||||
<newline/>
|
||||
<field name="score"/>
|
||||
</group>
|
||||
<separator string="Comments:" colspan="4"/>
|
||||
<field name="comment" colspan="4" nolabel="1"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Search view for Idea vote -->
|
||||
|
||||
<record model="ir.ui.view" id="view_idea_vote_search">
|
||||
<field name="name">idea.vote.search</field>
|
||||
<field name="model">idea.vote</field>
|
||||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Ideas vote">
|
||||
<group col="10" colspan="4">
|
||||
<field name="idea_id" widget="selection"/>
|
||||
<field name="user_id" widget="selection"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<group expand="1" string="Group By..." colspan="14">
|
||||
<filter string="Vote date" icon="terp-crm" domain="[]" context="{'group_by':'date'}"/>
|
||||
<filter string="Idea" icon="terp-crm" domain="[]" context="{'group_by':'idea_id'}"/>
|
||||
<filter string="User" name="user" icon="terp-partner" domain="[]" context="{'group_by':'user_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- New Idea Form View -->
|
||||
|
||||
|
@ -180,7 +218,8 @@
|
|||
<field name="score"/>
|
||||
<field name="nbr"/>
|
||||
</tree>
|
||||
</field>
|
||||
</field>
|
||||
|
||||
</page>
|
||||
</notebook>
|
||||
<group colspan="4" col="6">
|
||||
|
@ -188,7 +227,6 @@
|
|||
<button name="idea_open" string="Open" states="draft" icon="gtk-go-forward"/>
|
||||
<button name="idea_close" string="Accept" states="open" icon="gtk-jump-to"/>
|
||||
<button name="idea_cancel" string="Refuse" states="open" icon="gtk-cancel"/>
|
||||
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
|
@ -201,15 +239,15 @@
|
|||
<field name="model">idea.idea</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="All Ideas">
|
||||
<tree string="Ideas">
|
||||
<field name="title"/>
|
||||
<field name="category_id" />
|
||||
<field name="create_date"/>
|
||||
<field name="created_date"/>
|
||||
<field name="vote_avg" widget="progressbar"/>
|
||||
<field name="count_comments" />
|
||||
<field name="count_votes" />
|
||||
<field name="state"/>
|
||||
<button name="%(action_idea_post_vote)d" icon="gtk-execute" type="action" states="draft,open" string="Vote"/>
|
||||
<button name="%(idea.action_idea_post_vote)d" icon="gtk-execute" type="action" states="open" string="Submit Vote"/>
|
||||
<button name="idea_close" string="Accept" states="open" icon="gtk-jump-to"/>
|
||||
<button name="idea_cancel" string="Refuse" states="open" icon="gtk-cancel"/>
|
||||
</tree>
|
||||
|
@ -244,23 +282,6 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Comments on Idea Tree View -->
|
||||
|
||||
<record model="ir.ui.view" id="view_idea_comment_tree">
|
||||
<field name="name">idea.comment.tree</field>
|
||||
<field name="model">idea.comment</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Comments">
|
||||
<field name="create_date" />
|
||||
<field name="user_id" />
|
||||
<field name="content" string="Comment" />
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Idea Action -->
|
||||
|
||||
<record model="ir.actions.act_window" id="action_idea_idea">
|
||||
<field name="name">Ideas</field>
|
||||
<field name="res_model">idea.idea</field>
|
||||
|
@ -348,9 +369,10 @@
|
|||
<field name="res_model">idea.vote</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="search_view_id" ref="view_idea_vote_search"/>
|
||||
</record>
|
||||
|
||||
<menuitem name="All Votes" parent="menu_ideas" id="menu_idea_vote" action="action_idea_vote"/>
|
||||
<menuitem name="Votes" parent="menu_ideas" id="menu_idea_vote" action="action_idea_vote"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
|
||||
"access_idea_category","idea.category","model_idea_category","base.group_user",1,0,0,0
|
||||
"access_idea_idea","idea.idea","model_idea_idea","base.group_user",1,1,1,1
|
||||
"access_idea_comment","idea.comment","model_idea_comment","base.group_user",1,1,1,1
|
||||
"access_idea_vote","idea.vote","model_idea_vote","base.group_user",1,1,1,1
|
||||
"access_idea_vote_stat","idea.vote.stat","model_idea_vote_stat","base.group_user",1,0,0,0
|
||||
"access_idea_category_system","idea.category system","model_idea_category","base.group_system",1,1,1,1
|
||||
"idea_post_vote","idea.post.vote","model_idea_post_vote","base.group_user",1,1,1,1
|
||||
"access_idea_select","idea.select","model_idea_select","base.group_user",1,1,1,1
|
||||
"access_idea_comment","idea.comment","model_idea_comment","base.group_system",1,1,1,1
|
||||
|
|
|
|
@ -8,10 +8,10 @@
|
|||
name: Technical
|
||||
- |
|
||||
I create a New Idea of "Technical presentation for 1 hours in every day" and specify category "Technical".
|
||||
|
||||
-
|
||||
!record {model: idea.idea, id: idea_idea_0}:
|
||||
category_id: idea_category_technical0
|
||||
created_date: '05/13/2010 19:16:26'
|
||||
description: I want that Technical presentation are arranged for 1 hours in every
|
||||
day.\nso, on that presentation, we can know all things what improvement and development
|
||||
are done in our company.\n\n\n\n\n
|
||||
|
@ -44,52 +44,50 @@
|
|||
!record {model: res.users, id: res_users_user1}:
|
||||
company_id: base.main_company
|
||||
context_lang: en_US
|
||||
groups_id:
|
||||
- base.group_system
|
||||
- base.group_user
|
||||
login: user2
|
||||
name: user2
|
||||
password: user2
|
||||
|
||||
- |
|
||||
In order to post vote I connect as user1 and open the idea page
|
||||
I click on "Vote" wizard and vote the idea as "Normal"
|
||||
I click on "Submit Vote" wizard button and vote the idea as "Normal"
|
||||
-
|
||||
!record {model: idea.post.vote, id: idea_post_vote_0}:
|
||||
vote: 50
|
||||
|
||||
- |
|
||||
Now I click on "Post Vote" button of wizard.
|
||||
Now I click on "Post" button of this wizard.
|
||||
-
|
||||
!python {model: idea.post.vote}: |
|
||||
uid = ref('res_users_user0')
|
||||
self.do_vote(cr, uid, [ref("idea_post_vote_0")], {'active_id': ref('idea_idea_0')})
|
||||
self.do_vote(cr, uid, [ref("idea_post_vote_0")], {'active_ids': [ref('idea_idea_0')]})
|
||||
|
||||
- |
|
||||
To add other vote I connect as user2 and open the idea page
|
||||
I click on "Vote" wizard and vote the idea as "Very Good"
|
||||
To add other vote I connect as user2 and open the idea page.
|
||||
|
||||
I click on "Submit Vote" wizard button and vote the idea as "Very Good".
|
||||
|
||||
and put comment "We can learn many things from technical presentation".
|
||||
|
||||
-
|
||||
!record {model: idea.post.vote, id: idea_post_vote_1}:
|
||||
vote: 100
|
||||
|
||||
note: 'We can learn many things from technical presentation'
|
||||
- |
|
||||
I click on "Post Vote" button of this wizard.
|
||||
I click on "Post" button of this wizard.
|
||||
-
|
||||
!python {model: idea.post.vote}: |
|
||||
uid = ref('res_users_user1')
|
||||
self.do_vote(cr, uid, [ref("idea_post_vote_1")], {'active_id': ref('idea_idea_0')})
|
||||
self.do_vote(cr, uid, [ref("idea_post_vote_1")], {'active_ids': [ref('idea_idea_0')]})
|
||||
|
||||
- |
|
||||
I can see that the Average score changed in "Average score" field with value 75
|
||||
-
|
||||
!record {model: idea.idea, id: idea_idea_0}:
|
||||
vote_avg: 75
|
||||
|
||||
- |
|
||||
I put one comment "We can learn many things from technical presentation" for the idea.
|
||||
-
|
||||
!record {model: idea.idea, id: idea.idea_idea_0}:
|
||||
comment_ids:
|
||||
- content: "We can learn many things from technical presentation"
|
||||
idea_id: idea.idea_idea_0
|
||||
user_id: res_users_user1
|
||||
|
||||
- |
|
||||
I connect as Manager and close this idea by click on "Close" button.
|
||||
|
|
|
@ -34,11 +34,11 @@ class idea_post_vote(osv.osv_memory):
|
|||
('25', 'Bad'),
|
||||
('50', 'Normal'),
|
||||
('75', 'Good'),
|
||||
('100', 'Very Good') ],
|
||||
('100', 'Very Good') ],
|
||||
'Post Vote', required=True),
|
||||
'note': fields.text('Description'),
|
||||
}
|
||||
|
||||
|
||||
def get_default(self, cr, uid, context={}):
|
||||
"""
|
||||
This function checks for precondition before wizard executes
|
||||
|
@ -49,17 +49,17 @@ class idea_post_vote(osv.osv_memory):
|
|||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
idea_obj = self.pool.get('idea.idea')
|
||||
|
||||
|
||||
if context.get('active_id'):
|
||||
idea = idea_obj.browse(cr, uid, context.get('active_id'))
|
||||
return idea.my_vote
|
||||
else:
|
||||
return 75
|
||||
|
||||
|
||||
_defaults = {
|
||||
'vote': get_default,
|
||||
}
|
||||
|
||||
|
||||
def view_init(self, cr, uid, fields, context=None):
|
||||
"""
|
||||
This function checks for precondition before wizard executes
|
||||
|
@ -70,15 +70,28 @@ class idea_post_vote(osv.osv_memory):
|
|||
@param context: A standard dictionary for contextual values
|
||||
"""
|
||||
idea_obj = self.pool.get('idea.idea')
|
||||
vote_obj = self.pool.get('idea.vote')
|
||||
|
||||
for idea in idea_obj.browse(cr, uid, context.get('active_ids', [])):
|
||||
if idea.state in ['draft', 'close', 'cancel']:
|
||||
raise osv.except_osv(_("Warning !"), _("Draft/Accepted/Cancelled ideas Could not be voted"))
|
||||
|
||||
for active_id in context.get('active_ids'):
|
||||
|
||||
vote_ids = vote_obj.search(cr, uid, [('user_id', '=', uid), ('idea_id', '=', active_id)])
|
||||
vote_obj_id = vote_obj.browse(cr, uid, vote_ids)
|
||||
count = 0
|
||||
for vote in vote_obj_id:
|
||||
count += 1
|
||||
|
||||
user_limit = idea.vote_limit
|
||||
if count >= user_limit:
|
||||
raise osv.except_osv(_('Warning !'),_("You can not give Vote for this idea more than %s times") % (user_limit))
|
||||
|
||||
if idea.state != 'open':
|
||||
raise osv.except_osv(_('Warning !'), _('idea should be in \'Open\' state before vote for that idea.'))
|
||||
raise osv.except_osv(_('Warning !'), _('Idea should be in \
|
||||
\'Open\' state before vote for that idea.'))
|
||||
return False
|
||||
|
||||
def do_vote(self, cr, uid, ids, context):
|
||||
def do_vote(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
Create idea vote.
|
||||
@param cr: the current row, from the database cursor,
|
||||
|
@ -86,8 +99,8 @@ class idea_post_vote(osv.osv_memory):
|
|||
@param ids: List of Idea Post vote’s IDs.
|
||||
@return: Dictionary {}
|
||||
"""
|
||||
|
||||
vote_id = context and context.get('active_id', False) or False
|
||||
|
||||
vote_ids = context and context.get('active_ids', []) or []
|
||||
vote_pool = self.pool.get('idea.vote')
|
||||
idea_pool = self.pool.get('idea.idea')
|
||||
comment_pool = self.pool.get('idea.comment')
|
||||
|
@ -96,8 +109,8 @@ class idea_post_vote(osv.osv_memory):
|
|||
score = str(do_vote_obj['vote'])
|
||||
comment = do_vote_obj.get('note', False)
|
||||
vote = {
|
||||
'idea_id': vote_id,
|
||||
'user_id': uid,
|
||||
'idea_id': vote_id,
|
||||
'user_id': uid,
|
||||
'score': score
|
||||
}
|
||||
if comment:
|
||||
|
@ -114,5 +127,44 @@ class idea_post_vote(osv.osv_memory):
|
|||
|
||||
idea_post_vote()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
class idea_select(osv.osv_memory):
|
||||
|
||||
""" Select idea for vote."""
|
||||
|
||||
_name = "idea.select"
|
||||
_description = "select idea"
|
||||
|
||||
_columns = {
|
||||
'idea_id': fields.many2one('idea.idea', 'Idea', required=True),
|
||||
}
|
||||
|
||||
def open_vote(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
This function load column.
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current users ID for security checks,
|
||||
@param ids: List of load column,
|
||||
@return: dictionary of query logs clear message window
|
||||
"""
|
||||
idea_obj = self.browse(cr, uid, ids)
|
||||
for idea in idea_obj:
|
||||
idea_id = idea.idea_id.id
|
||||
|
||||
data_obj = self.pool.get('ir.model.data')
|
||||
id2 = data_obj._get_id(cr, uid, 'idea', 'view_idea_post_vote')
|
||||
if id2:
|
||||
id2 = data_obj.browse(cr, uid, id2, context=context).res_id
|
||||
value = {
|
||||
'view_type': 'form',
|
||||
'view_mode': 'form',
|
||||
'res_model': 'idea.post.vote',
|
||||
'views': [(id2, 'form'), (False, 'tree'), (False, 'calendar'), (False, 'graph')],
|
||||
'type': 'ir.actions.act_window',
|
||||
'target': 'new',
|
||||
'context': {'active_ids': [idea_id]}
|
||||
}
|
||||
return value
|
||||
|
||||
idea_select()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue