[MERGE] Merged lp:openobject-addons.

bzr revid: psa@tinyerp.com-20130409053450-8pb9vy1z478kxvsb
This commit is contained in:
Paramjit Singh Sahota 2013-04-09 11:04:50 +05:30
commit 8e9556a2fb
120 changed files with 2125 additions and 963 deletions

View File

@ -1027,6 +1027,9 @@ class account_period(osv.osv):
def action_draft(self, cr, uid, ids, *args): def action_draft(self, cr, uid, ids, *args):
mode = 'draft' mode = 'draft'
for period in self.browse(cr, uid, ids):
if period.fiscalyear_id.state == 'done':
raise osv.except_osv(_('Warning !'), _('You can not re-open a period which belongs to closed fiscal year'))
cr.execute('update account_journal_period set state=%s where period_id in %s', (mode, tuple(ids),)) cr.execute('update account_journal_period set state=%s where period_id in %s', (mode, tuple(ids),))
cr.execute('update account_period set state=%s where id in %s', (mode, tuple(ids),)) cr.execute('update account_period set state=%s where id in %s', (mode, tuple(ids),))
return True return True

View File

@ -453,10 +453,11 @@
<filter name="invoices" string="Invoices" domain="[('state','not in',['draft','cancel'])]" help="Proforma/Open/Paid Invoices"/> <filter name="invoices" string="Invoices" domain="[('state','not in',['draft','cancel'])]" help="Proforma/Open/Paid Invoices"/>
<filter name="unpaid" string="Unpaid" domain="[('state','=','open')]" help="Unpaid Invoices"/> <filter name="unpaid" string="Unpaid" domain="[('state','=','open')]" help="Unpaid Invoices"/>
<separator/> <separator/>
<filter domain="[('user_id','=',uid)]" help="My Invoices" icon="terp-personal"/>
<field name="partner_id"/> <field name="partner_id"/>
<field name="user_id" string="Salesperson"/> <field name="user_id" string="Salesperson"/>
<field name="period_id" string="Period"/> <field name="period_id" string="Period"/>
<separator/>
<filter domain="[('user_id','=',uid)]" help="My Invoices"/>
<group expand="0" string="Group By..."> <group expand="0" string="Group By...">
<filter string="Partner" icon="terp-partner" domain="[]" context="{'group_by':'partner_id'}"/> <filter string="Partner" icon="terp-partner" domain="[]" context="{'group_by':'partner_id'}"/>
<filter string="Responsible" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/> <filter string="Responsible" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/>

View File

@ -742,7 +742,7 @@ class account_move_line(osv.osv):
def list_partners_to_reconcile(self, cr, uid, context=None): def list_partners_to_reconcile(self, cr, uid, context=None):
cr.execute( cr.execute(
"""SELECT partner_id FROM ( """SELECT partner_id FROM (
SELECT l.partner_id, p.last_reconciliation_date, SUM(l.debit) AS debit, SUM(l.credit) AS credit, MAX(l.date) AS max_date SELECT l.partner_id, p.last_reconciliation_date, SUM(l.debit) AS debit, SUM(l.credit) AS credit, MAX(l.create_date) AS max_date
FROM account_move_line l FROM account_move_line l
RIGHT JOIN account_account a ON (a.id = l.account_id) RIGHT JOIN account_account a ON (a.id = l.account_id)
RIGHT JOIN res_partner p ON (l.partner_id = p.id) RIGHT JOIN res_partner p ON (l.partner_id = p.id)
@ -753,9 +753,14 @@ class account_move_line(osv.osv):
) AS s ) AS s
WHERE debit > 0 AND credit > 0 AND (last_reconciliation_date IS NULL OR max_date > last_reconciliation_date) WHERE debit > 0 AND credit > 0 AND (last_reconciliation_date IS NULL OR max_date > last_reconciliation_date)
ORDER BY last_reconciliation_date""") ORDER BY last_reconciliation_date""")
ids = cr.fetchall() ids = [x[0] for x in cr.fetchall()]
ids = len(ids) and [x[0] for x in ids] or [] if not ids:
return self.pool.get('res.partner').name_get(cr, uid, ids, context=context) return []
# To apply the ir_rules
partner_obj = self.pool.get('res.partner')
ids = partner_obj.search(cr, uid, [('id', 'in', ids)], context=context)
return partner_obj.name_get(cr, uid, ids, context=context)
def reconcile_partial(self, cr, uid, ids, type='auto', context=None, writeoff_acc_id=False, writeoff_period_id=False, writeoff_journal_id=False): def reconcile_partial(self, cr, uid, ids, type='auto', context=None, writeoff_acc_id=False, writeoff_period_id=False, writeoff_journal_id=False):
move_rec_obj = self.pool.get('account.move.reconcile') move_rec_obj = self.pool.get('account.move.reconcile')

View File

@ -210,8 +210,8 @@ class account_invoice_report(osv.osv):
cr.id IN (SELECT id cr.id IN (SELECT id
FROM res_currency_rate cr2 FROM res_currency_rate cr2
WHERE (cr2.currency_id = sub.currency_id) WHERE (cr2.currency_id = sub.currency_id)
AND ((sub.date IS NOT NULL AND cr.name <= sub.date) AND ((sub.date IS NOT NULL AND cr2.name <= sub.date)
OR (sub.date IS NULL AND cr.name <= NOW())) OR (sub.date IS NULL AND cr2.name <= NOW()))
ORDER BY name DESC LIMIT 1) ORDER BY name DESC LIMIT 1)
)""" % ( )""" % (
self._table, self._table,

View File

@ -168,7 +168,7 @@
</para> </para>
<para style="terp_default_8">Tel. : [[ (o.partner_id.phone) or removeParentNode('para') ]]</para> <para style="terp_default_8">Tel. : [[ (o.partner_id.phone) or removeParentNode('para') ]]</para>
<para style="terp_default_8">Fax : [[ (o.partner_id.fax) or removeParentNode('para') ]]</para> <para style="terp_default_8">Fax : [[ (o.partner_id.fax) or removeParentNode('para') ]]</para>
<para style="terp_default_8">VAT : [[ (o.partner_id.vat) or removeParentNode('para') ]]</para> <para style="terp_default_8">TIN : [[ (o.partner_id.vat) or removeParentNode('para') ]]</para>
</td> </td>
</tr> </tr>
</blockTable> </blockTable>

View File

@ -181,9 +181,9 @@ class account_invoice_refund(osv.osv_memory):
invoice = invoice[0] invoice = invoice[0]
del invoice['id'] del invoice['id']
invoice_lines = inv_line_obj.browse(cr, uid, invoice['invoice_line'], context=context) invoice_lines = inv_line_obj.browse(cr, uid, invoice['invoice_line'], context=context)
invoice_lines = inv_obj._refund_cleanup_lines(cr, uid, invoice_lines) invoice_lines = inv_obj._refund_cleanup_lines(cr, uid, invoice_lines, context=context)
tax_lines = inv_tax_obj.browse(cr, uid, invoice['tax_line'], context=context) tax_lines = inv_tax_obj.browse(cr, uid, invoice['tax_line'], context=context)
tax_lines = inv_obj._refund_cleanup_lines(cr, uid, tax_lines) tax_lines = inv_obj._refund_cleanup_lines(cr, uid, tax_lines, context=context)
invoice.update({ invoice.update({
'type': inv.type, 'type': inv.type,
'date_invoice': date, 'date_invoice': date,

View File

@ -352,10 +352,9 @@ class account_analytic_account(osv.osv):
res[account.id] = 0.0 res[account.id] = 0.0
sale_ids = sale_obj.search(cr, uid, [('project_id','=', account.id), ('state', '=', 'manual')], context=context) sale_ids = sale_obj.search(cr, uid, [('project_id','=', account.id), ('state', '=', 'manual')], context=context)
for sale in sale_obj.browse(cr, uid, sale_ids, context=context): for sale in sale_obj.browse(cr, uid, sale_ids, context=context):
if not sale.invoiced:
res[account.id] += sale.amount_untaxed res[account.id] += sale.amount_untaxed
for invoice in sale.invoice_ids: for invoice in sale.invoice_ids:
if invoice.state not in ('draft', 'cancel'): if invoice.state != 'cancel':
res[account.id] -= invoice.amount_untaxed res[account.id] -= invoice.amount_untaxed
return res return res

View File

@ -267,7 +267,7 @@
</field> </field>
</record> </record>
<menuitem id="base.menu_sales" name="Sales" parent="base.menu_base_partner" sequence="1"/> <menuitem id="base.menu_sales" name="Sales" parent="base.menu_base_partner" sequence="1"/>
<menuitem action="action_account_analytic_overdue_all" id="menu_action_account_analytic_overdue_all" sequence="7" parent="base.menu_sales"/> <menuitem action="action_account_analytic_overdue_all" id="menu_action_account_analytic_overdue_all" sequence="8" parent="base.menu_sales"/>
<!-- Action Sales/Invoicing/Time and Material to Invoice --> <!-- Action Sales/Invoicing/Time and Material to Invoice -->
<record id="action_hr_tree_invoiced_all" model="ir.actions.act_window"> <record id="action_hr_tree_invoiced_all" model="ir.actions.act_window">

View File

@ -7,19 +7,19 @@ msgstr ""
"Project-Id-Version: OpenERP Server 6.0dev\n" "Project-Id-Version: OpenERP Server 6.0dev\n"
"Report-Msgid-Bugs-To: support@openerp.com\n" "Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-12-21 17:05+0000\n" "POT-Creation-Date: 2012-12-21 17:05+0000\n"
"PO-Revision-Date: 2011-01-30 16:46+0000\n" "PO-Revision-Date: 2013-04-04 13:17+0000\n"
"Last-Translator: Krisztian Eyssen <krisz@eyssen.hu>\n" "Last-Translator: krnkris <Unknown>\n"
"Language-Team: \n" "Language-Team: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n" "Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-16 05:42+0000\n" "X-Launchpad-Export-Date: 2013-04-05 05:37+0000\n"
"X-Generator: Launchpad (build 16532)\n" "X-Generator: Launchpad (build 16550)\n"
#. module: account_cancel #. module: account_cancel
#: view:account.invoice:0 #: view:account.invoice:0
msgid "Cancel" msgid "Cancel"
msgstr "" msgstr "Sztornó"
#~ msgid "Account Cancel" #~ msgid "Account Cancel"
#~ msgstr "Érvénytelenítés" #~ msgstr "Érvénytelenítés"

File diff suppressed because it is too large Load Diff

View File

@ -7,19 +7,19 @@ msgstr ""
"Project-Id-Version: OpenERP Server 6.0dev\n" "Project-Id-Version: OpenERP Server 6.0dev\n"
"Report-Msgid-Bugs-To: support@openerp.com\n" "Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-12-21 17:04+0000\n" "POT-Creation-Date: 2012-12-21 17:04+0000\n"
"PO-Revision-Date: 2013-03-26 15:03+0000\n" "PO-Revision-Date: 2013-04-04 11:34+0000\n"
"Last-Translator: krnkris <Unknown>\n" "Last-Translator: krnkris <Unknown>\n"
"Language-Team: \n" "Language-Team: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n" "Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-27 04:36+0000\n" "X-Launchpad-Export-Date: 2013-04-05 05:37+0000\n"
"X-Generator: Launchpad (build 16540)\n" "X-Generator: Launchpad (build 16550)\n"
#. module: account_voucher #. module: account_voucher
#: field:account.bank.statement.line,voucher_id:0 #: field:account.bank.statement.line,voucher_id:0
msgid "Reconciliation" msgid "Reconciliation"
msgstr "" msgstr "Párosítás"
#. module: account_voucher #. module: account_voucher
#: model:ir.model,name:account_voucher.model_account_config_settings #: model:ir.model,name:account_voucher.model_account_config_settings
@ -51,7 +51,7 @@ msgstr "Nyitott vevő tételek"
#: view:account.voucher:0 #: view:account.voucher:0
#: view:sale.receipt.report:0 #: view:sale.receipt.report:0
msgid "Group By..." msgid "Group By..."
msgstr "Csoportosítás" msgstr "Csoportosítás ezzel..."
#. module: account_voucher #. module: account_voucher
#: help:account.voucher,writeoff_amount:0 #: help:account.voucher,writeoff_amount:0
@ -102,7 +102,7 @@ msgstr "Számla kifizetése"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
msgid "Are you sure you want to cancel this receipt?" msgid "Are you sure you want to cancel this receipt?"
msgstr "" msgstr "Biztos, hogy vissza akarja vonni ezt a bevételi bizonylatot?"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
@ -137,6 +137,8 @@ msgid ""
"You can not change the journal as you already reconciled some statement " "You can not change the journal as you already reconciled some statement "
"lines!" "lines!"
msgstr "" msgstr ""
"Nem tudja a naplót megváltoztatni mivel a kivonatok egyes sorait már "
"párosította!"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
@ -160,6 +162,15 @@ msgid ""
" </p>\n" " </p>\n"
" " " "
msgstr "" msgstr ""
"<p class=\"oe_view_nocontent_create\">\n"
" Kattintson vásárlási bevételi bizonylat rögzítéséhez. \n"
" </p><p>\n"
" Ha a vásárlási bevételi bizonylat igazolva lett, rögzítheti "
"a \n"
" vásárlási bevételi bizonylathoz kapcsolódó beszállítói "
"kifizetést.\n"
" </p>\n"
" "
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
@ -169,7 +180,7 @@ msgstr "Nyugták keresése"
#. module: account_voucher #. module: account_voucher
#: field:account.voucher,writeoff_acc_id:0 #: field:account.voucher,writeoff_acc_id:0
msgid "Counterpart Account" msgid "Counterpart Account"
msgstr "" msgstr "Ellenszámla"
#. module: account_voucher #. module: account_voucher
#: field:account.voucher,account_id:0 #: field:account.voucher,account_id:0
@ -191,7 +202,7 @@ msgstr "Rendben"
#. module: account_voucher #. module: account_voucher
#: field:account.voucher.line,reconcile:0 #: field:account.voucher.line,reconcile:0
msgid "Full Reconcile" msgid "Full Reconcile"
msgstr "" msgstr "Teljes párosítás"
#. module: account_voucher #. module: account_voucher
#: field:account.voucher,date_due:0 #: field:account.voucher,date_due:0
@ -215,7 +226,7 @@ msgstr "Üzenetek"
#: model:ir.actions.act_window,name:account_voucher.action_purchase_receipt #: model:ir.actions.act_window,name:account_voucher.action_purchase_receipt
#: model:ir.ui.menu,name:account_voucher.menu_action_purchase_receipt #: model:ir.ui.menu,name:account_voucher.menu_action_purchase_receipt
msgid "Purchase Receipts" msgid "Purchase Receipts"
msgstr "" msgstr "Vásárlások bevételi bizonylatai"
#. module: account_voucher #. module: account_voucher
#: field:account.voucher.line,move_line_id:0 #: field:account.voucher.line,move_line_id:0
@ -271,11 +282,18 @@ msgid ""
" </p>\n" " </p>\n"
" " " "
msgstr "" msgstr ""
"<p class=\"oe_view_nocontent_create\">\n"
" Kattintson értékesítési bevételi bizonylat létrehozásához.\n"
" </p><p>\n"
" Ha az értékesítési bizonylat igazolva lett, rögzítheti az \n"
" értékesítéshez tartozó vevői befizetést.\n"
" </p>\n"
" "
#. module: account_voucher #. module: account_voucher
#: help:account.voucher,message_unread:0 #: help:account.voucher,message_unread:0
msgid "If checked new messages require your attention." msgid "If checked new messages require your attention."
msgstr "" msgstr "Ha be van jelölve, akkor figyelje az új üzeneteket."
#. module: account_voucher #. module: account_voucher
#: model:ir.model,name:account_voucher.model_account_bank_statement_line #: model:ir.model,name:account_voucher.model_account_bank_statement_line
@ -298,17 +316,17 @@ msgstr "ÁFA"
#: code:addons/account_voucher/account_voucher.py:879 #: code:addons/account_voucher/account_voucher.py:879
#, python-format #, python-format
msgid "Invalid Action!" msgid "Invalid Action!"
msgstr "" msgstr "Érvénytelen lépés!"
#. module: account_voucher #. module: account_voucher
#: field:account.voucher,comment:0 #: field:account.voucher,comment:0
msgid "Counterpart Comment" msgid "Counterpart Comment"
msgstr "" msgstr "Ellenoldali meglyegyzés"
#. module: account_voucher #. module: account_voucher
#: field:account.voucher.line,account_analytic_id:0 #: field:account.voucher.line,account_analytic_id:0
msgid "Analytic Account" msgid "Analytic Account"
msgstr "Gyűjtőkód" msgstr "Gyűjtő/elemző könyvelés"
#. module: account_voucher #. module: account_voucher
#: help:account.voucher,message_summary:0 #: help:account.voucher,message_summary:0
@ -316,11 +334,13 @@ msgid ""
"Holds the Chatter summary (number of messages, ...). This summary is " "Holds the Chatter summary (number of messages, ...). This summary is "
"directly in html format in order to be inserted in kanban views." "directly in html format in order to be inserted in kanban views."
msgstr "" msgstr ""
"A chettelés összegzést megállítja (üzenetek száma,...). Ez az összegzés "
"direkt HTML formátumú ahhoz hogy beilleszthető legyen a kanban nézetekbe."
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
msgid "Total Allocation" msgid "Total Allocation"
msgstr "" msgstr "Összes kiosztás"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
@ -330,7 +350,7 @@ msgstr "Fizetési információ"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
msgid "(update)" msgid "(update)"
msgstr "" msgstr "(frissítés)"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
@ -349,20 +369,20 @@ msgstr "Számlák importálása"
#: code:addons/account_voucher/account_voucher.py:1112 #: code:addons/account_voucher/account_voucher.py:1112
#, python-format #, python-format
msgid "Wrong voucher line" msgid "Wrong voucher line"
msgstr "Nem megfelelő nyugta sorok" msgstr "Nem megfelelő nyugta sor"
#. module: account_voucher #. module: account_voucher
#: selection:account.voucher,pay_now:0 #: selection:account.voucher,pay_now:0
#: selection:sale.receipt.report,pay_now:0 #: selection:sale.receipt.report,pay_now:0
msgid "Pay Later or Group Funds" msgid "Pay Later or Group Funds"
msgstr "Későbbi fizetés" msgstr "Fizessen később vagy csoportosítsa a pénzeket"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
#: selection:account.voucher,type:0 #: selection:account.voucher,type:0
#: selection:sale.receipt.report,type:0 #: selection:sale.receipt.report,type:0
msgid "Receipt" msgid "Receipt"
msgstr "Befizetés" msgstr "Bevételi bizonylat"
#. module: account_voucher #. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:1018 #: code:addons/account_voucher/account_voucher.py:1018
@ -372,6 +392,9 @@ msgid ""
"settings, to manage automatically the booking of accounting entries related " "settings, to manage automatically the booking of accounting entries related "
"to differences between exchange rates." "to differences between exchange rates."
msgstr "" msgstr ""
"Be kell állítani a 'Átváltási arány nyereség számlája' a könyvelés "
"beállításainál, ahhoz, hogy kezelni tudja az automatikus könyvelését azoknak "
"a számla tételeknek, melyek az átváltási arányok különbségéből adódhatnak."
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
@ -399,7 +422,7 @@ msgstr "Szállítói nyugta"
#. module: account_voucher #. module: account_voucher
#: field:account.voucher,message_follower_ids:0 #: field:account.voucher,message_follower_ids:0
msgid "Followers" msgid "Followers"
msgstr "" msgstr "Követők"
#. module: account_voucher #. module: account_voucher
#: selection:account.voucher.line,type:0 #: selection:account.voucher.line,type:0
@ -410,13 +433,13 @@ msgstr "Tartozik"
#: code:addons/account_voucher/account_voucher.py:1547 #: code:addons/account_voucher/account_voucher.py:1547
#, python-format #, python-format
msgid "Unable to change journal !" msgid "Unable to change journal !"
msgstr "" msgstr "Naplót nem lehet megváltoztatni !"
#. module: account_voucher #. module: account_voucher
#: view:sale.receipt.report:0 #: view:sale.receipt.report:0
#: field:sale.receipt.report,nbr:0 #: field:sale.receipt.report,nbr:0
msgid "# of Voucher Lines" msgid "# of Voucher Lines"
msgstr "Nyugtasorok száma" msgstr "# nyugta sor száma"
#. module: account_voucher #. module: account_voucher
#: view:sale.receipt.report:0 #: view:sale.receipt.report:0
@ -446,6 +469,13 @@ msgid ""
" </p>\n" " </p>\n"
" " " "
msgstr "" msgstr ""
"<p class=\"oe_view_nocontent_create\">\n"
" Kattintson új beszállítói fizetés létrehozásához.\n"
" </p><p>\n"
" OpenERP segít a kifizetéseinek, valamint a beszállítók "
"részére még fizetendő mérleg könnyű nyomon követéséhez.\n"
" </p>\n"
" "
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
@ -460,12 +490,12 @@ msgstr "Nyugta tételek"
#. module: account_voucher #. module: account_voucher
#: field:account.voucher,name:0 #: field:account.voucher,name:0
msgid "Memo" msgid "Memo"
msgstr "Megnevezés" msgstr "Emlékeztető"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
msgid "Are you sure to unreconcile and cancel this record ?" msgid "Are you sure to unreconcile and cancel this record ?"
msgstr "" msgstr "Biztosan visszavonja a bejegyzés párosítását?"
#. module: account_voucher #. module: account_voucher
#: field:account.voucher,is_multi_currency:0 #: field:account.voucher,is_multi_currency:0
@ -494,17 +524,25 @@ msgid ""
"\n" "\n"
"* The 'Cancelled' status is used when user cancel voucher." "* The 'Cancelled' status is used when user cancel voucher."
msgstr "" msgstr ""
" * A 'Tervezet' állapotot használja amint egy felhasználó létrehoz egy új és "
"még le nem igazolt nyugtát. \n"
"* 'Pro-forma' lesz, ha a nyugta Pro-forma állapotú, a nyugtának még nincs "
"nyugta száma. \n"
"* 'Elküldött' állapotú, ha egy felhasználó létrehozta a nyugtát, egy nyugta "
"számot generált hozzá, és a könyvelésben egy nyugta bevitel létre lett hozva "
" \n"
"* A 'Visszavonva' állapot lesz, ha egy felhasználó visszavonta a nyugtát."
#. module: account_voucher #. module: account_voucher
#: field:account.voucher,writeoff_amount:0 #: field:account.voucher,writeoff_amount:0
msgid "Difference Amount" msgid "Difference Amount"
msgstr "" msgstr "Különbség számla"
#. module: account_voucher #. module: account_voucher
#: view:sale.receipt.report:0 #: view:sale.receipt.report:0
#: field:sale.receipt.report,due_delay:0 #: field:sale.receipt.report,due_delay:0
msgid "Avg. Due Delay" msgid "Avg. Due Delay"
msgstr "Álagos fizetési határidő" msgstr "Álagos fizetési késedelem"
#. module: account_voucher #. module: account_voucher
#: code:addons/account_voucher/invoice.py:34 #: code:addons/account_voucher/invoice.py:34
@ -543,12 +581,24 @@ msgid ""
" </p>\n" " </p>\n"
" " " "
msgstr "" msgstr ""
"<p class=\"oe_view_nocontent_create\">\n"
" Kattintson új kifizetés rögzítéséhez. \n"
" </p><p>\n"
" Vigye be a vásárlót és a fizetési módot és utána, vagy "
"hozzon\n"
" létre kézzel egy fizetési rekordot, vagy az OpenERP fel fog "
"ajánlani\n"
" automatikusan a fizetéshez tartozó összeegyeztetést a\n"
" nyitott számlákkal vagy értékesítési bevételi "
"bizonylatokkal.\n"
" </p>\n"
" "
#. module: account_voucher #. module: account_voucher
#: field:account.config.settings,expense_currency_exchange_account_id:0 #: field:account.config.settings,expense_currency_exchange_account_id:0
#: field:res.company,expense_currency_exchange_account_id:0 #: field:res.company,expense_currency_exchange_account_id:0
msgid "Loss Exchange Rate Account" msgid "Loss Exchange Rate Account"
msgstr "" msgstr "Árfolyamveszteség számla"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
@ -572,7 +622,7 @@ msgstr "Ellenőrizendő"
#: code:addons/account_voucher/account_voucher.py:1194 #: code:addons/account_voucher/account_voucher.py:1194
#, python-format #, python-format
msgid "change" msgid "change"
msgstr "" msgstr "módosítás"
#. module: account_voucher #. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:1014 #: code:addons/account_voucher/account_voucher.py:1014
@ -582,6 +632,9 @@ msgid ""
"settings, to manage automatically the booking of accounting entries related " "settings, to manage automatically the booking of accounting entries related "
"to differences between exchange rates." "to differences between exchange rates."
msgstr "" msgstr ""
"Be kell állítani a 'Árfolyamveszteség számla' a könyvelés beállításoknál, "
"ahhoz, hogy kezelni tudja automatikusan a könyvelési tételek rögzítését, "
"melyek az átváltási árfolyam különbségekkel összefüggenek."
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
@ -599,11 +652,13 @@ msgid ""
"Fields with internal purpose only that depicts if the voucher is a multi " "Fields with internal purpose only that depicts if the voucher is a multi "
"currency one or not" "currency one or not"
msgstr "" msgstr ""
"Belső használatú mezők, melyek azt ábrázolják, hogy a nyugták több "
"pénzneműek vagy nem"
#. module: account_voucher #. module: account_voucher
#: view:account.invoice:0 #: view:account.invoice:0
msgid "Register Payment" msgid "Register Payment"
msgstr "Kifizetés" msgstr "Kifizetés rögzítés"
#. module: account_voucher #. module: account_voucher
#: field:account.statement.from.invoice.lines,line_ids:0 #: field:account.statement.from.invoice.lines,line_ids:0
@ -618,7 +673,7 @@ msgstr "December"
#. module: account_voucher #. module: account_voucher
#: view:sale.receipt.report:0 #: view:sale.receipt.report:0
msgid "Group by month of Invoice Date" msgid "Group by month of Invoice Date"
msgstr "" msgstr "Csoportosítás számla dátuma alapján"
#. module: account_voucher #. module: account_voucher
#: view:sale.receipt.report:0 #: view:sale.receipt.report:0
@ -636,7 +691,7 @@ msgstr "Pénznem"
#. module: account_voucher #. module: account_voucher
#: view:account.statement.from.invoice.lines:0 #: view:account.statement.from.invoice.lines:0
msgid "Payable and Receivables" msgid "Payable and Receivables"
msgstr "Vevők és szállítók" msgstr "Fizetendők & Bevételek"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
@ -651,7 +706,7 @@ msgstr "Nyugta állapota"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
msgid "Are you sure to unreconcile this record?" msgid "Are you sure to unreconcile this record?"
msgstr "" msgstr "Biztosan törölni szeretné ennek a rekordnak a párosítását?"
#. module: account_voucher #. module: account_voucher
#: field:account.voucher,company_id:0 #: field:account.voucher,company_id:0
@ -664,18 +719,18 @@ msgstr "Vállalat"
#. module: account_voucher #. module: account_voucher
#: help:account.voucher,paid:0 #: help:account.voucher,paid:0
msgid "The Voucher has been totally paid." msgid "The Voucher has been totally paid."
msgstr "A nyugta ki lett egyenlítve" msgstr "A nyugta teljesen ki lett egyenlítve"
#. module: account_voucher #. module: account_voucher
#: selection:account.voucher,payment_option:0 #: selection:account.voucher,payment_option:0
msgid "Reconcile Payment Balance" msgid "Reconcile Payment Balance"
msgstr "" msgstr "Fizetési egyenleg párosítás"
#. module: account_voucher #. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:975 #: code:addons/account_voucher/account_voucher.py:975
#, python-format #, python-format
msgid "Configuration Error !" msgid "Configuration Error !"
msgstr "" msgstr "Beállítási hiba!"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
@ -687,7 +742,7 @@ msgstr "Nyugta tervezetek"
#: view:sale.receipt.report:0 #: view:sale.receipt.report:0
#: field:sale.receipt.report,price_total_tax:0 #: field:sale.receipt.report,price_total_tax:0
msgid "Total With Tax" msgid "Total With Tax"
msgstr "Bruttó érték" msgstr "Bruttó érték adóval"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
@ -699,18 +754,18 @@ msgstr "Beszerzési nyugta"
#: field:account.voucher,state:0 #: field:account.voucher,state:0
#: view:sale.receipt.report:0 #: view:sale.receipt.report:0
msgid "Status" msgid "Status"
msgstr "" msgstr "Állapot"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
msgid "Allocation" msgid "Allocation"
msgstr "" msgstr "Kiosztás"
#. module: account_voucher #. module: account_voucher
#: view:account.statement.from.invoice.lines:0 #: view:account.statement.from.invoice.lines:0
#: view:account.voucher:0 #: view:account.voucher:0
msgid "or" msgid "or"
msgstr "" msgstr "vagy"
#. module: account_voucher #. module: account_voucher
#: selection:sale.receipt.report,month:0 #: selection:sale.receipt.report,month:0
@ -720,7 +775,7 @@ msgstr "Augusztus"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
msgid "Validate Payment" msgid "Validate Payment"
msgstr "" msgstr "Fizetés jóváhagyása"
#. module: account_voucher #. module: account_voucher
#: help:account.voucher,audit:0 #: help:account.voucher,audit:0
@ -728,6 +783,8 @@ msgid ""
"Check this box if you are unsure of that journal entry and if you want to " "Check this box if you are unsure of that journal entry and if you want to "
"note it as 'to be reviewed' by an accounting expert." "note it as 'to be reviewed' by an accounting expert."
msgstr "" msgstr ""
"Jelölje be, ha bizonytalan a napló tétel kontírozásában. Ennek hatására "
"könyvelő szekértő által 'ellenőrizendő'-ként jelölődik meg."
#. module: account_voucher #. module: account_voucher
#: selection:sale.receipt.report,month:0 #: selection:sale.receipt.report,month:0
@ -738,7 +795,7 @@ msgstr "Október"
#: code:addons/account_voucher/account_voucher.py:976 #: code:addons/account_voucher/account_voucher.py:976
#, python-format #, python-format
msgid "Please activate the sequence of selected journal !" msgid "Please activate the sequence of selected journal !"
msgstr "" msgstr "Kérem a sorozat aktiválását a kiválasztott naplóra !"
#. module: account_voucher #. module: account_voucher
#: selection:sale.receipt.report,month:0 #: selection:sale.receipt.report,month:0
@ -748,23 +805,23 @@ msgstr "Június"
#. module: account_voucher #. module: account_voucher
#: field:account.voucher,payment_rate_currency_id:0 #: field:account.voucher,payment_rate_currency_id:0
msgid "Payment Rate Currency" msgid "Payment Rate Currency"
msgstr "" msgstr "Fizetési pénznem aránya"
#. module: account_voucher #. module: account_voucher
#: field:account.voucher,paid:0 #: field:account.voucher,paid:0
msgid "Paid" msgid "Paid"
msgstr "" msgstr "Rendezett"
#. module: account_voucher #. module: account_voucher
#: model:ir.actions.act_window,name:account_voucher.action_sale_receipt #: model:ir.actions.act_window,name:account_voucher.action_sale_receipt
#: model:ir.ui.menu,name:account_voucher.menu_action_sale_receipt #: model:ir.ui.menu,name:account_voucher.menu_action_sale_receipt
msgid "Sales Receipts" msgid "Sales Receipts"
msgstr "" msgstr "Értékesítési bevételi bizonylatok"
#. module: account_voucher #. module: account_voucher
#: field:account.voucher,message_is_follower:0 #: field:account.voucher,message_is_follower:0
msgid "Is a Follower" msgid "Is a Follower"
msgstr "" msgstr "Ez egy követő"
#. module: account_voucher #. module: account_voucher
#: field:account.voucher,analytic_id:0 #: field:account.voucher,analytic_id:0
@ -791,7 +848,7 @@ msgstr "Kiterjesztett szűrők"
#. module: account_voucher #. module: account_voucher
#: field:account.voucher,paid_amount_in_company_currency:0 #: field:account.voucher,paid_amount_in_company_currency:0
msgid "Paid Amount in Company Currency" msgid "Paid Amount in Company Currency"
msgstr "" msgstr "Kifizetett összeg a vállalat pénznemében"
#. module: account_voucher #. module: account_voucher
#: field:account.bank.statement.line,amount_reconciled:0 #: field:account.bank.statement.line,amount_reconciled:0
@ -807,7 +864,7 @@ msgstr "Azonnali kifizetés"
#. module: account_voucher #. module: account_voucher
#: field:account.voucher.line,type:0 #: field:account.voucher.line,type:0
msgid "Dr/Cr" msgid "Dr/Cr"
msgstr "" msgstr "T/K"
#. module: account_voucher #. module: account_voucher
#: field:account.voucher,pre_line:0 #: field:account.voucher,pre_line:0
@ -818,7 +875,7 @@ msgstr "Előző kifizetések ?"
#: code:addons/account_voucher/account_voucher.py:1112 #: code:addons/account_voucher/account_voucher.py:1112
#, python-format #, python-format
msgid "The invoice you are willing to pay is not valid anymore." msgid "The invoice you are willing to pay is not valid anymore."
msgstr "" msgstr "A kifizetni kívánt számla már nem érvényes."
#. module: account_voucher #. module: account_voucher
#: selection:sale.receipt.report,month:0 #: selection:sale.receipt.report,month:0
@ -829,52 +886,52 @@ msgstr "Január"
#: model:ir.actions.act_window,name:account_voucher.action_voucher_list #: model:ir.actions.act_window,name:account_voucher.action_voucher_list
#: model:ir.ui.menu,name:account_voucher.menu_encode_entries_by_voucher #: model:ir.ui.menu,name:account_voucher.menu_encode_entries_by_voucher
msgid "Journal Vouchers" msgid "Journal Vouchers"
msgstr "Nyugták" msgstr "Nyugták naplói"
#. module: account_voucher #. module: account_voucher
#: model:ir.model,name:account_voucher.model_res_company #: model:ir.model,name:account_voucher.model_res_company
msgid "Companies" msgid "Companies"
msgstr "" msgstr "Vállalatok"
#. module: account_voucher #. module: account_voucher
#: field:account.voucher,message_summary:0 #: field:account.voucher,message_summary:0
msgid "Summary" msgid "Summary"
msgstr "" msgstr "Összegzés"
#. module: account_voucher #. module: account_voucher
#: field:account.voucher,active:0 #: field:account.voucher,active:0
msgid "Active" msgid "Active"
msgstr "" msgstr "Aktív"
#. module: account_voucher #. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:982 #: code:addons/account_voucher/account_voucher.py:982
#, python-format #, python-format
msgid "Please define a sequence on the journal." msgid "Please define a sequence on the journal."
msgstr "" msgstr "Kérem egy sorozat meghatározását a naplón."
#. module: account_voucher #. module: account_voucher
#: model:ir.actions.act_window,name:account_voucher.act_pay_voucher #: model:ir.actions.act_window,name:account_voucher.act_pay_voucher
#: model:ir.actions.act_window,name:account_voucher.action_vendor_receipt #: model:ir.actions.act_window,name:account_voucher.action_vendor_receipt
#: model:ir.ui.menu,name:account_voucher.menu_action_vendor_receipt #: model:ir.ui.menu,name:account_voucher.menu_action_vendor_receipt
msgid "Customer Payments" msgid "Customer Payments"
msgstr "" msgstr "Vevői befizetések"
#. module: account_voucher #. module: account_voucher
#: model:ir.actions.act_window,name:account_voucher.action_sale_receipt_report_all #: model:ir.actions.act_window,name:account_voucher.action_sale_receipt_report_all
#: model:ir.ui.menu,name:account_voucher.menu_action_sale_receipt_report_all #: model:ir.ui.menu,name:account_voucher.menu_action_sale_receipt_report_all
#: view:sale.receipt.report:0 #: view:sale.receipt.report:0
msgid "Sales Receipts Analysis" msgid "Sales Receipts Analysis"
msgstr "" msgstr "Értékesítési bevételi bizonylatok elemzései"
#. module: account_voucher #. module: account_voucher
#: view:sale.receipt.report:0 #: view:sale.receipt.report:0
msgid "Group by Invoice Date" msgid "Group by Invoice Date"
msgstr "" msgstr "Számla dátuma szerinti csoportosítása"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
msgid "Post" msgid "Post"
msgstr "Könyvelés" msgstr "Elküld"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
@ -885,7 +942,7 @@ msgstr "Számlák és kifizetetlen tételek"
#: view:sale.receipt.report:0 #: view:sale.receipt.report:0
#: field:sale.receipt.report,price_total:0 #: field:sale.receipt.report,price_total:0
msgid "Total Without Tax" msgid "Total Without Tax"
msgstr "Nettó érték" msgstr "Nettó, adó nélküli érték"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
@ -921,7 +978,7 @@ msgstr "Bankkivonat"
#. module: account_voucher #. module: account_voucher
#: view:account.bank.statement:0 #: view:account.bank.statement:0
msgid "onchange_amount(amount)" msgid "onchange_amount(amount)"
msgstr "" msgstr "onchange_amount(amount)"
#. module: account_voucher #. module: account_voucher
#: selection:sale.receipt.report,month:0 #: selection:sale.receipt.report,month:0
@ -954,19 +1011,19 @@ msgstr "Nyugta tételsorok"
#: view:account.statement.from.invoice.lines:0 #: view:account.statement.from.invoice.lines:0
#: view:account.voucher:0 #: view:account.voucher:0
msgid "Cancel" msgid "Cancel"
msgstr "Mégsem" msgstr "Visszavonás"
#. module: account_voucher #. module: account_voucher
#: model:ir.actions.client,name:account_voucher.action_client_invoice_menu #: model:ir.actions.client,name:account_voucher.action_client_invoice_menu
msgid "Open Invoicing Menu" msgid "Open Invoicing Menu"
msgstr "" msgstr "Számlázási menü megnyitása"
#. module: account_voucher #. module: account_voucher
#: selection:account.voucher,state:0 #: selection:account.voucher,state:0
#: view:sale.receipt.report:0 #: view:sale.receipt.report:0
#: selection:sale.receipt.report,state:0 #: selection:sale.receipt.report,state:0
msgid "Pro-forma" msgid "Pro-forma"
msgstr "Pro forma" msgstr "Pro-forma"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
@ -979,6 +1036,8 @@ msgstr "Könyvelési tételsorok"
#, python-format #, python-format
msgid "Please define default credit/debit accounts on the journal \"%s\"." msgid "Please define default credit/debit accounts on the journal \"%s\"."
msgstr "" msgstr ""
"Kérem meghatározni az alapértelmezett követelés/tartozás könyvelést a naplón "
"\"%s\"."
#. module: account_voucher #. module: account_voucher
#: selection:account.voucher,type:0 #: selection:account.voucher,type:0
@ -995,7 +1054,7 @@ msgstr "Fizetés"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
msgid "Currency Options" msgid "Currency Options"
msgstr "" msgstr "Pénznem lehetőségek"
#. module: account_voucher #. module: account_voucher
#: help:account.voucher,payment_option:0 #: help:account.voucher,payment_option:0
@ -1005,6 +1064,10 @@ msgid ""
"either choose to keep open this difference on the partner's account, or " "either choose to keep open this difference on the partner's account, or "
"reconcile it with the payment(s)" "reconcile it with the payment(s)"
msgstr "" msgstr ""
"Ez a mező megkönnyíti a választást ahhoz, hogy mit szeretne tenni a "
"kifizetett összeg és a kiosztott összeg közti különbségekkel. Hagyhatja "
"nyitottan ezt a különbséget a partner számláján, vagy párosíthatja a "
"fizetés(ek)el."
#. module: account_voucher #. module: account_voucher
#: model:ir.actions.act_window,help:account_voucher.action_sale_receipt_report_all #: model:ir.actions.act_window,help:account_voucher.action_sale_receipt_report_all
@ -1018,16 +1081,24 @@ msgid ""
" </p>\n" " </p>\n"
" " " "
msgstr "" msgstr ""
"<p>\n"
" Erről a jelentésről, a vevőnek elküldött számlákról és fizetési\n"
" határidőkről és késve fizetésről áttekintést kaphat. A \n"
" keresési eszköz használható a számla beszámolók személyre\n"
" szabásához és így, az elemzést az igényének megfelelően "
"alakíthatja.\n"
" </p>\n"
" "
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
msgid "Posted Vouchers" msgid "Posted Vouchers"
msgstr "" msgstr "Elküldött nyugták"
#. module: account_voucher #. module: account_voucher
#: field:account.voucher,payment_rate:0 #: field:account.voucher,payment_rate:0
msgid "Exchange Rate" msgid "Exchange Rate"
msgstr "" msgstr "Árfolyam arány"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
@ -1047,7 +1118,7 @@ msgstr "Május"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
msgid "Sale Receipt" msgid "Sale Receipt"
msgstr "" msgstr "Értékesítési bevételi bizonylat"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
@ -1066,7 +1137,7 @@ msgstr "Belső megjegyzések"
#: view:account.voucher:0 #: view:account.voucher:0
#: field:account.voucher,line_cr_ids:0 #: field:account.voucher,line_cr_ids:0
msgid "Credits" msgid "Credits"
msgstr "Követel" msgstr "Követelések"
#. module: account_voucher #. module: account_voucher
#: field:account.voucher.line,amount_original:0 #: field:account.voucher.line,amount_original:0
@ -1076,7 +1147,7 @@ msgstr "Eredeti összeg"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
msgid "Purchase Receipt" msgid "Purchase Receipt"
msgstr "" msgstr "Vásárlási bevételi bizonylatok"
#. module: account_voucher #. module: account_voucher
#: help:account.voucher,payment_rate:0 #: help:account.voucher,payment_rate:0
@ -1084,6 +1155,8 @@ msgid ""
"The specific rate that will be used, in this voucher, between the selected " "The specific rate that will be used, in this voucher, between the selected "
"currency (in 'Payment Rate Currency' field) and the voucher currency." "currency (in 'Payment Rate Currency' field) and the voucher currency."
msgstr "" msgstr ""
"Az arány, mely ezen nyugtán lesz használva, a kiválasztott pénznem (a "
"'Fizetési pénznem aránya' mezőben) és a nyugta pénzneme közt."
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
@ -1115,12 +1188,12 @@ msgstr "Február"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
msgid "Supplier Invoices and Outstanding transactions" msgid "Supplier Invoices and Outstanding transactions"
msgstr "Bejövő számlák és kifizetetlen tételek" msgstr "Beszállítók bejövő számlái és kifizetetlen tételek"
#. module: account_voucher #. module: account_voucher
#: field:account.voucher,reference:0 #: field:account.voucher,reference:0
msgid "Ref #" msgid "Ref #"
msgstr "Hiv. szám" msgstr "Hiv. szám #"
#. module: account_voucher #. module: account_voucher
#: view:sale.receipt.report:0 #: view:sale.receipt.report:0
@ -1132,7 +1205,7 @@ msgstr "Év"
#: field:account.config.settings,income_currency_exchange_account_id:0 #: field:account.config.settings,income_currency_exchange_account_id:0
#: field:res.company,income_currency_exchange_account_id:0 #: field:res.company,income_currency_exchange_account_id:0
msgid "Gain Exchange Rate Account" msgid "Gain Exchange Rate Account"
msgstr "" msgstr "Árfolyamnyereség számla"
#. module: account_voucher #. module: account_voucher
#: selection:account.voucher,type:0 #: selection:account.voucher,type:0
@ -1148,7 +1221,7 @@ msgstr "Április"
#. module: account_voucher #. module: account_voucher
#: help:account.voucher,tax_id:0 #: help:account.voucher,tax_id:0
msgid "Only for tax excluded from price" msgid "Only for tax excluded from price"
msgstr "" msgstr "Csak az árakból kihagyott adók"
#. module: account_voucher #. module: account_voucher
#: field:account.voucher,type:0 #: field:account.voucher,type:0
@ -1158,7 +1231,7 @@ msgstr "Alapértelmezett típus"
#. module: account_voucher #. module: account_voucher
#: help:account.voucher,message_ids:0 #: help:account.voucher,message_ids:0
msgid "Messages and communication history" msgid "Messages and communication history"
msgstr "" msgstr "Üzenetek és kommunikációs történet"
#. module: account_voucher #. module: account_voucher
#: model:ir.model,name:account_voucher.model_account_statement_from_invoice_lines #: model:ir.model,name:account_voucher.model_account_statement_from_invoice_lines
@ -1182,12 +1255,16 @@ msgid ""
"The amount of the voucher must be the same amount as the one on the " "The amount of the voucher must be the same amount as the one on the "
"statement line." "statement line."
msgstr "" msgstr ""
"A nyugtán lévő összegnek ugyanannak kell lennie mint ami a kivonat sorában "
"szerepel."
#. module: account_voucher #. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:879 #: code:addons/account_voucher/account_voucher.py:879
#, python-format #, python-format
msgid "Cannot delete voucher(s) which are already opened or paid." msgid "Cannot delete voucher(s) which are already opened or paid."
msgstr "" msgstr ""
"Nem lehet olyan nyugtá(ka)t törölni, melyek meg lettek nyitva vagy ki lettek "
"fozetve."
#. module: account_voucher #. module: account_voucher
#: help:account.voucher,date:0 #: help:account.voucher,date:0
@ -1197,7 +1274,7 @@ msgstr "Könyvelési tételek teljesítési dátuma"
#. module: account_voucher #. module: account_voucher
#: model:mail.message.subtype,name:account_voucher.mt_voucher_state_change #: model:mail.message.subtype,name:account_voucher.mt_voucher_state_change
msgid "Status Change" msgid "Status Change"
msgstr "" msgstr "Állapotváltozás"
#. module: account_voucher #. module: account_voucher
#: selection:account.voucher,payment_option:0 #: selection:account.voucher,payment_option:0
@ -1225,7 +1302,7 @@ msgstr "Nettó érték"
#. module: account_voucher #. module: account_voucher
#: model:ir.model,name:account_voucher.model_sale_receipt_report #: model:ir.model,name:account_voucher.model_sale_receipt_report
msgid "Sales Receipt Statistics" msgid "Sales Receipt Statistics"
msgstr "Értékesítési nyugta statisztika" msgstr "Értékesítési bevételi bizonylatok statisztikái"
#. module: account_voucher #. module: account_voucher
#: view:account.voucher:0 #: view:account.voucher:0
@ -1244,14 +1321,14 @@ msgstr "Nyitott egyenleg"
#. module: account_voucher #. module: account_voucher
#: model:mail.message.subtype,description:account_voucher.mt_voucher_state_change #: model:mail.message.subtype,description:account_voucher.mt_voucher_state_change
msgid "Status <b>changed</b>" msgid "Status <b>changed</b>"
msgstr "" msgstr "Állapot <b>megváltozott</b>"
#. module: account_voucher #. module: account_voucher
#: code:addons/account_voucher/account_voucher.py:1014 #: code:addons/account_voucher/account_voucher.py:1014
#: code:addons/account_voucher/account_voucher.py:1018 #: code:addons/account_voucher/account_voucher.py:1018
#, python-format #, python-format
msgid "Insufficient Configuration!" msgid "Insufficient Configuration!"
msgstr "" msgstr "Nem megfelelő beállítás!"
#. module: account_voucher #. module: account_voucher
#: help:account.voucher,active:0 #: help:account.voucher,active:0
@ -1260,6 +1337,9 @@ msgid ""
"inactive, which allow to hide the customer/supplier payment while the bank " "inactive, which allow to hide the customer/supplier payment while the bank "
"statement isn't confirmed." "statement isn't confirmed."
msgstr "" msgstr ""
"Alapértelmezetten, a tervezet bank kivonathoz párosított nyugták nem lesznek "
"aktívak, így el lehet tüntetni a vevő/beszállító fizetéseket amíg a banki "
"kivonatok nem kerülnek jóváhagyásra."
#~ msgid "Particulars" #~ msgid "Particulars"
#~ msgstr "Adatok" #~ msgstr "Adatok"
@ -1310,9 +1390,6 @@ msgstr ""
#~ msgid "Want to remove accounting entries too ?" #~ msgid "Want to remove accounting entries too ?"
#~ msgstr "A könyvelési tételeket is törölni szeretné?" #~ msgstr "A könyvelési tételeket is törölni szeretné?"
#~ msgid "Sales Receipt"
#~ msgstr "Nyugta"
#~ msgid "Unreconciliation" #~ msgid "Unreconciliation"
#~ msgstr "Párosítás visszavonása" #~ msgstr "Párosítás visszavonása"
@ -1485,3 +1562,6 @@ msgstr ""
#~ msgid "Canceled" #~ msgid "Canceled"
#~ msgstr "Érvénytelenített" #~ msgstr "Érvénytelenített"
#~ msgid "Sales Receipt"
#~ msgstr "Értékesítési bevételi bizonylat"

View File

@ -5,6 +5,7 @@ openerp.auth_oauth = function(instance) {
start: function(parent, params) { start: function(parent, params) {
var self = this; var self = this;
var d = this._super.apply(this, arguments); var d = this._super.apply(this, arguments);
this.$el.hide();
this.$el.on('click', 'a.zocial', this.on_oauth_sign_in); this.$el.on('click', 'a.zocial', this.on_oauth_sign_in);
this.oauth_providers = []; this.oauth_providers = [];
if(this.params.oauth_error === 1) { if(this.params.oauth_error === 1) {
@ -24,6 +25,8 @@ openerp.auth_oauth = function(instance) {
var db = this.$("form [name=db]").val(); var db = this.$("form [name=db]").val();
if (db) { if (db) {
this.rpc("/auth_oauth/list_providers", { dbname: db }).done(this.on_oauth_loaded); this.rpc("/auth_oauth/list_providers", { dbname: db }).done(this.on_oauth_loaded);
} else {
this.$el.show();
} }
}, },
on_oauth_loaded: function(result) { on_oauth_loaded: function(result) {
@ -32,6 +35,7 @@ openerp.auth_oauth = function(instance) {
if (this.oauth_providers.length === 1 && params.type === 'signup') { if (this.oauth_providers.length === 1 && params.type === 'signup') {
this.do_oauth_sign_in(this.oauth_providers[0]); this.do_oauth_sign_in(this.oauth_providers[0]);
} else { } else {
this.$el.show();
this.$('.oe_oauth_provider_login_button').remove(); this.$('.oe_oauth_provider_login_button').remove();
var buttons = QWeb.render("auth_oauth.Login.button",{"widget":this}); var buttons = QWeb.render("auth_oauth.Login.button",{"widget":this});
this.$(".oe_login_pane form ul").after(buttons); this.$(".oe_login_pane form ul").after(buttons);
@ -57,7 +61,7 @@ openerp.auth_oauth = function(instance) {
state: JSON.stringify(state), state: JSON.stringify(state),
}; };
var url = provider.auth_endpoint + '?' + $.param(params); var url = provider.auth_endpoint + '?' + $.param(params);
window.location = url; instance.web.redirect(url);
}, },
_oauth_state: function(provider) { _oauth_state: function(provider) {
// return the state object sent back with the redirected uri // return the state object sent back with the redirected uri

View File

@ -419,8 +419,10 @@ instance.board.AddToDashboard = instance.web.search.Input.extend({
instance.web.SearchView.include({ instance.web.SearchView.include({
add_common_inputs: function() { add_common_inputs: function() {
this._super(); this._super();
var vm = this.getParent().getParent();
if (vm.inner_action && vm.inner_action.views) {
(new instance.board.AddToDashboard(this)); (new instance.board.AddToDashboard(this));
}
} }
}); });

View File

@ -81,6 +81,8 @@ Dashboard for CRM will include:
'crm_lead_view.xml', 'crm_lead_view.xml',
'crm_lead_menu.xml', 'crm_lead_menu.xml',
'crm_case_section_view.xml',
'crm_meeting_menu.xml', 'crm_meeting_menu.xml',
'crm_phonecall_view.xml', 'crm_phonecall_view.xml',
@ -103,20 +105,37 @@ Dashboard for CRM will include:
'crm_action_rule_demo.xml', 'crm_action_rule_demo.xml',
], ],
'test': [ 'test': [
'test/process/communication_with_customer.yml', 'test/crm_lead_message.yml',
'test/process/lead2opportunity2win.yml', 'test/lead2opportunity2win.yml',
'test/process/lead2opportunity_assign_salesmen.yml', 'test/lead2opportunity_assign_salesmen.yml',
'test/process/merge_opportunity.yml', 'test/crm_lead_merge.yml',
'test/process/cancel_lead.yml', 'test/crm_lead_cancel.yml',
'test/process/segmentation.yml', 'test/segmentation.yml',
'test/process/phonecalls.yml', 'test/phonecalls.yml',
'test/ui/crm_demo.yml', 'test/crm_lead_onchange.yml',
'test/ui/duplicate_lead.yml', 'test/crm_lead_copy.yml',
'test/ui/delete_lead.yml', 'test/crm_lead_unlink.yml',
],
'css': [
'static/src/css/crm.css'
],
'js': [
'static/src/js/crm.js'
], ],
'installable': True, 'installable': True,
'application': True, 'application': True,
'auto_install': False, 'auto_install': False,
'images': ['images/crm_dashboard.png', 'images/customers.png','images/leads.png','images/opportunities_kanban.png','images/opportunities_form.png','images/opportunities_calendar.png','images/opportunities_graph.png','images/logged_calls.png','images/scheduled_calls.png','images/stages.png'], 'images': [
'images/crm_dashboard.png',
'images/customers.png',
'images/leads.png',
'images/opportunities_kanban.png',
'images/opportunities_form.png',
'images/opportunities_calendar.png',
'images/opportunities_graph.png',
'images/logged_calls.png',
'images/scheduled_calls.png',
'images/stages.png',
],
} }
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -98,6 +98,7 @@ class crm_case_stage(osv.osv):
'case_default': True, 'case_default': True,
} }
class crm_case_section(osv.osv): class crm_case_section(osv.osv):
""" Model for sales teams. """ """ Model for sales teams. """
_name = "crm.case.section" _name = "crm.case.section"
@ -128,6 +129,15 @@ class crm_case_section(osv.osv):
'alias_id': fields.many2one('mail.alias', 'Alias', ondelete="cascade", required=True, 'alias_id': fields.many2one('mail.alias', 'Alias', ondelete="cascade", required=True,
help="The email address associated with this team. New emails received will automatically " help="The email address associated with this team. New emails received will automatically "
"create new leads assigned to the team."), "create new leads assigned to the team."),
'open_lead_ids': fields.one2many('crm.lead', 'section_id',
string='Open Leads', readonly=True,
domain=['&', ('type', '!=', 'opportunity'), ('state', 'not in', ['done', 'cancel'])]),
'open_opportunity_ids': fields.one2many('crm.lead', 'section_id',
string='Open Opportunities', readonly=True,
domain=['&', '|', ('type', '=', 'opportunity'), ('type', '=', 'both'), ('state', 'not in', ['done', 'cancel'])]),
'color': fields.integer('Color Index'),
'use_leads': fields.boolean('Leads',
help="This enables the management of leads in the sales team. Otherwise the sales team manages only opportunities."),
} }
def _get_stage_common(self, cr, uid, context): def _get_stage_common(self, cr, uid, context):
@ -137,7 +147,7 @@ class crm_case_section(osv.osv):
_defaults = { _defaults = {
'active': 1, 'active': 1,
'stage_ids': _get_stage_common, 'stage_ids': _get_stage_common,
'alias_domain': False, # always hide alias during creation 'use_leads': True,
} }
_sql_constraints = [ _sql_constraints = [
@ -167,9 +177,9 @@ class crm_case_section(osv.osv):
def create(self, cr, uid, vals, context=None): def create(self, cr, uid, vals, context=None):
mail_alias = self.pool.get('mail.alias') mail_alias = self.pool.get('mail.alias')
if not vals.get('alias_id'): if not vals.get('alias_id'):
vals.pop('alias_name', None) # prevent errors during copy() alias_name = vals.pop('alias_name', None) or vals.get('name') # prevent errors during copy()
alias_id = mail_alias.create_unique_alias(cr, uid, alias_id = mail_alias.create_unique_alias(cr, uid,
{'alias_name': vals['name']}, {'alias_name': alias_name},
model_name="crm.lead", model_name="crm.lead",
context=context) context=context)
vals['alias_id'] = alias_id vals['alias_id'] = alias_id
@ -230,4 +240,5 @@ class crm_payment_mode(osv.osv):
'section_id': fields.many2one('crm.case.section', 'Sales Team'), 'section_id': fields.many2one('crm.case.section', 'Sales Team'),
} }
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,294 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<!-- CRM lead search by Salesteams -->
<record model="ir.actions.act_window" id="crm_case_form_view_salesteams_lead">
<field name="name">Leads</field>
<field name="res_model">crm.lead</field>
<field name="view_mode">tree,form</field>
<field name="domain">['|', ('type','=','lead'), ('type','=',False)]</field>
<field name="view_id" ref="crm_case_tree_view_leads"/>
<field name="search_view_id" ref="crm.view_crm_case_leads_filter"/>
<field name="context">{
'search_default_section_id': [active_id],
'search_default_open': 1,
'default_section_id': active_id,
'default_type': 'lead',
'stage_type': 'lead',
}
</field>
<field name="help" type="html">
<p>
Use leads if you need a qualification step before creating an
opportunity or a customer. It can be a business card you received,
a contact form filled in your website, or a file of unqualified
prospects you import, etc.
</p><p>
Once qualified, the lead can be converted into a business
opportunity and/or a new customer in your address book.
</p>
</field>
</record>
<!-- CRM opportunity search by Salesteams -->
<record model="ir.actions.act_window" id="crm_case_form_view_salesteams_opportunity">
<field name="name">Opportunities</field>
<field name="res_model">crm.lead</field>
<field name="view_mode">kanban,tree,graph,form,calendar</field>
<field name="domain">[('type','=','opportunity')]</field>
<field name="view_id" ref="crm.crm_case_kanban_view_leads"/>
<field name="search_view_id" ref="crm.view_crm_case_opportunities_filter"/>
<field name="context">{
'search_default_section_id': [active_id],
'search_default_new': 1,
'search_default_open': 1,
'default_section_id': active_id,
'stage_type': 'opportunity',
'default_type': 'opportunity',
'default_user_id': uid,
}
</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to create a new opportunity.
</p><p>
OpenERP helps you keep track of your sales pipeline to follow
up potential sales and better forecast your future revenues.
</p><p>
You will be able to plan meetings and phone calls from
opportunities, convert them into quotations, attach related
documents, track all discussions, and much more.
</p>
</field>
</record>
<!-- Case Sections Salesteams kanban view -->
<record model="ir.ui.view" id="crm_case_section_salesteams_view_kanban">
<field name="name">crm.case.section.kanban</field>
<field name="model">crm.case.section</field>
<field name="arch" type="xml">
<kanban version="7.0" class="oe_background_grey">
<field name="use_leads"/>
<field name="name"/>
<field name="user_id"/>
<field name="member_ids"/>
<field name="note"/>
<field name="alias_id"/>
<field name="color"/>
<field name="open_lead_ids"/>
<field name="open_opportunity_ids"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_color_#{kanban_getcolor(record.color.raw_value)} oe_kanban_card oe_kanban_project oe_kanban_global_click oe_kanban_crm_salesteams">
<div class="oe_dropdown_toggle oe_dropdown_kanban" groups="base.group_user">
<span class="oe_e">í</span>
<ul class="oe_dropdown_menu">
<li t-if="widget.view.is_action_enabled('edit')"><a type="edit">Sales Teams Settings</a></li>
<li t-if="widget.view.is_action_enabled('delete')"><a type="delete">Delete</a></li>
<li t-if="widget.view.is_action_enabled('edit')"><ul class="oe_kanban_colorpicker" data-field="color"/></li>
</ul>
</div>
<div class="oe_kanban_content">
<h4><field name="name"/></h4>
<div class="oe_kanban_alias" t-if="record.use_leads.raw_value and record.alias_id.value">
<span class="oe_e">%%</span><small><field name="alias_id"/></small>
</div>
<div class="oe_items_list">
<a t-if="record.use_leads.raw_value" name="%(crm_case_form_view_salesteams_lead)d" type="action">
<t t-raw="record.open_lead_ids.raw_value.length"/>
<t t-if="record.open_lead_ids.raw_value.length &gt;= 2">Leads</t>
<t t-if="record.open_lead_ids.raw_value.length &lt; 2">Lead</t></a>
<a name="%(crm_case_form_view_salesteams_opportunity)d" type="action">
<t t-raw="record.open_opportunity_ids.raw_value.length"/>
<t t-if="record.open_opportunity_ids.raw_value.length &gt;= 2">Opportunities</t>
<t t-if="record.open_opportunity_ids.raw_value.length &lt; 2">Opportunity</t></a>
</div>
<div class="oe_avatars">
<img t-if="record.user_id.raw_value" t-att-src="kanban_image('res.users', 'image_small', record.user_id.raw_value)" t-att-data-member_id="record.user_id.raw_value"/>
<t t-foreach="record.member_ids.raw_value.slice(0,11)" t-as="member">
<img t-att-src="kanban_image('res.users', 'image_small', member)" t-att-data-member_id="member"/>
</t>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<!-- Case Sections Action -->
<record id="crm_case_section_salesteams_act" model="ir.actions.act_window">
<field name="name">Sales Teams</field>
<field name="res_model">crm.case.section</field>
<field name="view_type">form</field>
<field name="view_mode">kanban,tree,form</field>
<field name="view_id" ref="crm_case_section_salesteams_view_kanban"/>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click here to define a new sales team.
</p><p>
Use sales team to organize your different salespersons or
departments into separate teams. Each team will work in
its own list of opportunities.
</p>
</field>
</record>
<!-- Case Sections Form View -->
<record id="crm_case_section_view_form" model="ir.ui.view">
<field name="name">crm.case.section.form</field>
<field name="model">crm.case.section</field>
<field name="arch" type="xml">
<form string="Sales Team" version="7.0">
<sheet>
<div class="oe_title">
<label for="name" class="oe_edit_only" string="Project Name"/>
<h1>
<field name="name" string="Project Name"/>
</h1>
<div name="group_alias"
attrs="{'invisible': [('alias_domain', '=', False)]}">
<label for="alias_id" string="Email Alias"/>
<field name="alias_id" class="oe_inline oe_read_only" required="0" nolabel="1"/>
<span name="edit_alias" class="oe_edit_only">
<field name="alias_name" class="oe_inline"
attrs="{'required': [('use_leads', '=', True), ('alias_id', '!=', False)]}"/>
@
<field name="alias_domain" class="oe_inline" readonly="1"/>
</span>
</div>
<div name="options_active">
<field name="use_leads" class="oe_inline"/><label for="use_leads"/>
</div>
</div>
<group>
<group>
<field name="parent_id"/>
<field name="resource_calendar_id"/>
<field name="active"/>
</group>
<group>
<field name="user_id"/>
<field name="code"/>
</group>
<group colspan="4" attrs="{'invisible': [('use_leads', '=', False)]}">
</group>
</group>
<notebook colspan="4">
<page string="Sales Team">
<group>
<field name="change_responsible"/>
</group>
<separator string="Team Members"/>
<field name="member_ids" widget="many2many_kanban">
<kanban quick_create="false" create="true">
<field name="name"/>
<templates>
<t t-name="kanban-box">
<div style="position: relative">
<a t-if="! read_only_mode" type="delete" style="position: absolute; right: 0; padding: 4px; diplay: inline-block">X</a>
<div class="oe_module_vignette">
<div class="oe_module_desc">
<field name="name"/>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</page>
<page string="Stages">
<separator string="Select Stages for this Sales Team"/>
<field name="stage_ids"/>
</page>
<page string="Notes">
<field name="note"/>
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers" help="Follow this salesteam to automatically track the events associated to users of this team."/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<!-- Case Sections Tree View -->
<record id="crm_case_section_view_tree" model="ir.ui.view">
<field name="name">crm.case.section.tree</field>
<field name="model">crm.case.section</field>
<field name="field_parent">child_ids</field>
<field name="arch" type="xml">
<tree string="Sales Team">
<field name="name"/>
<field name="code"/>
<field name="user_id"/>
</tree>
</field>
</record>
<!-- Case Sections Action -->
<record model="ir.actions.act_window.view" id="action_crm_tag_kanban_view_salesteams_oppor11">
<field name="sequence" eval="0"/>
<field name="view_mode">kanban</field>
<field name="view_id" ref="crm_case_kanban_view_leads"/>
<field name="act_window_id" ref="crm_case_form_view_salesteams_opportunity"/>
</record>
<record model="ir.actions.act_window.view" id="action_crm_tag_tree_view_salesteams_oppor11">
<field name="sequence" eval="1"/>
<field name="view_mode">tree</field>
<field name="view_id" ref="crm_case_tree_view_oppor"/>
<field name="act_window_id" ref="crm_case_form_view_salesteams_opportunity"/>
</record>
<record model="ir.actions.act_window.view" id="action_crm_tag_form_view_salesteams_oppor11">
<field name="sequence" eval="2"/>
<field name="view_mode">form</field>
<field name="view_id" ref="crm_case_form_view_oppor"/>
<field name="act_window_id" ref="crm_case_form_view_salesteams_opportunity"/>
</record>
<record id="crm_case_section_act_tree" model="ir.actions.act_window">
<field name="name">Cases by Sales Team</field>
<field name="res_model">crm.case.section</field>
<field name="domain">[('parent_id','=',False)]</field>
<field name="view_type">tree</field>
<field name="view_id" ref="crm_case_section_view_tree"/>
</record>
<record id="crm_case_section_act" model="ir.actions.act_window">
<field name="name">Sales Teams</field>
<field name="res_model">crm.case.section</field>
<field name="view_type">form</field>
<field name="view_id" ref="crm_case_section_view_tree"/>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click here to define a new sales team.
</p><p>
Use sales team to organize your different salespersons or
departments into separate teams. Each team will work in
its own list of opportunities.
</p>
</field>
</record>
<menuitem id="crm.menu_crm_case_section_act"
action="crm_case_section_salesteams_act"
sequence="1"
parent="base.menu_sales"
groups="base.group_multi_salesteams"/>
</data>
</openerp>

View File

@ -27,8 +27,10 @@
</record> </record>
<record model="crm.case.section" id="section_sales_department"> <record model="crm.case.section" id="section_sales_department">
<field name="name">Sales Department</field> <field name="name">Sales</field>
<field name="code">Sales</field> <field name="code">Sales</field>
<field name="use_leads">True</field>
<field name="member_ids" eval="[(4, ref('base.user_root'))]"/>
</record> </record>
<!-- Payment Mode --> <!-- Payment Mode -->
@ -64,12 +66,6 @@
<p>To manage quotations and sale orders, install the "Sales Management" application.</p>]]></field> <p>To manage quotations and sale orders, install the "Sales Management" application.</p>]]></field>
</record> </record>
<record model="mail.alias" id="default_sales_alias">
<field name="alias_name">sales</field>
<field name="alias_model_id" ref="model_crm_lead"/>
<field name="alias_user_id" ref="base.user_root"/>
<field name="alias_defaults">{'type':'lead'}</field>
</record>
</data> </data>
</openerp> </openerp>

View File

@ -22,6 +22,7 @@
from openerp.addons.base_status.base_stage import base_stage from openerp.addons.base_status.base_stage import base_stage
import crm import crm
from datetime import datetime from datetime import datetime
from operator import itemgetter
from openerp.osv import fields, osv from openerp.osv import fields, osv
import time import time
from openerp import tools from openerp import tools
@ -84,6 +85,22 @@ class crm_lead(base_stage, format_address, osv.osv):
}, },
} }
def get_empty_list_help(self, cr, uid, help, context=None):
if context.get('default_type') == 'lead':
context['empty_list_help_model'] = 'crm.case.section'
context['empty_list_help_id'] = context.get('default_section_id')
context['empty_list_help_document_name'] = _("leads")
return super(crm_lead, self).get_empty_list_help(cr, uid, help, context=context)
def onchange_user_id(self, cr, uid, ids, section_id, user_id, context=None):
""" When changing the user, also set a section_id or restrict section id
to the ones user_id is member of. """
if user_id:
section_ids = self.pool.get('crm.case.section').search(cr, uid, ['|', ('user_id', '=', user_id), ('member_ids', '=', user_id)], context=context)
if len(section_ids) > 0 and section_id not in section_ids:
section_id = section_ids[0]
return {'value': {'section_id': section_id}}
def create(self, cr, uid, vals, context=None): def create(self, cr, uid, vals, context=None):
if context is None: if context is None:
context = {} context = {}
@ -628,12 +645,13 @@ class crm_lead(base_stage, format_address, osv.osv):
opportunities = self.browse(cr, uid, ids, context=context) opportunities = self.browse(cr, uid, ids, context=context)
sequenced_opps = [] sequenced_opps = []
for opportunity in opportunities: for opportunity in opportunities:
sequence = -1
if opportunity.stage_id and opportunity.stage_id.state != 'cancel': if opportunity.stage_id and opportunity.stage_id.state != 'cancel':
sequenced_opps.append((opportunity.stage_id.sequence, opportunity)) sequence = opportunity.stage_id.sequence
else: sequenced_opps.append(((int(sequence != -1 and opportunity.type == 'opportunity'), sequence, -opportunity.id), opportunity))
sequenced_opps.append((-1, opportunity))
sequenced_opps.sort(key=lambda tup: tup[0], reverse=True) sequenced_opps.sort(reverse=True)
opportunities = [opportunity for sequence, opportunity in sequenced_opps] opportunities = map(itemgetter(1), sequenced_opps)
ids = [opportunity.id for opportunity in opportunities] ids = [opportunity.id for opportunity in opportunities]
highest = opportunities[0] highest = opportunities[0]
opportunities_rest = opportunities[1:] opportunities_rest = opportunities[1:]
@ -652,11 +670,10 @@ class crm_lead(base_stage, format_address, osv.osv):
opportunities.extend(opportunities_rest) opportunities.extend(opportunities_rest)
self._merge_notify(cr, uid, highest, opportunities, context=context) self._merge_notify(cr, uid, highest, opportunities, context=context)
# Check if the stage is in the stages of the sales team. If not, assign the stage with the lowest sequence # Check if the stage is in the stages of the sales team. If not, assign the stage with the lowest sequence
if merged_data.get('type') == 'opportunity' and merged_data.get('section_id'): if merged_data.get('section_id'):
section_stages = self.pool.get('crm.case.section').read(cr, uid, merged_data['section_id'], ['stage_ids'], context=context) section_stage_ids = self.pool.get('crm.case.stage').search(cr, uid, [('section_ids', 'in', merged_data['section_id']), ('type', '=', merged_data.get('type'))], order='sequence', context=context)
if merged_data.get('stage_id') not in section_stages['stage_ids']: if merged_data.get('stage_id') not in section_stage_ids:
stages_sequences = self.pool.get('crm.case.stage').search(cr, uid, [('id','in',section_stages['stage_ids'])], order='sequence', limit=1, context=context) merged_data['stage_id'] = section_stage_ids and section_stage_ids[0] or False
merged_data['stage_id'] = stages_sequences and stages_sequences[0] or False
# Write merged data into first opportunity # Write merged data into first opportunity
self.write(cr, uid, [highest.id], merged_data, context=context) self.write(cr, uid, [highest.id], merged_data, context=context)
# Delete tail opportunities # Delete tail opportunities

View File

@ -7,68 +7,69 @@
<field name="name">New</field> <field name="name">New</field>
<field eval="1" name="case_default"/> <field eval="1" name="case_default"/>
<field name="state">draft</field> <field name="state">draft</field>
<field eval="'10'" name="probability"/> <field eval="0" name="probability"/>
<field eval="'10'" name="sequence"/> <field eval="10" name="sequence"/>
<field name="type">both</field> <field name="type">both</field>
</record> </record>
<record model="crm.case.stage" id="stage_lead2"> <record model="crm.case.stage" id="stage_lead2">
<field name="name">Opportunity</field> <field name="name">Opportunity</field>
<field eval="1" name="case_default"/> <field eval="1" name="case_default"/>
<field name="state">open</field> <field name="state">open</field>
<field eval="'20'" name="probability"/> <field eval="20" name="probability"/>
<field eval="'11'" name="sequence"/> <field eval="20" name="sequence"/>
<field name="type">lead</field> <field name="type">lead</field>
</record> </record>
<record model="crm.case.stage" id="stage_lead3">
<field name="name">Qualification</field>
<field eval="1" name="case_default"/>
<field name="state">open</field>
<field eval="'20'" name="probability"/>
<field eval="'12'" name="sequence"/>
<field name="type">opportunity</field>
</record>
<record model="crm.case.stage" id="stage_lead4">
<field name="name">Proposition</field>
<field eval="1" name="case_default"/>
<field name="state">open</field>
<field eval="'40'" name="probability"/>
<field eval="'13'" name="sequence"/>
<field name="type">opportunity</field>
</record>
<record model="crm.case.stage" id="stage_lead5">
<field name="name">Negotiation</field>
<field eval="1" name="case_default"/>
<field name="state">open</field>
<field eval="'60'" name="probability"/>
<field eval="'14'" name="sequence"/>
<field name="type">opportunity</field>
</record>
<record model="crm.case.stage" id="stage_lead6">
<field name="name">Won</field>
<field eval="1" name="case_default"/>
<field name="state">done</field>
<field eval="'100'" name="probability"/>
<field eval="'15'" name="sequence"/>
<field eval="1" name="on_change"/>
<field name="type">opportunity</field>
</record>
<record model="crm.case.stage" id="stage_lead7"> <record model="crm.case.stage" id="stage_lead7">
<field name="name">Dead</field> <field name="name">Dead</field>
<field eval="1" name="case_default"/> <field eval="1" name="case_default"/>
<field eval="False" name="fold"/> <field eval="False" name="fold"/>
<field name="state">cancel</field> <field name="state">cancel</field>
<field eval="'0'" name="probability"/> <field eval="0" name="probability"/>
<field eval="'16'" name="sequence"/> <field eval="30" name="sequence"/>
<field name="type">lead</field> <field name="type">lead</field>
</record> </record>
<record model="crm.case.stage" id="stage_lead3">
<field name="name">Qualification</field>
<field eval="1" name="case_default"/>
<field name="state">open</field>
<field eval="20" name="probability"/>
<field eval="100" name="sequence"/>
<field name="type">opportunity</field>
</record>
<record model="crm.case.stage" id="stage_lead4">
<field name="name">Proposition</field>
<field eval="1" name="case_default"/>
<field name="state">open</field>
<field eval="40" name="probability"/>
<field eval="110" name="sequence"/>
<field name="type">opportunity</field>
</record>
<record model="crm.case.stage" id="stage_lead5">
<field name="name">Negotiation</field>
<field eval="1" name="case_default"/>
<field name="state">open</field>
<field eval="60" name="probability"/>
<field eval="120" name="sequence"/>
<field name="type">opportunity</field>
</record>
<record model="crm.case.stage" id="stage_lead6">
<field name="name">Won</field>
<field eval="True" name="fold"/>
<field eval="1" name="case_default"/>
<field name="state">done</field>
<field eval="100" name="probability"/>
<field eval="130" name="sequence"/>
<field eval="1" name="on_change"/>
<field name="type">opportunity</field>
</record>
<record model="crm.case.stage" id="stage_lead8"> <record model="crm.case.stage" id="stage_lead8">
<field name="name">Lost</field> <field name="name">Lost</field>
<field eval="1" name="case_default"/> <field eval="1" name="case_default"/>
<field eval="True" name="fold"/> <field eval="True" name="fold"/>
<field eval="1" name="on_change"/> <field eval="1" name="on_change"/>
<field name="state">cancel</field> <field name="state">cancel</field>
<field eval="'0'" name="probability"/> <field eval="0" name="probability"/>
<field eval="'17'" name="sequence"/> <field eval="140" name="sequence"/>
<field name="type">opportunity</field> <field name="type">opportunity</field>
</record> </record>

View File

@ -9,11 +9,14 @@
<field name="domain">['|', ('type','=','lead'), ('type','=',False)]</field> <field name="domain">['|', ('type','=','lead'), ('type','=',False)]</field>
<field name="view_id" ref="crm_case_tree_view_leads"/> <field name="view_id" ref="crm_case_tree_view_leads"/>
<field name="search_view_id" ref="crm.view_crm_case_leads_filter"/> <field name="search_view_id" ref="crm.view_crm_case_leads_filter"/>
<field name="context">{'default_type':'lead', 'stage_type':'lead'}</field> <field name="context">{
'default_type':'lead',
'stage_type':'lead',
'search_default_unassigned':1,
}
</field>
<field name="help" type="html"> <field name="help" type="html">
<p class="oe_view_nocontent_create"> <p>
Click to create an unqualified lead.
</p><p>
Use leads if you need a qualification step before creating an Use leads if you need a qualification step before creating an
opportunity or a customer. It can be a business card you received, opportunity or a customer. It can be a business card you received,
a contact form filled in your website, or a file of unqualified a contact form filled in your website, or a file of unqualified
@ -25,26 +28,17 @@
</field> </field>
</record> </record>
<record model="ir.actions.act_window.view" id="action_crm_tag_tree_view_leads_all">
<field name="sequence" eval="1"/>
<field name="view_mode">tree</field>
<field name="view_id" ref="crm_case_tree_view_leads"/>
<field name="act_window_id" ref="crm_case_category_act_leads_all"/>
</record>
<record model="ir.actions.act_window.view" id="action_crm_tag_form_view_leads_all">
<field name="sequence" eval="3"/>
<field name="view_mode">form</field>
<field name="view_id" ref="crm_case_form_view_leads"/>
<field name="act_window_id" ref="crm_case_category_act_leads_all"/>
</record>
<record model="ir.actions.act_window" id="crm_case_category_act_oppor11"> <record model="ir.actions.act_window" id="crm_case_category_act_oppor11">
<field name="name">Opportunities</field> <field name="name">Opportunities</field>
<field name="res_model">crm.lead</field> <field name="res_model">crm.lead</field>
<field name="view_mode">kanban,tree,graph,form,calendar</field> <field name="view_mode">kanban,tree,graph,form,calendar</field>
<field name="domain">[('type','=','opportunity')]</field> <field name="domain">[('type','=','opportunity')]</field>
<field name="context">{'stage_type': 'opportunity', 'default_type': 'opportunity', 'default_user_id': uid}</field> <field name="context">{
'stage_type': 'opportunity',
'default_type': 'opportunity',
'default_user_id': uid
}
</field>
<field name="view_id" eval="False"/> <field name="view_id" eval="False"/>
<field name="search_view_id" ref="crm.view_crm_case_opportunities_filter"/> <field name="search_view_id" ref="crm.view_crm_case_opportunities_filter"/>
<field name="help" type="html"> <field name="help" type="html">
@ -83,8 +77,12 @@
</record> </record>
<menuitem name="Sales" id="base.menu_sales" parent="base.menu_base_partner" sequence="1"/> <menuitem name="Sales" id="base.menu_sales" parent="base.menu_base_partner" sequence="1"/>
<menuitem name="Leads" id="menu_crm_leads" parent="base.menu_sales" action="crm_case_category_act_leads_all" sequence="2" /> <menuitem name="Leads" id="menu_crm_leads" parent="base.menu_sales" sequence="3"
<menuitem name="Opportunities" id="menu_crm_opportunities" parent="base.menu_sales" action="crm_case_category_act_oppor11" sequence="3" /> action="crm_case_category_act_leads_all"
groups="base.group_mono_salesteams,base.group_sale_manager"/>
<menuitem name="Opportunities" id="menu_crm_opportunities" parent="base.menu_sales" sequence="4"
action="crm_case_category_act_oppor11"
groups="base.group_mono_salesteams,base.group_sale_manager"/>
</data> </data>
</openerp> </openerp>

View File

@ -100,6 +100,7 @@
<button name="case_cancel" string="Cancel Case" type="object" <button name="case_cancel" string="Cancel Case" type="object"
states="draft,open,pending"/> states="draft,open,pending"/>
<field name="stage_id" widget="statusbar" clickable="True" <field name="stage_id" widget="statusbar" clickable="True"
domain="['&amp;', '|', ('case_default', '=', True), ('section_ids', '=', section_id), '|', ('type', '=', type), ('type', '=', 'both')]"
on_change="onchange_stage_id(stage_id)"/> on_change="onchange_stage_id(stage_id)"/>
</header> </header>
<sheet> <sheet>
@ -151,12 +152,13 @@
--> -->
</group> </group>
<group> <group>
<field name="user_id" <field name="user_id" on_change="onchange_user_id(section_id, user_id)"
context="{'default_groups_ref': ['base.group_user', 'base.group_sale_salesman_all_leads'] }"/> context="{'default_groups_ref': ['base.group_user', 'base.group_sale_salesman_all_leads'] }"/>
<label for="section_id"/> <label for="section_id" groups="base.group_multi_salesteams"/>
<div> <div groups="base.group_multi_salesteams">
<field name="section_id"/> <field name="section_id"/>
<button name="case_escalate" string="Escalate" type="object" attrs="{'invisible': ['|', ('section_id','=',False), ('state', 'not in', ['draft','open','pending'])]}"/> <button name="case_escalate" string="Escalate" type="object"
attrs="{'invisible': ['|', ('section_id','=',False), ('state', 'not in', ['draft','open','pending'])]}"/>
</div> </div>
<field name="type" invisible="1"/> <field name="type" invisible="1"/>
</group> </group>
@ -228,7 +230,7 @@
<field name="stage_id"/> <field name="stage_id"/>
<field name="user_id" invisible="1"/> <field name="user_id" invisible="1"/>
<field name="partner_id" invisible="1"/> <field name="partner_id" invisible="1"/>
<field name="section_id" invisible="context.get('invisible_section', True)"/> <field name="section_id" invisible="context.get('invisible_section', True)" groups="base.group_multi_salesteams"/>
<field name="state" invisible="1"/> <field name="state" invisible="1"/>
<field name="type_id" invisible="1"/> <field name="type_id" invisible="1"/>
<field name="referred" invisible="1"/> <field name="referred" invisible="1"/>
@ -326,7 +328,7 @@
<search string="Search Leads"> <search string="Search Leads">
<field name="name" string="Lead / Customer" filter_domain="['|','|',('partner_name','ilike',self),('email_from','ilike',self),('name','ilike',self)]"/> <field name="name" string="Lead / Customer" filter_domain="['|','|',('partner_name','ilike',self),('email_from','ilike',self),('name','ilike',self)]"/>
<field name="categ_ids" string="Category" filter_domain="[('categ_ids','ilike',self)]"/> <field name="categ_ids" string="Category" filter_domain="[('categ_ids','ilike',self)]"/>
<field name="section_id" context="{'invisible_section': False, 'default_section_id': self}"/> <field name="section_id" context="{'invisible_section': False}" groups="base.group_multi_salesteams"/>
<field name="user_id"/> <field name="user_id"/>
<field name="partner_id"/> <field name="partner_id"/>
<field name="create_date"/> <field name="create_date"/>
@ -334,7 +336,7 @@
<separator/> <separator/>
<filter string="Open" name="open" domain="[('state','!=','cancel')]" help="Open Leads"/> <filter string="Open" name="open" domain="[('state','!=','cancel')]" help="Open Leads"/>
<filter string="Dead" name="dead" domain="[('state','=','cancel')]"/> <filter string="Dead" name="dead" domain="[('state','=','cancel')]"/>
<filter string="Unassigned" domain="[('user_id','=', False)]" help="No salesperson"/> <filter string="Unassigned" name="unassigned" domain="[('user_id','=', False)]" help="No salesperson"/>
<filter string="Unread Messages" name="message_unread" domain="[('message_unread','=',True)]" help="Unread messages"/> <filter string="Unread Messages" name="message_unread" domain="[('message_unread','=',True)]" help="Unread messages"/>
<filter string="Assigned to Me" <filter string="Assigned to Me"
domain="[('user_id','=',uid)]" context="{'invisible_section': False}" domain="[('user_id','=',uid)]" context="{'invisible_section': False}"
@ -427,9 +429,9 @@
</group> </group>
<group> <group>
<field name="user_id" context="{'default_groups_ref': ['base.group_user', 'base.group_sale_salesman_all_leads']}"/> <field name="user_id" on_change="onchange_user_id(section_id, user_id)" context="{'default_groups_ref': ['base.group_user', 'base.group_sale_salesman_all_leads']}"/>
<label for="section_id"/> <label for="section_id" groups="base.group_multi_salesteams"/>
<div> <div groups="base.group_multi_salesteams">
<field name="section_id" widget="selection"/> <field name="section_id" widget="selection"/>
<button name="case_escalate" string="Escalate" type="object" class="oe_link" attrs="{'invisible': ['|', ('section_id','=',False), ('state', 'not in', ['draft','open','pending'])]}"/> <button name="case_escalate" string="Escalate" type="object" class="oe_link" attrs="{'invisible': ['|', ('section_id','=',False), ('state', 'not in', ['draft','open','pending'])]}"/>
</div> </div>
@ -525,7 +527,7 @@
<field name="stage_id"/> <field name="stage_id"/>
<field name="planned_revenue" sum="Expected Revenues"/> <field name="planned_revenue" sum="Expected Revenues"/>
<field name="probability" avg="Avg. of Probability"/> <field name="probability" avg="Avg. of Probability"/>
<field name="section_id" invisible="context.get('invisible_section', True)"/> <field name="section_id" invisible="context.get('invisible_section', True)" groups="base.group_multi_salesteams"/>
<field name="user_id"/> <field name="user_id"/>
<field name="referred" invisible="1"/> <field name="referred" invisible="1"/>
<field name="priority" invisible="1"/> <field name="priority" invisible="1"/>
@ -544,7 +546,7 @@
<search string="Search Opportunities"> <search string="Search Opportunities">
<field name="name" string="Opportunity" filter_domain="['|','|','|',('partner_id','ilike',self),('partner_name','ilike',self),('email_from','ilike',self),('name', 'ilike', self)]"/> <field name="name" string="Opportunity" filter_domain="['|','|','|',('partner_id','ilike',self),('partner_name','ilike',self),('email_from','ilike',self),('name', 'ilike', self)]"/>
<field name="categ_ids" string="Category" filter_domain="[('categ_ids','ilike', self)]"/> <field name="categ_ids" string="Category" filter_domain="[('categ_ids','ilike', self)]"/>
<field name="section_id" context="{'invisible_section': False, 'default_section_id': self}"/> <field name="section_id" context="{'invisible_section': False}" groups="base.group_multi_salesteams"/>
<field name="user_id"/> <field name="user_id"/>
<field name="partner_id"/> <field name="partner_id"/>
<separator/> <separator/>
@ -552,7 +554,7 @@
<filter string="In Progress" name="open" domain="[('state','=','open')]" help="Open Opportunities"/> <filter string="In Progress" name="open" domain="[('state','=','open')]" help="Open Opportunities"/>
<filter string="Won" name="won" domain="[('state','=','done')]"/> <filter string="Won" name="won" domain="[('state','=','done')]"/>
<filter string="Lost" name="lost" domain="[('state','=','cancel')]"/> <filter string="Lost" name="lost" domain="[('state','=','cancel')]"/>
<filter string="Unassigned" domain="[('user_id','=', False)]" help="No salesperson"/> <filter string="Unassigned" name="unassigned" domain="[('user_id','=', False)]" help="No salesperson"/>
<filter string="Unread Messages" name="message_unread" domain="[('message_unread','=',True)]" help="Unread messages"/> <filter string="Unread Messages" name="message_unread" domain="[('message_unread','=',True)]" help="Unread messages"/>
<filter string="Assigned to Me" <filter string="Assigned to Me"
domain="[('user_id','=',uid)]" context="{'invisible_section': False}" domain="[('user_id','=',uid)]" context="{'invisible_section': False}"

View File

@ -103,7 +103,8 @@
<field name="date"/> <field name="date"/>
<field name="user_id"/> <field name="user_id"/>
<field name="duration" widget="float_time"/> <field name="duration" widget="float_time"/>
<field name="section_id" colspan="1" widget="selection"/> <field name="section_id" colspan="1" widget="selection"
groups="base.group_multi_salesteams"/>
<field name="partner_id" on_change="onchange_partner_id(partner_id)"/> <field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
<field name="email_from" invisible="1"/> <!--not needed because of the chatter, thus invisible, but must be in the view as it's returned by onchange_partner_id()--> <field name="email_from" invisible="1"/> <!--not needed because of the chatter, thus invisible, but must be in the view as it's returned by onchange_partner_id()-->
<field name="categ_id" widget="selection" <field name="categ_id" widget="selection"
@ -187,7 +188,8 @@
help="Phone Calls Assigned to the current user or with a team having the current user as team leader"/> help="Phone Calls Assigned to the current user or with a team having the current user as team leader"/>
<field name="partner_id"/> <field name="partner_id"/>
<field name="user_id"/> <field name="user_id"/>
<field name="section_id" string="Sales Team"/> <field name="section_id" string="Sales Team"
groups="base.group_multi_salesteams"/>
<group expand="0" string="Group By..."> <group expand="0" string="Group By...">
<filter string="Partner" icon="terp-partner" domain="[]" context="{'group_by':'partner_id'}"/> <filter string="Partner" icon="terp-partner" domain="[]" context="{'group_by':'partner_id'}"/>
<filter string="Responsible" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/> <filter string="Responsible" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/>

View File

@ -12,7 +12,7 @@
<field name="name"/> <field name="name"/>
<field name="month"/> <field name="month"/>
<field name="user_id"/> <field name="user_id"/>
<field name="section_id"/> <field name="section_id" groups="base.group_multi_salesteams"/>
<field name="category2_id"/> <field name="category2_id"/>
<field name="stage_id"/> <field name="stage_id"/>
<field name="amount_revenue"/> <field name="amount_revenue"/>
@ -33,7 +33,8 @@
<field name="name"/> <field name="name"/>
<field name="month"/> <field name="month"/>
<field name="user_id"/> <field name="user_id"/>
<field name="section_id" widget="selection"/> <field name="section_id" widget="selection"
groups="base.group_multi_salesteams"/>
<field name="category2_id" /> <field name="category2_id" />
<field name="stage_id"/> <field name="stage_id"/>
<field name="amount_revenue"/> <field name="amount_revenue"/>
@ -53,7 +54,8 @@
<graph string="Cases by Teams and Type" type="bar" orientation="horizontal"> <graph string="Cases by Teams and Type" type="bar" orientation="horizontal">
<field name="category2_id"/> <field name="category2_id"/>
<field name="amount_revenue" operator="+"/> <field name="amount_revenue" operator="+"/>
<field name="section_id" group="True"/> <field name="section_id" group="True"
groups="base.group_multi_salesteams"/>
</graph> </graph>
</field> </field>
</record> </record>
@ -69,7 +71,7 @@
<field name="month"/> <field name="month"/>
<field name="nbr"/> <field name="nbr"/>
<field name="state"/> <field name="state"/>
<field name="section_id"/> <field name="section_id" groups="base.group_multi_salesteams"/>
<field name="category2_id"/> <field name="category2_id"/>
</search> </search>
</field> </field>
@ -95,7 +97,7 @@
<field name="name"/> <field name="name"/>
<field name="month"/> <field name="month"/>
<field name="user_id"/> <field name="user_id"/>
<field name="section_id"/> <field name="section_id" groups="base.group_multi_salesteams"/>
<field name="stage_id"/> <field name="stage_id"/>
<field name="amount_revenue"/> <field name="amount_revenue"/>
<field name="nbr"/> <field name="nbr"/>
@ -115,7 +117,8 @@
<field name="name"/> <field name="name"/>
<field name="month"/> <field name="month"/>
<field name="user_id"/> <field name="user_id"/>
<field name="section_id" widget="selection"/> <field name="section_id" widget="selection"
groups="base.group_multi_salesteams"/>
<field name="stage_id"/> <field name="stage_id"/>
<field name="amount_revenue"/> <field name="amount_revenue"/>
<field name="nbr" /> <field name="nbr" />
@ -134,7 +137,7 @@
<graph string="Cases by Team and Stage" type="bar" orientation="horizontal"> <graph string="Cases by Team and Stage" type="bar" orientation="horizontal">
<field name="stage_id"/> <field name="stage_id"/>
<field name="amount_revenue" operator="+"/> <field name="amount_revenue" operator="+"/>
<field name="section_id" group="True"/> <field name="section_id" group="True" groups="base.group_multi_salesteams"/>
</graph> </graph>
</field> </field>
</record> </record>
@ -150,7 +153,7 @@
<field name="month"/> <field name="month"/>
<field name="nbr"/> <field name="nbr"/>
<field name="state"/> <field name="state"/>
<field name="section_id"/> <field name="section_id" groups="base.group_multi_salesteams"/>
</search> </search>
</field> </field>
</record> </record>
@ -175,7 +178,7 @@
<field name="name"/> <field name="name"/>
<field name="month"/> <field name="month"/>
<field name="user_id"/> <field name="user_id"/>
<field name="section_id"/> <field name="section_id" groups="base.group_multi_salesteams"/>
<field name="categ_id"/> <field name="categ_id"/>
<field name="stage_id"/> <field name="stage_id"/>
<field name="nbr"/> <field name="nbr"/>
@ -195,7 +198,7 @@
<field name="name"/> <field name="name"/>
<field name="month"/> <field name="month"/>
<field name="user_id"/> <field name="user_id"/>
<field name="section_id" widget="selection"/> <field name="section_id" widget="selection" groups="base.group_multi_salesteams"/>
<field name="categ_id"/> <field name="categ_id"/>
<field name="stage_id"/> <field name="stage_id"/>
<field name="nbr" /> <field name="nbr" />
@ -216,7 +219,7 @@
<field name="month"/> <field name="month"/>
<field name="nbr"/> <field name="nbr"/>
<field name="state"/> <field name="state"/>
<field name="section_id"/> <field name="section_id" groups="base.group_multi_salesteams"/>
</search> </search>
</field> </field>
</record> </record>
@ -230,7 +233,7 @@
<graph string="Cases by Section, Category and Stage" type="bar" orientation="horizontal"> <graph string="Cases by Section, Category and Stage" type="bar" orientation="horizontal">
<field name="categ_id"/> <field name="categ_id"/>
<field name="nbr" operator="+"/> <field name="nbr" operator="+"/>
<field name="section_id" group="True"/> <field name="section_id" group="True" groups="base.group_multi_salesteams"/>
</graph> </graph>
</field> </field>
</record> </record>
@ -255,7 +258,7 @@
<field name="name"/> <field name="name"/>
<field name="month"/> <field name="month"/>
<field name="user_id"/> <field name="user_id"/>
<field name="section_id"/> <field name="section_id" groups="base.group_multi_salesteams"/>
<field name="categ_id"/> <field name="categ_id"/>
<field name="category2_id"/> <field name="category2_id"/>
<field name="stage_id"/> <field name="stage_id"/>
@ -276,7 +279,7 @@
<field name="name"/> <field name="name"/>
<field name="month"/> <field name="month"/>
<field name="user_id"/> <field name="user_id"/>
<field name="section_id" widget="selection"/> <field name="section_id" widget="selection" groups="base.group_multi_salesteams"/>
<field name="categ_id"/> <field name="categ_id"/>
<field name="category2_id"/> <field name="category2_id"/>
<field name="stage_id"/> <field name="stage_id"/>
@ -298,7 +301,7 @@
<field name="month"/> <field name="month"/>
<field name="nbr"/> <field name="nbr"/>
<field name="state"/> <field name="state"/>
<field name="section_id"/> <field name="section_id" groups="base.group_multi_salesteams"/>
</search> </search>
</field> </field>
</record> </record>
@ -312,7 +315,7 @@
<graph string="Cases by Section, Category and Type" type="bar" orientation="horizontal"> <graph string="Cases by Section, Category and Type" type="bar" orientation="horizontal">
<field name="category2_id"/> <field name="category2_id"/>
<field name="nbr" operator="+"/> <field name="nbr" operator="+"/>
<field name="section_id" group="True"/> <field name="section_id" group="True" groups="base.group_multi_salesteams"/>
</graph> </graph>
</field> </field>
</record> </record>

View File

@ -70,109 +70,6 @@
<menuitem action="crm_case_channel_action" id="menu_crm_case_channel" parent="base.menu_crm_config_lead" sequence="4" groups="base.group_no_one"/> <menuitem action="crm_case_channel_action" id="menu_crm_case_channel" parent="base.menu_crm_config_lead" sequence="4" groups="base.group_no_one"/>
<!-- Case Sections Form View -->
<record id="crm_case_section_view_form" model="ir.ui.view">
<field name="name">crm.case.section.form</field>
<field name="model">crm.case.section</field>
<field name="arch" type="xml">
<form string="Sales Team" version="7.0">
<group>
<group>
<field name="name" colspan="2"/>
<field name="parent_id"/>
<field name="code"/>
</group>
<group>
<field name="user_id"/>
<field name="resource_calendar_id"/>
<field name="active"/>
</group>
</group>
<notebook colspan="4">
<page string="Sales Team">
<group>
<field name="alias_id" invisible="1" required="0"/>
<label for="alias_name" attrs="{'invisible': [('alias_domain', '=', False)]}"/>
<div attrs="{'invisible': [('alias_domain', '=', False)]}">
<field name="alias_name" class="oe_inline" attrs="{'required': [('alias_id', '!=', False)]}"/>@<field name="alias_domain" class="oe_inline"/>
</div>
<field name="change_responsible"/>
</group>
<separator string="Team Members"/>
<field name="member_ids" widget="many2many_kanban">
<kanban quick_create="false" create="true">
<field name="name"/>
<templates>
<t t-name="kanban-box">
<div style="position: relative">
<a t-if="! read_only_mode" type="delete" style="position: absolute; right: 0; padding: 4px; diplay: inline-block">X</a>
<div class="oe_module_vignette">
<div class="oe_module_desc">
<field name="name"/>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</page>
<page string="Stages">
<separator string="Select Stages for this Sales Team"/>
<field name="stage_ids"/>
</page>
<page string="Notes">
<field name="note"/>
</page>
</notebook>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers" help="Follow this salesteam to automatically track the events associated to users of this team."/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<!-- Case Sections Tree View -->
<record id="crm_case_section_view_tree" model="ir.ui.view">
<field name="name">crm.case.section.tree</field>
<field name="model">crm.case.section</field>
<field name="field_parent">child_ids</field>
<field name="arch" type="xml">
<tree string="Sales Team">
<field name="name"/>
<field name="code"/>
<field name="user_id"/>
</tree>
</field>
</record>
<!-- Case Sections Action -->
<record id="crm_case_section_act" model="ir.actions.act_window">
<field name="name">Sales Teams</field>
<field name="res_model">crm.case.section</field>
<field name="view_type">form</field>
<field name="view_id" ref="crm_case_section_view_tree"/>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to define a new sales team.
</p><p>
Use sales team to organize your different salespersons or
departments into separate teams. Each team will work in
its own list of opportunities.
</p>
</field>
</record>
<menuitem action="crm_case_section_act"
id="menu_crm_case_section_act" sequence="15"
parent="base.menu_base_config" groups="base.group_sale_manager"/>
<!-- CRM Stage Tree View --> <!-- CRM Stage Tree View -->
<record model="ir.ui.view" id="crm_case_stage_tree"> <record model="ir.ui.view" id="crm_case_stage_tree">
@ -233,7 +130,7 @@
<form string="Case Category" version="7.0"> <form string="Case Category" version="7.0">
<group> <group>
<field name="name"/> <field name="name"/>
<field name="section_id"/> <field name="section_id" groups="base.group_multi_salesteams"/>
<field name="object_id" invisible="1"/> <field name="object_id" invisible="1"/>
</group> </group>
</form> </form>
@ -248,7 +145,7 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="Case Category"> <tree string="Case Category">
<field name="name"/> <field name="name"/>
<field name="section_id"/> <field name="section_id" groups="base.group_multi_salesteams"/>
</tree> </tree>
</field> </field>
</record> </record>
@ -261,7 +158,7 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="Campaign"> <tree string="Campaign">
<field name="name"/> <field name="name"/>
<field name="section_id"/> <field name="section_id" groups="base.group_multi_salesteams"/>
</tree> </tree>
</field> </field>
</record> </record>
@ -275,7 +172,7 @@
<form string="Campaign" version="7.0"> <form string="Campaign" version="7.0">
<group> <group>
<field name="name"/> <field name="name"/>
<field name="section_id"/> <field name="section_id" groups="base.group_multi_salesteams"/>
</group> </group>
</form> </form>
</field> </field>
@ -295,13 +192,6 @@
groups="base.group_no_one" groups="base.group_no_one"
parent="base.menu_crm_config_lead"/> parent="base.menu_crm_config_lead"/>
<record id="crm_case_section_act_tree" model="ir.actions.act_window">
<field name="name">Cases by Sales Team</field>
<field name="res_model">crm.case.section</field>
<field name="domain">[('parent_id','=',False)]</field>
<field name="view_type">tree</field>
<field name="view_id" ref="crm_case_section_view_tree"/>
</record>
<!-- Segmentation line Tree View --> <!-- Segmentation line Tree View -->
@ -434,7 +324,7 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="Payment Mode"> <tree string="Payment Mode">
<field name="name"/> <field name="name"/>
<field name="section_id"/> <field name="section_id" groups="base.group_multi_salesteams"/>
</tree> </tree>
</field> </field>
</record> </record>
@ -448,7 +338,7 @@
<form string="Payment Mode" version="7.0"> <form string="Payment Mode" version="7.0">
<group> <group>
<field name="name"/> <field name="name"/>
<field name="section_id"/> <field name="section_id" groups="base.group_multi_salesteams"/>
</group> </group>
</form> </form>
</field> </field>

View File

@ -19,7 +19,8 @@
<field name="channel_id" invisible="1"/> <field name="channel_id" invisible="1"/>
<field name="type" invisible="1"/> <field name="type" invisible="1"/>
<field name="priority" invisible="1"/> <field name="priority" invisible="1"/>
<field name="section_id" invisible="1"/> <field name="section_id" invisible="1"
groups="base.group_multi_salesteams"/>
<field name="user_id" invisible="1"/> <field name="user_id" invisible="1"/>
<field name="company_id" invisible="1"/> <field name="company_id" invisible="1"/>
<field name="partner_id" invisible="1"/> <field name="partner_id" invisible="1"/>
@ -77,7 +78,8 @@
help="Leads/Opportunities that are assigned to one of the sale teams I manage"/> help="Leads/Opportunities that are assigned to one of the sale teams I manage"/>
<separator/> <separator/>
<filter icon="terp-personal" string="My Case(s)" help="Leads/Opportunities that are assigned to me" domain="[('user_id','=',uid)]"/> <filter icon="terp-personal" string="My Case(s)" help="Leads/Opportunities that are assigned to me" domain="[('user_id','=',uid)]"/>
<field name="section_id" context="{'invisible_section': False}"/> <field name="section_id" context="{'invisible_section': False}"
groups="base.group_multi_salesteams"/>
<field name="user_id" string="Salesperson"/> <field name="user_id" string="Salesperson"/>
<group expand="0" string="Extended Filters..."> <group expand="0" string="Extended Filters...">
<field name="partner_id"/> <field name="partner_id"/>
@ -134,7 +136,8 @@
<field name="creation_month" invisible="1"/> <field name="creation_month" invisible="1"/>
<field name="creation_day" invisible="1"/> <field name="creation_day" invisible="1"/>
<field name="deadline_month" invisible="1"/> <field name="deadline_month" invisible="1"/>
<field name="section_id" invisible="1"/> <field name="section_id" invisible="1"
groups="base.group_multi_salesteams"/>
<field name="user_id" invisible="1"/> <field name="user_id" invisible="1"/>
<field name="partner_id" invisible="1"/> <field name="partner_id" invisible="1"/>
<field name="country_id" invisible="1"/> <field name="country_id" invisible="1"/>

View File

@ -11,7 +11,8 @@
<tree string="Phone calls" create="false"> <tree string="Phone calls" create="false">
<field name="name" invisible="1"/> <field name="name" invisible="1"/>
<field name="month" invisible="1"/> <field name="month" invisible="1"/>
<field name="section_id" invisible="1"/> <field name="section_id" invisible="1"
groups="base.group_multi_salesteams"/>
<field name="priority" invisible="1"/> <field name="priority" invisible="1"/>
<field name="user_id" invisible="1"/> <field name="user_id" invisible="1"/>
<field name="company_id" invisible="1"/> <field name="company_id" invisible="1"/>
@ -59,7 +60,8 @@
help="Phone calls that are assigned to one of the sale teams I manage"/> help="Phone calls that are assigned to one of the sale teams I manage"/>
<separator/> <separator/>
<filter icon="terp-personal" string="My Phone Calls" help="Phone Calls that are assigned to me" domain="[('user_id','=',uid)]" /> <filter icon="terp-personal" string="My Phone Calls" help="Phone Calls that are assigned to me" domain="[('user_id','=',uid)]" />
<field name="section_id" string="Sales Team" context="{'invisible_section': False}"/> <field name="section_id" string="Sales Team" context="{'invisible_section': False}"
groups="base.group_multi_salesteams"/>
<field name="user_id" string="Salesperson"/> <field name="user_id" string="Salesperson"/>
<group expand="0" string="Extended Filters..."> <group expand="0" string="Extended Filters...">
<field name="partner_id"/> <field name="partner_id"/>

View File

@ -2,7 +2,7 @@
############################################################################## ##############################################################################
# #
# OpenERP, Open Source Business Applications # OpenERP, Open Source Business Applications
# Copyright (C) 2004-2012 OpenERP S.A. (<http://openerp.com>). # Copyright (C) 2004-TODAY OpenERP S.A. (<http://openerp.com>).
# #
# This program is free software: you can redistribute it and/or modify # This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as # it under the terms of the GNU Affero General Public License as
@ -21,14 +21,39 @@
from openerp.osv import fields, osv from openerp.osv import fields, osv
class crm_configuration(osv.osv_memory):
class crm_configuration(osv.TransientModel):
_name = 'sale.config.settings' _name = 'sale.config.settings'
_inherit = ['sale.config.settings', 'fetchmail.config.settings'] _inherit = ['sale.config.settings', 'fetchmail.config.settings']
def set_group_multi_salesteams(self, cr, uid, ids, context=None):
""" This method is automatically called by res_config as it begins
with set. It is used to implement the 'one group or another'
behavior. We have to perform some group manipulation by hand
because in res_config.execute(), set_* methods are called
after group_*; therefore writing on an hidden res_config file
could not work.
If group_multi_salesteams is checked: remove group_mono_salesteams
from group_user, remove the users. Otherwise, just add
group_mono_salesteams in group_user.
The inverse logic about group_multi_salesteams is managed by the
normal behavior of 'group_multi_salesteams' field.
"""
def ref(xml_id):
mod, xml = xml_id.split('.', 1)
return self.pool['ir.model.data'].get_object(cr, uid, mod, xml, context)
for obj in self.browse(cr, uid, ids, context=context):
config_group = ref('base.group_mono_salesteams')
base_group = ref('base.group_user')
if obj.group_multi_salesteams:
base_group.write({'implied_ids': [(3, config_group.id)]})
config_group.write({'users': [(3, u.id) for u in base_group.users]})
else:
base_group.write({'implied_ids': [(4, config_group.id)]})
return True
_columns = { _columns = {
'fetchmail_lead': fields.boolean("Create leads from incoming mails",
fetchmail_model='crm.lead', fetchmail_name='Incoming Leads',
help="""Allows you to configure your incoming mail server, and create leads from incoming emails."""),
'group_fund_raising': fields.boolean("Manage Fund Raising", 'group_fund_raising': fields.boolean("Manage Fund Raising",
implied_group='crm.group_fund_raising', implied_group='crm.group_fund_raising',
help="""Allows you to trace and manage your activities for fund raising."""), help="""Allows you to trace and manage your activities for fund raising."""),
@ -37,8 +62,10 @@ class crm_configuration(osv.osv_memory):
This installs the module crm_claim."""), This installs the module crm_claim."""),
'module_crm_helpdesk': fields.boolean("Manage Helpdesk and Support", 'module_crm_helpdesk': fields.boolean("Manage Helpdesk and Support",
help="""Allows you to communicate with Customer, process Customer query, and provide better help and support. This installs the module crm_helpdesk."""), help="""Allows you to communicate with Customer, process Customer query, and provide better help and support. This installs the module crm_helpdesk."""),
'group_multi_salesteams': fields.boolean("Organize Sales activities into multiple Sales Teams",
implied_group='base.group_multi_salesteams',
help="""Allows you to use Sales Teams to manage your leads and opportunities."""),
} }
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -22,20 +22,15 @@
</div> </div>
</div> </div>
</group> </group>
</div> <separator string="Sales Teams Configuration"/>
<group name="On Mail Client" version="7.0" position="after">
<group> <group>
<label for="id" string="On Mail Server"/> <label for="id" string="Use Sales Teams"/>
<div> <div>
<div name="fetchmail_lead"> <field name="group_multi_salesteams" class="oe_inline"/>
<field name="fetchmail_lead" class="oe_inline"/> <label for="group_multi_salesteams"/>
<label for="fetchmail_lead"/>
<button name="configure_fetchmail_lead" type="object" string="Configure" icon="gtk-go-forward"
attrs="{'invisible': [('fetchmail_lead','=',False)]}" class="oe_link"/>
</div>
</div> </div>
</group> </group>
</group> </div>
</field> </field>
</record> </record>

View File

@ -10,7 +10,7 @@
<field eval="18" name="priority"/> <field eval="18" name="priority"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="user_id" position="after"> <field name="user_id" position="after">
<field name="section_id" completion="1"/> <field name="section_id" completion="1" groups="base.group_multi_salesteams"/>
</field> </field>
</field> </field>
</record> </record>
@ -30,8 +30,11 @@
<field name="res_model">crm.lead</field> <field name="res_model">crm.lead</field>
<field name="view_mode">kanban,tree,form,graph,calendar</field> <field name="view_mode">kanban,tree,form,graph,calendar</field>
<field name="domain">[('type','=','opportunity')]</field> <field name="domain">[('type','=','opportunity')]</field>
<field name="context">{'search_default_partner_id': active_id, <field name="context">{
'stage_type': 'opportunity', 'default_type': 'opportunity'}</field> 'search_default_partner_id': active_id,
'stage_type': 'opportunity',
'default_type': 'opportunity'
}</field>
<field name="view_id" eval="False"/> <field name="view_id" eval="False"/>
<field name="search_view_id" ref="crm.view_crm_case_opportunities_filter"/> <field name="search_view_id" ref="crm.view_crm_case_opportunities_filter"/>
<field name="help" type="html"> <field name="help" type="html">

View File

@ -23,6 +23,19 @@
<field name="users" eval="[(4, ref('base.user_root'))]"/> <field name="users" eval="[(4, ref('base.user_root'))]"/>
</record> </record>
<record id="base.group_mono_salesteams" model="res.groups">
<field name="name">Do Not Use Sales Teams</field>
<field name="category_id" ref="base.module_category_hidden"/>
</record>
<record id="base.group_user" model="res.groups">
<field name="implied_ids" eval="[(4, ref('base.group_mono_salesteams'))]"/>
</record>
<record id="base.group_multi_salesteams" model="res.groups">
<field name="name">Manage Sales Teams</field>
<field name="category_id" ref="base.module_category_hidden"/>
</record>
<record id="group_fund_raising" model="res.groups"> <record id="group_fund_raising" model="res.groups">
<field name="name">Manage Fund Raising</field> <field name="name">Manage Fund Raising</field>
<field name="category_id" ref="base.module_category_hidden"/> <field name="category_id" ref="base.module_category_hidden"/>

View File

@ -11,9 +11,7 @@ access_crm_lead_manager,crm.lead.manager,model_crm_lead,base.group_sale_manager,
access_crm_phonecall_manager,crm.phonecall.manager,model_crm_phonecall,base.group_sale_manager,1,1,1,1 access_crm_phonecall_manager,crm.phonecall.manager,model_crm_phonecall,base.group_sale_manager,1,1,1,1
access_crm_case_categ,crm.case.categ,model_crm_case_categ,base.group_user,1,0,0,0 access_crm_case_categ,crm.case.categ,model_crm_case_categ,base.group_user,1,0,0,0
access_crm_lead,crm.lead,model_crm_lead,base.group_sale_salesman,1,1,1,0 access_crm_lead,crm.lead,model_crm_lead,base.group_sale_salesman,1,1,1,0
access_crm_lead_all,crm.lead.all,model_crm_lead,base.group_user,1,0,0,0
access_crm_phonecall,crm.phonecall,model_crm_phonecall,base.group_sale_salesman,1,1,1,0 access_crm_phonecall,crm.phonecall,model_crm_phonecall,base.group_sale_salesman,1,1,1,0
access_crm_phonecall_all,crm.phonecall.all,model_crm_phonecall,base.group_user,1,0,0,0
access_crm_case_section_user,crm.case.section.user,model_crm_case_section,base.group_sale_salesman,1,1,1,0 access_crm_case_section_user,crm.case.section.user,model_crm_case_section,base.group_sale_salesman,1,1,1,0
access_crm_case_section_manager,crm.case.section.manager,model_crm_case_section,base.group_sale_manager,1,1,1,1 access_crm_case_section_manager,crm.case.section.manager,model_crm_case_section,base.group_sale_manager,1,1,1,1
access_crm_case_stage,crm.case.stage,model_crm_case_stage,,1,0,0,0 access_crm_case_stage,crm.case.stage,model_crm_case_stage,,1,0,0,0

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
11 access_crm_phonecall_manager crm.phonecall.manager model_crm_phonecall base.group_sale_manager 1 1 1 1
12 access_crm_case_categ crm.case.categ model_crm_case_categ base.group_user 1 0 0 0
13 access_crm_lead crm.lead model_crm_lead base.group_sale_salesman 1 1 1 0
access_crm_lead_all crm.lead.all model_crm_lead base.group_user 1 0 0 0
14 access_crm_phonecall crm.phonecall model_crm_phonecall base.group_sale_salesman 1 1 1 0
access_crm_phonecall_all crm.phonecall.all model_crm_phonecall base.group_user 1 0 0 0
15 access_crm_case_section_user crm.case.section.user model_crm_case_section base.group_sale_salesman 1 1 1 0
16 access_crm_case_section_manager crm.case.section.manager model_crm_case_section base.group_sale_manager 1 1 1 1
17 access_crm_case_stage crm.case.stage model_crm_case_stage 1 0 0 0

View File

@ -0,0 +1,42 @@
.openerp .oe_kanban_view .oe_kanban_crm_salesteams {
width: 345px;
}
.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_avatars {
text-align: right;
margin: -5px 0 -10px 0;
}
.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_avatars img {
width: 30px;
height: 30px;
padding-left: 0px;
margin-top: 3px;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}
.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_items_list {
margin: 10px 0;
}
.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_items_list a {
width: 110px;
display: inline-block;
}
.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_items_list a:hover {
text-decoration: underline !important;
}
.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_center {
text-align: center;
margin: 3px 0;
}
.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_center .oe_sum {
margin: 0;
font-size: 40px;
}
.openerp .oe_kanban_view .oe_kanban_crm_salesteams .oe_center .oe_subsum {
font-size: 10px;
}

View File

@ -0,0 +1,11 @@
openerp.crm = function(openerp) {
openerp.web_kanban.KanbanRecord.include({
on_card_clicked: function() {
if (this.view.dataset.model === 'crm.case.section') {
this.$('.oe_kanban_crm_salesteams_list a').first().click();
} else {
this._super.apply(this, arguments);
}
},
});
};

View File

@ -37,20 +37,19 @@
I check for the resulting merged opp (based on name and partner). I check for the resulting merged opp (based on name and partner).
- -
!python {model: crm.lead}: | !python {model: crm.lead}: |
merge_id = self.search(cr, uid, [('name', '=', 'Test lead 1'), ('partner_id','=', ref("base.res_partner_1"))]) merge_id = self.search(cr, uid, [('name', '=', 'Test opportunity 1'), ('partner_id','=', ref("base.res_partner_5"))])
assert merge_id, 'Fail to create merge opportunity wizard' assert merge_id, 'Fail to create merge opportunity wizard'
merge_result = self.browse(cr, uid, merge_id)[0] merge_result = self.browse(cr, uid, merge_id)[0]
assert merge_result.partner_id.id == ref("base.res_partner_1"), 'Partner mismatch: when merging leads/opps with different m2o values, the first not null value prevails (the other are dropped)' assert merge_result.description == 'This is the description of the test opp 1.\n\nThis is the description of the test lead 1.\n\nThis is the description of the test lead 2.', 'Description mismatch: when merging leads/opps with different text values, these values should get concatenated and separated with line returns'
assert merge_result.description == 'This is the description of the test lead 1.\n\nThis is the description of the test lead 2.\n\nThis is the description of the test opp 1.', 'Description mismatch: when merging leads/opps with different text values, these values should get concatenated and separated with line returns'
assert merge_result.type == 'opportunity', 'Type mismatch: when at least one opp in involved in the merge, the result should be a new opp (instead of %s)' % merge_result.type assert merge_result.type == 'opportunity', 'Type mismatch: when at least one opp in involved in the merge, the result should be a new opp (instead of %s)' % merge_result.type
- -
The other (tailing) leads/opps shouldn't exist anymore. The other (tailing) leads/opps shouldn't exist anymore.
- -
!python {model: crm.lead}: | !python {model: crm.lead}: |
tailing_lead = self.search(cr, uid, [('id', '=', ref('test_crm_lead_02'))]) tailing_lead = self.search(cr, uid, [('id', '=', ref('test_crm_lead_01'))])
assert not tailing_lead, 'This tailing lead (id %s) should not exist anymore' % ref('test_crm_lead_02') assert not tailing_lead, 'This tailing lead (id %s) should not exist anymore' % ref('test_crm_lead_02')
tailing_opp = self.search(cr, uid, [('id', '=', ref('test_crm_opp_01'))]) tailing_opp = self.search(cr, uid, [('id', '=', ref('test_crm_lead_02'))])
assert not tailing_opp, 'This tailing opp (id %s) should not exist anymore' % ref('test_crm_opp_01') assert not tailing_opp, 'This tailing opp (id %s) should not exist anymore' % ref('test_crm_opp_01')
- -
I want to test leads merge. Start by creating two leads (with the same partner). I want to test leads merge. Start by creating two leads (with the same partner).

View File

@ -22,7 +22,7 @@
<field name="phone"/> <field name="phone"/>
<field name="stage_id"/> <field name="stage_id"/>
<field name="user_id"/> <field name="user_id"/>
<field name="section_id"/> <field name="section_id" groups="base.group_multi_salesteams"/>
</tree> </tree>
</field> </field>
</group> </group>
@ -68,13 +68,13 @@
<field name="phone"/> <field name="phone"/>
<field name="stage_id"/> <field name="stage_id"/>
<field name="user_id"/> <field name="user_id"/>
<field name="section_id"/> <field name="section_id" groups="base.group_multi_salesteams"/>
</tree> </tree>
</field> </field>
</group> </group>
<group string="Assign opportunities to" attrs="{'invisible': [('name', '=', '')]}"> <group string="Assign opportunities to" attrs="{'invisible': [('name', '=', '')]}">
<field name="section_id"/> <field name="section_id" groups="base.group_multi_salesteams"/>
<field name="user_ids" widget="many2many_tags"/> <field name="user_ids" widget="many2many_tags"/>
</group> </group>

View File

@ -19,7 +19,7 @@
<field name="phone"/> <field name="phone"/>
<field name="stage_id"/> <field name="stage_id"/>
<field name="user_id"/> <field name="user_id"/>
<field name="section_id"/> <field name="section_id" groups="base.group_multi_salesteams"/>
</tree> </tree>
</field> </field>
<footer> <footer>

View File

@ -23,7 +23,7 @@
<field name="partner_id" readonly="True"/> <field name="partner_id" readonly="True"/>
<field name="phone"/> <field name="phone"/>
<field name="user_id" attrs="{'invisible': [('action','=','log')]}"/> <field name="user_id" attrs="{'invisible': [('action','=','log')]}"/>
<field name="section_id" widget="selection" attrs="{'invisible': [('action','=','log')]}"/> <field name="section_id" widget="selection" attrs="{'invisible': [('action','=','log')]}" groups="base.group_multi_salesteams"/>
</group> </group>
</group> </group>
<field name="note" placeholder="Call Description" /> <field name="note" placeholder="Call Description" />

View File

@ -15,7 +15,7 @@
<field name="date" string="Planned Date" attrs="{'invisible': [('action','=','log')]}"/> <field name="date" string="Planned Date" attrs="{'invisible': [('action','=','log')]}"/>
<field name="partner_id" readonly="True"/> <field name="partner_id" readonly="True"/>
<field name="user_id"/> <field name="user_id"/>
<field name="section_id"/> <field name="section_id" groups="base.group_multi_salesteams"/>
</group> </group>
<footer> <footer>
<button name="action_schedule" type="object" string="Log Call" attrs="{'invisible' : [('action', '!=', 'log')]}" class="oe_highlight"/> <button name="action_schedule" type="object" string="Log Call" attrs="{'invisible' : [('action', '!=', 'log')]}" class="oe_highlight"/>

View File

@ -21,7 +21,6 @@
import crm_claim import crm_claim
import report import report
import res_config
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -41,7 +41,6 @@ automatically new claims based on incoming emails.
'crm_claim_menu.xml', 'crm_claim_menu.xml',
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'report/crm_claim_report_view.xml', 'report/crm_claim_report_view.xml',
'res_config_view.xml',
'crm_claim_data.xml', 'crm_claim_data.xml',
], ],
'demo': ['crm_claim_demo.xml'], 'demo': ['crm_claim_demo.xml'],

View File

@ -116,7 +116,7 @@
<group colspan="4" col="4" groups="base.group_user"> <group colspan="4" col="4" groups="base.group_user">
<field name="user_id"/> <field name="user_id"/>
<field name="priority"/> <field name="priority"/>
<field name="section_id"/> <field name="section_id" groups="base.group_multi_salesteams"/>
<field name="date_deadline"/> <field name="date_deadline"/>
<field name="state" groups="base.group_no_one"/> <field name="state" groups="base.group_no_one"/>
</group> </group>

View File

@ -11,7 +11,8 @@
<tree string="Claims" create="false"> <tree string="Claims" create="false">
<field name="name" invisible="1"/> <field name="name" invisible="1"/>
<field name="month" invisible="1"/> <field name="month" invisible="1"/>
<field name="section_id" invisible="1"/> <field name="section_id" invisible="1"
groups="base.group_multi_salesteams"/>
<field name="user_id" invisible="1"/> <field name="user_id" invisible="1"/>
<field name="company_id" invisible="1"/> <field name="company_id" invisible="1"/>
<field name="partner_id" invisible="1"/> <field name="partner_id" invisible="1"/>
@ -61,7 +62,8 @@
<filter icon="terp-personal" string="My Case(s)" help="My Case(s)" domain="[('user_id','=',uid)]" /> <filter icon="terp-personal" string="My Case(s)" help="My Case(s)" domain="[('user_id','=',uid)]" />
<field name="company_id" groups="base.group_multi_company"/> <field name="company_id" groups="base.group_multi_company"/>
<field name="user_id" string="Salesperson"/> <field name="user_id" string="Salesperson"/>
<field name="section_id" string="Sales Team" context="{'invisible_section': False}"/> <field name="section_id" string="Sales Team" context="{'invisible_section': False}"
groups="base.group_multi_salesteams"/>
<group expand="0" string="Extended Filters..."> <group expand="0" string="Extended Filters...">
<field name="partner_id"/> <field name="partner_id"/>
<field name="stage_id" domain="[('section_ids', '=', 'section_id')]"/> <field name="stage_id" domain="[('section_ids', '=', 'section_id')]"/>

View File

@ -1,32 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Business Applications
# Copyright (C) 2004-2012 OpenERP S.A. (<http://openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.osv import fields, osv
class crm_claim_settings(osv.osv_memory):
_name = 'sale.config.settings'
_inherit = ['sale.config.settings', 'fetchmail.config.settings']
_columns = {
'fetchmail_claim': fields.boolean("Create claims from incoming mails",
fetchmail_model='crm.claim', fetchmail_name='Incoming Claims',
help="""Allows you to configure your incoming mail server, and create claims from incoming emails."""),
}

View File

@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_project_config_claim" model="ir.ui.view">
<field name="name">crm_claim settings</field>
<field name="model">sale.config.settings</field>
<field name="inherit_id" ref="base_setup.view_sale_config_settings"/>
<field name="priority" eval="20"/>
<field name="arch" type="xml">
<div name="fetchmail_lead" position="after">
<div>
<field name="fetchmail_claim" class="oe_inline"/>
<label for="fetchmail_claim"/>
<button type="object" name="configure_fetchmail_claim" string="Configure" icon="gtk-go-forward"
attrs="{'invisible': [('fetchmail_claim','=',False)]}" class="oe_link"/>
</div>
</div>
</field>
</record>
</data>
</openerp>

View File

@ -48,7 +48,7 @@
<sheet string="Helpdesk Support"> <sheet string="Helpdesk Support">
<group col="4" class="oe_header"> <group col="4" class="oe_header">
<field name="name" string="Query"/> <field name="name" string="Query"/>
<field name="section_id" widget="selection"/> <field name="section_id" widget="selection" groups="base.group_multi_salesteams"/>
<field name="user_id"/> <field name="user_id"/>
<field name="date"/> <field name="date"/>
<field name="date_deadline"/> <field name="date_deadline"/>
@ -115,7 +115,7 @@
<field name="date" string="Date"/> <field name="date" string="Date"/>
<field name="date_deadline"/> <field name="date_deadline"/>
<field name="user_id"/> <field name="user_id"/>
<field name="section_id"/> <field name="section_id" groups="base.group_multi_salesteams"/>
<field name="priority"/> <field name="priority"/>
<field name="state"/> <field name="state"/>
</tree> </tree>
@ -154,7 +154,7 @@
help="Helpdesk requests that are assigned to me or to one of the sale teams I manage" /> help="Helpdesk requests that are assigned to me or to one of the sale teams I manage" />
<field name="partner_id" /> <field name="partner_id" />
<field name="user_id"/> <field name="user_id"/>
<field name="section_id" string="Sales Team"/> <field name="section_id" string="Sales Team" groups="base.group_multi_salesteams"/>
<group expand="0" string="Group By..."> <group expand="0" string="Group By...">
<filter string="Partner" icon="terp-partner" domain="[]" help="Partner" context="{'group_by':'partner_id'}" /> <filter string="Partner" icon="terp-partner" domain="[]" help="Partner" context="{'group_by':'partner_id'}" />
<filter string="Responsible" icon="terp-personal" domain="[]" help="Responsible User" context="{'group_by':'user_id'}" /> <filter string="Responsible" icon="terp-personal" domain="[]" help="Responsible User" context="{'group_by':'user_id'}" />

View File

@ -11,7 +11,7 @@
<tree string="Helpdesk" create="false"> <tree string="Helpdesk" create="false">
<field name="name" invisible="1"/> <field name="name" invisible="1"/>
<field name="month" invisible="1"/> <field name="month" invisible="1"/>
<field name="section_id" invisible="1"/> <field name="section_id" invisible="1" groups="base.group_multi_salesteams"/>
<field name="user_id" invisible="1"/> <field name="user_id" invisible="1"/>
<field name="company_id" invisible="1"/> <field name="company_id" invisible="1"/>
<field name="partner_id" invisible="1"/> <field name="partner_id" invisible="1"/>
@ -60,7 +60,7 @@
<separator/> <separator/>
<filter string="My Company" icon="terp-go-home" context="{'invisible_section': False}" domain="[('section_id.user_id.company_id','=',uid)]" help="My company"/> <filter string="My Company" icon="terp-go-home" context="{'invisible_section': False}" domain="[('section_id.user_id.company_id','=',uid)]" help="My company"/>
<field name="user_id" string="Salesperson"/> <field name="user_id" string="Salesperson"/>
<field name="section_id" string="Sales Team" context="{'invisible_section': False}"/> <field name="section_id" string="Sales Team" context="{'invisible_section': False}" groups="base.group_multi_salesteams"/>
<field name="company_id" groups="base.group_multi_company"/> <field name="company_id" groups="base.group_multi_company"/>
<group expand="0" string="Extended Filters..." groups="base.group_no_one"> <group expand="0" string="Extended Filters..." groups="base.group_no_one">
<field name="priority" string="Priority"/> <field name="priority" string="Priority"/>

View File

@ -10,7 +10,7 @@
<search string="Leads Analysis"> <search string="Leads Analysis">
<filter icon="terp-check" string="Current" domain="[('state','in',('draft','open'))]"/> <filter icon="terp-check" string="Current" domain="[('state','in',('draft','open'))]"/>
<filter icon="terp-dialog-close" string="Closed" domain="[('state','=','done')]"/> <filter icon="terp-dialog-close" string="Closed" domain="[('state','=','done')]"/>
<field name="section_id" context="{'invisible_section': False}"/> <field name="section_id" context="{'invisible_section': False}" groups="base.group_multi_salesteams"/>
<field name="grade_id"/> <field name="grade_id"/>
<field name="user_id"/> <field name="user_id"/>
<field name="partner_assigned_id"/> <field name="partner_assigned_id"/>
@ -69,7 +69,7 @@
<field name="year" invisible="1"/> <field name="year" invisible="1"/>
<field name="month" invisible="1"/> <field name="month" invisible="1"/>
<field name="date_assign" invisible="1"/> <field name="date_assign" invisible="1"/>
<field name="section_id" invisible="1"/> <field name="section_id" invisible="1" groups="base.group_multi_salesteams"/>
<field name="user_id" invisible="1"/> <field name="user_id" invisible="1"/>
<field name="grade_id" invisible="1" widget="selection"/> <field name="grade_id" invisible="1" widget="selection"/>
<field name="partner_assigned_id" invisible="1"/> <field name="partner_assigned_id" invisible="1"/>

View File

@ -8,7 +8,7 @@
<field name="model">crm.partner.report.assign</field> <field name="model">crm.partner.report.assign</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<search string="Partner assigned Analysis"> <search string="Partner assigned Analysis">
<field name="section_id"/> <field name="section_id" groups="base.group_multi_salesteams"/>
<field name="user_id"/> <field name="user_id"/>
<field name="grade_id"/> <field name="grade_id"/>
<field name="activation"/> <field name="activation"/>
@ -49,7 +49,7 @@
<field name="date_review" invisible="1"/> <field name="date_review" invisible="1"/>
<field name="date_partnership" invisible="1"/> <field name="date_partnership" invisible="1"/>
<field name="period_id" invisible="1"/> <field name="period_id" invisible="1"/>
<field name="section_id" invisible="1"/> <field name="section_id" invisible="1" groups="base.group_multi_salesteams"/>
<field name="user_id" invisible="1"/> <field name="user_id" invisible="1"/>
<field name="opp"/> <field name="opp"/>
<field name="turnover"/> <field name="turnover"/>

View File

@ -145,7 +145,8 @@
states="open,pending" type="object" states="open,pending" type="object"
icon="gtk-go-forward" /> icon="gtk-go-forward" />
<field name="section_id" <field name="section_id"
invisible="context.get('invisible_section', True)" /> invisible="context.get('invisible_section', True)"
groups="base.group_multi_salesteams"/>
<field name="user_id" /> <field name="user_id" />
<field name="state" /> <field name="state" />
<button name="case_cancel" string="Cancel" <button name="case_cancel" string="Cancel"

View File

@ -52,11 +52,10 @@
<field name="view_type">form</field> <field name="view_type">form</field>
<field name="view_mode">tree,form,calendar,gantt,graph,kanban</field> <field name="view_mode">tree,form,calendar,gantt,graph,kanban</field>
</record> </record>
<menuitem <menuitem id="menu_crm_todo"
id="menu_crm_todo"
parent="base.menu_sales" parent="base.menu_sales"
action="crm_todo_action" action="crm_todo_action"
sequence="6"/> sequence="7"/>
</data> </data>

View File

@ -258,7 +258,9 @@
name="Documents" name="Documents"
action="action_document_file_form" action="action_document_file_form"
id="menu_document_files" id="menu_document_files"
parent="menu_document_doc"/> parent="menu_document_doc"
sequence="0"
/>
<record model="ir.actions.act_window" id="action_document_file_directory_form"> <record model="ir.actions.act_window" id="action_document_file_directory_form">
<field name="type">ir.actions.act_window</field> <field name="type">ir.actions.act_window</field>

View File

@ -325,7 +325,7 @@ class abstracted_fs(object):
""" Get cr, uid, pool from a node """ Get cr, uid, pool from a node
""" """
assert node assert node
db = openerp.registry.(node.context.dbname).db db = openerp.registry(node.context.dbname).db
return db.cursor(), node.context.uid return db.cursor(), node.context.uid
def get_node_cr(self, node): def get_node_cr(self, node):

View File

@ -341,7 +341,8 @@
</group> </group>
<group> <group>
<field name="company_id" widget="selection" groups="base.group_multi_company"/> <field name="company_id" widget="selection" groups="base.group_multi_company"/>
<field name="department_id"/> </group> <field name="department_id"/>
</group>
</group> </group>
<div> <div>
<label for="description"/> <label for="description"/>

View File

@ -228,6 +228,8 @@ class hr_expense_expense(osv.osv):
for exp in self.browse(cr, uid, ids, context=context): for exp in self.browse(cr, uid, ids, context=context):
if not exp.employee_id.address_home_id: if not exp.employee_id.address_home_id:
raise osv.except_osv(_('Error!'), _('The employee must have a home address.')) raise osv.except_osv(_('Error!'), _('The employee must have a home address.'))
if not exp.employee_id.address_home_id.property_account_payable.id:
raise osv.except_osv(_('Error!'), _('The employee must have a payable account set on his home address.'))
company_currency = exp.company_id.currency_id.id company_currency = exp.company_id.currency_id.id
diff_currency_p = exp.currency_id.id <> company_currency diff_currency_p = exp.currency_id.id <> company_currency
@ -333,6 +335,8 @@ class hr_expense_expense(osv.osv):
acc = line.product_id.property_account_expense acc = line.product_id.property_account_expense
if not acc: if not acc:
acc = line.product_id.categ_id.property_account_expense_categ acc = line.product_id.categ_id.property_account_expense_categ
if not acc:
raise osv.except_osv(_('Error!'), _('No purchase account found for the product %s (or for his category), please configure one.') % (line.product_id.name))
else: else:
acc = property_obj.get(cr, uid, 'property_account_expense_categ', 'product.category', context={'force_company': company.id}) acc = property_obj.get(cr, uid, 'property_account_expense_categ', 'product.category', context={'force_company': company.id})
if not acc: if not acc:

View File

@ -112,7 +112,7 @@
<field name="date_value" string="Expense Date"/> <field name="date_value" string="Expense Date"/>
<field name="name"/> <field name="name"/>
<field name="ref"/> <field name="ref"/>
<field domain="[('type','in',['normal','contract']), ('parent_id','!=',False)]" name="analytic_account" groups="analytic.group_analytic_accounting"/> <field domain="[('type','in',['normal','contract'])]" name="analytic_account" groups="analytic.group_analytic_accounting"/>
<field name="uom_id" on_change="onchange_uom(product_id, uom_id, context)"/> <field name="uom_id" on_change="onchange_uom(product_id, uom_id, context)"/>
<field name="unit_amount"/> <field name="unit_amount"/>
<field name="unit_quantity"/> <field name="unit_quantity"/>

View File

@ -185,6 +185,16 @@ class hr_holidays(osv.osv):
('date_check', "CHECK ( number_of_days_temp >= 0 )", "The number of days must be greater than 0."), ('date_check', "CHECK ( number_of_days_temp >= 0 )", "The number of days must be greater than 0."),
] ]
def copy(self, cr, uid, id, default=None, context=None):
if default is None:
default = {}
if context is None:
context = {}
default = default.copy()
default['date_from'] = False
default['date_to'] = False
return super(hr_holidays, self).copy(cr, uid, id, default, context=context)
def _create_resource_leave(self, cr, uid, leaves, context=None): def _create_resource_leave(self, cr, uid, leaves, context=None):
'''This method will create entry in resource calendar leave object at the time of holidays validated ''' '''This method will create entry in resource calendar leave object at the time of holidays validated '''
obj_res_leave = self.pool.get('resource.calendar.leaves') obj_res_leave = self.pool.get('resource.calendar.leaves')

View File

@ -487,6 +487,12 @@ class hr_applicant(base_stage, osv.Model):
""" """
return self.set_priority(cr, uid, ids, '3') return self.set_priority(cr, uid, ids, '3')
def get_empty_list_help(self, cr, uid, help, context=None):
context['empty_list_help_model'] = 'hr.job'
context['empty_list_help_id'] = context.get('default_job_id', None)
context['empty_list_help_document_name'] = _("job applicants")
return super(hr_applicant, self).get_empty_list_help(cr, uid, help, context=context)
class hr_job(osv.osv): class hr_job(osv.osv):
_inherit = "hr.job" _inherit = "hr.job"

View File

@ -10,17 +10,13 @@
<field name="view_id" eval="False"/> <field name="view_id" eval="False"/>
<field name="search_view_id" ref="view_crm_case_jobs_filter"/> <field name="search_view_id" ref="view_crm_case_jobs_filter"/>
<field name="help" type="html"> <field name="help" type="html">
<p class="oe_view_nocontent_create"> <p>
Click to add a new job applicant.
</p><p>
OpenERP helps you track applicants in the recruitment OpenERP helps you track applicants in the recruitment
process and follow up all operations: meetings, interviews, etc. process and follow up all operations: meetings, interviews, etc.
</p><p> </p><p>
If you setup the email gateway, applicants and their attached Applicants and their attached CV are created automatically when an email is sent.
CV are created automatically when an email is sent to If you install the document management modules, all resumes are indexed automatically,
jobs@yourcompany.com. If you install the document management so that you can easily search through their content.
modules, all resumes are indexed automatically, so that you can
easily search through their content.
</p> </p>
</field> </field>
</record> </record>

View File

@ -312,11 +312,17 @@
attrs="{'invisible':[('survey_id','=',False)]}"/> attrs="{'invisible':[('survey_id','=',False)]}"/>
</div> </div>
</field> </field>
<xpath expr="//div[@class='oe_title']" version="7.0" position="after"> <xpath expr="//div[@class='oe_title']//h1" position="after">
<div attrs="{'invisible': [('alias_domain', '=', False)]}"> <div name="group_alias"
<field name="alias_id" invisible="1" required="0"/> attrs="{'invisible': [('alias_domain', '=', False)]}">
<label for="alias_name" class="oe_edit_only"/> <label for="alias_id" string="Email Alias"/>
<field name="alias_name" nolabel="1" class="oe_inline" attrs="{'required': [('alias_id', '!=', False)]}"/>@<field name="alias_domain" nolabel="1" class="oe_inline"/> <field name="alias_id" class="oe_inline oe_read_only" required="0" nolabel="1"/>
<span name="edit_alias" class="oe_edit_only">
<field name="alias_name" class="oe_inline"
attrs="{'required': [('alias_id', '!=', False)]}"/>
@
<field name="alias_domain" class="oe_inline" readonly="1"/>
</span>
</div> </div>
</xpath> </xpath>
</field> </field>

View File

@ -169,7 +169,7 @@ class lunch_order(osv.Model):
line_ref = self.pool.get("lunch.order.line") line_ref = self.pool.get("lunch.order.line")
if view_type == 'form': if view_type == 'form':
doc = etree.XML(res['arch']) doc = etree.XML(res['arch'])
pref_ids = line_ref.search(cr, uid, [('user_id', '=', uid)], order='create_date desc', context=context) pref_ids = line_ref.search(cr, uid, [('user_id', '=', uid)], order='id desc', context=context)
xml_start = etree.Element("div") xml_start = etree.Element("div")
#If there are no preference (it's the first time for the user) #If there are no preference (it's the first time for the user)
if len(pref_ids)==0: if len(pref_ids)==0:
@ -223,10 +223,17 @@ class lunch_order(osv.Model):
xml_pref_1.append(xml_pref_2) xml_pref_1.append(xml_pref_2)
i = 0 i = 0
value = value.values() value = value.values()
#TODO: sorted_values is used for a quick and dirty hack in order to display the 5 last orders of each categories.
#It would be better to fetch only the 5 items to display instead of fetching everything then sorting them in order to keep only the 5 last.
#NB: The note could also be ignored + we could fetch the preferences on the most ordered products instead of the last ones...
sorted_values = {}
for val in value: for val in value:
for pref in val.values(): for elmt in val.values():
sorted_values[elmt.id] = elmt
for key, pref in sorted(sorted_values.iteritems(), key=lambda (k, v): (k, v), reverse=True):
#We only show 5 preferences per category (or it will be too long) #We only show 5 preferences per category (or it will be too long)
if i==5: break if i == 5:
break
i += 1 i += 1
xml_pref_3 = etree.Element("div") xml_pref_3 = etree.Element("div")
xml_pref_3.set('class','oe_lunch_vignette') xml_pref_3.set('class','oe_lunch_vignette')

View File

@ -117,8 +117,13 @@ class mail_alias(osv.Model):
mail catchall domain from config. mail catchall domain from config.
e.g. `jobs@openerp.my.openerp.com` or `sales@openerp.my.openerp.com` e.g. `jobs@openerp.my.openerp.com` or `sales@openerp.my.openerp.com`
""" """
return [(record['id'], "%s@%s" % (record['alias_name'], record['alias_domain'])) res = []
for record in self.read(cr, uid, ids, ['alias_name', 'alias_domain'], context=context)] for record in self.browse(cr, uid, ids, context=context):
if record.alias_name and record.alias_domain:
res.append((record['id'], "%s@%s" % (record.alias_name, record.alias_domain)))
else:
res.append((record['id'], False))
return res
def _find_unique(self, cr, uid, name, context=None): def _find_unique(self, cr, uid, name, context=None):
"""Find a unique alias name similar to ``name``. If ``name`` is """Find a unique alias name similar to ``name``. If ``name`` is

View File

@ -144,11 +144,19 @@ class mail_group(osv.Model):
search_ref = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'mail', 'view_message_search') search_ref = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'mail', 'view_message_search')
params = { params = {
'search_view_id': search_ref and search_ref[1] or False, 'search_view_id': search_ref and search_ref[1] or False,
'domain': [('model', '=', 'mail.group'), ('res_id', '=', mail_group_id)], 'domain': [
'context': {'default_model': 'mail.group', 'default_res_id': mail_group_id, 'search_default_message_unread': True}, ('model', '=', 'mail.group'),
('res_id', '=', mail_group_id),
],
'context': {
'default_model': 'mail.group',
'default_res_id': mail_group_id,
},
'res_model': 'mail.message', 'res_model': 'mail.message',
'thread_level': 1, 'thread_level': 1,
'header_description': self._generate_header_description(cr, uid, group, context=context) 'header_description': self._generate_header_description(cr, uid, group, context=context),
'view_mailbox': True,
'compose_placeholder': 'Send a message to the group',
} }
cobj = self.pool.get('ir.actions.client') cobj = self.pool.get('ir.actions.client')
newref = cobj.copy(cr, SUPERUSER_ID, ref[1], default={'params': str(params), 'name': vals['name']}, context=context) newref = cobj.copy(cr, SUPERUSER_ID, ref[1], default={'params': str(params), 'name': vals['name']}, context=context)

View File

@ -7,7 +7,6 @@
<field name="tag">mail.wall</field> <field name="tag">mail.wall</field>
<field name="res_model">mail.message</field> <field name="res_model">mail.message</field>
<field name="context">{ <field name="context">{
'search_default_message_unread': True
}</field> }</field>
<field name="params">{ <field name="params">{
'read_action': 'read' 'read_action': 'read'
@ -30,6 +29,7 @@
<field name="message_is_follower"/> <field name="message_is_follower"/>
<field name="message_summary"/> <field name="message_summary"/>
<field name="description"/> <field name="description"/>
<field name="alias_id"/>
<templates> <templates>
<t t-name="kanban-description"> <t t-name="kanban-description">
<div class="oe_group_description" t-if="record.description.raw_value"> <div class="oe_group_description" t-if="record.description.raw_value">
@ -43,6 +43,9 @@
</div> </div>
<div class="oe_group_details"> <div class="oe_group_details">
<h4><a type="open"><field name="name"/></a></h4> <h4><a type="open"><field name="name"/></a></h4>
<div class="oe_kanban_alias" t-if="record.alias_id.value">
<span class="oe_e">%%</span><small><field name="alias_id"/></small>
</div>
<div class="oe_grey"> <div class="oe_grey">
<field name="description"/> <field name="description"/>
</div> </div>
@ -69,21 +72,26 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<form string="Group Form" version="7.0"> <form string="Group Form" version="7.0">
<sheet class="openerp_mail_group_sheet"> <sheet class="openerp_mail_group_sheet">
<field name="image" widget='image' class="oe_avatar oe_left" options='{"preview_image": "image_medium"}'/> <field name="image" widget='image' class="oe_avatar oe_left" options='{"preview_image": "image_small"}'/>
<div class="oe_title"> <div class="oe_title">
<div class="oe_edit_only"> <div class="oe_edit_only">
<label for="name" string="Group Name"/> <label for="name" string="Group Name"/>
</div> </div>
<h1><field name="name" readonly="0"/></h1> <h1><field name="name" readonly="0"/></h1>
<div name="alias_box" colspan="4" attrs="{'invisible': [('alias_domain', '=', False)]}"> <div name="group_alias"
<field name="alias_id" invisible="1" required="0"/> attrs="{'invisible': [('alias_domain', '=', False)]}">
<label for="alias_name" class="oe_edit_only"/> <label for="alias_id" string="Email Alias"/>
<field name="alias_name" nolabel="1" class="oe_inline" attrs="{'required': [('alias_id', '!=', False)]}"/>@<field name="alias_domain" nolabel="1" class="oe_inline"/> <field name="alias_id" class="oe_inline oe_read_only" required="0" nolabel="1"/>
<span name="edit_alias" class="oe_edit_only">
<field name="alias_name" class="oe_inline"
attrs="{'required': [('alias_id', '!=', False)]}"/>
@
<field name="alias_domain" class="oe_inline" readonly="1"/>
</span>
</div>
</div> </div>
<field name="description" placeholder="Topics discussed in this group..."/> <field name="description" placeholder="Topics discussed in this group..."/>
</div>
<div class="oe_clear"/> <div class="oe_clear"/>
<group>
<group class="oe_edit_only"> <group class="oe_edit_only">
<field name="public"/> <field name="public"/>
<field name="group_public_id" <field name="group_public_id"
@ -91,7 +99,7 @@
/> />
<field name="group_ids" widget="many2many_tags"/> <field name="group_ids" widget="many2many_tags"/>
</group> </group>
<group> <group attrs="{'invisible': [('public', 'not in', ['public', 'private'])]}">
<div class="oe_grey" attrs="{'invisible': [('public','&lt;&gt;','public')]}"> <div class="oe_grey" attrs="{'invisible': [('public','&lt;&gt;','public')]}">
This group is visible by everyone, This group is visible by everyone,
including your customers if you installed including your customers if you installed
@ -102,7 +110,6 @@
discussions on this group. discussions on this group.
</div> </div>
</group> </group>
</group>
</sheet> </sheet>
<div class="oe_chatter"> <div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers" groups="base.group_user"/> <field name="message_follower_ids" widget="mail_followers" groups="base.group_user"/>

View File

@ -256,7 +256,19 @@ class mail_mail(osv.Model):
body = self.send_get_mail_body(cr, uid, mail, partner=partner, context=context) body = self.send_get_mail_body(cr, uid, mail, partner=partner, context=context)
subject = self.send_get_mail_subject(cr, uid, mail, partner=partner, context=context) subject = self.send_get_mail_subject(cr, uid, mail, partner=partner, context=context)
body_alternative = tools.html2plaintext(body) body_alternative = tools.html2plaintext(body)
email_to = ['%s <%s>' % (partner.name, partner.email)] if partner else tools.email_split(mail.email_to)
# generate email_to, heuristic:
# 1. if 'partner' is specified and there is a related document: Followers of 'Doc' <email>
# 2. if 'partner' is specified, but no related document: Partner Name <email>
# 3; fallback on mail.email_to that we split to have an email addresses list
if partner and mail.record_name:
sanitized_record_name = re.sub(r'[^\w+.]+', '-', mail.record_name)
email_to = [_('"Followers of %s" <%s>') % (sanitized_record_name, partner.email)]
elif partner:
email_to = ['%s <%s>' % (partner.name, partner.email)]
else:
email_to = tools.email_split(mail.email_to)
return { return {
'body': body, 'body': body,
'body_alternative': body_alternative, 'body_alternative': body_alternative,

View File

@ -268,19 +268,25 @@ class mail_message(osv.Model):
domain = [('partner_id', '=', user_pid), ('message_id', 'in', msg_ids)] domain = [('partner_id', '=', user_pid), ('message_id', 'in', msg_ids)]
if not create_missing: if not create_missing:
domain += [('starred', '=', not starred)] domain += [('starred', '=', not starred)]
values = {
'starred': starred
}
if starred:
values['read'] = False
notif_ids = notification_obj.search(cr, uid, domain, context=context) notif_ids = notification_obj.search(cr, uid, domain, context=context)
# all message have notifications: already set them as (un)starred # all message have notifications: already set them as (un)starred
if len(notif_ids) == len(msg_ids) or not create_missing: if len(notif_ids) == len(msg_ids) or not create_missing:
notification_obj.write(cr, uid, notif_ids, {'starred': starred}, context=context) notification_obj.write(cr, uid, notif_ids, values, context=context)
return starred return starred
# some messages do not have notifications: find which one, create notification, update starred status # some messages do not have notifications: find which one, create notification, update starred status
notified_msg_ids = [notification.message_id.id for notification in notification_obj.browse(cr, uid, notif_ids, context=context)] notified_msg_ids = [notification.message_id.id for notification in notification_obj.browse(cr, uid, notif_ids, context=context)]
to_create_msg_ids = list(set(msg_ids) - set(notified_msg_ids)) to_create_msg_ids = list(set(msg_ids) - set(notified_msg_ids))
for msg_id in to_create_msg_ids: for msg_id in to_create_msg_ids:
notification_obj.create(cr, uid, {'partner_id': user_pid, 'starred': starred, 'message_id': msg_id}, context=context) notification_obj.create(cr, uid, dict(values, partner_id=user_pid, message_id=msg_id), context=context)
notification_obj.write(cr, uid, notif_ids, {'starred': starred}, context=context) notification_obj.write(cr, uid, notif_ids, values, context=context)
return starred return starred
#------------------------------------------------------ #------------------------------------------------------

View File

@ -89,6 +89,46 @@ class mail_thread(osv.AbstractModel):
# :param function lambda: returns whether the tracking should record using this subtype # :param function lambda: returns whether the tracking should record using this subtype
_track = {} _track = {}
def get_empty_list_help(self, cr, uid, help, context=None):
""" Override of BaseModel.get_empty_list_help() to generate an help message
that adds alias information. """
model = context.get('empty_list_help_model')
res_id = context.get('empty_list_help_id')
ir_config_parameter = self.pool.get("ir.config_parameter")
catchall_domain = ir_config_parameter.get_param(cr, uid, "mail.catchall.domain", context=context)
document_name = context.get('empty_list_help_document_name', _('document'))
alias = None
if catchall_domain and model and res_id: # specific res_id -> find its alias (i.e. section_id specified)
object_id = self.pool.get(model).browse(cr, uid, res_id, context=context)
alias = object_id.alias_id
elif catchall_domain and model: # no specific res_id given -> generic help message, take an example alias (i.e. alias of some section_id)
model_id = self.pool.get('ir.model').search(cr, uid, [("model", "=", self._name)], context=context)[0]
alias_obj = self.pool.get('mail.alias')
alias_ids = alias_obj.search(cr, uid, [("alias_model_id", "=", model_id)], context=context, limit=1, order='id ASC')
if alias_ids:
alias = alias_obj.browse(cr, uid, alias_ids[0], context=context)
if alias:
alias_email = alias.name_get()[0][1]
return _("""<p class='oe_view_nocontent_create'>
Click here to add a new %(document)s or send an email to: <a href='mailto:%(email)s'>%(email)s</a>
</p>
%(static_help)s"""
) % {
'document': document_name,
'email': alias_email,
'static_help': help or ''
}
if document_name != 'document' and help and help.find("oe_view_nocontent_create") == -1:
return _("<p class='oe_view_nocontent_create'>Click here to add a new %(document)s</p>%(static_help)s") % {
'document': document_name,
'static_help': help or '',
}
return help
def _get_message_data(self, cr, uid, ids, name, args, context=None): def _get_message_data(self, cr, uid, ids, name, args, context=None):
""" Computes: """ Computes:
- message_unread: has uid unread message for the document - message_unread: has uid unread message for the document
@ -468,6 +508,8 @@ class mail_thread(osv.AbstractModel):
""" """
assert isinstance(message, Message), 'message must be an email.message.Message at this point' assert isinstance(message, Message), 'message must be an email.message.Message at this point'
message_id = message.get('Message-Id') message_id = message.get('Message-Id')
email_from = decode_header(message, 'From')
email_to = decode_header(message, 'To')
references = decode_header(message, 'References') references = decode_header(message, 'References')
in_reply_to = decode_header(message, 'In-Reply-To') in_reply_to = decode_header(message, 'In-Reply-To')
@ -481,8 +523,8 @@ class mail_thread(osv.AbstractModel):
model_pool = self.pool.get(model) model_pool = self.pool.get(model)
if thread_id and model and model_pool and model_pool.exists(cr, uid, thread_id) \ if thread_id and model and model_pool and model_pool.exists(cr, uid, thread_id) \
and hasattr(model_pool, 'message_update'): and hasattr(model_pool, 'message_update'):
_logger.debug('Routing mail with Message-Id %s: direct reply to model: %s, thread_id: %s, custom_values: %s, uid: %s', _logger.info('Routing mail from %s to %s with Message-Id %s: direct reply to model: %s, thread_id: %s, custom_values: %s, uid: %s',
message_id, model, thread_id, custom_values, uid) email_from, email_to, message_id, model, thread_id, custom_values, uid)
return [(model, thread_id, custom_values, uid)] return [(model, thread_id, custom_values, uid)]
# Verify whether this is a reply to a private message # Verify whether this is a reply to a private message
@ -493,8 +535,8 @@ class mail_thread(osv.AbstractModel):
], limit=1, context=context) ], limit=1, context=context)
if message_ids: if message_ids:
message = self.pool.get('mail.message').browse(cr, uid, message_ids[0], context=context) message = self.pool.get('mail.message').browse(cr, uid, message_ids[0], context=context)
_logger.debug('Routing mail with Message-Id %s: direct reply to a private message: %s, custom_values: %s, uid: %s', _logger.info('Routing mail from %s to %s with Message-Id %s: direct reply to a private message: %s, custom_values: %s, uid: %s',
message_id, message.id, custom_values, uid) email_from, email_to, message_id, message.id, custom_values, uid)
return [(message.model, message.res_id, custom_values, uid)] return [(message.model, message.res_id, custom_values, uid)]
# 2. Look for a matching mail.alias entry # 2. Look for a matching mail.alias entry
@ -521,10 +563,11 @@ class mail_thread(osv.AbstractModel):
# Note: recognized partners will be added as followers anyway # Note: recognized partners will be added as followers anyway
# user_id = self._message_find_user_id(cr, uid, message, context=context) # user_id = self._message_find_user_id(cr, uid, message, context=context)
user_id = uid user_id = uid
_logger.debug('No matching user_id for the alias %s', alias.alias_name) _logger.info('No matching user_id for the alias %s', alias.alias_name)
routes.append((alias.alias_model_id.model, alias.alias_force_thread_id, \ routes.append((alias.alias_model_id.model, alias.alias_force_thread_id, \
eval(alias.alias_defaults), user_id)) eval(alias.alias_defaults), user_id))
_logger.debug('Routing mail with Message-Id %s: direct alias match: %r', message_id, routes) _logger.info('Routing mail from %s to %s with Message-Id %s: direct alias match: %r',
email_from, email_to, message_id, routes)
return routes return routes
# 3. Fallback to the provided parameters, if they work # 3. Fallback to the provided parameters, if they work
@ -539,14 +582,14 @@ class mail_thread(osv.AbstractModel):
except: except:
thread_id = False thread_id = False
assert thread_id and hasattr(model_pool, 'message_update') or hasattr(model_pool, 'message_new'), \ assert thread_id and hasattr(model_pool, 'message_update') or hasattr(model_pool, 'message_new'), \
"No possible route found for incoming message with Message-Id %s. " \ "No possible route found for incoming message from %s to %s (Message-Id %s:)." \
"Create an appropriate mail.alias or force the destination model." % message_id "Create an appropriate mail.alias or force the destination model." % (email_from, email_to, message_id)
if thread_id and not model_pool.exists(cr, uid, thread_id): if thread_id and not model_pool.exists(cr, uid, thread_id):
_logger.warning('Received mail reply to missing document %s! Ignoring and creating new document instead for Message-Id %s', _logger.warning('Received mail reply to missing document %s! Ignoring and creating new document instead for Message-Id %s',
thread_id, message_id) thread_id, message_id)
thread_id = None thread_id = None
_logger.debug('Routing mail with Message-Id %s: fallback to model:%s, thread_id:%s, custom_values:%s, uid:%s', _logger.info('Routing mail from %s to %s with Message-Id %s: fallback to model:%s, thread_id:%s, custom_values:%s, uid:%s',
message_id, model, thread_id, custom_values, uid) email_from, email_to, message_id, model, thread_id, custom_values, uid)
return [(model, thread_id, custom_values, uid)] return [(model, thread_id, custom_values, uid)]
def message_process(self, cr, uid, model, message, custom_values=None, def message_process(self, cr, uid, model, message, custom_values=None,
@ -596,12 +639,24 @@ class mail_thread(osv.AbstractModel):
if isinstance(message, unicode): if isinstance(message, unicode):
message = message.encode('utf-8') message = message.encode('utf-8')
msg_txt = email.message_from_string(message) msg_txt = email.message_from_string(message)
routes = self.message_route(cr, uid, msg_txt, model,
thread_id, custom_values, # parse the message, verify we are not in a loop by checking message_id is not duplicated
context=context)
msg = self.message_parse(cr, uid, msg_txt, save_original=save_original, context=context) msg = self.message_parse(cr, uid, msg_txt, save_original=save_original, context=context)
if strip_attachments: if strip_attachments:
msg.pop('attachments', None) msg.pop('attachments', None)
if msg.get('message_id'): # should always be True as message_parse generate one if missing
existing_msg_ids = self.pool.get('mail.message').search(cr, SUPERUSER_ID, [
('message_id', '=', msg.get('message_id')),
], context=context)
if existing_msg_ids:
_logger.info('Ignored mail from %s to %s with Message-Id %s:: found duplicated Message-Id during processing',
msg.get('from'), msg.get('to'), msg.get('message_id'))
return False
# find possible routes for the message
routes = self.message_route(cr, uid, msg_txt, model,
thread_id, custom_values,
context=context)
# postpone setting msg.partner_ids after message_post, to avoid double notifications # postpone setting msg.partner_ids after message_post, to avoid double notifications
partner_ids = msg.pop('partner_ids', []) partner_ids = msg.pop('partner_ids', [])
@ -798,7 +853,7 @@ class mail_thread(osv.AbstractModel):
# as RFC2822 requires timezone offset in Date headers. # as RFC2822 requires timezone offset in Date headers.
stored_date = parsed_date.replace(tzinfo=pytz.utc) stored_date = parsed_date.replace(tzinfo=pytz.utc)
else: else:
stored_date = parsed_date.astimezone(pytz.utc) stored_date = parsed_date.astimezone(tz=pytz.utc)
except Exception: except Exception:
_logger.warning('Failed to parse Date header %r in incoming mail ' _logger.warning('Failed to parse Date header %r in incoming mail '
'with message-id %r, assuming current date/time.', 'with message-id %r, assuming current date/time.',
@ -817,7 +872,7 @@ class mail_thread(osv.AbstractModel):
if parent_ids: if parent_ids:
msg_dict['parent_id'] = parent_ids[0] msg_dict['parent_id'] = parent_ids[0]
msg_dict['body'], msg_dict['attachments'] = self._message_extract_payload(message) msg_dict['body'], msg_dict['attachments'] = self._message_extract_payload(message, save_original=save_original)
return msg_dict return msg_dict
#------------------------------------------------------ #------------------------------------------------------
@ -956,12 +1011,15 @@ class mail_thread(osv.AbstractModel):
], limit=1, context=context) ], limit=1, context=context)
if author_ids: if author_ids:
kwargs['author_id'] = author_ids[0] kwargs['author_id'] = author_ids[0]
author_id = kwargs.get('author_id')
if author_id is None: # keep False values
author_id = self.pool.get('mail.message')._get_default_author(cr, uid, context=context)
# 1: Handle content subtype: if plaintext, converto into HTML # 1: Handle content subtype: if plaintext, converto into HTML
if content_subtype == 'plaintext': if content_subtype == 'plaintext':
body = tools.plaintext2html(body) body = tools.plaintext2html(body)
# 2: Private message: add recipients (recipients and author of parent message) # 2: Private message: add recipients (recipients and author of parent message) - current author
# + legacy-code management (! we manage only 4 and 6 commands) # + legacy-code management (! we manage only 4 and 6 commands)
partner_ids = set() partner_ids = set()
kwargs_partner_ids = kwargs.pop('partner_ids', []) kwargs_partner_ids = kwargs.pop('partner_ids', [])
@ -974,11 +1032,13 @@ class mail_thread(osv.AbstractModel):
partner_ids.add(partner_id) partner_ids.add(partner_id)
else: else:
pass # we do not manage anything else pass # we do not manage anything else
if parent_id and model == 'mail.thread': if parent_id and not model:
parent_message = mail_message.browse(cr, uid, parent_id, context=context) parent_message = mail_message.browse(cr, uid, parent_id, context=context)
partner_ids |= set([partner.id for partner in parent_message.partner_ids]) private_followers = set([partner.id for partner in parent_message.partner_ids])
if parent_message.author_id: if parent_message.author_id:
partner_ids.add(parent_message.author_id.id) private_followers.add(parent_message.author_id.id)
private_followers -= set([author_id])
partner_ids |= private_followers
# 3. Attachments # 3. Attachments
# - HACK TDE FIXME: Chatter: attachments linked to the document (not done JS-side), load the message # - HACK TDE FIXME: Chatter: attachments linked to the document (not done JS-side), load the message
@ -1039,6 +1099,7 @@ class mail_thread(osv.AbstractModel):
values = kwargs values = kwargs
values.update({ values.update({
'author_id': author_id,
'model': model, 'model': model,
'res_id': thread_id or False, 'res_id': thread_id or False,
'body': body, 'body': body,

View File

@ -568,7 +568,6 @@
text-shadow: none; text-shadow: none;
width: 100%; width: 100%;
} }
.openerp .oe_followers button.oe_invite,
.openerp .oe_followers button.oe_follower.oe_following{ .openerp .oe_followers button.oe_follower.oe_following{
color: white; color: white;
background-color: #3465A4; background-color: #3465A4;
@ -626,6 +625,8 @@
height: 32px; height: 32px;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis;
margin-right: 10px;
} }
.openerp .oe_followers .oe_partner img{ .openerp .oe_followers .oe_partner img{
width: 32px; width: 32px;

View File

@ -14,6 +14,10 @@
padding: 0px 18px; padding: 0px 18px;
} }
.openerp .oe_form_sheetbg.openerp_mail_group_sheet .oe_avatar {
padding-top: 3px;
}
/* Resize footer width */ /* Resize footer width */
.openerp .oe_form div.oe_mail_group_footer { .openerp .oe_form div.oe_mail_group_footer {
max-width: 80%; max-width: 80%;
@ -21,7 +25,7 @@
/* Resize group description */ /* Resize group description */
.openerp .oe_form_sheetbg.openerp_mail_group_sheet .oe_form_field_text > textarea { .openerp .oe_form_sheetbg.openerp_mail_group_sheet .oe_form_field_text > textarea {
height: 40px; height: 60px;
} }
/* ------------------------------ */ /* ------------------------------ */

View File

@ -1208,7 +1208,7 @@ openerp.mail = function (session) {
this.author_id = datasets.author_id || false; this.author_id = datasets.author_id || false;
this.thread_level = (datasets.thread_level+1) || 0; this.thread_level = (datasets.thread_level+1) || 0;
datasets.partner_ids = datasets.partner_ids || []; datasets.partner_ids = datasets.partner_ids || [];
if (datasets.author_id && ! _.contains(datasets.partner_ids, datasets.author_id) && datasets.author_id[0]) { if (datasets.author_id && !_.contains(_.flatten(datasets.partner_ids),datasets.author_id[0]) && datasets.author_id[0]) {
datasets.partner_ids.push(datasets.author_id); datasets.partner_ids.push(datasets.author_id);
} }
this.partner_ids = datasets.partner_ids; this.partner_ids = datasets.partner_ids;
@ -1389,7 +1389,10 @@ openerp.mail = function (session) {
if (this.options.help) { if (this.options.help) {
no_message.html(this.options.help); no_message.html(this.options.help);
} }
if (!this.$el.find(".oe_view_nocontent").length)
{
no_message.appendTo(this.$el); no_message.appendTo(this.$el);
}
}, },
/** /**

View File

@ -246,7 +246,11 @@
<!-- message itself --> <!-- message itself -->
<div class="oe_msg_content"> <div class="oe_msg_content">
<h1 t-if="(widget.show_record_name or widget.subject) and !widget.thread_level" class="oe_msg_title"> <h1 t-if="(widget.show_record_name or widget.subject) and !widget.thread_level" class="oe_msg_title">
<a t-if="widget.options.show_link and widget.show_record_name" class="oe_mail_action_model" t-attf-href="#model=#{widget.model}&amp;id=#{widget.res_id}"><t t-raw="widget.record_name"/></a><span t-if="!widget.options.show_link and widget.show_record_name"><t t-raw="widget.record_name"/></span><t t-if="widget.show_record_name">: </t> <a t-if="widget.options.show_link and widget.show_record_name" class="oe_mail_action_model" t-attf-href="#model=#{widget.model}&amp;id=#{widget.res_id}">
<t t-raw="widget.record_name"/>
</a>
<span t-if="!widget.options.show_link and widget.show_record_name"><t t-raw="widget.record_name"/></span>
<t t-if="widget.show_record_name and widget.subject">: </t>
<t t-if="widget.subject" t-raw="widget.subject"/> <t t-if="widget.subject" t-raw="widget.subject"/>
</h1> </h1>
<div class="oe_msg_body"> <div class="oe_msg_body">

View File

@ -30,7 +30,7 @@
--> -->
<div t-name="mail.followers.partner" class='oe_partner'> <div t-name="mail.followers.partner" class='oe_partner'>
<img class="oe_mail_thumbnail oe_mail_frame" t-attf-src="{record.avatar_url}"/> <img class="oe_mail_thumbnail oe_mail_frame" t-attf-src="{record.avatar_url}"/>
<a t-attf-href="#model=res.partner&amp;id=#{record.id}"><t t-raw="record.name"/></a> <a t-attf-href="#model=res.partner&amp;id=#{record.id}" t-att-title="record.name"><t t-esc="record.name"/></a>
<span t-if="widget.view_is_editable" class="oe_remove_follower oe_e" title="Remove this follower" t-att-data-id="record.id">X</span> <span t-if="widget.view_is_editable" class="oe_remove_follower oe_e" title="Remove this follower" t-att-data-id="record.id">X</span>
</div> </div>

View File

@ -280,7 +280,8 @@ class test_mail(TestMailBase):
'message_post: mail.mail notifications should have been auto-deleted!') 'message_post: mail.mail notifications should have been auto-deleted!')
# Test: notifications emails: to a and b, c is email only, r is author # Test: notifications emails: to a and b, c is email only, r is author
test_emailto = ['Administrator <a@a>', 'Bert Tartopoils <b@b>'] # test_emailto = ['Administrator <a@a>', 'Bert Tartopoils <b@b>']
test_emailto = ['"Followers of -Pigs-" <a@a>', '"Followers of -Pigs-" <b@b>']
self.assertEqual(len(sent_emails), 2, self.assertEqual(len(sent_emails), 2,
'message_post: notification emails wrong number of send emails') 'message_post: notification emails wrong number of send emails')
self.assertEqual(set([m['email_to'][0] for m in sent_emails]), set(test_emailto), self.assertEqual(set([m['email_to'][0] for m in sent_emails]), set(test_emailto),
@ -353,7 +354,8 @@ class test_mail(TestMailBase):
self.assertFalse(self.mail_mail.search(cr, uid, [('mail_message_id', '=', msg2_id)]), 'mail.mail notifications should have been auto-deleted!') self.assertFalse(self.mail_mail.search(cr, uid, [('mail_message_id', '=', msg2_id)]), 'mail.mail notifications should have been auto-deleted!')
# Test: emails send by server (to a, b, c, d) # Test: emails send by server (to a, b, c, d)
test_emailto = [u'Administrator <a@a>', u'Bert Tartopoils <b@b>', u'Carine Poilvache <c@c>', u'D\xe9d\xe9 Grosbedon <d@d>'] # test_emailto = [u'Administrator <a@a>', u'Bert Tartopoils <b@b>', u'Carine Poilvache <c@c>', u'D\xe9d\xe9 Grosbedon <d@d>']
test_emailto = [u'"Followers of Pigs" <a@a>', u'"Followers of Pigs" <b@b>', u'"Followers of Pigs" <c@c>', u'"Followers of Pigs" <d@d>']
# self.assertEqual(len(sent_emails), 3, 'sent_email number of sent emails incorrect') # self.assertEqual(len(sent_emails), 3, 'sent_email number of sent emails incorrect')
for sent_email in sent_emails: for sent_email in sent_emails:
self.assertEqual(sent_email['email_from'], 'Raoul Grosbedon <r@r>', self.assertEqual(sent_email['email_from'], 'Raoul Grosbedon <r@r>',

View File

@ -116,8 +116,11 @@ class TestMailgateway(TestMailBase):
frog_groups = format_and_process(MAIL_TEMPLATE, to='groups@example.com, other@gmail.com') frog_groups = format_and_process(MAIL_TEMPLATE, to='groups@example.com, other@gmail.com')
sent_emails = self._build_email_kwargs_list sent_emails = self._build_email_kwargs_list
# Test: one group created by mailgateway administrator # Test: one group created by mailgateway administrator
self.assertTrue(len(frog_groups) == 1) self.assertEqual(len(frog_groups), 1, 'message_process: a new mail.group should have been created')
frog_group = self.mail_group.browse(cr, uid, frog_groups[0]) frog_group = self.mail_group.browse(cr, uid, frog_groups[0])
res = self.mail_group.perm_read(cr, uid, [frog_group.id], details=False)
self.assertEqual(res[0].get('create_uid'), uid,
'message_process: group should have been created by uid as alias_user__id is False on the alias')
# Test: one message that is the incoming email # Test: one message that is the incoming email
self.assertEqual(len(frog_group.message_ids), 1, self.assertEqual(len(frog_group.message_ids), 1,
'message_process: newly created group should have the incoming email in message_ids') 'message_process: newly created group should have the incoming email in message_ids')
@ -150,9 +153,12 @@ class TestMailgateway(TestMailBase):
self._init_mock_build_email() self._init_mock_build_email()
frog_groups = format_and_process(MAIL_TEMPLATE, to='groups@example.com, other@gmail.com') frog_groups = format_and_process(MAIL_TEMPLATE, to='groups@example.com, other@gmail.com')
sent_emails = self._build_email_kwargs_list sent_emails = self._build_email_kwargs_list
# Test: one group created by raoul # Test: one group created by Raoul
self.assertTrue(len(frog_groups) == 1) self.assertEqual(len(frog_groups), 1, 'message_process: a new mail.group should have been created')
frog_group = self.mail_group.browse(cr, uid, frog_groups[0]) frog_group = self.mail_group.browse(cr, uid, frog_groups[0])
res = self.mail_group.perm_read(cr, uid, [frog_group.id], details=False)
self.assertEqual(res[0].get('create_uid'), self.user_raoul_id,
'message_process: group should have been created by alias_user_id')
# Test: one message that is the incoming email # Test: one message that is the incoming email
self.assertEqual(len(frog_group.message_ids), 1, self.assertEqual(len(frog_group.message_ids), 1,
'message_process: newly created group should have the incoming email in message_ids') 'message_process: newly created group should have the incoming email in message_ids')
@ -175,8 +181,8 @@ class TestMailgateway(TestMailBase):
# Do: incoming email from a known partner that is also an user that can create a mail.group # Do: incoming email from a known partner that is also an user that can create a mail.group
self.res_users.create(cr, uid, {'partner_id': p1id, 'login': 'sylvie', 'groups_id': [(6, 0, [self.group_employee_id])]}) self.res_users.create(cr, uid, {'partner_id': p1id, 'login': 'sylvie', 'groups_id': [(6, 0, [self.group_employee_id])]})
frog_groups = format_and_process(MAIL_TEMPLATE, to='groups@example.com, other@gmail.com') frog_groups = format_and_process(MAIL_TEMPLATE, to='groups@example.com, other@gmail.com')
# Test: one group created by Sylvie # Test: one group created by Raoul (or Sylvie maybe, if we implement it)
self.assertTrue(len(frog_groups) == 1) self.assertEqual(len(frog_groups), 1, 'message_process: a new mail.group should have been created')
frog_group = self.mail_group.browse(cr, uid, frog_groups[0]) frog_group = self.mail_group.browse(cr, uid, frog_groups[0])
# Test: one message that is the incoming email # Test: one message that is the incoming email
self.assertEqual(len(frog_group.message_ids), 1, self.assertEqual(len(frog_group.message_ids), 1,
@ -195,6 +201,7 @@ class TestMailgateway(TestMailBase):
# Do: even with a wrong destination, a reply should end up in the correct thread # Do: even with a wrong destination, a reply should end up in the correct thread
frog_groups = format_and_process(MAIL_TEMPLATE, email_from='other@gmail.com', frog_groups = format_and_process(MAIL_TEMPLATE, email_from='other@gmail.com',
msg_id='<1198923581.41972151344608186760.JavaMail.diff1@agrolait.com>',
to='erroneous@example.com>', subject='Re: news', to='erroneous@example.com>', subject='Re: news',
extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>\n' % frog_group.id) extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>\n' % frog_group.id)
# Test: no group 'Re: news' created, still only 1 Frogs group # Test: no group 'Re: news' created, still only 1 Frogs group
@ -205,12 +212,30 @@ class TestMailgateway(TestMailBase):
'message_process: reply on Frogs should not have created a duplicate group with old subject') 'message_process: reply on Frogs should not have created a duplicate group with old subject')
frog_group = self.mail_group.browse(cr, uid, frog_groups[0]) frog_group = self.mail_group.browse(cr, uid, frog_groups[0])
# Test: one new message # Test: one new message
self.assertTrue(len(frog_group.message_ids) == 2, 'message_process: group should contain 2 messages after reply') self.assertEqual(len(frog_group.message_ids), 2, 'message_process: group should contain 2 messages after reply')
# Test: author (and not recipient) added as follower # Test: author (and not recipient) added as follower
frog_follower_ids = set([p.id for p in frog_group.message_follower_ids]) frog_follower_ids = set([p.id for p in frog_group.message_follower_ids])
self.assertEqual(frog_follower_ids, set([p1id, p2id]), self.assertEqual(frog_follower_ids, set([p1id, p2id]),
'message_process: after reply, group should have 2 followers') 'message_process: after reply, group should have 2 followers')
# Do: due to some issue, same email goes back into the mailgateway
frog_groups = format_and_process(MAIL_TEMPLATE, email_from='other@gmail.com',
msg_id='<1198923581.41972151344608186760.JavaMail.diff1@agrolait.com>',
subject='Re: news', extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>\n' % frog_group.id)
# Test: no group 'Re: news' created, still only 1 Frogs group
self.assertEqual(len(frog_groups), 0,
'message_process: reply on Frogs should not have created a new group with new subject')
frog_groups = self.mail_group.search(cr, uid, [('name', '=', 'Frogs')])
self.assertEqual(len(frog_groups), 1,
'message_process: reply on Frogs should not have created a duplicate group with old subject')
frog_group = self.mail_group.browse(cr, uid, frog_groups[0])
# Test: no new message
self.assertEqual(len(frog_group.message_ids), 2, 'message_process: message with already existing message_id should not have been duplicated')
# Test: message_id is still unique
msg_ids = self.mail_message.search(cr, uid, [('message_id', 'ilike', '<1198923581.41972151344608186760.JavaMail.diff1@agrolait.com>')])
self.assertEqual(len(msg_ids), 1,
'message_process: message with already existing message_id should not have been duplicated')
# -------------------------------------------------- # --------------------------------------------------
# Test3: email_from and partner finding # Test3: email_from and partner finding
# -------------------------------------------------- # --------------------------------------------------
@ -223,6 +248,7 @@ class TestMailgateway(TestMailBase):
# Do: post a new message, with a known partner -> duplicate emails -> partner # Do: post a new message, with a known partner -> duplicate emails -> partner
format_and_process(MAIL_TEMPLATE, email_from='Lombrik Lubrik <test_raoul@email.com>', format_and_process(MAIL_TEMPLATE, email_from='Lombrik Lubrik <test_raoul@email.com>',
to='erroneous@example.com>', subject='Re: news (2)', to='erroneous@example.com>', subject='Re: news (2)',
msg_id='<1198923581.41972151344608186760.JavaMail.new1@agrolait.com>',
extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>\n' % frog_group.id) extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>\n' % frog_group.id)
frog_groups = self.mail_group.search(cr, uid, [('name', '=', 'Frogs')]) frog_groups = self.mail_group.search(cr, uid, [('name', '=', 'Frogs')])
frog_group = self.mail_group.browse(cr, uid, frog_groups[0]) frog_group = self.mail_group.browse(cr, uid, frog_groups[0])
@ -236,6 +262,7 @@ class TestMailgateway(TestMailBase):
self.res_users.write(cr, uid, self.user_raoul_id, {'email': 'test_raoul@email.com'}) self.res_users.write(cr, uid, self.user_raoul_id, {'email': 'test_raoul@email.com'})
format_and_process(MAIL_TEMPLATE, email_from='Lombrik Lubrik <test_raoul@email.com>', format_and_process(MAIL_TEMPLATE, email_from='Lombrik Lubrik <test_raoul@email.com>',
to='erroneous@example.com>', subject='Re: news (3)', to='erroneous@example.com>', subject='Re: news (3)',
msg_id='<1198923581.41972151344608186760.JavaMail.new2@agrolait.com>',
extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>\n' % frog_group.id) extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>\n' % frog_group.id)
frog_groups = self.mail_group.search(cr, uid, [('name', '=', 'Frogs')]) frog_groups = self.mail_group.search(cr, uid, [('name', '=', 'Frogs')])
frog_group = self.mail_group.browse(cr, uid, frog_groups[0]) frog_group = self.mail_group.browse(cr, uid, frog_groups[0])
@ -250,6 +277,7 @@ class TestMailgateway(TestMailBase):
self.res_users.write(cr, uid, self.user_raoul_id, {'email': 'test_raoul@email.com'}) self.res_users.write(cr, uid, self.user_raoul_id, {'email': 'test_raoul@email.com'})
format_and_process(MAIL_TEMPLATE, email_from='Lombrik Lubrik <test_raoul@email.com>', format_and_process(MAIL_TEMPLATE, email_from='Lombrik Lubrik <test_raoul@email.com>',
to='erroneous@example.com>', subject='Re: news (3)', to='erroneous@example.com>', subject='Re: news (3)',
msg_id='<1198923581.41972151344608186760.JavaMail.new3@agrolait.com>',
extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>\n' % frog_group.id) extra='In-Reply-To: <12321321-openerp-%d-mail.group@example.com>\n' % frog_group.id)
frog_groups = self.mail_group.search(cr, uid, [('name', '=', 'Frogs')]) frog_groups = self.mail_group.search(cr, uid, [('name', '=', 'Frogs')])
frog_group = self.mail_group.browse(cr, uid, frog_groups[0]) frog_group = self.mail_group.browse(cr, uid, frog_groups[0])
@ -266,22 +294,31 @@ class TestMailgateway(TestMailBase):
# Do: incoming email with model that does not accepts incoming emails must raise # Do: incoming email with model that does not accepts incoming emails must raise
self.assertRaises(AssertionError, self.assertRaises(AssertionError,
format_and_process, format_and_process,
MAIL_TEMPLATE, to='noone@example.com', subject='spam', extra='', model='res.country') MAIL_TEMPLATE,
to='noone@example.com', subject='spam', extra='', model='res.country',
msg_id='<1198923581.41972151344608186760.JavaMail.new4@agrolait.com>')
# Do: incoming email without model and without alias must raise # Do: incoming email without model and without alias must raise
self.assertRaises(AssertionError, self.assertRaises(AssertionError,
format_and_process, format_and_process,
MAIL_TEMPLATE, to='noone@example.com', subject='spam', extra='') MAIL_TEMPLATE,
to='noone@example.com', subject='spam', extra='',
msg_id='<1198923581.41972151344608186760.JavaMail.new5@agrolait.com>')
# Do: incoming email with model that accepting incoming emails as fallback # Do: incoming email with model that accepting incoming emails as fallback
frog_groups = format_and_process(MAIL_TEMPLATE, to='noone@example.com', subject='Spammy', extra='', model='mail.group') frog_groups = format_and_process(MAIL_TEMPLATE,
to='noone@example.com',
subject='Spammy', extra='', model='mail.group',
msg_id='<1198923581.41972151344608186760.JavaMail.new6@agrolait.com>')
self.assertEqual(len(frog_groups), 1, self.assertEqual(len(frog_groups), 1,
'message_process: erroneous email but with a fallback model should have created a new mail.group') 'message_process: erroneous email but with a fallback model should have created a new mail.group')
# Do: incoming email in plaintext should be stored as html # Do: incoming email in plaintext should be stored as html
frog_groups = format_and_process(MAIL_TEMPLATE_PLAINTEXT, to='groups@example.com', subject='Frogs Return', extra='', msg_id='<deadcafe.1337@smtp.agrolait.com>') frog_groups = format_and_process(MAIL_TEMPLATE_PLAINTEXT,
to='groups@example.com', subject='Frogs Return', extra='',
msg_id='<deadcafe.1337@smtp.agrolait.com>')
# Test: one group created with one message # Test: one group created with one message
self.assertTrue(len(frog_groups) == 1) self.assertEqual(len(frog_groups), 1, 'message_process: a new mail.group should have been created')
frog_group = self.mail_group.browse(cr, uid, frog_groups[0]) frog_group = self.mail_group.browse(cr, uid, frog_groups[0])
msg = frog_group.message_ids[0] msg = frog_group.message_ids[0]
# Test: plain text content should be wrapped and stored as html # Test: plain text content should be wrapped and stored as html
@ -305,19 +342,27 @@ class TestMailgateway(TestMailBase):
# Reply to msg1, make sure the reply is properly attached using the various reply identification mechanisms # Reply to msg1, make sure the reply is properly attached using the various reply identification mechanisms
# 0. Direct alias match # 0. Direct alias match
reply_msg1 = format(MAIL_TEMPLATE, to='Pretty Pigs <group+pigs@example.com>', extra='In-Reply-To: %s' % msg1.message_id) reply_msg1 = format(MAIL_TEMPLATE, to='Pretty Pigs <group+pigs@example.com>',
extra='In-Reply-To: %s' % msg1.message_id,
msg_id='<1198923581.41972151344608186760.JavaMail.2@agrolait.com>')
self.mail_group.message_process(cr, uid, None, reply_msg1) self.mail_group.message_process(cr, uid, None, reply_msg1)
# 1. In-Reply-To header # 1. In-Reply-To header
reply_msg2 = format(MAIL_TEMPLATE, to='erroneous@example.com', extra='In-Reply-To: %s' % msg1.message_id) reply_msg2 = format(MAIL_TEMPLATE, to='erroneous@example.com',
extra='In-Reply-To: %s' % msg1.message_id,
msg_id='<1198923581.41972151344608186760.JavaMail.3@agrolait.com>')
self.mail_group.message_process(cr, uid, None, reply_msg2) self.mail_group.message_process(cr, uid, None, reply_msg2)
# 2. References header # 2. References header
reply_msg3 = format(MAIL_TEMPLATE, to='erroneous@example.com', extra='References: <2233@a.com>\r\n\t<3edss_dsa@b.com> %s' % msg1.message_id) reply_msg3 = format(MAIL_TEMPLATE, to='erroneous@example.com',
extra='References: <2233@a.com>\r\n\t<3edss_dsa@b.com> %s' % msg1.message_id,
msg_id='<1198923581.41972151344608186760.JavaMail.4@agrolait.com>')
self.mail_group.message_process(cr, uid, None, reply_msg3) self.mail_group.message_process(cr, uid, None, reply_msg3)
# 3. Subject contains [<ID>] + model passed to message+process -> only attached to group, but not to mail (not in msg1.child_ids) # 3. Subject contains [<ID>] + model passed to message+process -> only attached to group, but not to mail (not in msg1.child_ids)
reply_msg4 = format(MAIL_TEMPLATE, to='erroneous@example.com', extra='', subject='Re: [%s] 1' % self.group_pigs_id) reply_msg4 = format(MAIL_TEMPLATE, to='erroneous@example.com',
extra='', subject='Re: [%s] 1' % self.group_pigs_id,
msg_id='<1198923581.41972151344608186760.JavaMail.5@agrolait.com>')
self.mail_group.message_process(cr, uid, 'mail.group', reply_msg4) self.mail_group.message_process(cr, uid, 'mail.group', reply_msg4)
group_pigs.refresh() group_pigs.refresh()
@ -327,4 +372,55 @@ class TestMailgateway(TestMailBase):
def test_20_private_discussion(self): def test_20_private_discussion(self):
""" Testing private discussion between partners. """ """ Testing private discussion between partners. """
pass cr, uid = self.cr, self.uid
# Do: Raoul writes to Bert and Administrator, with a thread_model in context that should not be taken into account
msg1_pids = [self.partner_admin_id, self.partner_bert_id]
msg1_id = self.mail_thread.message_post(cr, self.user_raoul_id, False,
partner_ids=msg1_pids,
subtype='mail.mt_comment',
context={'thread_model': 'mail.group'})
# Test: message recipients
msg = self.mail_message.browse(cr, uid, msg1_id)
msg_pids = [p.id for p in msg.partner_ids]
msg_nids = [p.id for p in msg.notified_partner_ids]
test_pids = msg1_pids
test_nids = msg1_pids
self.assertEqual(set(msg_pids), set(test_pids),
'message_post: private discussion: incorrect recipients')
self.assertEqual(set(msg_nids), set(test_nids),
'message_post: private discussion: incorrect notified recipients')
self.assertEqual(msg.model, False,
'message_post: private discussion: context key "thread_model" not correctly ignored when having no res_id')
# Do: Bert replies through mailgateway (is a customer)
msg2_id = self.mail_thread.message_post(cr, uid, False,
author_id=self.partner_bert_id,
parent_id=msg1_id, subtype='mail.mt_comment')
# Test: message recipients
msg = self.mail_message.browse(cr, uid, msg2_id)
msg_pids = [p.id for p in msg.partner_ids]
msg_nids = [p.id for p in msg.notified_partner_ids]
test_pids = [self.partner_admin_id, self.partner_raoul_id]
test_nids = test_pids
self.assertEqual(set(msg_pids), set(test_pids),
'message_post: private discussion: incorrect recipients when replying')
self.assertEqual(set(msg_nids), set(test_nids),
'message_post: private discussion: incorrect notified recipients when replying')
# Do: Administrator replies
msg3_id = self.mail_thread.message_post(cr, uid, False,
parent_id=msg2_id, subtype='mail.mt_comment')
# Test: message recipients
msg = self.mail_message.browse(cr, uid, msg3_id)
msg_pids = [p.id for p in msg.partner_ids]
msg_nids = [p.id for p in msg.notified_partner_ids]
test_pids = [self.partner_bert_id, self.partner_raoul_id]
test_nids = test_pids
self.assertEqual(set(msg_pids), set(test_pids),
'message_post: private discussion: incorrect recipients when replying')
self.assertEqual(set(msg_nids), set(test_nids),
'message_post: private discussion: incorrect notified recipients when replying')

View File

@ -175,11 +175,17 @@ class mail_compose_message(osv.TransientModel):
:param int res_id: id of the document record this mail is related to :param int res_id: id of the document record this mail is related to
""" """
doc_name_get = self.pool.get(model).name_get(cr, uid, [res_id], context=context) doc_name_get = self.pool.get(model).name_get(cr, uid, [res_id], context=context)
record_name = False
if doc_name_get: if doc_name_get:
record_name = doc_name_get[0][1] record_name = doc_name_get[0][1]
else: values = {
record_name = False 'model': model,
return {'model': model, 'res_id': res_id, 'record_name': record_name} 'res_id': res_id,
'record_name': record_name,
}
if record_name:
values['subject'] = 'Re: %s' % record_name
return values
def get_message_data(self, cr, uid, message_id, context=None): def get_message_data(self, cr, uid, message_id, context=None):
""" Returns a defaults-like dict with initial values for the composition """ Returns a defaults-like dict with initial values for the composition
@ -197,7 +203,7 @@ class mail_compose_message(osv.TransientModel):
# create subject # create subject
re_prefix = _('Re:') re_prefix = _('Re:')
reply_subject = tools.ustr(message_data.subject or '') reply_subject = tools.ustr(message_data.subject or message_data.record_name or '')
if not (reply_subject.startswith('Re:') or reply_subject.startswith(re_prefix)) and message_data.subject: if not (reply_subject.startswith('Re:') or reply_subject.startswith(re_prefix)) and message_data.subject:
reply_subject = "%s %s" % (re_prefix, reply_subject) reply_subject = "%s %s" % (re_prefix, reply_subject)
# get partner_ids from original message # get partner_ids from original message

View File

@ -45,7 +45,7 @@ class StockMove(osv.osv):
procurement_obj = self.pool.get('procurement.order') procurement_obj = self.pool.get('procurement.order')
product_obj = self.pool.get('product.product') product_obj = self.pool.get('product.product')
processed_ids = [move.id] processed_ids = [move.id]
if move.product_id.supply_method == 'produce' and move.product_id.procure_method == 'make_to_order': if move.product_id.supply_method == 'produce':
bis = bom_obj.search(cr, uid, [ bis = bom_obj.search(cr, uid, [
('product_id','=',move.product_id.id), ('product_id','=',move.product_id.id),
('bom_id','=',False), ('bom_id','=',False),

View File

@ -4,7 +4,8 @@ Created on 18 oct. 2011
@author: openerp @author: openerp
''' '''
from openerp.osv import fields, osv from openerp.osv import osv
from openerp.tools.translate import _
class plugin_handler(osv.osv_memory): class plugin_handler(osv.osv_memory):
_name = 'plugin.handler' _name = 'plugin.handler'
@ -95,17 +96,16 @@ class plugin_handler(osv.osv_memory):
msg = self.pool.get('mail.thread').message_parse(cr, uid, email) msg = self.pool.get('mail.thread').message_parse(cr, uid, email)
message_id = msg.get('message-id') message_id = msg.get('message-id')
mail_ids = mail_message.search(cr, uid, [('message_id', '=', message_id), ('res_id', '=', res_id), ('model', '=', model)]) mail_ids = mail_message.search(cr, uid, [('message_id', '=', message_id), ('res_id', '=', res_id), ('model', '=', model)])
if message_id and mail_ids: if message_id and mail_ids:
mail_record = mail_message.browse(cr, uid, mail_ids)[0] mail_record = mail_message.browse(cr, uid, mail_ids)[0]
res_id = mail_record.res_id res_id = mail_record.res_id
notify = "Email already pushed" notify = _("Email already pushed")
elif res_id == 0: elif res_id == 0:
if model == 'res.partner': if model == 'res.partner':
notify = 'User the Partner button to create a new partner' notify = _('Use the Partner button to create a new partner')
else: else:
res_id = model_obj.message_process(cr, uid, model, email) res_id = model_obj.message_process(cr, uid, model, email)
notify = "Mail successfully pushed, a new %s has been created " % model notify = _("Mail successfully pushed, a new %s has been created.") % model
else: else:
model_obj.message_post(cr, uid, [res_id], model_obj.message_post(cr, uid, [res_id],
body=msg.get('body'), body=msg.get('body'),
@ -113,7 +113,7 @@ class plugin_handler(osv.osv_memory):
type='email', type='email',
parent_id=msg.get('parent_id'), parent_id=msg.get('parent_id'),
attachments=msg.get('attachments')) attachments=msg.get('attachments'))
notify = "Mail successfully pushed" notify = _("Mail successfully pushed")
url = self._make_url(cr, uid, res_id, model) url = self._make_url(cr, uid, res_id, model)
return (model, res_id, url, notify) return (model, res_id, url, notify)
@ -155,6 +155,7 @@ class plugin_handler(osv.osv_memory):
push_mail = self.push_message(cr, uid, model, headers, res_id) push_mail = self.push_message(cr, uid, model, headers, res_id)
res_id = push_mail[1] res_id = push_mail[1]
model = push_mail[0] model = push_mail[0]
notify = push_mail[3]
for name in attachments.keys(): for name in attachments.keys():
attachment_ids = ir_attachment_obj.search(cr, uid, [('res_model', '=', model), ('res_id', '=', res_id), ('datas_fname', '=', name)]) attachment_ids = ir_attachment_obj.search(cr, uid, [('res_model', '=', model), ('res_id', '=', res_id), ('datas_fname', '=', name)])
if attachment_ids: if attachment_ids:
@ -164,6 +165,6 @@ class plugin_handler(osv.osv_memory):
attach_ids.append(ir_attachment_obj.create(cr, uid, vals)) attach_ids.append(ir_attachment_obj.create(cr, uid, vals))
mail_ids = mail_message.search(cr, uid, [('message_id', '=', message_id), ('res_id', '=', res_id), ('model', '=', model)]) mail_ids = mail_message.search(cr, uid, [('message_id', '=', message_id), ('res_id', '=', res_id), ('model', '=', model)])
if mail_ids: if mail_ids:
ids = mail_message.write(cr, uid, mail_ids[0], { 'attachment_ids': [(6, 0, attach_ids)],'body':body,'body_html':body_html}) mail_message.write(cr, uid, mail_ids[0], {'attachment_ids': [(6, 0, attach_ids)], 'body': body, 'body_html': body_html})
url = self._make_url(cr, uid, res_id, model) url = self._make_url(cr, uid, res_id, model)
return (model, res_id, url) return (model, res_id, url, notify)

View File

@ -17,6 +17,7 @@
<UpgradeBackupLocation> <UpgradeBackupLocation>
</UpgradeBackupLocation> </UpgradeBackupLocation>
<OldToolsVersion>3.5</OldToolsVersion> <OldToolsVersion>3.5</OldToolsVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<PublishUrl>publish\</PublishUrl> <PublishUrl>publish\</PublishUrl>
<Install>true</Install> <Install>true</Install>
<InstallFrom>Disk</InstallFrom> <InstallFrom>Disk</InstallFrom>
@ -29,7 +30,6 @@
<MapFileExtensions>true</MapFileExtensions> <MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision> <ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion> <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust> <UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled> <BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup> </PropertyGroup>
@ -53,9 +53,8 @@
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="CookComputing.XmlRpcV2, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="CookComputing.XmlRpcV2">
<SpecificVersion>False</SpecificVersion> <HintPath>..\CookComputing.XmlRpcV2.dll</HintPath>
<HintPath>..\OpenERPOutlookPlugin\bin\Release\CookComputing.XmlRpcV2.dll</HintPath>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core"> <Reference Include="System.Core">
@ -81,7 +80,7 @@
<ItemGroup> <ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5"> <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible> <Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName> <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install> <Install>false</Install>
</BootstrapperPackage> </BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1"> <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
@ -91,7 +90,7 @@
</BootstrapperPackage> </BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1"> <BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible> <Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName> <ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install> <Install>true</Install>
</BootstrapperPackage> </BootstrapperPackage>
</ItemGroup> </ItemGroup>

View File

@ -1,6 +1,6 @@
 
Microsoft Visual Studio Solution File, Format Version 10.00 Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2008 # Visual Studio 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenERPOutlookPlugin", "OpenERPOutlookPlugin\OpenERPOutlookPlugin.csproj", "{F4B2219B-F235-400F-81B4-92F15250BBA4}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenERPOutlookPlugin", "OpenERPOutlookPlugin\OpenERPOutlookPlugin.csproj", "{F4B2219B-F235-400F-81B4-92F15250BBA4}"
EndProject EndProject
Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "OpenERPOutlookPluginSetup", "OpenERPOutlookPluginSetup\OpenERPOutlookPluginSetup.vdproj", "{96333293-0156-4998-9065-42721CEB0368}" Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "OpenERPOutlookPluginSetup", "OpenERPOutlookPluginSetup\OpenERPOutlookPluginSetup.vdproj", "{96333293-0156-4998-9065-42721CEB0368}"

View File

@ -304,6 +304,7 @@ namespace OpenERPOutlookPlugin
foreach (outlook.MailItem mailitem in Tools.MailItems()) foreach (outlook.MailItem mailitem in Tools.MailItems())
{ {
Object[] contact = Cache.OpenERPOutlookPlugin.RedirectPartnerPage(mailitem); Object[] contact = Cache.OpenERPOutlookPlugin.RedirectPartnerPage(mailitem);
if ((int)contact[1] > 0) if ((int)contact[1] > 0)
{ {

View File

@ -95,7 +95,6 @@ namespace OpenERPOutlookPlugin
/* /*
* Will open the url into the web browser. * Will open the url into the web browser.
*/ */
System.Diagnostics.Process.Start(web_url.ToString()); System.Diagnostics.Process.Start(web_url.ToString());
} }
@ -163,10 +162,17 @@ namespace OpenERPOutlookPlugin
args.Add(attachments); args.Add(attachments);
object push_mail = this.Connection.Execute("plugin.handler", "push_message_outlook", args.ToArray()); object push_mail = this.Connection.Execute("plugin.handler", "push_message_outlook", args.ToArray());
object[] push = (object[])push_mail; object[] push = (object[])push_mail;
this.RedirectWeb(push[2].ToString()); if (Convert.ToInt32(push[1]) == 0)
return true; {
MessageBox.Show(push[3].ToString());
} }
else
{
this.RedirectWeb(push[2].ToString());
}
return true;
}
public long CreatePartnerRecord(string name) public long CreatePartnerRecord(string name)
{ {
/* /*

View File

@ -295,7 +295,8 @@ function openerp_pos_models(instance, module){ //module is instance.point_of_sal
return; return;
} }
//try to push an order to the server //try to push an order to the server
(new instance.web.Model('pos.order')).get_func('create_from_ui')([order]) // shadow : true is to prevent a spinner to appear in case of timeout
(new instance.web.Model('pos.order')).call('create_from_ui',[[order]],undefined,{ shadow:true })
.fail(function(unused, event){ .fail(function(unused, event){
//don't show error popup if it fails //don't show error popup if it fails
event.preventDefault(); event.preventDefault();

View File

@ -794,7 +794,7 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
renderElement: function() { renderElement: function() {
var self = this; var self = this;
this._super(); this._super();
this.$('.oe_pos_synch-notification-button').click(function(){ this.$el.click(function(){
self.pos.flush(); self.pos.flush();
}); });
}, },
@ -879,6 +879,8 @@ function openerp_pos_widgets(instance, module){ //module is instance.point_of_sa
instance.web.unblockUI(); instance.web.unblockUI();
self.$('.loader').animate({opacity:0},1500,'swing',function(){self.$('.loader').hide();}); self.$('.loader').animate({opacity:0},1500,'swing',function(){self.$('.loader').hide();});
self.pos.flush();
}).fail(function(){ // error when loading models data from the backend }).fail(function(){ // error when loading models data from the backend
instance.web.unblockUI(); instance.web.unblockUI();
return new instance.web.Model("ir.model.data").get_func("search_read")([['name', '=', 'action_pos_session_opening']], ['res_id']) return new instance.web.Model("ir.model.data").get_func("search_read")([['name', '=', 'action_pos_session_opening']], ['res_id'])

View File

@ -21,7 +21,6 @@
<field name="params" eval="&quot;{ <field name="params" eval="&quot;{
'domain': [ 'domain': [
('to_read', '=', True), ('to_read', '=', True),
('starred', '=', False),
], ],
'show_compose_message': False, 'show_compose_message': False,
'show_link': False, 'show_link': False,
@ -40,6 +39,7 @@
</field> </field>
</record> </record>
<!-- TODO: remove me in 8.0 -->
<record id="action_mail_star_feeds_portal" model="ir.actions.client"> <record id="action_mail_star_feeds_portal" model="ir.actions.client">
<field name="name">To-do</field> <field name="name">To-do</field>
<field name="tag">mail.wall</field> <field name="tag">mail.wall</field>
@ -67,6 +67,9 @@
</p> </p>
</field> </field>
</record> </record>
<menuitem name="To-do" id="portal_mail_starfeeds" parent="portal_messages"
action="action_mail_star_feeds_portal" sequence="20" groups="base.group_no_one"/>
<!-- end -->
<record id="action_mail_archives_feeds_portal" model="ir.actions.client"> <record id="action_mail_archives_feeds_portal" model="ir.actions.client">
<field name="name">Archives</field> <field name="name">Archives</field>
@ -84,7 +87,6 @@
'show_compose_message': False, 'show_compose_message': False,
'show_link': False, 'show_link': False,
'view_mailbox': True, 'view_mailbox': True,
'read_action': 'read'
}&quot;"/> }&quot;"/>
<field name="help" type="html"> <field name="help" type="html">
<p> <p>
@ -98,8 +100,6 @@
<menuitem name="Inbox" id="portal_inbox" parent="portal_messages" <menuitem name="Inbox" id="portal_inbox" parent="portal_messages"
action="action_mail_inbox_feeds_portal" sequence="10" groups="portal.group_portal"/> action="action_mail_inbox_feeds_portal" sequence="10" groups="portal.group_portal"/>
<menuitem name="To-do" id="portal_mail_starfeeds" parent="portal_messages"
action="action_mail_star_feeds_portal" sequence="20" groups="portal.group_portal"/>
<menuitem name="Archives" id="portal_mail_archivesfeeds" parent="portal_messages" <menuitem name="Archives" id="portal_mail_archivesfeeds" parent="portal_messages"
action="action_mail_archives_feeds_portal" sequence="30" groups="portal.group_portal"/> action="action_mail_archives_feeds_portal" sequence="30" groups="portal.group_portal"/>
@ -107,7 +107,7 @@
Create menu items that we'll leave empty for now - they'll be Create menu items that we'll leave empty for now - they'll be
filled up by other portal modules. filled up by other portal modules.
--> -->
<menuitem name="Quotations and Sales Orders" id="portal_orders" parent="portal_menu" sequence="20"/> <menuitem name="Billing" id="portal_orders" parent="portal_menu" sequence="20"/>
<menuitem name="After Sale Services" id="portal_after_sales" parent="portal_menu" sequence="30"/> <menuitem name="After Sale Services" id="portal_after_sales" parent="portal_menu" sequence="30"/>
<menuitem name="Projects" id="portal_projects" parent="portal_menu" sequence="40"/> <menuitem name="Projects" id="portal_projects" parent="portal_menu" sequence="40"/>

View File

@ -59,19 +59,8 @@ class sale_order(osv.Model):
assert len(ids) == 1 assert len(ids) == 1
document = self.browse(cr, uid, ids[0], context=context) document = self.browse(cr, uid, ids[0], context=context)
partner = document.partner_id partner = document.partner_id
# TDE note: this code should be improved: used a real invite wizard instead of an ugly email
if partner.id not in document.message_follower_ids: if partner.id not in document.message_follower_ids:
self.message_subscribe(cr, uid, ids, [partner.id], context=context) self.message_subscribe(cr, uid, ids, [partner.id], context=context)
mail_values = {
'recipient_ids': [(4, partner.id)],
'subject': 'Invitation to follow %s' % document.name_get()[0][1],
'body_html': 'You have been invited to follow %s' % document.name_get()[0][1],
'auto_delete': True,
'type': 'email',
}
mail_obj = self.pool.get('mail.mail')
mail_id = mail_obj.create(cr, uid, mail_values, context=context)
mail_obj.send(cr, uid, [mail_id], context=context)
return super(sale_order, self).action_button_confirm(cr, uid, ids, context=context) return super(sale_order, self).action_button_confirm(cr, uid, ids, context=context)
def get_signup_url(self, cr, uid, ids, context=None): def get_signup_url(self, cr, uid, ids, context=None):

View File

@ -374,7 +374,7 @@ class product_pricelist_item(osv.osv):
result.append((line.id, line.name)) result.append((line.id, line.name))
result.append((-1, _('Other Pricelist'))) result.append((-1, _('Other Pricelist')))
result.append((-2, _('Partner section of the product form'))) result.append((-2, _('Supplier Prices on the product form')))
return result return result
_name = "product.pricelist.item" _name = "product.pricelist.item"

View File

@ -590,8 +590,11 @@ class product_product(osv.osv):
if not other_product_ids: if not other_product_ids:
unlink_product_tmpl_ids.append(tmpl_id) unlink_product_tmpl_ids.append(tmpl_id)
unlink_ids.append(product.id) unlink_ids.append(product.id)
res = super(product_product, self).unlink(cr, uid, unlink_ids, context=context)
# delete templates after calling super, as deleting template could lead to deleting
# products due to ondelete='cascade'
self.pool.get('product.template').unlink(cr, uid, unlink_product_tmpl_ids, context=context) self.pool.get('product.template').unlink(cr, uid, unlink_product_tmpl_ids, context=context)
return super(product_product, self).unlink(cr, uid, unlink_ids, context=context) return res
def onchange_uom(self, cursor, user, ids, uom_id, uom_po_id): def onchange_uom(self, cursor, user, ids, uom_id, uom_po_id):
if uom_id and uom_po_id: if uom_id and uom_po_id:

View File

@ -581,6 +581,7 @@
<field name="delay"/> <field name="delay"/>
<field name="company_id" groups="base.group_multi_company" widget="selection"/> <field name="company_id" groups="base.group_multi_company" widget="selection"/>
</group> </group>
<p groups="product.group_purchase_pricelist" class="oe_grey">The prices below will only be taken into account when your pricelist is set as based on supplier prices.</p>
<field groups="product.group_purchase_pricelist" name="pricelist_ids"> <field groups="product.group_purchase_pricelist" name="pricelist_ids">
<tree editable="bottom" string="Pricelist"> <tree editable="bottom" string="Pricelist">
<field name="min_quantity"/> <field name="min_quantity"/>

View File

@ -286,7 +286,6 @@ class project(osv.osv):
'type_ids': _get_type_common, 'type_ids': _get_type_common,
'alias_model': 'project.task', 'alias_model': 'project.task',
'privacy_visibility': 'public', 'privacy_visibility': 'public',
'alias_domain': False, # always hide alias during creation
} }
# TODO: Why not using a SQL contraints ? # TODO: Why not using a SQL contraints ?
@ -531,11 +530,11 @@ def Project():
context = dict(context, project_creation_in_progress=True) context = dict(context, project_creation_in_progress=True)
mail_alias = self.pool.get('mail.alias') mail_alias = self.pool.get('mail.alias')
if not vals.get('alias_id') and vals.get('name', False): if not vals.get('alias_id') and vals.get('name', False):
vals.pop('alias_name', None) # prevent errors during copy() alias_name = vals.pop('alias_name', None) # prevent errors during copy()
alias_id = mail_alias.create_unique_alias(cr, uid, alias_id = mail_alias.create_unique_alias(cr, uid,
# Using '+' allows using subaddressing for those who don't # Using '+' allows using subaddressing for those who don't
# have a catchall domain setup. # have a catchall domain setup.
{'alias_name': "project+"+short_name(vals['name'])}, {'alias_name': alias_name or "project+"+short_name(vals['name'])},
model_name=vals.get('alias_model', 'project.task'), model_name=vals.get('alias_model', 'project.task'),
context=context) context=context)
vals['alias_id'] = alias_id vals['alias_id'] = alias_id
@ -605,8 +604,7 @@ class task(base_stage, osv.osv):
search_domain = [] search_domain = []
project_id = self._resolve_project_id_from_context(cr, uid, context=context) project_id = self._resolve_project_id_from_context(cr, uid, context=context)
if project_id: if project_id:
search_domain += ['|', ('project_ids', '=', project_id)] search_domain += [('project_ids', '=', project_id)]
search_domain += [('id', 'in', ids)]
stage_ids = stage_obj._search(cr, uid, search_domain, order=order, access_rights_uid=access_rights_uid, context=context) stage_ids = stage_obj._search(cr, uid, search_domain, order=order, access_rights_uid=access_rights_uid, context=context)
result = stage_obj.name_get(cr, access_rights_uid, stage_ids, context=context) result = stage_obj.name_get(cr, access_rights_uid, stage_ids, context=context)
# restore order of the search # restore order of the search
@ -889,6 +887,12 @@ class task(base_stage, osv.osv):
res['fields'][f]['string'] = res['fields'][f]['string'].replace('Hours',tm) res['fields'][f]['string'] = res['fields'][f]['string'].replace('Hours',tm)
return res return res
def get_empty_list_help(self, cr, uid, help, context=None):
context['empty_list_help_id'] = context.get('default_project_id')
context['empty_list_help_model'] = 'project.project'
context['empty_list_help_document_name'] = _("tasks")
return super(task, self).get_empty_list_help(cr, uid, help, context=context)
# ---------------------------------------- # ----------------------------------------
# Case management # Case management
# ---------------------------------------- # ----------------------------------------

View File

@ -21,6 +21,7 @@
<record id="all_projects_account" model="account.analytic.account"> <record id="all_projects_account" model="account.analytic.account">
<field name="name">Projects</field> <field name="name">Projects</field>
<field name="code">3</field> <field name="code">3</field>
<field name="type">view</field>
</record> </record>
<function id="parent_project_default_set" model="ir.values" name="set" eval="('default',False,'parent_id', [('project.project', False)], all_projects_account, True, False, False, False, True)"/> <function id="parent_project_default_set" model="ir.values" name="set" eval="('default',False,'parent_id', [('project.project', False)], all_projects_account, True, False, False, False, True)"/>

Some files were not shown because too many files have changed in this diff Show More