diff options
| author | mra (Open ERP) <mra@tinyerp.com> | 2010-06-03 13:54:29 +0530 |
|---|---|---|
| committer | mra (Open ERP) <mra@tinyerp.com> | 2010-06-03 13:54:29 +0530 |
| commit | 7d239dc01d9b986ebd311ff5bdfdcb72ec02fb07 (patch) | |
| tree | 4eafee22b0e9da13efcb4e449ab83d73f4f2f13e /addons | |
| parent | 10c2d3a2181f37f2cfb4c5bdc65c03bb18c2529e (diff) | |
| parent | a4d86b14fe06532324e3bb1556480d8703083e3c (diff) | |
[MERGE]
bzr revid: mra@tinyerp.com-20100602105812-7odoaq66n7m1f0kk
bzr revid: mra@tinyerp.com-20100603032341-0euqt6n9h7303ta2
bzr revid: mra@tinyerp.com-20100603082429-8dwpjz5hdag161dq
Diffstat (limited to 'addons')
77 files changed, 3935 insertions, 764 deletions
diff --git a/addons/account/i18n/nl_BE.po b/addons/account/i18n/nl_BE.po index f298c31854d..5df4bb0be72 100644 --- a/addons/account/i18n/nl_BE.po +++ b/addons/account/i18n/nl_BE.po @@ -7,30 +7,30 @@ msgstr "" "Project-Id-Version: OpenERP Server 5.0.0\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2009-08-28 16:01+0000\n" -"PO-Revision-Date: 2009-04-24 15:00+0000\n" -"Last-Translator: Fabien (Open ERP) <fp@tinyerp.com>\n" +"PO-Revision-Date: 2010-06-02 08:19+0000\n" +"Last-Translator: jan@synkronized.be <Unknown>\n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2010-04-17 04:08+0000\n" +"X-Launchpad-Export-Date: 2010-06-03 03:33+0000\n" "X-Generator: Launchpad (build Unknown)\n" #. module: account #: field:account.tax.template,description:0 msgid "Internal Name" -msgstr "" +msgstr "Interne naam" #. module: account #: view:account.tax.code:0 msgid "Account Tax Code" -msgstr "" +msgstr "Belasting code" #. module: account #: model:ir.actions.act_window,name:account.action_invoice_tree9 #: model:ir.ui.menu,name:account.menu_action_invoice_tree9 msgid "Unpaid Supplier Invoices" -msgstr "" +msgstr "Onbetaalde inkoopfacturen" #. module: account #: model:ir.ui.menu,name:account.menu_finance_entries @@ -50,12 +50,12 @@ msgstr "" #. module: account #: model:account.account.type,name:account.account_type_asset msgid "Asset" -msgstr "" +msgstr "Activa" #. module: account #: constraint:ir.actions.act_window:0 msgid "Invalid model name in the action definition." -msgstr "" +msgstr "Ongeldige modelnaam in de actie-definitie." #. module: account #: help:account.journal,currency:0 @@ -65,7 +65,7 @@ msgstr "" #. module: account #: wizard_view:account_use_models,init_form:0 msgid "Select Message" -msgstr "" +msgstr "Kies bericht" #. module: account #: help:product.category,property_account_income_categ:0 @@ -82,19 +82,19 @@ msgstr "" #. module: account #: wizard_view:account.automatic.reconcile,reconcile:0 msgid "Reconciliation result" -msgstr "" +msgstr "Afletterresultaat" #. module: account #: model:ir.actions.act_window,name:account.act_account_acount_move_line_open_unreconciled msgid "Unreconciled entries" -msgstr "" +msgstr "Niet afgeletterde boekingen" #. module: account #: field:account.invoice.tax,base_code_id:0 #: field:account.tax,base_code_id:0 #: field:account.tax.template,base_code_id:0 msgid "Base Code" -msgstr "" +msgstr "Basiscode" #. module: account #: view:account.account:0 @@ -2132,7 +2132,8 @@ msgid "Analytic Entry" msgstr "" #. module: account -#: view:res.company:0 field:res.company,overdue_msg:0 +#: view:res.company:0 +#: field:res.company,overdue_msg:0 msgid "Overdue Payments Message" msgstr "" diff --git a/addons/account/report/account_balance.py b/addons/account/report/account_balance.py index e4731e2c994..78683b5120b 100644 --- a/addons/account/report/account_balance.py +++ b/addons/account/report/account_balance.py @@ -22,9 +22,15 @@ import xml import copy from operator import itemgetter -import time import datetime from report import report_sxw +import xml.dom.minidom +import os, time +import osv +import re +import tools +import pooler +import sys class account_balance(report_sxw.rml_parse): _name = 'report.account.account.balance' @@ -44,6 +50,10 @@ class account_balance(report_sxw.rml_parse): }) self.context = context + def _add_header(self, node, header=1): + if header==0: + self.rml_header = "" + return True def get_fiscalyear(self, form): res=[] if form.has_key('fiscalyear'): @@ -56,16 +66,14 @@ class account_balance(report_sxw.rml_parse): def get_periods(self, form): result='' - if form.has_key('periods') and form['periods'][0][2]: - period_ids = form['periods'][0][2] - self.cr.execute("select name from account_period where id =ANY(%s)" ,(period_ids)) - res = self.cr.fetchall() - len_res = len(res) - for r in res: - if (r == res[len_res-1]): - result+=r[0]+". " + if form.has_key('periods') and form['periods']: + period_ids = form['periods'] + per_ids = self.pool.get('account.period').browse(self.cr,self.uid,form['periods']) + for r in per_ids: + if r == per_ids[len(per_ids)-1]: + result+=r.name+". " else: - result+=r[0]+", " + result+=r.name+", " else: fy_obj = self.pool.get('account.fiscalyear').browse(self.cr,self.uid,form['fiscalyear']) res = fy_obj.period_ids @@ -172,5 +180,8 @@ class account_balance(report_sxw.rml_parse): def _sum_debit(self): return self.sum_debit -report_sxw.report_sxw('report.account.account.balance', 'account.account', 'addons/account/report/account_balance.rml', parser=account_balance, header=False) + + + +report_sxw.report_sxw('report.account.account.balance', 'account.account', 'addons/account/report/account_balance.rml', parser=account_balance, header=0) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/account/report/account_balance.rml b/addons/account/report/account_balance.rml index fb8eb53c418..af4cee7a7ba 100644 --- a/addons/account/report/account_balance.rml +++ b/addons/account/report/account_balance.rml @@ -66,6 +66,27 @@ <blockAlignment value="LEFT"/> <blockValign value="TOP"/> </blockTableStyle> + <blockTableStyle id="Table3a"> + <blockAlignment value="LEFT"/> + <blockValign value="TOP"/> + <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="0,0" stop="0,-1"/> + <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="0,0" stop="0,0"/> + <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,-1" stop="0,-1"/> + <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="1,0" stop="1,-1"/> + <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="1,0" stop="1,0"/> + <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="1,-1" stop="1,-1"/> + <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="2,0" stop="2,-1"/> + <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="2,0" stop="2,0"/> + <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="2,-1" stop="2,-1"/> + <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="3,0" stop="3,-1"/> + <lineStyle kind="LINEAFTER" colorName="#e6e6e6" start="3,0" stop="3,-1"/> + <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="3,0" stop="3,0"/> + <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="3,-1" stop="3,-1"/> + <lineStyle kind="LINEAFTER" colorName="#e6e6e6" start="4,0" stop="4,-1"/> + <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="4,0" stop="4,0"/> + <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="4,-1" stop="4,-1"/> + </blockTableStyle> + <blockTableStyle id="Table4"> <blockAlignment value="LEFT"/> <blockValign value="TOP"/> @@ -95,6 +116,8 @@ <paraStyle name="P9b" fontName="Helvetica" fontSize="9" leftIndent="0.0" alignment="LEFT"/> <paraStyle name="P9b" fontName="Helvetica" fontSize="8" leftIndent="-5.0" alignment="LEFT"/> <paraStyle name="P12" fontName="Helvetica-Bold" fontSize="8.0" leading="14" alignment="CENTER" spaceBefore="0.0" spaceAfter="6.0"/> + <paraStyle name="terp_default_Centre_8" fontName="Helvetica" fontSize="8.0" leading="10" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/> + <paraStyle name="terp_tblheader_General_Centre" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="CENTER" spaceBefore="6.0" spaceAfter="6.0"/> <paraStyle name="P12a" fontName="Helvetica-Bold" fontSize="8.0" leading="14" alignment="LEFT" spaceBefore="0.0" spaceAfter="6.0"/> <paraStyle name="P12b" fontName="Helvetica-Bold" fontSize="8.0" leading="14" alignment="CENTER" spaceBefore="0.0" spaceAfter="6.0"/> <paraStyle name="P14" rightIndent="17.0" leftIndent="-0.0" fontName="Helvetica-Bold" fontSize="8.0" leading="10" spaceBefore="0.0" spaceAfter="6.0"/> @@ -141,14 +164,46 @@ <para style="P2"> <font color="white"> </font> </para> -<blockTable colWidths="527.00" style="Table4" repeatRows="1"> + + <blockTable colWidths="78.0,108.0,108.0,108.0,138" style="Table3a"> + <tr> + <td> + <para style="terp_tblheader_General_Centre">Fiscal Year</para> + </td> + <td> + <para style="terp_tblheader_General_Centre">End Date</para> + </td> + <td> + <para style="terp_tblheader_General_Centre">Start Date</para> + </td> + <td> + <para style="terp_tblheader_General_Centre">Display Account</para> + </td> + <td> + <para style="terp_tblheader_General_Centre">Periods</para> + </td> + </tr> + </blockTable> + <blockTable colWidths="78.0,108.0,108.0,108.0,138" style="Table3a"> <tr> <td> - <para style="P9a">[[ get_fiscalyear(data['form']) or removeParentNode('para') ]]:</para> - <para style="P9b"><i> [[ get_periods(data['form']) or removeParentNode('para') ]]</i></para> + <para style="terp_default_Centre_8">[[ get_fiscalyear(data['form']) ]]</para> + </td> + <td> + <para style="terp_default_Centre_8">[[ data['form']['date_from'] ]]</para> + </td> + <td> + <para style="terp_default_Centre_8">[[ data['form']['date_to'] ]]</para> + </td> + <td> + <para style="terp_default_Centre_8">[[ (data['form']['display_account']=='bal_all' and 'All') or (data['form']['display_account']=='bal_mouvement' and 'With movements') or 'With balance is not equal to 0']]</para> + </td> + <td> + <para style="terp_default_Centre_8"> [[data['form']['periods'] and get_periods(data['form']) or '']]</para> </td> </tr> -</blockTable> + </blockTable> + <para style="P2"> <font color="white"> </font> diff --git a/addons/account_budget/crossovered_budget_view.xml b/addons/account_budget/crossovered_budget_view.xml index 00dec853486..b48ccc55daa 100644 --- a/addons/account_budget/crossovered_budget_view.xml +++ b/addons/account_budget/crossovered_budget_view.xml @@ -178,12 +178,33 @@ </field> </record> + <record id="view_crossovered_budget_search" model="ir.ui.view"> + <field name="name">crossovered.budget.search</field> + <field name="model">crossovered.budget</field> + <field name="type">search</field> + <field name="arch" type="xml"> + <search string="Budget"> + <group col="20" colspan="4"> + <filter string="Draft" domain="[('state','=','draft')]" help="Draft Budgets" default="1"/> + <filter string="To Validate" domain="[('state','=','validate')]" help="To Validate Budgets" /> + <separator orientation="vertical"/> + <field name="name" select="1"/> + <field name="code" select="1" /> + <field name="state"/> + <field name="date_from"/> + <field name="date_to"/> + </group> + </search> + </field> + </record> + <record model="ir.actions.act_window" id="act_crossovered_budget_view"> <field name="name">Budget</field> <field name="res_model">crossovered.budget</field> <field name="view_type">form</field> <field name="view_mode">tree,form</field> <field name="view_id" ref="crossovered_budget_view_tree"/> + <field name="search_view_id" ref="view_crossovered_budget_search"/> </record> <menuitem parent="next_id_31" id="menu_act_crossovered_budget_view" diff --git a/addons/account_invoice_layout/account_invoice_layout.py b/addons/account_invoice_layout/account_invoice_layout.py index 2317e0c65a9..fda547f3c68 100644 --- a/addons/account_invoice_layout/account_invoice_layout.py +++ b/addons/account_invoice_layout/account_invoice_layout.py @@ -170,6 +170,7 @@ class account_invoice_line(osv.osv): _defaults = { 'state': lambda *a: 'article', + 'sequence': lambda *a : 0, # 'account_id': _default_account } account_invoice_line() diff --git a/addons/base_action_rule/base_action_rule_view.xml b/addons/base_action_rule/base_action_rule_view.xml index 2bd56a3b513..0882b6f0e1b 100644 --- a/addons/base_action_rule/base_action_rule_view.xml +++ b/addons/base_action_rule/base_action_rule_view.xml @@ -46,7 +46,7 @@ </group> <separator colspan="4" string="Note"/> <label align="0.0" colspan="4" width="900" - string="The rule use a AND operator. The model must match all non empty fields so that the rule execute the action described in the 'Actions' tab." /> + string="The rule uses the AND operator. The model must match all non-empty fields so that the rule executes the action described in the 'Actions' tab." /> </page> <page string="Actions"> <separator colspan="4" string="Fields to Change"/> diff --git a/addons/base_calendar/base_calendar_view.xml b/addons/base_calendar/base_calendar_view.xml index a5afddc9823..fc5140c8303 100644 --- a/addons/base_calendar/base_calendar_view.xml +++ b/addons/base_calendar/base_calendar_view.xml @@ -137,15 +137,14 @@ </record> <!-- Calenadar's menu --> - - <menuitem id="base.menu_calendar_configuration" name="Calendar" - parent="base.menu_base_config" sequence="10" /> + <menuitem id="base.menu_calendar_configuration" name="Calendar" + parent="base.menu_config_address_book" sequence="15" /> <!-- Invitation menu --> - <menuitem id="menu_attendee_invitations" - name="Event Invitations" parent="base.menu_calendar_configuration" - sequence="10" action="action_view_attendee_form" /> + <menuitem id="menu_attendee_invitations" + name="Event Invitations" parent="base.menu_calendar_configuration" + sequence="10" action="action_view_attendee_form" /> <!-- ALARM FORM VIEW--> @@ -192,11 +191,10 @@ <!-- Menu for Alarms--> - <menuitem id="menu_crm_meeting_avail_alarm" + <menuitem id="menu_crm_meeting_avail_alarm" groups="base.group_extended" action="base_calendar.action_res_alarm_view" parent="base.menu_calendar_configuration" /> - <!-- Event Form View--> <record model="ir.ui.view" id="event_form_view"> @@ -427,9 +425,9 @@ <!-- Event menu --> - <menuitem id="menu_events" - name="Events" parent="base.menu_calendar_configuration" - sequence="5" action="action_view_event" /> + <menuitem id="menu_events" + name="Events" parent="base.menu_calendar_configuration" + sequence="5" action="action_view_event" /> </data> </openerp> diff --git a/addons/base_vat/i18n/id.po b/addons/base_vat/i18n/id.po index 8881f0627cc..e969ecfa9ad 100644 --- a/addons/base_vat/i18n/id.po +++ b/addons/base_vat/i18n/id.po @@ -7,13 +7,13 @@ msgstr "" "Project-Id-Version: OpenERP Server 5.0.4\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2009-08-28 16:01+0000\n" -"PO-Revision-Date: 2009-11-09 13:47+0000\n" -"Last-Translator: <>\n" +"PO-Revision-Date: 2010-06-03 01:30+0000\n" +"Last-Translator: Abdul Munif Hanafi <Unknown>\n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2010-04-17 04:03+0000\n" +"X-Launchpad-Export-Date: 2010-06-03 03:33+0000\n" "X-Generator: Launchpad (build Unknown)\n" #. module: base_vat @@ -25,7 +25,7 @@ msgstr "" #. module: base_vat #: constraint:ir.ui.view:0 msgid "Invalid XML for View Architecture!" -msgstr "" +msgstr "XML tidak sah untuk Menampilkan Arsitektur!" #. module: base_vat #: field:res.partner,vat_subjected:0 @@ -35,4 +35,4 @@ msgstr "" #. module: base_vat #: model:ir.module.module,shortdesc:base_vat.module_meta_information msgid "VAT" -msgstr "" +msgstr "VAT" diff --git a/addons/crm/crm_phonecall.py b/addons/crm/crm_phonecall.py index cc26ad89c89..657360a4206 100644 --- a/addons/crm/crm_phonecall.py +++ b/addons/crm/crm_phonecall.py @@ -90,6 +90,7 @@ class crm_phonecall(osv.osv, crm_case): 'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'), 'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0], 'state': lambda *a: 'draft', + 'user_id': lambda self,cr,uid,ctx: uid, 'active': lambda *a: 1, } diff --git a/addons/crm_claim/crm_claim_view.xml b/addons/crm_claim/crm_claim_view.xml index 7b462646784..2b3f883024c 100644 --- a/addons/crm_claim/crm_claim_view.xml +++ b/addons/crm_claim/crm_claim_view.xml @@ -2,6 +2,10 @@ <openerp> <data> + <menuitem id="menu_config_claim" name="Claim" + groups="base.group_extended" + parent="base.menu_base_config" sequence="8" /> + <!-- Claims categories --> <record id="crm_claim_categ_action" model="ir.actions.act_window"> @@ -13,8 +17,9 @@ <field name="context">{'object_id':'crm.claim'}</field> </record> - <menuitem action="crm_claim_categ_action" - id="menu_crm_case_claim-act" parent="crm.menu_crm_case_categ" /> + <menuitem action="crm_claim_categ_action" name="Categories" + id="menu_crm_case_claim-act" parent="menu_config_claim" /> + <!-- Claim Stages --> @@ -27,8 +32,8 @@ <field name="context">{'object_id':'crm.claim'}</field> </record> - <menuitem action="crm_claim_stage_act" - id="menu_crm_claim_stage_act" parent="crm.menu_crm_case_stage" /> + <menuitem action="crm_claim_stage_act" name="Stages" + id="menu_crm_claim_stage_act" parent="menu_config_claim" /> <!-- Claim Resource Type --> @@ -41,9 +46,9 @@ <field name="context">{'object_id':'crm.claim'}</field> </record> - <menuitem action="crm_claim_resource_act" + <menuitem action="crm_claim_resource_act" name="Resource Type" id="menu_crm_claim_stage_act" - parent="crm.menu_crm_case_resource_type" /> + parent="menu_config_claim" /> <!-- Claims --> diff --git a/addons/crm_fundraising/crm_fundraising_view.xml b/addons/crm_fundraising/crm_fundraising_view.xml index 78123fd32b7..6853da7c89a 100644 --- a/addons/crm_fundraising/crm_fundraising_view.xml +++ b/addons/crm_fundraising/crm_fundraising_view.xml @@ -1,6 +1,10 @@ <?xml version="1.0"?> <openerp> <data> + <!-- Fund Raising Configuration Menu --> + <menuitem id="menu_config_fundrising" name="Fund Raising" + groups="base.group_extended" + parent="base.menu_base_config" sequence="7" /> <!-- Fund Raising Categories Form View --> @@ -13,9 +17,9 @@ <field name="context">{'object_id':'crm.fundraising'}</field> </record> - <menuitem action="crm_fund_categ_action" + <menuitem action="crm_fund_categ_action" name="Categories" id="menu_crm_case_fundraising-act" groups="base.group_extended" - parent="crm.menu_crm_case_categ" /> + parent="menu_config_fundrising" /> <!-- Fund Stage Form View --> @@ -28,10 +32,11 @@ <field name="context">{'object_id':'crm.fundraising'}</field> </record> - <menuitem action="crm_fundraising_stage_act" - groups="base.group_extended" + <menuitem action="crm_fundraising_stage_act" + groups="base.group_extended" name="Stages" id="menu_crm_fundraising_stage_act" - parent="crm.menu_crm_case_stage" /> + parent="menu_config_fundrising" /> + <!-- Fund Resource Type Form View --> @@ -44,10 +49,10 @@ <field name="context">{'object_id':'crm.fundraising'}</field> </record> - <menuitem action="crm_fundraising_resource_act" - groups="base.group_extended" + <menuitem action="crm_fundraising_resource_act" + groups="base.group_extended" name="Resource Type" id="menu_crm_fundraising_resource_act" - parent="crm.menu_crm_case_resource_type" /> + parent="menu_config_fundrising" /> <!-- Fund Raising Tree View --> diff --git a/addons/crm_helpdesk/crm_helpdesk_view.xml b/addons/crm_helpdesk/crm_helpdesk_view.xml index 4642f60e7e2..451f6c7119e 100644 --- a/addons/crm_helpdesk/crm_helpdesk_view.xml +++ b/addons/crm_helpdesk/crm_helpdesk_view.xml @@ -1,6 +1,10 @@ <?xml version="1.0"?> <openerp> <data> + <!-- Helpdesk Support Categories Configuration Menu--> + <menuitem id="menu_config_helpdesk" name="Helpdesk" + groups="base.group_extended" + parent="base.menu_base_config" sequence="8" /> <!-- Helpdesk Support Categories Form View --> @@ -13,8 +17,8 @@ <field name="context">{'object_id':'crm.helpdesk'}</field> </record> - <menuitem action="crm_helpdesk_categ_action" - id="menu_crm_case_helpdesk-act" parent="crm.menu_crm_case_categ" /> + <menuitem action="crm_helpdesk_categ_action" name="Categories" + id="menu_crm_case_helpdesk-act" parent="menu_config_helpdesk" /> <!-- Helpdesk Support Form View --> diff --git a/addons/crm_profiling/crm_profiling_view.xml b/addons/crm_profiling/crm_profiling_view.xml index 040dff1ff38..eeb95d77fc1 100644 --- a/addons/crm_profiling/crm_profiling_view.xml +++ b/addons/crm_profiling/crm_profiling_view.xml @@ -15,9 +15,9 @@ <field name="view_type">form</field> <field name="view_mode">tree,form</field> </record> - <menuitem parent="base.menu_crm_configuration" id="menu_segm_questionnaire" - action="open_questionnaires" /> + <menuitem parent="base.menu_crm_config_sales" id="menu_segm_questionnaire" + action="open_questionnaires" /> <record model="ir.actions.act_window" id="open_questions"> <field name="name">Questions</field> @@ -25,7 +25,8 @@ <field name="view_type">form</field> <field name="view_mode">tree,form</field> </record> - <menuitem parent="base.menu_crm_configuration" id="menu_segm_answer" + + <menuitem parent="base.menu_crm_config_sales" id="menu_segm_answer" action="open_questions" /> <!-- Profiling Questionnaire Tree view --> diff --git a/addons/email_template/__init__.py b/addons/email_template/__init__.py new file mode 100755 index 00000000000..c959f7204da --- /dev/null +++ b/addons/email_template/__init__.py @@ -0,0 +1,5 @@ +import email_template_account +import email_template +import email_template_mailbox +import wizard + diff --git a/addons/email_template/__openerp__.py b/addons/email_template/__openerp__.py new file mode 100755 index 00000000000..9c5f7bb5c70 --- /dev/null +++ b/addons/email_template/__openerp__.py @@ -0,0 +1,24 @@ +{ + "name" : "Email Template for Open ERP", + "version" : "0.7 RC", + "author" : "Open ERP", + "website" : "http://openerp.com", + "category" : "Added functionality", + "depends" : ['base'], + "description": """ + Email Template is extraction of Power Email basically just to send the emails. + """, + "init_xml": ['email_template_scheduler_data.xml'], + "update_xml": [ + 'security/email_template_security.xml', + 'email_template_workflow.xml', + 'email_template_account_view.xml', + 'email_template_view.xml', + 'email_template_mailbox_view.xml', + 'wizard/email_template_send_wizard_view.xml', + ], + "installable": True, + "active": False, +} + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/email_template/email_template.py b/addons/email_template/email_template.py new file mode 100755 index 00000000000..6c46da458c6 --- /dev/null +++ b/addons/email_template/email_template.py @@ -0,0 +1,698 @@ +import base64 +import random +import time +import types +import netsvc + +LOGGER = netsvc.Logger() + +TEMPLATE_ENGINES = [] + +from osv import osv, fields +from tools.translate import _ +from mako.template import Template #For backward combatibility +try: + from mako.template import Template as MakoTemplate + from mako import exceptions + TEMPLATE_ENGINES.append(('mako', 'Mako Templates')) +except: + LOGGER.notifyChannel( + _("Email Template"), + netsvc.LOG_ERROR, + _("Mako templates not installed") + ) +try: + from django.template import Context, Template as DjangoTemplate + #Workaround for bug: + #http://code.google.com/p/django-tagging/issues/detail?id=110 + from django.conf import settings + settings.configure() + #Workaround ends + TEMPLATE_ENGINES.append(('django', 'Django Template')) +except: + LOGGER.notifyChannel( + _("Email Template"), + netsvc.LOG_ERROR, + _("Django templates not installed") + ) + +import email_template_engines +import tools +import report +import pooler + + +def get_value(cursor, user, recid, message=None, template=None, context=None): + """ + Evaluates an expression and returns its value + @param cursor: Database Cursor + @param user: ID of current user + @param recid: ID of the target record under evaluation + @param message: The expression to be evaluated + @param template: BrowseRecord object of the current template + @param context: Open ERP Context + @return: Computed message (unicode) or u"" + """ + pool = pooler.get_pool(cursor.dbname) + if message is None: + message = {} + #Returns the computed expression + if message: + try: + message = tools.ustr(message) + object = pool.get(template.model_int_name).browse(cursor, user, recid, context) + env = { + 'user':pool.get('res.users').browse(cursor, user, user, context), + 'db':cursor.dbname + } + if template.template_language == 'mako': + templ = MakoTemplate(message, input_encoding='utf-8') + reply = MakoTemplate(message).render_unicode(object=object, + peobject=object, + env=env, + format_exceptions=True) + elif template.template_language == 'django': + templ = DjangoTemplate(message) + env['object'] = object + env['peobject'] = object + reply = templ.render(Context(env)) + return reply or False + except Exception: + return u"" + else: + return message + +class email_template(osv.osv): + "Templates for sending Email" + + _name = "email.template" + _description = 'Email Templates for Models' + + def change_model(self, cursor, user, ids, object_name, context=None): + if object_name: + mod_name = self.pool.get('ir.model').read( + cursor, + user, + object_name, + ['model'], context)['model'] + else: + mod_name = False + return { + 'value':{'model_int_name':mod_name} + } + + _columns = { + 'name' : fields.char('Name of Template', size=100, required=True), + 'object_name':fields.many2one('ir.model', 'Model'), + 'model_int_name':fields.char('Model Internal Name', size=200,), + 'def_to':fields.char( + 'Recepient (To)', + size=250, + help="The default recepient of email." + "Placeholders can be used here."), + 'def_cc':fields.char( + 'Default CC', + size=250, + help="The default CC for the email." + " Placeholders can be used here."), + 'def_bcc':fields.char( + 'Default BCC', + size=250, + help="The default BCC for the email." + " Placeholders can be used here."), + 'lang':fields.char( + 'Language', + size=250, + help="The default language for the email." + " Placeholders can be used here. " + "eg. ${object.partner_id.lang}"), + 'def_subject':fields.char( + 'Default Subject', + size=200, + help="The default subject of email." + " Placeholders can be used here.", + translate=True), + 'def_body_text':fields.text( + 'Standard Body (Text)', + help="The text version of the mail", + translate=True), + 'def_body_html':fields.text( + 'Body (Text-Web Client Only)', + help="The text version of the mail", + translate=True), + 'use_sign':fields.boolean( + 'Use Signature', + help="the signature from the User details" + "will be appened to the mail"), + 'file_name':fields.char( + 'File Name Pattern', + size=200, + help="File name pattern can be specified with placeholders." + "eg. 2009_SO003.pdf", + translate=True), + 'report_template':fields.many2one( + 'ir.actions.report.xml', + 'Report to send'), + 'ref_ir_act_window':fields.many2one( + 'ir.actions.act_window', + 'Window Action', + readonly=True), + 'ref_ir_value':fields.many2one( + 'ir.values', + 'Wizard Button', + readonly=True), + 'allowed_groups':fields.many2many( + 'res.groups', + 'template_group_rel', + 'templ_id', 'group_id', + string="Allowed User Groups", + help="Only users from these groups will be" + " allowed to send mails from this Template"), + 'enforce_from_account':fields.many2one( + 'email_template.account', + string="Enforce From Account", + help="Emails will be sent only from this account.", + domain="[('company','=','yes')]"), + 'model_object_field':fields.many2one( + 'ir.model.fields', + string="Field", + help="Select the field from the model you want to use." + "\nIf it is a relationship field you will be able to " + "choose the nested values in the box below\n(Note:If " + "there are no values make sure you have selected the" + " correct model)", + store=False), + 'sub_object':fields.many2one( + 'ir.model', + 'Sub-model', + help='When a relation field is used this field' + ' will show you the type of field you have selected', + store=False), + 'sub_model_object_field':fields.many2one( + 'ir.model.fields', + 'Sub Field', + help="When you choose relationship fields " + "this field will specify the sub value you can use.", + store=False), + 'null_value':fields.char( + 'Null Value', + help="This Value is used if the field is empty", + size=50, store=False), + 'copyvalue':fields.char( + 'Expression', + size=100, + help="Copy and paste the value in the " + "location you want to use a system value.", + store=False), + 'table_html':fields.text( + 'HTML code', + help="Copy this html code to your HTML message" + " body for displaying the info in your mail.", + store=False), + #Template language(engine eg.Mako) specifics + 'template_language':fields.selection( + TEMPLATE_ENGINES, + 'Templating Language', + required=True + ) + } + + _defaults = { + + } + _sql_constraints = [ + ('name', 'unique (name)', _('The template name must be unique !')) + ] + + def create(self, cr, uid, vals, context=None): + id = super(email_template, self).create(cr, uid, vals, context) + src_obj = self.pool.get('ir.model').read(cr, uid, vals['object_name'], ['model'], context)['model'] + vals['ref_ir_act_window'] = self.pool.get('ir.actions.act_window').create(cr, uid, { + 'name': _("%s Mail Form") % vals['name'], + 'type': 'ir.actions.act_window', + 'res_model': 'email_template.send.wizard', + 'src_model': src_obj, + 'view_type': 'form', + 'context': "{'src_model':'%s','template_id':'%d','src_rec_id':active_id,'src_rec_ids':active_ids}" % (src_obj, id), + 'view_mode':'form,tree', + 'view_id': self.pool.get('ir.ui.view').search(cr, uid, [('name', '=', 'email_template.send.wizard.form')], context=context)[0], + 'target': 'new', + 'auto_refresh':1 + }, context) + vals['ref_ir_value'] = self.pool.get('ir.values').create(cr, uid, { + 'name': _('Send Mail (%s)') % vals['name'], + 'model': src_obj, + 'key2': 'client_action_multi', + 'value': "ir.actions.act_window," + str(vals['ref_ir_act_window']), + 'object': True, + }, context) + self.write(cr, uid, id, { + 'ref_ir_act_window': vals['ref_ir_act_window'], + 'ref_ir_value': vals['ref_ir_value'], + }, context) + return id + + def unlink(self, cr, uid, ids, context=None): + for template in self.browse(cr, uid, ids, context): + obj = self.pool.get(template.object_name.model) + try: + if template.ref_ir_act_window: + self.pool.get('ir.actions.act_window').unlink(cr, uid, template.ref_ir_act_window.id, context) + if template.ref_ir_value: + self.pool.get('ir.values').unlink(cr, uid, template.ref_ir_value.id, context) + except: + raise osv.except_osv(_("Warning"), _("Deletion of Record failed")) + return super(email_template, self).unlink(cr, uid, ids, context) + + def copy(self, cr, uid, id, default=None, context=None): + if default is None: + default = {} + default = default.copy() + old = self.read(cr, uid, id, ['name'], context=context) + new_name = _("Copy of template ") + old.get('name', 'No Name') + check = self.search(cr, uid, [('name', '=', new_name)], context=context) + if check: + new_name = new_name + '_' + random.choice('abcdefghij') + random.choice('lmnopqrs') + random.choice('tuvwzyz') + default.update({'name':new_name}) + return super(email_template, self).copy(cr, uid, id, default, context) + + def compute_pl(self, + model_object_field, + sub_model_object_field, + null_value, template_language='mako'): + """ + Returns the expression based on data provided + @param model_object_field: First level field + @param sub_model_object_field: Second level drilled down field (M2O) + @param null_value: What has to be returned if the value is empty + @param template_language: The language used for templating + @return: computed expression + """ + #Configure for MAKO + copy_val = '' + if template_language == 'mako': + if model_object_field: + copy_val = "${object." + model_object_field + if sub_model_object_field: + copy_val += "." + sub_model_object_field + if null_value: + copy_val += " or '" + null_value + "'" + if model_object_field: + copy_val += "}" + elif template_language == 'django': + if model_object_field: + copy_val = "{{object." + model_object_field + if sub_model_object_field: + copy_val += "." + sub_model_object_field + if null_value: + copy_val = copy_val + '|default:"' + null_value + '"' + copy_val = copy_val + "}}" + return copy_val + + def onchange_model_object_field(self, cr, uid, ids, model_object_field, template_language, context=None): + if not model_object_field: + return {} + result = {} + field_obj = self.pool.get('ir.model.fields').browse(cr, uid, model_object_field, context) + #Check if field is relational + if field_obj.ttype in ['many2one', 'one2many', 'many2many']: + res_ids = self.pool.get('ir.model').search(cr, uid, [('model', '=', field_obj.relation)], context=context) + if res_ids: + result['sub_object'] = res_ids[0] + result['copyvalue'] = self.compute_pl(False, + False, + False, + template_language) + result['sub_model_object_field'] = False + result['null_value'] = False + else: + #Its a simple field... just compute placeholder + result['sub_object'] = False + result['copyvalue'] = self.compute_pl(field_obj.name, + False, + False, + template_language + ) + result['sub_model_object_field'] = False + result['null_value'] = False + return {'value':result} + + def onchange_sub_model_object_field(self, cr, uid, ids, model_object_field, sub_model_object_field, template_language, context=None): + if not model_object_field or not sub_model_object_field: + return {} + result = {} + field_obj = self.pool.get('ir.model.fields').browse(cr, uid, model_object_field, context) + if field_obj.ttype in ['many2one', 'one2many', 'many2many']: + res_ids = self.pool.get('ir.model').search(cr, uid, [('model', '=', field_obj.relation)], context=context) + sub_field_obj = self.pool.get('ir.model.fields').browse(cr, uid, sub_model_object_field, context) + if res_ids: + result['sub_object'] = res_ids[0] + result['copyvalue'] = self.compute_pl(field_obj.name, + sub_field_obj.name, + False, + template_language + ) + result['sub_model_object_field'] = sub_model_object_field + result['null_value'] = False + else: + #Its a simple field... just compute placeholder + result['sub_object'] = False + result['copyvalue'] = self.compute_pl(field_obj.name, + False, + False, + template_language + ) + result['sub_model_object_field'] = False + result['null_value'] = False + return {'value':result} + + def onchange_null_value(self, cr, uid, ids, model_object_field, sub_model_object_field, null_value, template_language, context=None): + if not model_object_field and not null_value: + return {} + result = {} + field_obj = self.pool.get('ir.model.fields').browse(cr, uid, model_object_field, context) + if field_obj.ttype in ['many2one', 'one2many', 'many2many']: + res_ids = self.pool.get('ir.model').search(cr, uid, [('model', '=', field_obj.relation)], context=context) + sub_field_obj = self.pool.get('ir.model.fields').browse(cr, uid, sub_model_object_field, context) + if res_ids: + result['sub_object'] = res_ids[0] + result['copyvalue'] = self.compute_pl(field_obj.name, + sub_field_obj.name, + null_value, + template_language + ) + result['sub_model_object_field'] = sub_model_object_field + result['null_value'] = null_value + else: + #Its a simple field... just compute placeholder + result['sub_object'] = False + result['copyvalue'] = self.compute_pl(field_obj.name, + False, + null_value, + template_language + ) + result['sub_model_object_field'] = False + result['null_value'] = null_value + return {'value':result} + + def generate_attach_reports(self, + cursor, + user, + template, + record_id, + mail, + context=None): + """ + Generate report to be attached and attach it + to the email + + @param cursor: Database Cursor + @param user: ID of User + @param template: Browse record of + template + @param record_id: ID of the target model + for which this mail has + to be generated + @param mail: Browse record of email object + @return: True + """ + reportname = 'report.' + \ + self.pool.get('ir.actions.report.xml').read( + cursor, + user, + template.report_template.id, + ['report_name'], + context)['report_name'] + service = netsvc.LocalService(reportname) + data = {} + data['model'] = template.model_int_name + (result, format) = service.create(cursor, + user, + [record_id], + data, + context) + attachment_obj = self.pool.get('ir.attachment') + new_att_vals = { + 'name':mail.subject + ' (Email Attachment)', + 'datas':base64.b64encode(result), + 'datas_fname':tools.ustr( + get_value( + cursor, + user, + record_id, + template.file_name, + template, + context + ) or 'Report') + "." + format, + 'description':mail.subject or "No Description", + 'res_model':'email_template.mailbox', + 'res_id':mail.id + } + attachment_id = attachment_obj.create(cursor, + user, + new_att_vals, + context) + if attachment_id: + self.pool.get('email_template.mailbox').write( + cursor, + user, + mail.id, + { + 'attachments_ids':[ + [6, 0, [attachment_id]] + ], + 'mail_type':'multipart/mixed' + }, + context) + return True + + def generate_mailbox_item_from_template(self, + cursor, + user, + template, + record_id, + context=None): + """ + Generates an email from the template for + record record_id of target object + + @param cursor: Database Cursor + @param user: ID of User + @param template: Browse record of + template + @param record_id: ID of the target model + for which this mail has + to be generated + @return: ID of created object + """ + if context is None: + context = {} + #If account to send from is in context select it, else use enforced account + if 'account_id' in context.keys(): + from_account = self.pool.get('email_template.account').read( + cursor, + user, + context.get('account_id'), + ['name', 'email_id'], + context + ) + else: + from_account = { + 'id':template.enforce_from_account.id, + 'name':template.enforce_from_account.name, + 'email_id':template.enforce_from_account.email_id + } + lang = get_value(cursor, + user, + record_id, + template.lang, + template, + context) + if lang: + ctx = context.copy() + ctx.update({'lang':lang}) + template = self.browse(cursor, user, template_id, context=ctx) + mailbox_values = { + 'email_from': tools.ustr(from_account['name']) + \ + "<" + tools.ustr(from_account['email_id']) + ">", + 'email_to':get_value(cursor, + user, + record_id, + template.def_to, + template, + context), + 'email_cc':get_value(cursor, + user, + record_id, + template.def_cc, + template, + context), + 'email_bcc':get_value(cursor, + user, + record_id, + template.def_bcc, + template, + context), + 'subject':get_value(cursor, + user, + record_id, + template.def_subject, + template, + context), + 'body_text':get_value(cursor, + user, + record_id, + template.def_body_text, + template, + context), + 'body_html':get_value(cursor, + user, + record_id, + template.def_body_html, + template, + context), + 'account_id' :from_account['id'], + #This is a mandatory field when automatic emails are sent + 'state':'na', + 'folder':'drafts', + 'mail_type':'multipart/alternative' + } + #Use signatures if allowed + if template.use_sign: + sign = self.pool.get('res.users').read(cursor, + user, + user, + ['signature'], + context)['signature'] + if mailbox_values['body_text']: + mailbox_values['body_text'] += sign + if mailbox_values['body_html']: + mailbox_values['body_html'] += sign + mailbox_id = self.pool.get('email_template.mailbox').create( + cursor, + user, + mailbox_values, + context) + return mailbox_id + + def generate_mail(self, + cursor, + user, + template_id, + record_ids, + context=None): + if context is None: + context = {} + template = self.browse(cursor, user, template_id, context=context) + if not template: + raise Exception("The requested template could not be loaded") + for record_id in record_ids: + mailbox_id = self._generate_mailbox_item_from_template( + cursor, + user, + template, + record_id, + context) + mail = self.pool.get('email_template.mailbox').browse( + cursor, + user, + mailbox_id, + context=context + ) + if template.report_template: + self._generate_attach_reports( + cursor, + user, + template, + record_id, + mail, + context + ) + self.pool.get('email_template.mailbox').write( + cursor, + user, + mailbox_id, + {'folder':'outbox'}, + context=context + ) + return True + +email_template() + +class email_template_preview(osv.osv_memory): + _name = "email_template.preview" + _description = "Email Template Preview" + + def _get_model_recs(self, cr, uid, context=None): + if context is None: + context = {} + #Fills up the selection box which allows records from the selected object to be displayed + self.context = context + if 'active_id' in context.keys(): +# context['active_id'] = 5 + ref_obj_id = self.pool.get('email.template').read(cr, uid, context['active_id'], ['object_name'], context) + ref_obj_name = self.pool.get('ir.model').read(cr, uid, ref_obj_id[0], ['model'], context)['model'] + ref_obj_ids = self.pool.get(ref_obj_name).search(cr, uid, [], context=context) + ref_obj_recs = self.pool.get(ref_obj_name).name_get(cr, uid, ref_obj_ids, context) + return ref_obj_recs + + def _default_model(self, cursor, user, context=None): + """ + Returns the default value for model field + @param cursor: Database Cursor + @param user: ID of current user + @param context: Open ERP Context + """ + return self.pool.get('email.template').read( + cursor, + user, + context['active_id'], + ['object_name'], + context)['object_name'] + + _columns = { + 'ref_template':fields.many2one( + 'email.template', + 'Template', readonly=True), + 'rel_model':fields.many2one('ir.model', 'Model', readonly=True), + 'rel_model_ref':fields.selection(_get_model_recs, 'Referred Document'), + 'to':fields.char('To', size=250, readonly=True), + 'cc':fields.char('CC', size=250, readonly=True), + 'bcc':fields.char('BCC', size=250, readonly=True), + 'subject':fields.char('Subject', size=200, readonly=True), + 'body_text':fields.text('Body', readonly=True), + 'body_html':fields.text('Body', readonly=True), + 'report':fields.char('Report Name', size=100, readonly=True), + } + _defaults = { + 'ref_template': lambda self, cr, uid, ctx:ctx['active_id'], + 'rel_model': _default_model + } + + def on_change_ref(self, cr, uid, ids, rel_model_ref, context=None): + if context is None: + context = {} + if not rel_model_ref: + return {} + vals = {} + if context == {}: + context = self.context + template = self.pool.get('email.template').browse(cr, uid, context['active_id'], context) + #Search translated template + lang = get_value(cr, uid, rel_model_ref, template.lang, template, context) + if lang: + ctx = context.copy() + ctx.update({'lang':lang}) + template = self.pool.get('email.template').browse(cr, uid, context['active_id'], ctx) + vals['to'] = get_value(cr, uid, rel_model_ref, template.def_to, template, context) + vals['cc'] = get_value(cr, uid, rel_model_ref, template.def_cc, template, context) + vals['bcc'] = get_value(cr, uid, rel_model_ref, template.def_bcc, template, context) + vals['subject'] = get_value(cr, uid, rel_model_ref, template.def_subject, template, context) + vals['body_text'] = get_value(cr, uid, rel_model_ref, template.def_body_text, template, context) + vals['body_html'] = get_value(cr, uid, rel_model_ref, template.def_body_html, template, context) + vals['report'] = get_value(cr, uid, rel_model_ref, template.file_name, template, context) + return {'value':vals} + +email_template_preview() + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/email_template/email_template_account.py b/addons/email_template/email_template_account.py new file mode 100755 index 00000000000..2503d19cd10 --- /dev/null +++ b/addons/email_template/email_template_account.py @@ -0,0 +1,440 @@ +from osv import osv, fields +from html2text import html2text +import re +import smtplib +import base64 +from email import Encoders +from email.mime.base import MIMEBase +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText +from email.header import decode_header, Header +from email.utils import formatdate +import re +import netsvc +import string +import email +import time, datetime +import email_template_engines +from tools.translate import _ +import tools + +class email_template_account(osv.osv): + """ + Object to store email account settings + """ + _name = "email_template.account" + _known_content_types = ['multipart/mixed', + 'multipart/alternative', + 'multipart/related', + 'text/plain', + 'text/html' + ] + _columns = { + 'name': fields.char('Email Account Desc', + size=64, required=True, + readonly=True, select=True, + states={'draft':[('readonly', False)]}), + 'user':fields.many2one('res.users', + 'Related User', required=True, + readonly=True, states={'draft':[('readonly', False)]}), + 'email_id': fields.char('Email ID', + size=120, required=True, + readonly=True, states={'draft':[('readonly', False)]} , + help=" eg:yourname@yourdomain.com "), + 'smtpserver': fields.char('Server', + size=120, required=True, + readonly=True, states={'draft':[('readonly', False)]}, + help="Enter name of outgoing server,eg:smtp.gmail.com "), + 'smtpport': fields.integer('SMTP Port ', + size=64, required=True, + readonly=True, states={'draft':[('readonly', False)]}, + help="Enter port number,eg:SMTP-587 "), + 'smtpuname': fields.char('User Name', + size=120, required=False, + readonly=True, states={'draft':[('readonly', False)]}), + 'smtppass': fields.char('Password', + size=120, invisible=True, + required=False, readonly=True, + states={'draft':[('readonly', False)]}), + 'smtptls':fields.boolean('Use TLS', + states={'draft':[('readonly', False)]}, readonly=True), + + 'smtpssl':fields.boolean('Use SSL/TLS (only in python 2.6)', + states={'draft':[('readonly', False)]}, readonly=True), + 'send_pref':fields.selection([ + ('html', 'HTML otherwise Text'), + ('text', 'Text otherwise HTML'), + ('both', 'Both HTML & Text') + ], 'Mail Format', required=True), + 'allowed_groups':fields.many2many( + 'res.groups', + 'account_group_rel', 'templ_id', 'group_id', + string="Allowed User Groups", + help="Only users from these groups will be" \ + "allowed to send mails from this ID"), + 'company':fields.selection([ + ('yes', 'Yes'), + ('no', 'No') + ], 'Company Mail A/c', + readonly=True, + help="Select if this mail account does not belong" \ + "to specific user but the organisation as a whole." \ + "eg:info@somedomain.com", + required=True, states={ + 'draft':[('readonly', False)] + }), + + 'state':fields.selection([ + ('draft', 'Initiated'), + ('suspended', 'Suspended'), + ('approved', 'Approved') + ], + 'Account Status', required=True, readonly=True), + } + + _defaults = { + 'name':lambda self, cursor, user, context:self.pool.get( + 'res.users' + ).read( + cursor, + user, + user, + ['name'], + context + )['name'], + 'smtpssl':lambda * a:True, + 'state':lambda * a:'draft', + 'user':lambda self, cursor, user, context:user, + 'send_pref':lambda * a: 'html', + 'smtptls':lambda * a:True, + } + + _sql_constraints = [ + ( + 'email_uniq', + 'unique (email_id)', + 'Another setting already exists with this email ID !') + ] + + def _constraint_unique(self, cursor, user, ids): + """ + This makes sure that you dont give personal + users two accounts with same ID (Validated in sql constaints) + However this constraint exempts company accounts. + Any no of co accounts for a user is allowed + """ + if self.read(cursor, user, ids, ['company'])[0]['company'] == 'no': + accounts = self.search(cursor, user, [ + ('user', '=', user), + ('company', '=', 'no') + ]) + if len(accounts) > 1 : + return False + else : + return True + else: + return True + + _constraints = [ + (_constraint_unique, + 'Error: You are not allowed to have more than 1 account.', + []) + ] + + def on_change_emailid(self, cursor, user, ids, name=None, email_id=None, context=None): + """ + Called when the email ID field changes. + + UI enhancement + Writes the same email value to the smtpusername + and incoming username + """ + #TODO: Check and remove the write. Is it needed? + self.write(cursor, user, ids, {'state':'draft'}, context=context) + return { + 'value': { + 'state': 'draft', + 'smtpuname':email_id, + 'isuser':email_id + } + } + + def get_outgoing_server(self, cursor, user, ids, context=None): + """ + Returns the Out Going Connection (SMTP) object + + @attention: DO NOT USE except_osv IN THIS METHOD + @param cursor: Database Cursor + @param user: ID of current user + @param ids: ID/list of ids of current object for + which connection is required + First ID will be chosen from lists + @param context: Context + + @return: SMTP server object or Exception + """ + #Type cast ids to integer + if type(ids) == list: + ids = ids[0] + this_object = self.browse(cursor, user, ids, context) + if this_object: + if this_object.smtpserver and this_object.smtpport: + try: + if this_object.smtpssl: + serv = smtplib.SMTP_SSL(this_object.smtpserver, this_object.smtpport) + else: + serv = smtplib.SMTP(this_object.smtpserver, this_object.smtpport) + if this_object.smtptls: + serv.ehlo() + serv.starttls() + serv.ehlo() + except Exception, error: + raise error + try: + if serv.has_extn('AUTH') or this_object.smtpuname or this_object.smtppass: + serv.login(this_object.smtpuname, this_object.smtppass) + except Exception, error: + raise error + return serv + raise Exception(_("SMTP SERVER or PORT not specified")) + raise Exception(_("Core connection for the given ID does not exist")) + + def check_outgoing_connection(self, cursor, user, ids, context=None): + """ + checks SMTP credentials and confirms if outgoing connection works + (Attached to button) + @param cursor: Database Cursor + @param user: ID of current user + @param ids: list of ids of current object for + which connection is required + @param context: Context + """ + try: + self.get_outgoing_server(cursor, user, ids, context) + raise osv.except_osv(_("SMTP Test Connection Was Successful"), '') + except osv.except_osv, success_message: + raise success_message + except Exception, error: + raise osv.except_osv( + _("Out going connection test failed"), + _("Reason: %s") % error + ) + + def do_approval(self, cr, uid, ids, context={}): + #TODO: Check if user has rights + self.write(cr, uid, ids, {'state':'approved'}, context=context) +# wf_service = netsvc.LocalService("workflow") + + def smtp_connection(self, cursor, user, id, context=None): + """ + This method should now wrap smtp_connection + """ + #This function returns a SMTP server object + logger = netsvc.Logger() + core_obj = self.browse(cursor, user, id, context) + if core_obj.smtpserver and core_obj.smtpport and core_obj.state == 'approved': + try: + serv = self.get_outgoing_server(cursor, user, id, context) + except Exception, error: + logger.notifyChannel(_("Email Template"), netsvc.LOG_ERROR, _("Mail from Account %s failed on login. Probable Reason:Could not login to server\nError: %s") % (id, error)) + return False + #Everything is complete, now return the connection + return serv + else: + logger.notifyChannel(_("Email Template"), netsvc.LOG_ERROR, _("Mail from Account %s failed. Probable Reason:Account not approved") % id) + return False + +#**************************** MAIL SENDING FEATURES ***********************# + def split_to_ids(self, ids_as_str): + """ + Identifies email IDs separated by separators + and returns a list + TODO: Doc this + "a@b.com,c@bcom; d@b.com;e@b.com->['a@b.com',...]" + """ + email_sep_by_commas = ids_as_str \ + .replace('; ', ',') \ + .replace(';', ',') \ + .replace(', ', ',') + return email_sep_by_commas.split(',') + + def get_ids_from_dict(self, addresses={}): + """ + TODO: Doc this + """ + result = {'all':[]} + keys = ['To', 'CC', 'BCC'] + for each in keys: + ids_as_list = self.split_to_ids(addresses.get(each, u'')) + while u'' in ids_as_list: + ids_as_list.remove(u'') + result[each] = ids_as_list + result['all'].extend(ids_as_list) + return result + + def send_mail(self, cr, uid, ids, addresses, subject='', body=None, payload=None, context=None): + #TODO: Replace all this crap with a single email object + if body is None: + body = {} + if payload is None: + payload = {} + if context is None: + context = {} + logger = netsvc.Logger() + for id in ids: + core_obj = self.browse(cr, uid, id, context) + serv = self.smtp_connection(cr, uid, id) + if serv: + try: + msg = MIMEMultipart() + if subject: + msg['Subject'] = subject + sender_name = Header(core_obj.name, 'utf-8').encode() + msg['From'] = sender_name + " <" + core_obj.email_id + ">" + msg['Organization'] = tools.ustr(core_obj.user.company_id.name) + msg['Date'] = formatdate() + addresses_l = self.get_ids_from_dict(addresses) + if addresses_l['To']: + msg['To'] = u','.join(addresses_l['To']) + if addresses_l['CC']: + msg['CC'] = u','.join(addresses_l['CC']) +# if addresses_l['BCC']: +# msg['BCC'] = u','.join(addresses_l['BCC']) + if body.get('text', False): + temp_body_text = body.get('text', '') + l = len(temp_body_text.replace(' ', '').replace('\r', '').replace('\n', '')) + if l == 0: + body['text'] = u'No Mail Message' + # Attach parts into message container. + # According to RFC 2046, the last part of a multipart message, in this case + # the HTML message, is best and preferred. + if core_obj.send_pref == 'text' or core_obj.send_pref == 'both': + body_text = body.get('text', u'No Mail Message') + body_text = tools.ustr(body_text) + msg.attach(MIMEText(body_text.encode("utf-8"), _charset='UTF-8')) + if core_obj.send_pref == 'html' or core_obj.send_pref == 'both': + html_body = body.get('html', u'') + if len(html_body) == 0 or html_body == u'': + html_body = body.get('text', u'<p>No Mail Message</p>').replace('\n', '<br/>').replace('\r', '<br/>') + html_body = tools.ustr(html_body) + msg.attach(MIMEText(html_body.encode("utf-8"), _subtype='html', _charset='UTF-8')) + #Now add attachments if any + for file in payload.keys(): + part = MIMEBase('application', "octet-stream") + part.set_payload(base64.decodestring(payload[file])) + part.add_header('Content-Disposition', 'attachment; filename="%s"' % file) + Encoders.encode_base64(part) + msg.attach(part) + except Exception, error: + logger.notifyChannel(_("Email Template"), netsvc.LOG_ERROR, _("Mail from Account %s failed. Probable Reason:MIME Error\nDescription: %s") % (id, error)) + return error + try: + #print msg['From'],toadds + serv.sendmail(msg['From'], addresses_l['all'], msg.as_string()) + except Exception, error: + logger.notifyChannel(_("Email Template"), netsvc.LOG_ERROR, _("Mail from Account %s failed. Probable Reason:Server Send Error\nDescription: %s") % (id, error)) + return error + #The mail sending is complete + serv.close() + logger.notifyChannel(_("Email Template"), netsvc.LOG_INFO, _("Mail from Account %s successfully Sent.") % (id)) + return True + else: + logger.notifyChannel(_("Email Template"), netsvc.LOG_ERROR, _("Mail from Account %s failed. Probable Reason:Account not approved") % id) + + def extracttime(self, time_as_string): + """ + TODO: DOC THis + """ + logger = netsvc.Logger() + #The standard email dates are of format similar to: + #Thu, 8 Oct 2009 09:35:42 +0200 + #print time_as_string + date_as_date = False + convertor = {'+':1, '-':-1} + try: + time_as_string = time_as_string.replace(',', '') + date_list = time_as_string.split(' ') + date_temp_str = ' '.join(date_list[1:5]) + if len(date_list) >= 6: + sign = convertor.get(date_list[5][0], False) + else: + sign = False + try: + dt = datetime.datetime.strptime( + date_temp_str, + "%d %b %Y %H:%M:%S") + except: + try: + dt = datetime.datetime.strptime( + date_temp_str, + "%d %b %Y %H:%M") + except: + return False + if sign: + try: + offset = datetime.timedelta( + hours=sign * int( + date_list[5][1:3] + ), + minutes=sign * int( + date_list[5][3:5] + ) + ) + except Exception, e2: + """Looks like UT or GMT, just forget decoding""" + return False + else: + offset = datetime.timedelta(hours=0) + dt = dt + offset + date_as_date = dt.strftime('%Y-%m-%d %H:%M:%S') + #print date_as_date + except Exception, e: + logger.notifyChannel( + _("Email Template"), + netsvc.LOG_WARNING, + _( + "Datetime Extraction failed.Date:%s \ + \tError:%s") % ( + time_as_string, + e) + ) + return date_as_date + + def send_receive(self, cr, uid, ids, context=None): + self.get_mails(cr, uid, ids, context) + for id in ids: + ctx = context.copy() + ctx['filters'] = [('account_id', '=', id)] + self.pool.get('email_template.mailbox').send_all_mail(cr, uid, [], context=ctx) + return True + + def decode_header_text(self, text): + """ Decode internationalized headers RFC2822. + To, CC, BCC, Subject fields can contain + text slices with different encodes, like: + =?iso-8859-1?Q?Enric_Mart=ED?= <enricmarti@company.com>, + =?Windows-1252?Q?David_G=F3mez?= <david@company.com> + Sometimes they include extra " character at the beginning/ + end of the contact name, like: + "=?iso-8859-1?Q?Enric_Mart=ED?=" <enricmarti@company.com> + and decode_header() does not work well, so we use regular + expressions (?= ? ? ?=) to split the text slices + """ + if not text: + return text + p = re.compile("(=\?.*?\?.\?.*?\?=)") + text2 = '' + try: + for t2 in p.split(text): + text2 += ''.join( + [s.decode( + t or 'ascii' + ) for (s, t) in decode_header(t2)] + ).encode('utf-8') + except: + return text + return text2 + +email_template_account() + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/email_template/email_template_account_view.xml b/addons/email_template/email_template_account_view.xml new file mode 100755 index 00000000000..5f11fa033f4 --- /dev/null +++ b/addons/email_template/email_template_account_view.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data> + + <menuitem name="Tools" id="base.menu_tools" icon="STOCK_PREFERENCES" sequence="15"/> + <menuitem name="Email Template" id="menu_email_template" parent="base.menu_tools"/> + + <record model="ir.ui.view" id="email_template_account_form"> + <field name="name">email_template.account.form</field> + <field name="model">email_template.account</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="Email Account Configuration"> + <group colspan="2"> + <field name="name" select="1" /> + </group> + <notebook colspan="4"> + <page string="Outgoing"> + <separator string="Server Information" colspan="4" /> + <group colspan="4"> + <field name="smtpserver" select="1" colspan="2" /> + <field name="smtpport" select="2" colspan="2" /> + <field name="smtpssl" select="2" colspan="2" /> + <field name="smtptls" select="2" colspan="2" /> + </group> + <button name="check_outgoing_connection" type="object" string="Check Outgoing Connection" /> + <separator string="User Information" colspan="4" /> + <group col="2" colspan="2"> + <field name="email_id" select="1" on_change="on_change_emailid(name,email_id)" colspan="2" /> + <field name="smtppass" password="True" colspan="2" /> + <field name="company" select="2" colspan="2" /> + </group> + <group col="2" colspan="2"> + <field name="smtpuname" select="1" colspan="2" /> + <field name="user" select="2" colspan="2" /> + <field name="send_pref" colspan="2" /> + </group> + </page> + <page string="security" attrs="{'invisible':[('company','!=','yes')]}"> + <field name="allowed_groups" attrs="{'required':[('company','=','yes')]}" nolabel="1"/> + </page> + </notebook> + <group colspan="4" col="10"> + <field name="state" select="1"/> + <button string="Approve Account" name="button_approval" states="draft" type="workflow"/> + <button string="Suspend Account" name="button_suspended" states="approved" type="workflow" /> + <button string="Request Re-activation" name="get_reapprove" states="suspended" type="workflow" /> + <button string="Send/Receive" name="send_receive" states="approved" type="object" /> + </group> + </form> + </field> + </record> + + <record model="ir.ui.view" id="email_template_account_tree"> + <field name="name">email_template.account.tree</field> + <field name="model">email_template.account</field> + <field name="type">tree</field> + <field name="arch" type="xml"> + <tree string="SMTP Server"> + <field name="name" select="2" /> + <field name="email_id" select="2" /> + <field name="smtpuname" select="2" /> + <field name="user" select="2" /> + <field name="smtpserver" select="2" /> + <field name="smtpport" select="2" /> + <field name="state" select="2" /> + </tree> + </field> + </record> + + <record id="view_email_template_account_search" model="ir.ui.view"> + <field name="name">email_template.account.search</field> + <field name="model">email_template.account</field> + <field name="type">search</field> + <field name="arch" type="xml"> + <search string="Accounts"> + <filter icon="terp-crm" string="My Accounts" name="my" domain="[('user','=',uid)]"/> + <filter icon="terp-crm" string="Personal Accounts" domain="[('company','=','no')]"/> + <filter icon="terp-crm" string="Company Accounts" domain="[('company','=','yes')]"/> + <separator orientation="vertical"/> + <filter icon="terp-crm" string="Draft" name="draft" domain="[('state','=','draft')]"/> + <filter icon="terp-crm" string="Suspended" domain="[('state','=','suspended')]"/> + <separator orientation="vertical"/> + <field name="name" select="1"/> + <field name="user" select="1"/> + <field name="email_id" select="1"/> + </search> + </field> + </record> + + <record model="ir.actions.act_window" id="action_email_template_account_tree_all"> + <field name="name">Accounts</field> + <field name="res_model">email_template.account</field> + <field name="view_type">form</field> + <field name="view_mode">form,tree</field> + <field name="view_id" ref="email_template_account_tree" /> + <field name="context">{'group_by': [], 'search_default_draft': 1, 'search_default_my': 1}</field> + <field name="search_view_id" ref="view_email_template_account_search"/> + </record> + + <menuitem name="Configuration" id="menu_email_template_configuration" parent="menu_email_template" /> + + <menuitem name="All Accounts" id="menu_email_template_account_all" parent="menu_email_template_configuration" action="action_email_template_account_tree_all" groups="res_groups_email_template_manager" /> + + </data> +</openerp> + + + + diff --git a/addons/email_template/email_template_engines.py b/addons/email_template/email_template_engines.py new file mode 100755 index 00000000000..2fc58310e9b --- /dev/null +++ b/addons/email_template/email_template_engines.py @@ -0,0 +1,84 @@ +# To change this template, choose Tools | Templates +# and open the template in the editor. +from osv import fields,osv +import pooler +import netsvc +import re + +class email_template_engines(osv.osv): + _name = "email_template.engines" + _description = "Email Template Engine" + +# def __init__(self): +# print "Started Engine" + + def check(self): + print "Start self check" + + def strip_html(self,text): + #Removes HTML, Have to check if still relevent + if text: + def fixup(m): + text = m.group(0) + if text[:1] == "<": + return "" # ignore tags + if text[:2] == "&#": + try: + if text[:3] == "&#x": + return unichr(int(text[3:-1], 16)) + else: + return unichr(int(text[2:-1])) + except ValueError: + pass + elif text[:1] == "&": + import htmlentitydefs + entity = htmlentitydefs.entitydefs.get(text[1:-1]) + if entity: + if entity[:2] == "&#": + try: + return unichr(int(entity[2:-1])) + except ValueError: + pass + else: + return unicode(entity, "iso-8859-1") + return text # leave as is + return re.sub("(?s)<[^>]*>|&#?\w+;", fixup, text) + + def parsevalue(self,cr,uid,id,message,templateid,context): + #id: ID of the template's model's record to be used + #message: the complete text including placeholders + #templateid: the template id of the template + #context: TODO + #print cr,uid,id,message,templateid,context + if message: + logger = netsvc.Logger() + def merge(match): + template = self.pool.get("email.template").browse(cr,uid,templateid,context) + obj_pool = self.pool.get(template.object_name.model) + obj = obj_pool.browse(cr, uid, id, context) + exp = str(match.group()[2:-2]).strip() + #print "level 1:",exp + exp_spl = exp.split('/') + #print "level 2:",exp_spl + try: + result = eval(exp_spl[0], {'object':obj,}) + except: + result = "Rendering Error" + #print "result:",result + try: + if result in (None, False): + if len(exp_spl)>1: + return exp_spl[1] + else: + return 'Not Available' + return str(result) + except: + return "Rendering Error" + if message: + com = re.compile('(\[\[.+?\]\])') + retmessage = com.sub(merge, message) + else: + retmessage="" + return retmessage + +email_template_engines() diff --git a/addons/email_template/email_template_mailbox.py b/addons/email_template/email_template_mailbox.py new file mode 100755 index 00000000000..1934f4e0227 --- /dev/null +++ b/addons/email_template/email_template_mailbox.py @@ -0,0 +1,182 @@ +from osv import osv, fields +import time +import email_template_engines +import netsvc +from tools.translate import _ +import tools + +LOGGER = netsvc.Logger() + +class email_template_mailbox(osv.osv): + _name = "email_template.mailbox" + _description = 'Email Mailbox' + _rec_name = "subject" + _order = "date_mail desc" + + def run_mail_scheduler(self, cursor, user, context=None): + """ + This method is called by Open ERP Scheduler + to periodically send emails + """ + try: + self.send_all_mail(cursor, user, context) + except Exception, e: + LOGGER.notifyChannel( + _("Email Template"), + netsvc.LOG_ERROR, + _("Error sending mail: %s" % str(e))) + + def send_all_mail(self, cr, uid, ids=None, context=None): + if ids is None: + ids = [] + if context is None: + context = {} + filters = [('folder', '=', 'outbox'), ('state', '!=', 'sending')] + if 'filters' in context.keys(): + for each_filter in context['filters']: + filters.append(each_filter) + ids = self.search(cr, uid, filters, context=context) + self.write(cr, uid, ids, {'state':'sending'}, context) + self.send_this_mail(cr, uid, ids, context) + return True + + def send_this_mail(self, cr, uid, ids=None, context=None): + if ids is None: + ids = [] + for id in ids: + try: + account_obj = self.pool.get('email_template.account') + values = self.read(cr, uid, id, [], context) + payload = {} + if values['attachments_ids']: + for attid in values['attachments_ids']: + attachment = self.pool.get('ir.attachment').browse(cr, uid, attid, context)#,['datas_fname','datas']) + payload[attachment.datas_fname] = attachment.datas + print "233333333333333" + result = account_obj.send_mail(cr, uid, + [values['account_id'][0]], + {'To':values.get('email_to', u'') or u'', 'CC':values.get('email_cc', u'') or u'', 'BCC':values.get('email_bcc', u'') or u''}, + values['subject'] or u'', + {'text':values.get('body_text', u'') or u'', 'html':values.get('body_html', u'') or u''}, + payload=payload, context=context) + + if result == True: + self.write(cr, uid, id, {'folder':'sent', 'state':'na', 'date_mail':time.strftime("%Y-%m-%d %H:%M:%S")}, context) + self.historise(cr, uid, [id], "Email sent successfully", context) + else: + self.historise(cr, uid, [id], result, context) + except Exception, error: + logger = netsvc.Logger() + logger.notifyChannel(_("Power Email"), netsvc.LOG_ERROR, _("Sending of Mail %s failed. Probable Reason:Could not login to server\nError: %s") % (id, error)) + self.historise(cr, uid, [id], error, context) + self.write(cr, uid, id, {'state':'na'}, context) + return True + + def historise(self, cr, uid, ids, message='', context=None): + for id in ids: + history = self.read(cr, uid, id, ['history'], context).get('history', '') + self.write(cr, uid, id, {'history':history or '' + "\n" + time.strftime("%Y-%m-%d %H:%M:%S") + ": " + tools.ustr(message)}, context) + + _columns = { + 'email_from':fields.char( + 'From', + size=64), + 'email_to':fields.char( + 'Recepient (To)', + size=250,), + 'email_cc':fields.char( + ' CC', + size=250), + 'email_bcc':fields.char( + ' BCC', + size=250), + 'subject':fields.char( + ' Subject', + size=200,), + 'body_text':fields.text( + 'Standard Body (Text)'), + 'body_html':fields.text( + 'Body (Text-Web Client Only)'), + 'attachments_ids':fields.many2many( + 'ir.attachment', + 'mail_attachments_rel', + 'mail_id', + 'att_id', + 'Attachments'), + 'account_id' :fields.many2one( + 'email_template.account', + 'User account', + required=True), + 'user':fields.related( + 'account_id', + 'user', + type="many2one", + relation="res.users", + string="User"), + 'server_ref':fields.integer( + 'Server Reference of mail', + help="Applicable for inward items only"), + 'mail_type':fields.selection([ + ('multipart/mixed', + 'Has Attachments'), + ('multipart/alternative', + 'Plain Text & HTML with no attachments'), + ('multipart/related', + 'Intermixed content'), + ('text/plain', + 'Plain Text'), + ('text/html', + 'HTML Body'), + ], 'Mail Contents'), + #I like GMAIL which allows putting same mail in many folders + #Lets plan it for 0.9 + 'folder':fields.selection([ + ('drafts', 'Drafts'), + ('outbox', 'Outbox'), + ('trash', 'Trash'), + ('sent', 'Sent Items'), + ], 'Folder', required=True), + 'state':fields.selection([ + ('na', 'Not Applicable'), + ('sending', 'Sending'), + ], 'Status', required=True), + 'date_mail':fields.datetime( + 'Rec/Sent Date'), + 'history':fields.text( + 'History', + readonly=True, + store=True) + } + + _defaults = { + 'state': lambda * a: 'na', + 'folder': lambda * a: 'outbox', + } + + def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False): + if context is None: + context = {} + if context.get('company', False): + users_groups = self.pool.get('res.users').browse(cr, uid, uid, context).groups_id + group_acc_rel = {} + #get all accounts and get a table of {group1:[account1,account2],group2:[account1]} + for each_account_id in self.pool.get('email_template.account').search(cr, uid, [('state', '=', 'approved'), ('company', '=', 'yes')], context=context): + account = self.pool.get('email_template.account').browse(cr, uid, each_account_id, context) + for each_group in account.allowed_groups: + if not account.id in group_acc_rel.get(each_group, []): + groups = group_acc_rel.get(each_group, []) + groups.append(account.id) + group_acc_rel[each_group] = groups + users_company_accounts = [] + for each_group in group_acc_rel.keys(): + if each_group in users_groups: + for each_account in group_acc_rel[each_group]: + if not each_account in users_company_accounts: + users_company_accounts.append(each_account) + args.append(('account_id', 'in', users_company_accounts)) + return super(osv.osv, self).search(cr, uid, args, offset, limit, + order, context=context, count=count) + +email_template_mailbox() + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/email_template/email_template_mailbox_view.xml b/addons/email_template/email_template_mailbox_view.xml new file mode 100755 index 00000000000..e6ff86d1087 --- /dev/null +++ b/addons/email_template/email_template_mailbox_view.xml @@ -0,0 +1,170 @@ +<?xml version="1.0" encoding="UTF-8"?> +<openerp> + <data> + <!-- Email Template--> + <record model="ir.ui.view" id="email_template_mailbox_form"> + <field name="name">email_template.mailbox.form</field> + <field name="model">email_template.mailbox</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="Outbox"> + <group col="4" colspan="2"> + <field name="email_from" colspan="4" select="1"/> + <field name="email_cc" colspan="4" select="1"/> + <field name="date_mail" colspan="4" select="2"/> + </group> + <group col="4" colspan="2"> + <field name="email_to" colspan="4" required="1" select="1" /> + <field name="email_bcc" colspan="4" select="2"/> + <field name="subject" colspan="4" select="1"/> + </group> + <notebook colspan="4"> + <page string="Standard Body"> + <separator colspan="4" string="Standard Body" /> + <notebook colspan="4"> + <page string="Standard Body (Text)"> + <field name="body_text" nolabel="1" colspan="4" select="1"/> + </page> + <page string="Body (HTML-Web Client Only)"> + <field name="body_html" nolabel="1" colspan="4" /> + <!--<label string="Note: HTML body can't be edited with GTK desktop client." colspan="4"/> + --></page> + + </notebook> + </page> + + + <page string="Attachments"> + <group col="4"> + <separator colspan="4" string="Attachments" /> + <field name="attachments_ids" colspan="4" nolabel="1" /> + </group> + </page> + <page string="Advanced"> + <group col="4"> + <field name="account_id" colspan="2" /> + <field name="server_ref" colspan="2" /> + <field name="mail_type" colspan="2" /> + <field name="folder" colspan="2" select="2"/> + <separator string="History" colspan="4" /> + <field name="history" nolabel="1" colspan="4"/> + </group> + </page> + </notebook> + <separator colspan="4" string="" /> + <group col="4" colspan="4"> + <field name="state" colspan="2" readonly="1" /> + <button name="complete_mail" type="object" string="Download Full Mail" colspan="2" states="read,unread" /> + <button name="send_this_mail" type="object" string="Send Mail" /> + </group> + </form> + </field> + </record> + + <!--============================================= TREE VIEWS =============================================--> + <!--DRAFTS--> + <record model="ir.ui.view" id="email_template_drafts_tree"> + <field name="name">email_template.mailbox.draftstree</field> + <field name="model">email_template.mailbox</field> + <field name="type">tree</field> + <field name="arch" type="xml"> + <tree string="Drafts"> + <field name="user" /> + <field name="email_from" select="1" /> + <field name="subject" select="1" /> + <field name="attachments_ids" select="2" /> + <field name="date_mail" select="2" /> + </tree> + </field> + </record> + <!--OUTBOX--> + <record model="ir.ui.view" id="email_template_outbox_tree"> + <field name="name">email_template.mailbox.outboxtree</field> + <field name="model">email_template.mailbox</field> + <field name="type">tree</field> + <field name="arch" type="xml"> + <tree string="Outbox"> + <field name="user" /> + <field name="email_from" select="1" /> + <field name="subject" select="1" /> + <field name="attachments_ids" select="2" /> + <field name="date_mail" select="2" /> + </tree> + </field> + </record> + <!--SENT--> + <record model="ir.ui.view" id="email_template_sentbox_tree"> + <field name="name">email_template.mailbox.sentboxtree</field> + <field name="model">email_template.mailbox</field> + <field name="type">tree</field> + <field name="arch" type="xml"> + <tree string="Sent"> + <field name="user" /> + <field name="email_from" select="1" /> + <field name="subject" select="1" /> + <field name="attachments_ids" select="2" /> + <field name="date_mail" select="2" /> + </tree> + </field> + </record> + <!--TRASH--> + <record model="ir.ui.view" id="email_template_trashbox_tree"> + <field name="name">email_template.mailbox.trashboxtree</field> + <field name="model">email_template.mailbox</field> + <field name="type">tree</field> + <field name="arch" type="xml"> + <tree string="Trash"> + <field name="user" /> + <field name="email_from" select="1" /> + <field name="subject" select="1" /> + <field name="attachments_ids" select="2" /> + <field name="date_mail" select="2" /> + </tree> + </field> + </record> + + <record id="view_email_template_mailbox_search" model="ir.ui.view"> + <field name="name">email_template.mailbox.search</field> + <field name="model">email_template.mailbox</field> + <field name="type">search</field> + <field name="arch" type="xml"> + <search string="Mailboxes"> + <filter icon="terp-crm" string="Drafts" name="draft" domain="[('folder','=','drafts']"/> + <filter icon="terp-crm" string="Outbox" name="outbox" domain="[('folder','=','outbox')]"/> + <separator orientation="vertical"/> + <filter icon="terp-crm" string="Sent" domain="[('folder','=','sent')]"/> + <filter icon="terp-crm" string="Trash" domain="[('folder','=','trash')]"/> + <separator orientation="vertical"/> + <filter icon="terp-crm" string="Not Applicable" domain="[('state','=','na')]"/> + <filter icon="terp-crm" string="Sending" domain="[('state','=','sending')]"/> + <separator orientation="vertical"/> + <field name="email_from" select="1"/> + <field name="email_to" select="1"/> + <field name="subject" select="1"/> + </search> + </field> + </record> + + <record model="ir.actions.act_window" id="action_email_template_mailbox"> + <field name="name">Mailbox</field> + <field name="res_model">email_template.mailbox</field> + <field name="view_type">form</field> + <field name="view_mode">form,tree</field> + <field name="view_id" ref="email_template_outbox_tree" /> + <field name="context">{'group_by': [], 'search_default_draft': 1, 'search_default_outbox': 1}</field> + <field name="search_view_id" ref="view_email_template_mailbox_search"/> + </record> + + <!--======================================== MENUS ========================================--> + <menuitem name="MailBox" id="menu_email_template_mailbox_all_main2" parent="menu_email_template" /> + <menuitem name="Personal" id="menu_email_template_personal" parent="menu_email_template_mailbox_all_main2" /> + <menuitem name="Mails" id="menu_email_template_personal_mails" parent="menu_email_template_personal" action="action_email_template_mailbox"/> + <menuitem name="Company" id="menu_email_template_company" parent="menu_email_template_mailbox_all_main2" /> + <menuitem name="Mails" id="menu_email_template_company_mails" parent="menu_email_template_company" action="action_email_template_mailbox"/> + + </data> +</openerp> + + + + diff --git a/addons/email_template/email_template_scheduler_data.xml b/addons/email_template/email_template_scheduler_data.xml new file mode 100755 index 00000000000..30d69f99398 --- /dev/null +++ b/addons/email_template/email_template_scheduler_data.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data noupdate="1"> + <record forcecreate="True" id="ir_cron_mail_scheduler_action" model="ir.cron"> + <field name="name">Email Template scheduler</field> + <field name="user_id" ref="base.user_root"/> + <field name="interval_number">1</field> + <field name="interval_type">hours</field> + <field name="numbercall">12</field> + <field eval="False" name="doall"/> + <field eval="'email_template.mailbox'" name="model"/> + <field eval="'run_mail_scheduler'" name="function"/> + <field eval="'()'" name="args"/> + </record> + </data> +</openerp> diff --git a/addons/email_template/email_template_view.xml b/addons/email_template/email_template_view.xml new file mode 100755 index 00000000000..8e14a861edc --- /dev/null +++ b/addons/email_template/email_template_view.xml @@ -0,0 +1,188 @@ +<?xml version="1.0" encoding="UTF-8"?> +<openerp> + <data> + <!-- Email Template PReview --> + <record model="ir.ui.view" id="email_template_preview_form"> + <field name="name">email_template.preview.form</field> + <field name="model">email_template.preview</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="Email Preview"> + <field name="rel_model" /> + <newline /> + <field name="rel_model_ref" on_change="on_change_ref(rel_model_ref, context)" /> + <newline /> + <field name="to" /> + <newline /> + <field name="cc" /> + <newline /> + <field name="bcc" /> + <newline /> + <field name="subject" /> + <newline /> + <field name="body_text" /> + <newline /> + <!-- <field name="body_html" widget="text_html" />--> + <!-- + Removed text_html because it doesnt work in GTK + And TinyMCE messes up the HTML in Web Client + --> + <field name="body_html"/> + <newline /> + <field name="report" /> + <group> + <button icon="gtk-ok" special="cancel" string="OK" /> + </group> + </form> + </field> + </record> + + <record id="wizard_email_template_preview" model="ir.actions.act_window"> + <field name="name">Template Preview</field> + <field name="res_model">email_template.preview</field> + <field name="src_model">email_template.preview</field> + <field name="type">ir.actions.act_window</field> + <field name="view_type">form</field> + <field name="view_mode">form</field> + <field name="auto_refresh" eval="1" /> + <field name="target">new</field> + <field name="context">{'ids':active_id}</field> + </record> + <!--EMail client Form view --> + + <record model="ir.ui.view" id="email_template_form"> + <field name="name">email.template.form</field> + <field name="model">email.template</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="Email Templates"> + <field name="name" /> + <field name="object_name" required="1" + on_change="change_model(object_name)" /> + <field name="model_int_name" invisible="1" /> + <notebook colspan="4"> + <page string="Mail Details"> + <group col="4" colspan="2"> + <field name="def_to" colspan="4" required="1" /> + <field name="def_cc" colspan="4" /> + <field name="def_bcc" colspan="4" /> + </group> + <group col="2" colspan="2"> + <field name="def_subject" colspan="4" required="1" /> + <field name="use_sign" colspan="4" /> + <field name="lang" colspan="4" /> + </group> + <separator colspan="3" string="Standard Body" /> + <separator colspan="1" string="Expression Builder" /> + + <notebook> + <page string="Body (Text)"> + <field name="def_body_text" colspan="4" nolabel="1" /> + </page> + <page string="Body (Raw HTML)"> + <field name="def_body_html" colspan="4" nolabel="1" /> + <label string="Note: This is Raw HTML." colspan="4" /> + </page> + </notebook> + <group col="4"> + <field name="template_language" + on_change="onchange_null_value(model_object_field,sub_model_object_field,null_value,template_language,context)" /> + <notebook> + <page string="Insert Simple Field"> + + <field name="model_object_field" + domain="[('model_id','=',object_name),('ttype','!=','one2many'),('ttype','!=','many2many')]" + on_change="onchange_model_object_field(model_object_field, template_language,context)" + colspan="4" /> + <field name="sub_object" readonly="1" colspan="4" /> + <field name="sub_model_object_field" + domain="[('model_id','=',sub_object),('ttype','!=','one2many'),('ttype','!=','many2many')]" + colspan="4" + attrs="{'readonly':[('sub_object','=',False)],'required':[('sub_object','!=',False)]}" + on_change="onchange_sub_model_object_field(model_object_field,sub_model_object_field,template_language,context)" /> + <field name="null_value" colspan="4" + on_change="onchange_null_value(model_object_field,sub_model_object_field,null_value,template_language,context)" /> + <field name="copyvalue" colspan="4" /> + </page> + </notebook> + <button name="%(wizard_email_template_preview)d" string="Preview Template" + type="action" colspan="4" target="new" /> + </group> + </page> + <page string="Security"> + <separator colspan="4" string="Allowed User Groups" /> + <field name="allowed_groups" string="Allowed User Groups" + nolabel="1" /> + </page> + <page string="Advanced"> + <separator string="Automatic Email" colspan="4" /> + <field name="enforce_from_account" attrs="{'required':[('auto_email','=',True)]}" /> + <newline/> + <field name="ref_ir_act_window" /> + <field name="ref_ir_value" /> + <separator string="Attachments (Report to attach)" colspan="4"/> + <field name="file_name" colspan="2" /> + <field name="report_template" colspan="2" + domain="[('model','=',model_int_name)]" /> + </page> + </notebook> + </form> + </field> + </record> + + <record model="ir.ui.view" id="email_template_tree"> + <field name="name">email.template.tree</field> + <field name="model">email.template</field> + <field name="type">tree</field> + <field name="arch" type="xml"> + <tree string="Email Templates"> + <field name="name" select="1" /> + <field name="object_name" required="1" select="1" /> + <field name="def_to" colspan="4" select="2" /> + <field name="def_cc" colspan="4" select="2" /> + <field name="def_bcc" colspan="4" select="2" /> + <field name="def_subject" colspan="4" select="2" /> + <field name="use_sign" colspan="4" select="2" /> + <field name="file_name" colspan="4" /> + <field name="enforce_from_account" /> + </tree> + </field> + </record> + + <record id="view_email_template_search" model="ir.ui.view"> + <field name="name">email.template.search</field> + <field name="model">email.template</field> + <field name="type">search</field> + <field name="arch" type="xml"> + <search string="Templates"> + <separator orientation="vertical"/> + <field name="name" select="1"/> + <field name="object_name" select="1"/> + <field name="def_to" select="1"/> + <separator orientation="vertical"/> + <field name="lang" select="1"/> + <field name="def_subject" select="1"/> + <field name="file_name" select="1"/> + </search> + </field> + </record> + + <record model="ir.actions.act_window" id="action_email_template_tree_all"> + <field name="name">Email Templates</field> + <field name="res_model">email.template</field> + <field name="view_type">form</field> + <field name="view_mode">form,tree</field> + <field name="view_id" ref="email_template_tree" /> + <field name="search_view_id" ref="view_email_template_search"/> + </record> + + <menuitem name="E-MAIL Templates" id="menu_email_template_all" + parent="menu_email_template_configuration" action="action_email_template_tree_all" /> + + </data> +</openerp> + + + + + diff --git a/addons/email_template/email_template_workflow.xml b/addons/email_template/email_template_workflow.xml new file mode 100755 index 00000000000..4d3176f0ae0 --- /dev/null +++ b/addons/email_template/email_template_workflow.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data> + + <record id="PE_ADMIN" model="res.roles"> + <field name="name">Email Administrator</field> + </record> + + <record id="wkf_email_template_setting" model="workflow"> + <field name="name">Email Template Workflow</field> + <field name="osv">email_template.account</field> + <field name="on_create">True</field> + </record> + + <!--Activity --> + + <record id="act_draft" model="workflow.activity"> + <field name="wkf_id" ref="wkf_email_template_setting"/> + <field name="flow_start">True</field> + <field name="name">draft</field> + <field name="kind">function</field> + <field name="action">write({'state':'draft'})</field> + </record> + + <record id="act_approved" model="workflow.activity"> + <field name="name">approval</field> + <field name="wkf_id" ref="wkf_email_template_setting"/> + <field name="kind">function</field> + <field name="action">do_approval()</field> + </record> + + <record id="act_suspended" model="workflow.activity"> + <field name="name">suspended</field> + <field name="wkf_id" ref="wkf_email_template_setting"/> + <field name="kind">function</field> + <field name="action">write({'state':'suspended'})</field> + </record> + <record id="act_dummy" model="workflow.activity"> + <field name="name">dummy</field> + <field name="wkf_id" ref="wkf_email_template_setting"/> + <field name="flow_stop">True</field> + </record> + + <!-- Transition --> + + <record id="trans_awaiting_approved" model="workflow.transition"> + <field name="act_from" ref="act_draft"/> + <field name="act_to" ref="act_approved"/> + <field name="signal">button_approval</field> + <field name="role_id" ref="PE_ADMIN"/> + </record> + + <record id="trans_approved_suspended" model="workflow.transition"> + <field name="act_from" ref="act_approved"/> + <field name="act_to" ref="act_suspended"/> + <field name="signal">button_suspended</field> + <field name="role_id" ref="PE_ADMIN"/> + </record> + <record id="trans_suspended_reapproved" model="workflow.transition"> + <field name="act_from" ref="act_suspended"/> + <field name="act_to" ref="act_draft"/> + <field name="signal">get_reapprove</field> + <field name="role_id" ref="PE_ADMIN"/> + </record> + <record id="trans_suspended_dummy" model="workflow.transition"> + <field name="act_from" ref="act_suspended"/> + <field name="act_to" ref="act_dummy"/> + <field name="signal">get_never</field> + <field name="role_id" ref="PE_ADMIN"/> + </record> + </data> +</openerp> diff --git a/addons/email_template/html2text.py b/addons/email_template/html2text.py new file mode 100755 index 00000000000..f8be00adf0f --- /dev/null +++ b/addons/email_template/html2text.py @@ -0,0 +1,455 @@ +#!/usr/bin/env python +"""html2text: Turn HTML into equivalent Markdown-structured text.""" +__version__ = "2.36" +__author__ = "Aaron Swartz (me@aaronsw.com)" +__copyright__ = "(C) 2004-2008 Aaron Swartz. GNU GPL 3." +__contributors__ = ["Martin 'Joey' Schulze", "Ricardo Reyes", "Kevin Jay North"] + +# TODO: +# Support decoded entities with unifiable. + +if not hasattr(__builtins__, 'True'): True, False = 1, 0 +import re, sys, urllib, htmlentitydefs, codecs, StringIO, types +import sgmllib +import urlparse +sgmllib.charref = re.compile('&#([xX]?[0-9a-fA-F]+)[^0-9a-fA-F]') + +try: from textwrap import wrap +except: pass + +# Use Unicode characters instead of their ascii psuedo-replacements +UNICODE_SNOB = 0 + +# Put the links after each paragraph instead of at the end. +LINKS_EACH_PARAGRAPH = 0 + +# Wrap long lines at position. 0 for no wrapping. (Requires Python 2.3.) +BODY_WIDTH = 78 + +# Don't show internal links (href="#local-anchor") -- corresponding link targets +# won't be visible in the plain text file anyway. +SKIP_INTERNAL_LINKS = False + +### Entity Nonsense ### + +def name2cp(k): + if k == 'apos': return ord("'") + if hasattr(htmlentitydefs, "name2codepoint"): # requires Python 2.3 + return htmlentitydefs.name2codepoint[k] + else: + k = htmlentitydefs.entitydefs[k] + if k.startswith("&#") and k.endswith(";"): return int(k[2:-1]) # not in latin-1 + return ord(codecs.latin_1_decode(k)[0]) + +unifiable = {'rsquo':"'", 'lsquo':"'", 'rdquo':'"', 'ldquo':'"', +'copy':'(C)', 'mdash':'--', 'nbsp':' ', 'rarr':'->', 'larr':'<-', 'middot':'*', +'ndash':'-', 'oelig':'oe', 'aelig':'ae', +'agrave':'a', 'aacute':'a', 'acirc':'a', 'atilde':'a', 'auml':'a', 'aring':'a', +'egrave':'e', 'eacute':'e', 'ecirc':'e', 'euml':'e', +'igrave':'i', 'iacute':'i', 'icirc':'i', 'iuml':'i', +'ograve':'o', 'oacute':'o', 'ocirc':'o', 'otilde':'o', 'ouml':'o', +'ugrave':'u', 'uacute':'u', 'ucirc':'u', 'uuml':'u'} + +unifiable_n = {} + +for k in unifiable.keys(): + unifiable_n[name2cp(k)] = unifiable[k] + +def charref(name): + if name[0] in ['x','X']: + c = int(name[1:], 16) + else: + c = int(name) + + if not UNICODE_SNOB and c in unifiable_n.keys(): + return unifiable_n[c] + else: + return unichr(c) + +def entityref(c): + if not UNICODE_SNOB and c in unifiable.keys(): + return unifiable[c] + else: + try: name2cp(c) + except KeyError: return "&" + c + else: return unichr(name2cp(c)) + +def replaceEntities(s): + s = s.group(1) + if s[0] == "#": + return charref(s[1:]) + else: return entityref(s) + +r_unescape = re.compile(r"&(#?[xX]?(?:[0-9a-fA-F]+|\w{1,8}));") +def unescape(s): + return r_unescape.sub(replaceEntities, s) + +def fixattrs(attrs): + # Fix bug in sgmllib.py + if not attrs: return attrs + newattrs = [] + for attr in attrs: + newattrs.append((attr[0], unescape(attr[1]))) + return newattrs + +### End Entity Nonsense ### + +def onlywhite(line): + """Return true if the line does only consist of whitespace characters.""" + for c in line: + if c is not ' ' and c is not ' ': + return c is ' ' + return line + +def optwrap(text): + """Wrap all paragraphs in the provided text.""" + if not BODY_WIDTH: + return text + + assert wrap, "Requires Python 2.3." + result = '' + newlines = 0 + for para in text.split("\n"): + if len(para) > 0: + if para[0] is not ' ' and para[0] is not '-' and para[0] is not '*': + for line in wrap(para, BODY_WIDTH): + result += line + "\n" + result += "\n" + newlines = 2 + else: + if not onlywhite(para): + result += para + "\n" + newlines = 1 + else: + if newlines < 2: + result += "\n" + newlines += 1 + return result + +def hn(tag): + if tag[0] == 'h' and len(tag) == 2: + try: + n = int(tag[1]) + if n in range(1, 10): return n + except ValueError: return 0 + +class _html2text(sgmllib.SGMLParser): + def __init__(self, out=sys.stdout.write, baseurl=''): + sgmllib.SGMLParser.__init__(self) + + if out is None: self.out = self.outtextf + else: self.out = out + self.outtext = u'' + self.quiet = 0 + self.p_p = 0 + self.outcount = 0 + self.start = 1 + self.space = 0 + self.a = [] + self.astack = [] + self.acount = 0 + self.list = [] + self.blockquote = 0 + self.pre = 0 + self.startpre = 0 + self.lastWasNL = 0 + self.abbr_title = None # current abbreviation definition + self.abbr_data = None # last inner HTML (for abbr being defined) + self.abbr_list = {} # stack of abbreviations to write later + self.baseurl = baseurl + + def outtextf(self, s): + self.outtext += s + + def close(self): + sgmllib.SGMLParser.close(self) + + self.pbr() + self.o('', 0, 'end') + + return self.outtext + + def handle_charref(self, c): + self.o(charref(c)) + + def handle_entityref(self, c): + self.o(entityref(c)) + + def unknown_starttag(self, tag, attrs): + self.handle_tag(tag, attrs, 1) + + def unknown_endtag(self, tag): + self.handle_tag(tag, None, 0) + + def previousIndex(self, attrs): + """ returns the index of certain set of attributes (of a link) in the + self.a list + + If the set of attributes is not found, returns None + """ + if not attrs.has_key('href'): return None + + i = -1 + for a in self.a: + i += 1 + match = 0 + + if a.has_key('href') and a['href'] == attrs['href']: + if a.has_key('title') or attrs.has_key('title'): + if (a.has_key('title') and attrs.has_key('title') and + a['title'] == attrs['title']): + match = True + else: + match = True + + if match: return i + + def handle_tag(self, tag, attrs, start): + attrs = fixattrs(attrs) + + if hn(tag): + self.p() + if start: self.o(hn(tag)*"#" + ' ') + + if tag in ['p', 'div']: self.p() + + if tag == "br" and start: self.o(" \n") + + if tag == "hr" and start: + self.p() + self.o("* * *") + self.p() + + if tag in ["head", "style", 'script']: + if start: self.quiet += 1 + else: self.quiet -= 1 + + if tag in ["body"]: + self.quiet = 0 # sites like 9rules.com never close <head> + + if tag == "blockquote": + if start: + self.p(); self.o('> ', 0, 1); self.start = 1 + self.blockquote += 1 + else: + self.blockquote -= 1 + self.p() + + if tag in ['em', 'i', 'u']: self.o("_") + if tag in ['strong', 'b']: self.o("**") + if tag == "code" and not self.pre: self.o('`') #TODO: `` `this` `` + if tag == "abbr": + if start: + attrsD = {} + for (x, y) in attrs: attrsD[x] = y + attrs = attrsD + + self.abbr_title = None + self.abbr_data = '' + if attrs.has_key('title'): + self.abbr_title = attrs['title'] + else: + if self.abbr_title != None: + self.abbr_list[self.abbr_data] = self.abbr_title + self.abbr_title = None + self.abbr_data = '' + + if tag == "a": + if start: + attrsD = {} + for (x, y) in attrs: attrsD[x] = y + attrs = attrsD + if attrs.has_key('href') and not (SKIP_INTERNAL_LINKS and attrs['href'].startswith('#')): + self.astack.append(attrs) + self.o("[") + else: + self.astack.append(None) + else: + if self.astack: + a = self.astack.pop() + if a: + i = self.previousIndex(a) + if i is not None: + a = self.a[i] + else: + self.acount += 1 + a['count'] = self.acount + a['outcount'] = self.outcount + self.a.append(a) + self.o("][" + `a['count']` + "]") + + if tag == "img" and start: + attrsD = {} + for (x, y) in attrs: attrsD[x] = y + attrs = attrsD + if attrs.has_key('src'): + attrs['href'] = attrs['src'] + alt = attrs.get('alt', '') + i = self.previousIndex(attrs) + if i is not None: + attrs = self.a[i] + else: + self.acount += 1 + attrs['count'] = self.acount + attrs['outcount'] = self.outcount + self.a.append(attrs) + self.o("![") + self.o(alt) + self.o("]["+`attrs['count']`+"]") + + if tag == 'dl' and start: self.p() + if tag == 'dt' and not start: self.pbr() + if tag == 'dd' and start: self.o(' ') + if tag == 'dd' and not start: self.pbr() + + if tag in ["ol", "ul"]: + if start: + self.list.append({'name':tag, 'num':0}) + else: + if self.list: self.list.pop() + + self.p() + + if tag == 'li': + if start: + self.pbr() + if self.list: li = self.list[-1] + else: li = {'name':'ul', 'num':0} + self.o(" "*len(self.list)) #TODO: line up <ol><li>s > 9 correctly. + if li['name'] == "ul": self.o("* ") + elif li['name'] == "ol": + li['num'] += 1 + self.o(`li['num']`+". ") + self.start = 1 + else: + self.pbr() + + if tag in ["table", "tr"] and start: self.p() + if tag == 'td': self.pbr() + + if tag == "pre": + if start: + self.startpre = 1 + self.pre = 1 + else: + self.pre = 0 + self.p() + + def pbr(self): + if self.p_p == 0: self.p_p = 1 + + def p(self): self.p_p = 2 + + def o(self, data, puredata=0, force=0): + if self.abbr_data is not None: self.abbr_data += data + + if not self.quiet: + if puredata and not self.pre: + data = re.sub('\s+', ' ', data) + if data and data[0] == ' ': + self.space = 1 + data = data[1:] + if not data and not force: return + + if self.startpre: + #self.out(" :") #TODO: not output when already one there + self.startpre = 0 + + bq = (">" * self.blockquote) + if not (force and data and data[0] == ">") and self.blockquote: bq += " " + + if self.pre: + bq += " " + data = data.replace("\n", "\n"+bq) + + if self.start: + self.space = 0 + self.p_p = 0 + self.start = 0 + + if force == 'end': + # It's the end. + self.p_p = 0 + self.out("\n") + self.space = 0 + + + if self.p_p: + self.out(('\n'+bq)*self.p_p) + self.space = 0 + + if self.space: + if not self.lastWasNL: self.out(' ') + self.space = 0 + + if self.a and ((self.p_p == 2 and LINKS_EACH_PARAGRAPH) or force == "end"): + if force == "end": self.out("\n") + + newa = [] + for link in self.a: + if self.outcount > link['outcount']: + self.out(" ["+`link['count']`+"]: " + urlparse.urljoin(self.baseurl, link['href'])) + if link.has_key('title'): self.out(" ("+link['title']+")") + self.out("\n") + else: + newa.append(link) + + if self.a != newa: self.out("\n") # Don't need an extra line when nothing was done. + + self.a = newa + + if self.abbr_list and force == "end": + for abbr, definition in self.abbr_list.items(): + self.out(" *[" + abbr + "]: " + definition + "\n") + + self.p_p = 0 + self.out(data) + self.lastWasNL = data and data[-1] == '\n' + self.outcount += 1 + + def handle_data(self, data): + if r'\/script>' in data: self.quiet -= 1 + self.o(data, 1) + + def unknown_decl(self, data): pass + +def wrapwrite(text): sys.stdout.write(text.encode('utf8')) + +def html2text_file(html, out=wrapwrite, baseurl=''): + h = _html2text(out, baseurl) + h.feed(html) + h.feed("") + return h.close() + +def html2text(html, baseurl=''): + return optwrap(html2text_file(html, None, baseurl)) + +if __name__ == "__main__": + baseurl = '' + if sys.argv[1:]: + arg = sys.argv[1] + if arg.startswith('http://'): + baseurl = arg + j = urllib.urlopen(baseurl) + try: + from feedparser import _getCharacterEncoding as enc + except ImportError: + enc = lambda x, y: ('utf-8', 1) + text = j.read() + encoding = enc(j.headers, text)[0] + if encoding == 'us-ascii': encoding = 'utf-8' + data = text.decode(encoding) + + else: + encoding = 'utf8' + if len(sys.argv) > 2: + encoding = sys.argv[2] + f = open(arg, 'r') + try: + data = f.read().decode(encoding) + finally: + f.close() + else: + data = sys.stdin.read().decode('utf8') + wrapwrite(html2text(data, baseurl)) + diff --git a/addons/email_template/security/email_template_security.xml b/addons/email_template/security/email_template_security.xml new file mode 100755 index 00000000000..90067252eca --- /dev/null +++ b/addons/email_template/security/email_template_security.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data noupdate="0"> + + <record id="res_groups_email_template_manager" model="res.groups"> + <field name="name">Email Template / Settings_Manager</field> + </record> + + <record id="res_groups_email_template_userse" model="res.groups"> + <field name="name">Email Template / External_users</field> + </record> + + <record id="res_groups_email_template_usersi" model="res.groups"> + <field name="name">Email Template / Internal_users</field> + </record> + + + </data> +</openerp> diff --git a/addons/email_template/wizard/__init__.py b/addons/email_template/wizard/__init__.py new file mode 100755 index 00000000000..ea6fcfbcd86 --- /dev/null +++ b/addons/email_template/wizard/__init__.py @@ -0,0 +1 @@ +import email_template_send_wizard diff --git a/addons/email_template/wizard/email_template_send_wizard.py b/addons/email_template/wizard/email_template_send_wizard.py new file mode 100755 index 00000000000..7d27eab9adf --- /dev/null +++ b/addons/email_template/wizard/email_template_send_wizard.py @@ -0,0 +1,235 @@ +from osv import osv, fields +from mako.template import Template +from mako import exceptions +import netsvc +import base64 +import time +from tools.translate import _ +import tools +from email_template.email_template import get_value + +class email_template_send_wizard(osv.osv_memory): + _name = 'email_template.send.wizard' + _description = 'This is the wizard for sending mail' + _rec_name = "subject" + + def _get_accounts(self, cr, uid, context=None): + if context is None: + context = {} + + template = self._get_template(cr, uid, context) + if not template: + return [] + + logger = netsvc.Logger() + + if template.enforce_from_account: + return [(template.enforce_from_account.id, '%s (%s)' % (template.enforce_from_account.name, template.enforce_from_account.email_id))] + else: + account_id = self.pool.get('email_template.account').search(cr,uid,[('company','=','no'),('user','=',uid)], context=context) + if account_id: + account = self.pool.get('email_template.account').browse(cr,uid,account_id, context) + return [(r.id,r.name + " (" + r.email_id + ")") for r in account] + else: + logger.notifyChannel(_("Power Email"), netsvc.LOG_ERROR, _("No personal email accounts are configured for you. \nEither ask admin to enforce an account for this template or get yourself a personal power email account.")) + raise osv.except_osv(_("Power Email"),_("No personal email accounts are configured for you. \nEither ask admin to enforce an account for this template or get yourself a personal power email account.")) + + def get_value(self, cursor, user, template, message, context=None, id=None): + """Gets the value of the message parsed with the content of object id (or the first 'src_rec_ids' if id is not given)""" + if not message: + return '' + if not id: + id = context['src_rec_ids'][0] + return get_value(cursor, user, id, message, template, context) + + def _get_template(self, cr, uid, context=None): + if context is None: + context = {} + if not 'template' in context and not 'template_id' in context: + return None + if 'template_id' in context.keys(): + template_ids = self.pool.get('email.template').search(cr, uid, [('id','=',context['template_id'])], context=context) + elif 'template' in context.keys(): + # Old versions of email_template used the name of the template. This caused + # problems when the user changed the name of the template, but we keep the code + # for compatibility with those versions. + template_ids = self.pool.get('email.template').search(cr, uid, [('name','=',context['template'])], context=context) + if not template_ids: + return None + + template = self.pool.get('email.template').browse(cr, uid, template_ids[0], context) + + lang = self.get_value(cr, uid, template, template.lang, context) + if lang: + # Use translated template if necessary + ctx = context.copy() + ctx['lang'] = lang + template = self.pool.get('email.template').browse(cr, uid, template.id, ctx) + return template + + def _get_template_value(self, cr, uid, field, context=None): + template = self._get_template(cr, uid, context) + if not template: + return False + if len(context['src_rec_ids']) > 1: # Multiple Mail: Gets original template values for multiple email change + return getattr(template, field) + else: # Simple Mail: Gets computed template values + return self.get_value(cr, uid, template, getattr(template, field), context) + + _columns = { + 'state':fields.selection([ + ('single','Simple Mail Wizard Step 1'), + ('multi','Multiple Mail Wizard Step 1'), + ('done','Wizard Complete') + ],'Status',readonly=True), + 'ref_template':fields.many2one('email.template','Template',readonly=True), + 'rel_model':fields.many2one('ir.model','Model',readonly=True), + 'rel_model_ref':fields.integer('Referred Document',readonly=True), + 'from':fields.selection(_get_accounts,'From Account',select=True), + 'to':fields.char('To',size=250,required=True), + 'cc':fields.char('CC',size=250,), + 'bcc':fields.char('BCC',size=250,), + 'subject':fields.char('Subject',size=200), + 'body_text':fields.text('Body',), + 'body_html':fields.text('Body',), + 'report':fields.char('Report File Name',size=100,), + 'signature':fields.boolean('Attach my signature to mail'), + #'filename':fields.text('File Name'), + 'requested':fields.integer('No of requested Mails',readonly=True), + 'generated':fields.integer('No of generated Mails',readonly=True), + 'full_success':fields.boolean('Complete Success',readonly=True), + 'attachment_ids': fields.many2many('ir.attachment','send_wizard_attachment_rel', 'wizard_id', 'attachment_id', 'Attachments'), + } + + _defaults = { + 'state': lambda self,cr,uid,ctx: len(ctx['src_rec_ids']) > 1 and 'multi' or 'single', + 'rel_model': lambda self,cr,uid,ctx: self.pool.get('ir.model').search(cr,uid,[('model','=',ctx['src_model'])],context=ctx)[0], + 'rel_model_ref': lambda self,cr,uid,ctx: ctx['active_id'], + 'to': lambda self,cr,uid,ctx: self._get_template_value(cr, uid, 'def_to', ctx), + 'cc': lambda self,cr,uid,ctx: self._get_template_value(cr, uid, 'def_cc', ctx), + 'bcc': lambda self,cr,uid,ctx: self._get_template_value(cr, uid, 'def_bcc', ctx), + 'subject':lambda self,cr,uid,ctx: self._get_template_value(cr, uid, 'def_subject', ctx), + 'body_text':lambda self,cr,uid,ctx: self._get_template_value(cr, uid, 'def_body_text', ctx), + 'body_html':lambda self,cr,uid,ctx: self._get_template_value(cr, uid, 'def_body_html', ctx), + 'report': lambda self,cr,uid,ctx: self._get_template_value(cr, uid, 'file_name', ctx), + 'signature': lambda self,cr,uid,ctx: self._get_template(cr, uid, ctx).use_sign, + 'ref_template':lambda self,cr,uid,ctx: self._get_template(cr, uid, ctx).id, + 'requested':lambda self,cr,uid,ctx: len(ctx['src_rec_ids']), + 'full_success': lambda *a: False + } + + def fields_get(self, cr, uid, fields=None, context=None, read_access=True): + result = super(email_template_send_wizard, self).fields_get(cr, uid, fields, context, read_access) + if 'attachment_ids' in result and 'src_model' in context: + result['attachment_ids']['domain'] = [('res_model','=',context['src_model']),('res_id','=',context['active_id'])] + return result + + def sav_to_drafts(self, cr, uid, ids, context=None): + if context is None: + context = {} + mailid = self.save_to_mailbox(cr, uid, ids, context) + if self.pool.get('email_template.mailbox').write(cr, uid, mailid, {'folder':'drafts'}, context): + return {'type':'ir.actions.act_window_close' } + + def send_mail(self, cr, uid, ids, context=None): + if context is None: + context = {} + mailid = self.save_to_mailbox(cr, uid, ids, context) + if self.pool.get('email_template.mailbox').write(cr, uid, mailid, {'folder':'outbox'}, context): + return {'type':'ir.actions.act_window_close' } + + def get_generated(self, cr, uid, ids=None, context=None): + if ids is None: + ids = [] + if context is None: + context = {} + logger = netsvc.Logger() + if context['src_rec_ids'] and len(context['src_rec_ids'])>1: + #Means there are multiple items selected for email. + mail_ids = self.save_to_mailbox(cr, uid, ids, context) + if mail_ids: + self.pool.get('email_template.mailbox').write(cr, uid, mail_ids, {'folder':'outbox'}, context) + logger.notifyChannel(_("Power Email"), netsvc.LOG_INFO, _("Emails for multiple items saved in outbox.")) + self.write(cr, uid, ids, { + 'generated':len(mail_ids), + 'state':'done' + }, context) + else: + raise osv.except_osv(_("Power Email"),_("Email sending failed for one or more objects.")) + return True + + def save_to_mailbox(self, cr, uid, ids, context=None): + def get_end_value(id, value): + if len(context['src_rec_ids']) > 1: # Multiple Mail: Gets value from the template + return self.get_value(cr, uid, template, value, context, id) + else: + return value + + mail_ids = [] + template = self._get_template(cr, uid, context) + for id in context['src_rec_ids']: + print "@22222222222222222222222",ids + screen_vals = self.read(cr, uid, ids[0], [],context) + account = self.pool.get('email_template.account').read(cr, uid, screen_vals['from'], context=context) + vals = { + 'email_from': tools.ustr(account['name']) + "<" + tools.ustr(account['email_id']) + ">", + 'email_to': get_end_value(id, screen_vals['to']), + 'email_cc': get_end_value(id, screen_vals['cc']), + 'email_bcc': get_end_value(id, screen_vals['bcc']), + 'subject': get_end_value(id, screen_vals['subject']), + 'body_text': get_end_value(id, screen_vals['body_text']), + 'body_html': get_end_value(id, screen_vals['body_html']), + 'account_id': screen_vals['from'], + 'state':'na', + 'mail_type':'multipart/alternative' #Options:'multipart/mixed','multipart/alternative','text/plain','text/html' + } + if screen_vals['signature']: + signature = self.pool.get('res.users').read(cr, uid, uid, ['signature'], context)['signature'] + if signature: + vals['body_text'] = tools.ustr(vals['body_text'] or '') + signature + vals['body_html'] = tools.ustr(vals['body_html'] or '') + signature + + attachment_ids = [] + + #Create partly the mail and later update attachments + mail_id = self.pool.get('email_template.mailbox').create(cr, uid, vals, context) + mail_ids.append(mail_id) + if template.report_template: + reportname = 'report.' + self.pool.get('ir.actions.report.xml').read(cr, uid, template.report_template.id, ['report_name'], context)['report_name'] + data = {} + data['model'] = self.pool.get('ir.model').browse(cr, uid, screen_vals['rel_model'], context).model + + # Ensure report is rendered using template's language + ctx = context.copy() + if template.lang: + ctx['lang'] = self.get_value(cr, uid, template, template.lang, context, id) + service = netsvc.LocalService(reportname) + (result, format) = service.create(cr, uid, [id], data, ctx) + attachment_id = self.pool.get('ir.attachment').create(cr, uid, { + 'name': _('%s (Email Attachment)') % tools.ustr(vals['subject']), + 'datas': base64.b64encode(result), + 'datas_fname': tools.ustr(get_end_value(id, screen_vals['report']) or _('Report')) + "." + format, + 'description': vals['body_text'] or _("No Description"), + 'res_model': 'email_template.mailbox', + 'res_id': mail_id + }, context) + attachment_ids.append( attachment_id ) + + # Add document attachments + for attachment_id in screen_vals.get('attachment_ids',[]): + new_id = self.pool.get('ir.attachment').copy(cr, uid, attachment_id, { + 'res_model': 'email_template.mailbox', + 'res_id': mail_id, + }, context) + attachment_ids.append( new_id ) + + if attachment_ids: + self.pool.get('email_template.mailbox').write(cr, uid, mail_id, { + 'attachments_ids': [[6, 0, attachment_ids]], + 'mail_type': 'multipart/mixed' + }, context) + + return mail_ids +email_template_send_wizard() + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/email_template/wizard/email_template_send_wizard_view.xml b/addons/email_template/wizard/email_template_send_wizard_view.xml new file mode 100755 index 00000000000..5f2f1641e31 --- /dev/null +++ b/addons/email_template/wizard/email_template_send_wizard_view.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="utf-8"?> +<openerp> + <data> + + <record model="ir.ui.view" id="email_template_send_wizard_form"> + <field name="name">email_template.send.wizard.form</field> + <field name="model">email_template.send.wizard</field> + <field name="type">form</field> + <field name="arch" type="xml"> + <form string="Send mail Wizard"> + <group col="4" colspan="4"> + <field name="rel_model" colspan="2" /> + <field name="from" required="1" colspan="2" /> + </group> + <group col="4" colspan="4"> + <group col="6" colspan="4"> + <field name="to" select="1" colspan="4" /> + <newline /> + <field name="cc" select="2" colspan="4" /> + <newline /> + <field name="bcc" select="2" colspan="4" /> + <newline /> + <field name="subject" select="2" colspan="4" attrs="{'required':[('state','=','single')]}" /> + <newline /> + <field name="report" colspan="4" /> + </group> + <separator string="" colspan="4" /> + <notebook colspan="4"> + <page string="Body (Plain Text)"> + <field name="body_text" select="2" colspan="4" nolabel="1" /> + </page> + <page string="Body (HTML)"> + <field name="body_html" select="2" colspan="4" nolabel="1" /> + <!--<label string="Note: HTML body can't be edited with GTK desktop client." colspan="4"/> + --></page> + <page string="Attachments"> + <label string="Add here all attachments of the current document you want to include in the e-mail." colspan="4"/> + <field name="attachment_ids" colspan="4" nolabel="1"/> + </page> + </notebook> + <field name="signature" colspan="4" /> + </group> + <group col="4" colspan="4" attrs="{'invisible':[('state','!=','single')]}"> + <button icon="gtk-apply" name="sav_to_drafts" string="Save in Drafts" type="object" /> + <button icon="gtk-ok" name="send_mail" string="Send now" type="object" /> + <button icon="gtk-cancel" special="cancel" string="Discard Mail" /> + </group> + <group col="4" colspan="4" attrs="{'invisible':[('state','=','single')]}"> + <label string="Tip: Multiple emails are sent in the same language (the first one is proposed). We suggest you send emails in groups according to language." colspan="4"/> + <field name="requested" /> + <field name="generated" /> + <button icon="gtk-ok" name="get_generated" string="Send all mails" type="object" states="multi" colspan="2" /> + <button icon="gtk-cancel" special="cancel" string="Discard Mail" colspan="2" states="multi" /> + </group> + <button icon="gtk-ok" special="cancel" string="Close" colspan="4" states="done" /> + <field name="state" /> + <newline /> + <label string="After clicking send all mails, mails will be sent to outbox and cleared in next Send/Recieve" colspan="4"/> + </form> + </field> + </record> + </data> +</openerp> + diff --git a/addons/hr_recruitment/hr_recruitment_view.xml b/addons/hr_recruitment/hr_recruitment_view.xml index 277099aca02..65d5db06fe3 100644 --- a/addons/hr_recruitment/hr_recruitment_view.xml +++ b/addons/hr_recruitment/hr_recruitment_view.xml @@ -2,6 +2,12 @@ <openerp> <data> + <menuitem + id="menu_hr_config_applicant" + name="Applicant" + parent="hr.menu_hr_configuration" + /> + # ------------------------------------------------------ # Job Categories # ------------------------------------------------------ @@ -25,7 +31,8 @@ <field name="domain">[('object_id.model', '=', 'hr.applicant')]</field> <field name="context">{'object_id':'hr.applicant'}</field> </record> - <menuitem action="hr_job_stage_act" id="menu_hr_job_stage_act" parent="crm.menu_crm_case_stage"/> + + <menuitem action="hr_job_stage_act" id="menu_hr_job_stage_act" name="Stages" parent="menu_hr_config_applicant"/> # ------------------------------------------------------ # Jobs diff --git a/addons/hr_timesheet_invoice/report/hr_timesheet_invoice_report_view.xml b/addons/hr_timesheet_invoice/report/hr_timesheet_invoice_report_view.xml index eccdb721de0..880e5837fd2 100644 --- a/addons/hr_timesheet_invoice/report/hr_timesheet_invoice_report_view.xml +++ b/addons/hr_timesheet_invoice/report/hr_timesheet_invoice_report_view.xml @@ -462,6 +462,7 @@ <newline/> <group expand="1" string="Group By..."> <filter string="User" icon="terp-project" domain="[]" context="{'group_by':'user_id'}"/> + <separator orientation="vertical"/> <filter string="Product" icon="terp-project" domain="[]" context="{'group_by':'product_id'}"/> <filter string="Analytic Account" icon="terp-project" domain="[]" context="{'group_by':'analytic_account_id'}"/> <filter string="General Account" icon="terp-project" domain="[]" context="{'group_by':'general_account_id'}"/> diff --git a/addons/hr_timesheet_sheet/report/timesheet_report_view.xml b/addons/hr_timesheet_sheet/report/timesheet_report_view.xml index c7cf7b0495e..32e8bda4f7f 100644 --- a/addons/hr_timesheet_sheet/report/timesheet_report_view.xml +++ b/addons/hr_timesheet_sheet/report/timesheet_report_view.xml @@ -74,12 +74,12 @@ domain="[('user_id','=',False)]"/> </field> <field name="company_id" widget="selection" groups="base.group_multi_company"/> - </group> - <newline/> + </group> + <newline/> <group expand="1" string="Group By..."> <filter string="User" name="User" icon="terp-hr" context="{'group_by':'user_id'}"/> - <filter string="Product" icon="terp-hr" context="{'group_by':'product_id'}"/> <separator orientation="vertical"/> + <filter string="Product" icon="terp-hr" context="{'group_by':'product_id'}"/> <filter string="Type of Invoicing" icon="terp-hr" context="{'group_by':'to_invoice'}"/> <filter string="Analytic Account" icon="terp-hr" context="{'group_by':'account_id'}"/> <filter string="General Account" icon="terp-hr" context="{'group_by':'general_account_id'}"/> @@ -111,7 +111,7 @@ <separator orientation="vertical"/> <field name="general_account_id"/> <field name="to_invoice" widget="selection"/> - </group> + </group> </search> </field> </record> diff --git a/addons/mail_gateway/mail_gateway_view.xml b/addons/mail_gateway/mail_gateway_view.xml index 5cf35fa3420..611416055f7 100644 --- a/addons/mail_gateway/mail_gateway_view.xml +++ b/addons/mail_gateway/mail_gateway_view.xml @@ -8,32 +8,32 @@ <field name="arch" type="xml"> <form string="mailgate message"> <group colspan="4" col="6"> - <field name="name" required="1" select="1"/> - <field name="date" required="1" select="1"/> - <field name="user_id" string="Responsible" select="1"/> - </group> + <field name="name" required="1" select="1"/> + <field name="date" required="1" select="1"/> + <field name="user_id" string="Responsible" select="1"/> + </group> <notebook colspan="4"> - <page string="Details"> - <group col="4" colspan="4"> - <separator string="Email Details" colspan="4"/> - <field name="email_from" /> - <field name="email_to" /> - <field name="email_cc" /> - <field name="email_bcc" /> - <field name="message_id" /> - </group> - <separator string="Description" colspan="4"/> + <page string="Details"> + <group col="4" colspan="4"> + <separator string="Email Details" colspan="4"/> + <field name="email_from" /> + <field name="email_to" /> + <field name="email_cc" /> + <field name="email_bcc" /> + <field name="message_id" /> + </group> + <separator string="Description" colspan="4"/> <field name="description" nolabel="1" colspan="4" /> - </page> - <page string="Attachments"> - <separator string="Attachments" colspan="4"/> - <field name="attachment_ids" nolabel="1" colspan="4" readonly="1"/> - </page> - </notebook> + </page> + <page string="Attachments"> + <separator string="Attachments" colspan="4"/> + <field name="attachment_ids" nolabel="1" colspan="4" readonly="1"/> + </page> + </notebook> </form> </field> </record> - + <record model="ir.ui.view" id="view_mailgate_message_tree"> <field name="name">mailgate.message.tree</field> <field name="model">mailgate.message</field> @@ -41,12 +41,12 @@ <field name="arch" type="xml"> <tree string="Mailgateway Message"> <field name="date" /> - <field name="email_from" /> - <field name="user_id" /> + <field name="email_from" /> + <field name="user_id" /> </tree> </field> </record> - + <record model="ir.ui.view" id="view_mailgate_message_search"> <field name="name">mailgate.message.search</field> <field name="model">mailgate.message</field> @@ -56,11 +56,11 @@ <field name="name" /> <field name="date" /> <field name="user_id" /> - <field name="message_id" /> + <field name="message_id" /> </search> </field> </record> - + <record model="ir.ui.view" id="view_mailgate_thread_form"> <field name="name">mailgate.thread.form</field> @@ -71,33 +71,33 @@ <field name="thread" select="1"/> <separator string="Logs" colspan="4"/> <field name="log_ids" nolabel="1" colspan="4" domain="[('history', '=', True)]"> - <tree string="Mailgateway Logs"> - <field name="name" select="1" /> - <field name="date" /> - </tree> - <form string="Mailgate Logs"> - <field name="name" /> - <field name="date" /> - <field name="user_id" /> - <field name="message_id" /> - <notebook colspan="4"> - <page string="Email Details"> - <group col="4" colspan="4"> - <separator string="Email Details" colspan="4"/> - <field name="email_from" /> - <field name="email_to" /> - <field name="email_cc" /> - <field name="email_bcc" /> - </group> - <separator string="Description" colspan="4"/> + <tree string="Mailgateway Logs"> + <field name="name" select="1" /> + <field name="date" /> + </tree> + <form string="Mailgate Logs"> + <field name="name" /> + <field name="date" /> + <field name="user_id" /> + <field name="message_id" /> + <notebook colspan="4"> + <page string="Email Details"> + <group col="4" colspan="4"> + <separator string="Email Details" colspan="4"/> + <field name="email_from" /> + <field name="email_to" /> + <field name="email_cc" /> + <field name="email_bcc" /> + </group> + <separator string="Description" colspan="4"/> <field name="description" nolabel="1" colspan="4" /> - </page> - <page string="Attachments"> - <separator string="Attachments" colspan="4"/> - <field name="attachment_ids" nolabel="1" colspan="4" /> - </page> - </notebook> - </form> + </page> + <page string="Attachments"> + <separator string="Attachments" colspan="4"/> + <field name="attachment_ids" nolabel="1" colspan="4" /> + </page> + </notebook> + </form> </field> <separator string="Histories" colspan="4"/> <field name="message_ids" nolabel="1" colspan="4" domain="[('history', '=', True)]"> @@ -131,7 +131,7 @@ </form> </field> </record> - + <record model="ir.ui.view" id="view_mailgate_thread_tree"> <field name="name">mailgate.thread.tree</field> <field name="model">mailgate.thread</field> @@ -143,41 +143,41 @@ </tree> </field> </record> - + <record model="ir.actions.act_window" id="action_view_mailgate_thread"> - <field name="name">Mailgateway Threads</field> - <field name="res_model">mailgate.thread</field> - <field name="view_mode">tree,form</field> - <field name="view_type">form</field> - <field name="view_id" ref="view_mailgate_thread_tree"/> - </record> - - <record model="ir.actions.act_window.view" id="action_view_mailgate_thread_view1"> - <field name="sequence" eval="1"/> - <field name="view_mode">tree</field> - <field name="view_id" ref="view_mailgate_thread_tree"/> - <field name="act_window_id" ref="action_view_mailgate_thread"/> - </record> - <record model="ir.actions.act_window.view" id="action_view_mailgate_thread_view2"> - <field name="sequence" eval="2"/> - <field name="view_mode">form</field> - <field name="view_id" ref="view_mailgate_thread_form"/> - <field name="act_window_id" ref="action_view_mailgate_thread"/> - </record> - - - <!-- <menuitem id="base.menu_crm_configuration" name="Cases" + <field name="name">Mailgateway Threads</field> + <field name="res_model">mailgate.thread</field> + <field name="view_mode">tree,form</field> + <field name="view_type">form</field> + <field name="view_id" ref="view_mailgate_thread_tree"/> + </record> + + <record model="ir.actions.act_window.view" id="action_view_mailgate_thread_view1"> + <field name="sequence" eval="1"/> + <field name="view_mode">tree</field> + <field name="view_id" ref="view_mailgate_thread_tree"/> + <field name="act_window_id" ref="action_view_mailgate_thread"/> + </record> + <record model="ir.actions.act_window.view" id="action_view_mailgate_thread_view2"> + <field name="sequence" eval="2"/> + <field name="view_mode">form</field> + <field name="view_id" ref="view_mailgate_thread_form"/> + <field name="act_window_id" ref="action_view_mailgate_thread"/> + </record> + + + <!-- <menuitem id="base.menu_crm_configuration" name="Cases" parent="base.menu_base_config" sequence="0"/> <menuitem id="menu_mailgate_thread" name="Mailgateway Threads" action="action_view_mailgate_thread" - parent="base.menu_crm_configuration" sequence="20"/> - --> + parent="base.menu_crm_configuration" sequence="20"/> + --> <act_window domain="[('partner_id', '=', active_id), ('history', '=', True)]" id="act_res_partner_emails" name="Emails" res_model="mailgate.message" src_model="res.partner" - view_id="view_mailgate_message_tree" + view_id="view_mailgate_message_tree" /> </data> -</openerp> +</openerp>
\ No newline at end of file diff --git a/addons/marketing/marketing_view.xml b/addons/marketing/marketing_view.xml index 7a72f39c6eb..cc6200537cf 100644 --- a/addons/marketing/marketing_view.xml +++ b/addons/marketing/marketing_view.xml @@ -14,20 +14,16 @@ <form position="attributes"> <attribute name="string">Marketing Modules Installation</attribute> </form> - <separator string="title" position="attributes"> - <attribute name="string">Configure Your Marketing System</attribute> + <attribute name="string">Select Marketing Modules to Install</attribute> </separator> <xpath expr="//label[@string='description']" position="attributes"> - <attribute name="string">You can enhance OpenERP's basic Marketing support with a few additional OpenERP applications</attribute> + <attribute name="string">OpenERP provides tools to automate your leads process, design marketing campaigns and profile efficiently your customers.</attribute> </xpath> <group colspan="8"> - <group colspan="2" col="2"> - <separator string="Marketing Mdules" colspan="4" /> <field name="marketing_campaign" /> <field name="crm_profiling" /> - </group> </group> </data> </field> @@ -49,4 +45,4 @@ </record> </data> -</openerp>
\ No newline at end of file +</openerp> diff --git a/addons/marketing/marketing_wizard.py b/addons/marketing/marketing_wizard.py index 443fb09ed48..aee302283b2 100644 --- a/addons/marketing/marketing_wizard.py +++ b/addons/marketing/marketing_wizard.py @@ -24,15 +24,13 @@ from osv import fields, osv class marketing_installer(osv.osv_memory): _name = 'marketing.installer' _inherit = 'res.config.installer' - _columns = { # Generic modules - 'marketing_campaign':fields.boolean('Marketing Campaign', - help="Helps you to manage your marketing campaigns step by step."), - 'crm_profiling':fields.boolean('Crm Profile', - help="Helps you to perform segmentation within partners.") - } - + 'marketing_campaign':fields.boolean('Marketing Campaigns', + help="Helps you to manage marketing campaigns and automate actions and communication steps."), + 'crm_profiling':fields.boolean('Profiling Tools', + help="Helps you to perform segmentation within partners and design questionaires.") + } marketing_installer() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/marketing_campaign/__openerp__.py b/addons/marketing_campaign/__openerp__.py index aca6c2f6d28..992731c1332 100755 --- a/addons/marketing_campaign/__openerp__.py +++ b/addons/marketing_campaign/__openerp__.py @@ -24,10 +24,9 @@ "name" : "", "version" : "1.1", "depends" : ["marketing", - "crm", + "crm", "document", - "poweremail" # need to get this module form the branch - # lp:poweremail + "email_template" ], "author" : "Tiny", "category": 'Generic Modules/Marketing', @@ -40,7 +39,6 @@ 'marketing_campaign_data.xml', 'marketing_campaign_workflow.xml', 'report/campaign_analysis_view.xml', - 'marketing_campaign_demo.xml' ], 'demo_xml': [ 'marketing_campaign_demo.xml', diff --git a/addons/marketing_campaign/marketing_campaign.py b/addons/marketing_campaign/marketing_campaign.py index 398e0e805be..3f29e03c968 100755 --- a/addons/marketing_campaign/marketing_campaign.py +++ b/addons/marketing_campaign/marketing_campaign.py @@ -129,9 +129,7 @@ class marketing_campaign_segment(osv.osv): #{{{ curr_date = time.strftime('%Y-%m-%d %H:%M:%S') vals = {'state': 'running'} if not segment.date_run: - vals['date_run'] = segment.campaign_id.date_run and \ - segment.campaign_id.date_run or \ - time.strftime('%Y-%m-%d %H:%M:%S') + vals['date_run'] = time.strftime('%Y-%m-%d %H:%M:%S') if not segment.sync_last_date: vals['sync_last_date']=curr_date if not segment.date_done: @@ -142,7 +140,7 @@ class marketing_campaign_segment(osv.osv): #{{{ def state_done_set(self, cr, uid, ids, *args): date_done = self.browse(cr, uid, ids[0]).date_done - if (date_done > time.strftime('%Y-%m-%d')): + if (date_done > time.strftime('%Y-%m-%d %H:%M:%S')): raise osv.except_osv("Error", "Segment cannot be closed before end date") wi_ids = self.pool.get("marketing.campaign.workitem").search(cr, uid, @@ -186,7 +184,7 @@ class marketing_campaign_segment(osv.osv): #{{{ } self.pool.get('marketing.campaign.workitem').create( cr, uid, wi_vals) - self.write(cr, uid, segment.id, {'sync_last_date':action_date}) + self.write(cr, uid, segment.id, {'sync_last_date':action_date}) return True marketing_campaign_segment()#}}} @@ -196,7 +194,7 @@ class marketing_campaign_activity(osv.osv): #{{{ _description = "Campaign Activity" _columns = { - 'name': fields.char('Name', size=64, required=True), + 'name': fields.char('Name', size=128, required=True), 'campaign_id': fields.many2one('marketing.campaign', 'Campaign', required = True, ondelete='cascade'), 'object_id': fields.related('campaign_id','object_id', @@ -212,7 +210,7 @@ class marketing_campaign_activity(osv.osv): #{{{ ('action', 'Action'), ('subcampaign', 'Sub-Campaign')], 'Type', required=True), - 'email_template_id': fields.many2one('poweremail.templates','Email Template'), + 'email_template_id': fields.many2one('email.template','Email Template'), 'report_id': fields.many2one('ir.actions.report.xml', 'Reports', ), 'report_directory_id': fields.many2one('document.directory','Directory', help="Folder is used to store the generated reports"), @@ -254,8 +252,9 @@ class marketing_campaign_activity(osv.osv): #{{{ def process(self, cr, uid, act_id, wi_id, context={}): activity = self.browse(cr, uid, act_id) - workitem_obj = self.pool.get('marketing.campaign.workitem') + workitem_obj = self.pool.get('marketing.campaign.workitem') workitem = workitem_obj.browse(cr, uid, wi_id) + if activity.type == 'paper' : service = netsvc.LocalService('report.%s'%activity.report_id.report_name) (report_data, format) = service.create(cr, uid, [], {}, {}) @@ -278,12 +277,12 @@ class marketing_campaign_activity(osv.osv): #{{{ if not workitem.partner_id.email: return {'error_msg' : "There is no email defined for the partner"} vals = { - 'pem_from': tools.ustr(accounts.name) + "<" + tools.ustr(accounts.email_id) + ">", - 'pem_to': workitem.partner_id.email, - 'pem_subject': template.def_subject, - 'pem_body_text': template.def_body_text, - 'pem_body_html': template.def_body_html, - 'pem_account_id':accounts.id, + 'email_from': tools.ustr(accounts.name) + "<" + tools.ustr(accounts.email_id) + ">", + 'email_to': workitem.partner_id.email, + 'subject': template.def_subject, + 'body_text': template.def_body_text, + 'body_html': template.def_body_html, + 'account_id':accounts.id, 'state':'na', 'mail_type':'multipart/alternative' #Options:'multipart/mixed','multipart/alternative','text/plain','text/html' } @@ -294,12 +293,11 @@ class marketing_campaign_activity(osv.osv): #{{{ # vals['pem_body_html'] = tools.ustr(vals['pem_body_html'] or '') + signature #Create partly the mail and later update attachments - mail_id = self.pool.get('poweremail.mailbox').create(cr, uid, vals, context) + mail_id = self.pool.get('email_template.mailbox').create(cr, uid, vals, context) elif activity.type == 'action' : server_obj = self.pool.get('ir.actions.server') server_obj.run(cr, uid, [activity.server_action_id.id], context) #??? - return True marketing_campaign_activity()#}}} @@ -410,13 +408,13 @@ class marketing_campaign_workitem(osv.osv): #{{{ marketing_campaign_workitem() #}}} -class poweremail_templates(osv.osv): - _inherit = "poweremail.templates" +class email_template(osv.osv): + _inherit = "email.template" _defaults = { 'object_name': lambda obj, cr, uid, context: context.get('object_id',False), } -poweremail_templates() +email_template() class report_xml(osv.osv): diff --git a/addons/marketing_campaign/marketing_campaign_demo.xml b/addons/marketing_campaign/marketing_campaign_demo.xml index 9c2211903c5..7296ebf9c50 100644 --- a/addons/marketing_campaign/marketing_campaign_demo.xml +++ b/addons/marketing_campaign/marketing_campaign_demo.xml @@ -21,8 +21,9 @@ <field eval=""""ressource"""" name="type"/> <field name="ressource_type_id" ref="model_marketing_campaign"/> </record> -<!-- Power email tempalte --> - <record id="poweremail_templates_foropenerpondemandfreetrial0" model="poweremail.templates"> + + <!-- Email tempalte --> + <record id="email_template_1" model="email.template"> <field name="def_subject">Thanks for showing interest in OpenERP</field> <field name="def_to">info@tinyerp.com</field> <field eval="[(6,0,[])]" name="allowed_groups"/> @@ -32,17 +33,163 @@ <field model="ir.values" name="ref_ir_value" search="[('name', '=', u'Send Mail (For OpenERP OnDemand Free Trial 2010)')]"/> <field name="object_name" ref="crm.model_crm_lead"/> <field eval="0" name="use_sign"/> - <field name="def_body_text">Hello, -Thanks for generous interest you have shown in the open ERP. -Regards, -OpenERP Team,</field> + <field name="def_body_text">Hello,Thanks for generous interest you have shown in the open ERP.Regards,OpenERP Team,</field> <field name="template_language">mako</field> <field eval="0" name="send_on_create"/> <field name="name">For OpenERP OnDemand Free Trial 2010</field> <field name="model_int_name">crm.lead</field> <field eval="0" name="send_on_write"/> </record> -<!-- Report --> + <record id="email_template_2" model="email.template"> + <field name="def_subject">Propose to subscribe to the Open ERP Discovery Day on May 2010</field> + <field name="def_to">info@tinyerp.com</field> + <field eval="[(6,0,[])]" name="allowed_groups"/> + <field eval="0" name="auto_email"/> + <field model="ir.actions.act_window" name="ref_ir_act_window" search="[('name', '=', u'For OpenERP OnDemand Free Trial 2010 Mail Form')]"/> + <field eval="[(6,0,[])]" name="table_required_fields"/> + <field model="ir.values" name="ref_ir_value" search="[('name', '=', u'Send Mail (For OpenERP OnDemand Free Trial 2010)')]"/> + <field name="object_name" ref="crm.model_crm_lead"/> + <field eval="0" name="use_sign"/> + <field name="def_body_text">Hello,We have very good offer that might suit you. + We propose you to subscribe to the Open ERP Discovery Day on May 2010. + If any further information required kindly revert back. + We really appreciate your co-operation on this. + Regards,OpenERP Team,</field> + <field name="template_language">mako</field> + <field eval="0" name="send_on_create"/> + <field name="name">For Open ERP Discovery Day on May 2010</field> + <field name="model_int_name">crm.lead</field> + <field eval="0" name="send_on_write"/> + </record> + + <record id="email_template_3" model="email.template"> + <field name="def_subject">Thanks for subscribing to the Open ERP Discovery Day</field> + <field name="def_to">info@tinyerp.com</field> + <field eval="[(6,0,[])]" name="allowed_groups"/> + <field eval="0" name="auto_email"/> + <field model="ir.actions.act_window" name="ref_ir_act_window" search="[('name', '=', u'For OpenERP OnDemand Free Trial 2010 Mail Form')]"/> + <field eval="[(6,0,[])]" name="table_required_fields"/> + <field model="ir.values" name="ref_ir_value" search="[('name', '=', u'Send Mail (For OpenERP OnDemand Free Trial 2010)')]"/> + <field name="object_name" ref="crm.model_crm_lead"/> + <field eval="0" name="use_sign"/> + <field name="def_body_text">Hello,Thanks for showing intrest and for subscribing to the Open ERP Discovery Day. + If any further information required kindly revert back. + I really appreciate your co-operation on this. + Regards,OpenERP Team,</field> + <field name="template_language">mako</field> + <field eval="0" name="send_on_create"/> + <field name="name">For Open ERP Discovery Day</field> + <field name="model_int_name">crm.lead</field> + <field eval="0" name="send_on_write"/> + </record> + + <record id="email_template_4" model="email.template"> + <field name="def_subject">Thanks for buying the Open ERP book</field> + <field name="def_to">info@tinyerp.com</field> + <field eval="[(6,0,[])]" name="allowed_groups"/> + <field eval="0" name="auto_email"/> + <field model="ir.actions.act_window" name="ref_ir_act_window" search="[('name', '=', u'For OpenERP OnDemand Free Trial 2010 Mail Form')]"/> + <field eval="[(6,0,[])]" name="table_required_fields"/> + <field model="ir.values" name="ref_ir_value" search="[('name', '=', u'Send Mail (For OpenERP OnDemand Free Trial 2010)')]"/> + <field name="object_name" ref="crm.model_crm_lead"/> + <field eval="0" name="use_sign"/> + <field name="def_body_text">Hello,Thanks for showing intrest and buying the Open ERP book. + If any further information required kindly revert back. + I really appreciate your co-operation on this. + Regards,OpenERP Team,</field> + <field name="template_language">mako</field> + <field eval="0" name="send_on_create"/> + <field name="name">For Open ERP book</field> + <field name="model_int_name">crm.lead</field> + <field eval="0" name="send_on_write"/> + </record> + + <record id="email_template_5" model="email.template"> + <field name="def_subject">Propose a free technical training to Gold partners</field> + <field name="def_to">info@tinyerp.com</field> + <field eval="[(6,0,[])]" name="allowed_groups"/> + <field eval="0" name="auto_email"/> + <field model="ir.actions.act_window" name="ref_ir_act_window" search="[('name', '=', u'For OpenERP OnDemand Free Trial 2010 Mail Form')]"/> + <field eval="[(6,0,[])]" name="table_required_fields"/> + <field model="ir.values" name="ref_ir_value" search="[('name', '=', u'Send Mail (For OpenERP OnDemand Free Trial 2010)')]"/> + <field name="object_name" ref="crm.model_crm_lead"/> + <field eval="0" name="use_sign"/> + <field name="def_body_text">Hello, We have very good offer that might suit you. + For our gold partners,We are arranging free technical training on june,2010. + If any further information required kindly revert back. + I really appreciate your co-operation on this. + Regards,OpenERP Team,</field> + <field name="template_language">mako</field> + <field eval="0" name="send_on_create"/> + <field name="name">For technical training to Gold partners</field> + <field name="model_int_name">crm.lead</field> + <field eval="0" name="send_on_write"/> + </record> + + <record id="email_template_6" model="email.template"> + <field name="def_subject">Propose paid training to Silver partners</field> + <field name="def_to">info@tinyerp.com</field> + <field eval="[(6,0,[])]" name="allowed_groups"/> + <field eval="0" name="auto_email"/> + <field model="ir.actions.act_window" name="ref_ir_act_window" search="[('name', '=', u'For OpenERP OnDemand Free Trial 2010 Mail Form')]"/> + <field eval="[(6,0,[])]" name="table_required_fields"/> + <field model="ir.values" name="ref_ir_value" search="[('name', '=', u'Send Mail (For OpenERP OnDemand Free Trial 2010)')]"/> + <field name="object_name" ref="crm.model_crm_lead"/> + <field eval="0" name="use_sign"/> + <field name="def_body_text">Hello, We have very good offer that might suit you. + For our silver partners,We are paid technical training on june,2010. + If any further information required kindly revert back. + I really appreciate your co-operation on this. + Regards,OpenERP Team,</field> + <field name="template_language">mako</field> + <field eval="0" name="send_on_create"/> + <field name="name">For training to Silver partners</field> + <field name="model_int_name">crm.lead</field> + <field eval="0" name="send_on_write"/> + </record> + + <record id="email_template_7" model="email.template"> + <field name="def_subject">Propose gold partnership to silver partners</field> + <field name="def_to">info@tinyerp.com</field> + <field eval="[(6,0,[])]" name="allowed_groups"/> + <field eval="0" name="auto_email"/> + <field model="ir.actions.act_window" name="ref_ir_act_window" search="[('name', '=', u'For OpenERP OnDemand Free Trial 2010 Mail Form')]"/> + <field eval="[(6,0,[])]" name="table_required_fields"/> + <field model="ir.values" name="ref_ir_value" search="[('name', '=', u'Send Mail (For OpenERP OnDemand Free Trial 2010)')]"/> + <field name="object_name" ref="crm.model_crm_lead"/> + <field eval="0" name="use_sign"/> + <field name="def_body_text">Hello, We have very good offer that might suit you. + For our silver partners,We are offering Gold partnership. + If any further information required kindly revert back. + I really appreciate your co-operation on this. + Regards,OpenERP Team,</field> + <field name="template_language">mako</field> + <field eval="0" name="send_on_create"/> + <field name="name">For gold partnership to silver partners</field> + <field name="model_int_name">crm.lead</field> + <field eval="0" name="send_on_write"/> + </record> + + <record id="email_template_8" model="email.template"> + <field name="def_subject">Thanks for subscribing to technical training</field> + <field name="def_to">info@tinyerp.com</field> + <field eval="[(6,0,[])]" name="allowed_groups"/> + <field eval="0" name="auto_email"/> + <field model="ir.actions.act_window" name="ref_ir_act_window" search="[('name', '=', u'For OpenERP OnDemand Free Trial 2010 Mail Form')]"/> + <field eval="[(6,0,[])]" name="table_required_fields"/> + <field model="ir.values" name="ref_ir_value" search="[('name', '=', u'Send Mail (For OpenERP OnDemand Free Trial 2010)')]"/> + <field name="object_name" ref="crm.model_crm_lead"/> + <field eval="0" name="use_sign"/> + <field name="def_body_text">Hello, Thanks for showing intrest and for subscribing to technical training.If any further information required kindly revert back.I really appreciate your co-operation on this. + Regards,OpenERP Team,</field> + <field name="template_language">mako</field> + <field eval="0" name="send_on_create"/> + <field name="name">For subscribing to technical training</field> + <field name="model_int_name">crm.lead</field> + <field eval="0" name="send_on_write"/> + </record> + <!-- Report --> + <record id="mc_crm_lead_demo_report" model="ir.actions.report.xml"> <field name="name">Marketing campaign demo report</field> <field name="type">ir.actions.report.xml</field> @@ -51,12 +198,15 @@ OpenERP Team,</field> <field name="report_rml">marketing_campaign/report/crm_lead_mc_demo_report.rml</field> <field name="report_type">pdf</field> </record> -<!-- Campaign --> + + <!-- Campaign --> <record id="marketing_campaign_openerpondemandfreetrial0" model="marketing.campaign"> <field name="name">OpenERP OnDemand Free Trial 2010</field> <field name="object_id" ref="crm.model_crm_lead"/> </record> -<!-- Activity --> + + <!-- Activity --> + <record id="marketing_campaign_activity_0" model="marketing.campaign.activity"> <field name="name">Propose a 1 month free trial for an OnDemand offer</field> <field name="server_action_id" ref="base.action_start_configurator"/> @@ -70,13 +220,112 @@ OpenERP Team,</field> <field name="name">Thanks for showing interest</field> <field name="server_action_id" ref="base.action_start_configurator"/> <field model="marketing.campaign" name="campaign_id" ref="marketing_campaign_openerpondemandfreetrial0"/> + <field name="email_template_id" ref="email_template_1"/> </record> -<!-- Tranisition --> + + <record id="marketing_campaign_activity_2" model="marketing.campaign.activity"> + <field name="name">Propose to subscribe to the Open ERP Discovery Day on May 2010</field> + <field name="server_action_id" ref="base.action_start_configurator"/> + <field model="marketing.campaign" name="campaign_id" ref="marketing_campaign_openerpondemandfreetrial0"/> + <field name="email_template_id" ref="email_template_2"/> + </record> + + <record id="marketing_campaign_activity_3" model="marketing.campaign.activity"> + <field name="name">Thanks for subscribing to the Open ERP Discovery Day</field> + <field name="server_action_id" ref="base.action_start_configurator"/> + <field model="marketing.campaign" name="campaign_id" ref="marketing_campaign_openerpondemandfreetrial0"/> + <field name="email_template_id" ref="email_template_3"/> + </record> + <record id="marketing_campaign_activity_4" model="marketing.campaign.activity"> + <field name="name">Propose to buy the Open ERP Book</field> + <field name="server_action_id" ref="base.action_start_configurator"/> + <field model="marketing.campaign" name="campaign_id" ref="marketing_campaign_openerpondemandfreetrial0"/> + <field name="report_directory_id" ref="document_directory_campaign1"/> + <field name="type">paper</field> + <field name="report_id" ref="mc_crm_lead_demo_report"/> + </record> + + <record id="marketing_campaign_activity_5" model="marketing.campaign.activity"> + <field name="name">Thanks for buying the Open ERP book</field> + <field name="server_action_id" ref="base.action_start_configurator"/> + <field model="marketing.campaign" name="campaign_id" ref="marketing_campaign_openerpondemandfreetrial0"/> + <field name="email_template_id" ref="email_template_4"/> + </record> + <record id="marketing_campaign_activity_6" model="marketing.campaign.activity"> + <field name="name">Propose a free technical training to Gold partners</field> + <field name="server_action_id" ref="base.action_start_configurator"/> + <field model="marketing.campaign" name="campaign_id" ref="marketing_campaign_openerpondemandfreetrial0"/> + <field name="email_template_id" ref="email_template_5"/> + </record> + <record id="marketing_campaign_activity_7" model="marketing.campaign.activity"> + <field name="name">Propose paid training to Silver partners</field> + <field name="server_action_id" ref="base.action_start_configurator"/> + <field model="marketing.campaign" name="campaign_id" ref="marketing_campaign_openerpondemandfreetrial0"/> + <field name="email_template_id" ref="email_template_6"/> + </record> + + <record id="marketing_campaign_activity_8" model="marketing.campaign.activity"> + <field name="name">Propose gold partnership to silver partners</field> + <field name="server_action_id" ref="base.action_start_configurator"/> + <field model="marketing.campaign" name="campaign_id" ref="marketing_campaign_openerpondemandfreetrial0"/> + <field name="email_template_id" ref="email_template_7"/> + </record> + + <record id="marketing_campaign_activity_9" model="marketing.campaign.activity"> + <field name="name">Thanks for subscribing to technical training</field> + <field name="server_action_id" ref="base.action_start_configurator"/> + <field model="marketing.campaign" name="campaign_id" ref="marketing_campaign_openerpondemandfreetrial0"/> + <field name="email_template_id" ref="email_template_8"/> + </record> + + <!-- Tranisition --> <record id="marketing_campaign_transition_0" model="marketing.campaign.transition"> <field model="marketing.campaign.activity" name="activity_from_id" ref = "marketing_campaign_activity_0"/> <field model="marketing.campaign.activity" name="activity_to_id" ref = "marketing_campaign_activity_1"/> </record> -<!-- Segment --> + + <record id="marketing_campaign_transition_1" model="marketing.campaign.transition"> + <field model="marketing.campaign.activity" name="activity_from_id" ref = "marketing_campaign_activity_0"/> + <field model="marketing.campaign.activity" name="activity_to_id" ref = "marketing_campaign_activity_2"/> + </record> + <record id="marketing_campaign_transition_2" model="marketing.campaign.transition"> + <field model="marketing.campaign.activity" name="activity_from_id" ref = "marketing_campaign_activity_2"/> + <field model="marketing.campaign.activity" name="activity_to_id" ref = "marketing_campaign_activity_3"/> + </record> + <record id="marketing_campaign_transition_3" model="marketing.campaign.transition"> + <field model="marketing.campaign.activity" name="activity_from_id" ref = "marketing_campaign_activity_2"/> + <field model="marketing.campaign.activity" name="activity_to_id" ref = "marketing_campaign_activity_4"/> + </record> + <record id="marketing_campaign_transition_4" model="marketing.campaign.transition"> + <field model="marketing.campaign.activity" name="activity_from_id" ref = "marketing_campaign_activity_4"/> + <field model="marketing.campaign.activity" name="activity_to_id" ref = "marketing_campaign_activity_5"/> + </record> + <record id="marketing_campaign_transition_5" model="marketing.campaign.transition"> + <field model="marketing.campaign.activity" name="activity_from_id" ref = "marketing_campaign_activity_4"/> + <field model="marketing.campaign.activity" name="activity_to_id" ref = "marketing_campaign_activity_6"/> + </record> + <record id="marketing_campaign_transition_6" model="marketing.campaign.transition"> + <field model="marketing.campaign.activity" name="activity_from_id" ref = "marketing_campaign_activity_4"/> + <field model="marketing.campaign.activity" name="activity_to_id" ref = "marketing_campaign_activity_7"/> + </record> + <record id="marketing_campaign_transition_7" model="marketing.campaign.transition"> + <field model="marketing.campaign.activity" name="activity_from_id" ref = "marketing_campaign_activity_6"/> + <field model="marketing.campaign.activity" name="activity_to_id" ref = "marketing_campaign_activity_9"/> + </record> + <record id="marketing_campaign_transition_8" model="marketing.campaign.transition"> + <field model="marketing.campaign.activity" name="activity_from_id" ref = "marketing_campaign_activity_7"/> + <field model="marketing.campaign.activity" name="activity_to_id" ref = "marketing_campaign_activity_8"/> + </record> + <record id="marketing_campaign_transition_9" model="marketing.campaign.transition"> + <field model="marketing.campaign.activity" name="activity_from_id" ref = "marketing_campaign_activity_7"/> + <field model="marketing.campaign.activity" name="activity_to_id" ref = "marketing_campaign_activity_9"/> + </record> + <record id="marketing_campaign_transition_10" model="marketing.campaign.transition"> + <field model="marketing.campaign.activity" name="activity_from_id" ref = "marketing_campaign_activity_9"/> + <field model="marketing.campaign.activity" name="activity_to_id" ref = "marketing_campaign_activity_1"/> + </record> + + <!-- Segment --> <record id="marketing_campaign_segment_bosslistusassociationslist0" model="marketing.campaign.segment"> <field eval="time.strftime('%Y-%m-%d %H:%M:%S')" name="date_run"/> <field name="name">BossList US Associations List-0/90</field> diff --git a/addons/mrp/mrp_view.xml b/addons/mrp/mrp_view.xml index 15ed872391f..bcda66e8679 100644 --- a/addons/mrp/mrp_view.xml +++ b/addons/mrp/mrp_view.xml @@ -296,9 +296,9 @@ <field name="company_id" groups="base.group_multi_company"/> </group> <newline/> - <group expand="1" string="Group By" colspan="4" col="8" groups="base.group_extended"> - <filter string="Product" icon="terp-mrp" domain="[]" context="{'group_by':'product_id'}"/> - <filter string="Routing" icon="terp-mrp" domain="[]" context="{'group_by':'routing_id'}"/> + <group expand="0" string="Group By" colspan="4" col="8" groups="base.group_extended"> + <filter string="Product" icon="terp-accessories-archiver" domain="[]" context="{'group_by':'product_id'}"/> + <filter string="Routing" icon="terp-stock_align_left_24" domain="[]" context="{'group_by':'routing_id'}"/> </group> </search> </field> @@ -655,21 +655,21 @@ <field name="arch" type="xml"> <search string="Search Production"> <group col='9' colspan='4'> - <filter icon="terp-mrp" string="Draft" + <filter icon="terp-document-new" string="Draft" domain="[('state','=','draft')]" help="Non confirmed manufacturing orders"/> - <filter icon="terp-mrp" string="Current" name="Current" + <filter icon="terp-check" string="Current" name="Current" default="1" domain="[('state','in',('confirmed','ready','exception'))]" help="Manufacturing Orders which are waiting for raw materials"/> - <filter icon="terp-mrp" string="Ready" + <filter icon="terp-camera_test" string="Ready" domain="[('state','=','ready')]" help="Manufacturing Orders which are ready to produce" /> - <filter icon="terp-mrp" string="In Production" + <filter icon="terp-check" string="In Production" domain="[('state','=','in_production')]" help="Manufacturing Orders which are in production" /> <separator orientation="vertical"/> - <filter icon="terp-mrp" string="Late" + <filter icon="terp-gnome-cpu-frequency-applet+" string="Late" domain="['&', ('date_planned::date','<', current_date), ('state', 'in', ('draft', 'confirmed', 'ready'))]" help="Production started late" /> <separator orientation="vertical"/> @@ -679,12 +679,12 @@ <field name="origin"/> </group> <newline/> - <group expand="1" string="Group By" colspan="10" col="8"> - <filter string="Product" icon="terp-mrp" domain="[]" context="{'group_by':'product_id'}"/> - <filter string="State" icon="terp-mrp" domain="[]" context="{'group_by':'state'}"/> - <filter string="Routing" icon="terp-mrp" domain="[]" context="{'group_by':'routing_id'}" groups="base.group_extended"/> + <group expand="0" string="Group By" colspan="10" col="8"> + <filter string="Product" icon="terp-accessories-archiver" domain="[]" context="{'group_by':'product_id'}"/> + <filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/> + <filter string="Routing" icon="terp-stock_align_left_24" domain="[]" context="{'group_by':'routing_id'}" groups="base.group_extended"/> <separator orientation="vertical"/> - <filter string="Date" icon="terp-mrp" domain="[]" context="{'group_by':'date_planned'}"/> + <filter string="Date" icon="terp-go-month" domain="[]" context="{'group_by':'date_planned'}"/> </group> </search> </field> diff --git a/addons/mrp/report/mrp_production_order_view.xml b/addons/mrp/report/mrp_production_order_view.xml index 5663ef93210..55957619e31 100644 --- a/addons/mrp/report/mrp_production_order_view.xml +++ b/addons/mrp/report/mrp_production_order_view.xml @@ -12,19 +12,18 @@ <field name="arch" type="xml"> <tree string="Production"> <field name="date_planned"/> - <field name="origin"/> - <field name="bom_id" /> - <field name="product_id"/> + <field name="bom_id" invisible="1"/> + <field name="product_id" invisible="1"/> <field name="product_qty" sum='Product Qty'/> <field name="nbr" string="#Production Orders" sum='#Production Orders'/> - <field name="state"/> - <field name="routing_id" invisible="1"/> + <field name="state" invisible="1"/> <field name="picking_id" invisible="1"/> <field name="priority" invisible="1"/> <field name="year" invisible="1" /> <field name="month" invisible="1"/> <field name="location_src_id" invisible="1"/> <field name="location_dest_id" invisible="1"/> + <field name="company_id" groups="base.group_multi_company" invisible="1"/> </tree> </field> </record> @@ -48,50 +47,57 @@ <field name="arch" type="xml"> <search string="Search"> <group col="16" colspan="6"> - <filter string="This Year" icon="terp-mrp" domain="[('year','=',time.localtime()[0])]" default="1" /> - <filter string="This Month" icon="terp-mrp" domain="[('month','=',time.strftime('%%m'))]" default="1"/> - <separator orientation="vertical"/> - <filter string="Current" icon="terp-mrp" domain="[('state','in',('open','draft'))]"/> - <separator orientation="vertical"/> - <field name="origin"/> - <field name="date_planned"/> + <filter icon="terp-go-year" string=" 365 Days " + domain="[('date_start','<=', time.strftime('%%Y-%%m-%%d')),('date_start','>',(datetime.date.today()-datetime.timedelta(days=365)).strftime('%%Y-%%m-%%d'))]" + help="Production performed in last 365 Days"/> + <filter icon="terp-go-month" string=" 30 Days " + name="month" + domain="[('date_start','<=', time.strftime('%%Y-%%m-%%d')), ('date_start','>',(datetime.date.today()-datetime.timedelta(days=30)).strftime('%%Y-%%m-%%d'))]" + help="Production performed in last 30 days"/> + <filter icon="terp-go-week" + string=" 7 Days " + separator="1" + domain="[('date_start','<=', time.strftime('%%Y-%%m-%%d')), ('date_start','>',(datetime.date.today()-datetime.timedelta(days=7)).strftime('%%Y-%%m-%%d'))]" + help="Production during last 7 days"/> + <separator orientation="vertical"/> + <filter string="Current" icon="terp-check" domain="[('state','in',('open','draft'))]"/> + <filter icon="terp-check" string="In Production" domain="[('state','=','in_production')]"/> + <filter icon="terp-dialog-close" string="Done" domain="[('state','=','done')]"/> + <separator orientation="vertical"/> + <field name="location_src_id" /> + <field name="location_dest_id" /> </group> <newline/> - <group expand="1" string="Group By..."> - <filter string="Source Location" icon="terp-mrp" context="{'group_by':'location_src_id'}"/> - <filter string="Destination Location" icon="terp-mrp" context="{'group_by':'location_dest_id'}"/> - <filter string="Picking" icon="terp-mrp" context="{'group_by':'picking_id'}"/> - <separator orientation="vertical"/> - <filter string="Routing" icon="terp-mrp" context="{'group_by':'routing_id'}"/> - <filter string="Product" name="Product" icon="terp-mrp" context="{'group_by':'product_id'}" /> - <filter string="State" icon="terp-mrp" context="{'group_by':'state'}"/> + <group expand="0" string="Group By..."> + <filter string="Raw Material Location" icon="terp-gtk-jump-to-rtl" context="{'group_by':'location_src_id'}"/> + <filter string="Finished Products Location" icon="terp-gtk-jump-to-ltr" context="{'group_by':'location_dest_id'}"/> <separator orientation="vertical"/> + <filter string="Product" name="Product" icon="terp-accessories-archiver" context="{'group_by':'product_id'}" /> <filter string="BOM" icon="terp-mrp" context="{'group_by':'bom_id'}"/> - <filter string="Month" icon="terp-mrp" context="{'group_by':'month'}"/> - <filter string="Year" icon="terp-mrp" context="{'group_by':'year'}"/> + <separator orientation="vertical"/> + <filter string="State" icon="terp-stock_effects-object-colorize" context="{'group_by':'state'}"/> + <separator orientation="vertical"/> + <filter string="Company" icon="terp-go-home" context="{'group_by':'company_id'}"/> + <separator orientation="vertical"/> + <filter string="Day" icon="terp-go-month" context="{'group_by':'day'}"/> + <filter string="Month" name="month" icon="terp-go-month" context="{'group_by':'month'}"/> + <filter string="Year" icon="terp-go-year" context="{'group_by':'year'}"/> </group> <newline/> <group expand="0" string="Extended options..." groups="base.group_extended"> - <filter icon="terp-mrp" string="Draft" domain="[('state','=','draft')]"/> - <filter icon="terp-mrp" string="Picking Exception" domain="[('state','=','picking_except')]"/> - <separator orientation="vertical"/> - <filter icon="terp-mrp" string="Waiting Goods" domain="[('state','=','confirmed')]"/> - <filter icon="terp-mrp" string="Ready to Produce" domain="[('state','=','ready')]"/> - <separator orientation="vertical"/> - <filter icon="terp-mrp" string="In Production" domain="[('state','=','in_production')]"/> - <filter icon="terp-mrp" string="Done" domain="[('state','=','done')]"/> - <filter icon="terp-mrp" string="Cancelled" domain="[('state','=','cancel')]"/> - <newline/> - <filter icon="terp-mrp" string="Not urgent" domain="[('priority','=','0')]"/> - <filter icon="terp-mrp" string="Normal" domain="[('priority','=','1')]"/> - <separator orientation="vertical"/> - <filter icon="terp-mrp" string="Urgent" domain="[('priority','=','2')]"/> - <filter icon="terp-mrp" string="Very Urgent" domain="[('priority','=','3')]"/> + <filter icon="terp-emblem-important" string="Picking Exception" domain="[('state','=','picking_except')]"/> + <filter icon="terp-gtk-media-pause" string="Waiting Goods" domain="[('state','=','confirmed')]"/> + <filter icon="terp-camera_test" string="Ready to Produce" domain="[('state','=','ready')]"/> <separator orientation="vertical"/> + <field name="priority"/> + <separator orientation="vertical"/> + <field name="company_id" groups="base.group_multi_company"/> + <newline/> <field name="date_start"/> - <field name="date_finnished"/> - </group> + <field name="date_planned"/> + <field name="date_finnished"/> + </group> </search> </field> </record> @@ -102,7 +108,7 @@ <field name="view_mode">tree,graph</field> <field name="view_id" ref="view_report_mrp_production_order_tree"/> <field name="search_view_id" ref="view_report_mrp_production_order_filter"/> - <field name="context">{'search_default_Product': 1}</field> + <field name="context">{'search_default_Product': 1,'search_default_month':1,'group_by_no_leaf':1,'group_by':[]}</field> </record> diff --git a/addons/mrp_operations/mrp_operations_view.xml b/addons/mrp_operations/mrp_operations_view.xml index 37e90a995b4..a5c6564644e 100644 --- a/addons/mrp_operations/mrp_operations_view.xml +++ b/addons/mrp_operations/mrp_operations_view.xml @@ -96,10 +96,10 @@ <field name="production_id"/> </group> <newline/> - <group expand="1" string="Group By" colspan="10" col="8" groups="base.group_extended"> - <filter string="Product" icon="terp-mrp" domain="[]" context="{'group_by':'product'}"/> - <filter string="State" icon="terp-mrp" domain="[]" context="{'group_by':'state'}"/> - <filter string="Date" icon="terp-mrp" domain="[]" context="{'group_by':'date_planned'}"/> + <group expand="0" string="Group By" colspan="10" col="8" groups="base.group_extended"> + <filter string="Product" icon="terp-accessories-archiver" domain="[]" context="{'group_by':'product'}"/> + <filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/> + <filter string="Date" icon="terp-go-month" domain="[]" context="{'group_by':'date_planned'}"/> </group> </search> </field> diff --git a/addons/mrp_procurement/mrp_procurement_view.xml b/addons/mrp_procurement/mrp_procurement_view.xml index 1defa214754..7345dc94f93 100644 --- a/addons/mrp_procurement/mrp_procurement_view.xml +++ b/addons/mrp_procurement/mrp_procurement_view.xml @@ -86,12 +86,12 @@ <field name="arch" type="xml"> <search string="Search Procurement"> <group col='10' colspan='4'> - <filter icon="terp-mrp" string="Current" domain="[('state','in',('draft','confirmed'))]" name="current" help="Procurement Orders in draft or open state."/> - <filter icon="terp-mrp" string="Exceptions" domain="[('state','=','exception')]" help="Procurement Orders with exceptions"/> - <filter icon="terp-mrp" string="Late" + <filter icon="terp-check" string="Current" domain="[('state','in',('draft','confirmed'))]" name="current" help="Procurement Orders in draft or open state."/> + <filter icon="terp-emblem-important" string="Exceptions" domain="[('state','=','exception')]" help="Procurement Orders with exceptions"/> + <filter icon="terp-gnome-cpu-frequency-applet+" string="Late" domain="['&', ('date_planned::date','<', current_date), ('state', 'in', ('draft', 'confirmed'))]" help="Procurement started late" /> - <filter icon="terp-mrp" string="To Fix" domain="[('state', '=', 'exception'),('message','=','')]" help="Procurement Orders with exceptions and without message"/> + <filter icon="terp-gtk-go-back-rtl" string="To Fix" domain="[('state', '=', 'exception'),('message','=','')]" help="Procurement Orders with exceptions and without message"/> <separator orientation="vertical"/> <field name="name"/> <field name="origin"/> @@ -100,11 +100,11 @@ <field name="state" /> </group> <newline/> - <group expand="1" string="Group By" colspan="4" col="8" groups="base.group_extended"> - <filter string="Product" icon="terp-mrp" domain="[]" context="{'group_by':'product_id'}"/> - <filter string="Reason" icon="terp-mrp" domain="[]" context="{'group_by':'name'}"/> - <filter string="Scheduled Date" icon="terp-mrp" domain="[]" context="{'group_by':'date_planned'}"/> - <filter string="State" icon="terp-mrp" domain="[]" context="{'group_by':'state'}"/> + <group expand="0" string="Group By" colspan="4" col="8" groups="base.group_extended"> + <filter string="Product" icon="terp-accessories-archiver" domain="[]" context="{'group_by':'product_id'}"/> + <filter string="Reason" icon="terp-gtk-jump-to-rtl" domain="[]" context="{'group_by':'name'}"/> + <filter string="Scheduled Date" icon="terp-go-month" domain="[]" context="{'group_by':'date_planned'}"/> + <filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/> </group> </search> </field> @@ -191,9 +191,9 @@ <field name="product_id"/> </group> <newline/> - <group expand="1" string="Group By..." colspan="4" col="10"> - <filter string="Warehouse" icon="terp-stock" domain="[]" context="{'group_by':'warehouse_id'}"/> - <filter string="Location" icon="terp-stock" domain="[]" context="{'group_by':'location_id'}"/> + <group expand="0" string="Group By..." colspan="4" col="10"> + <filter string="Warehouse" icon="terp-go-home" domain="[]" context="{'group_by':'warehouse_id'}"/> + <filter string="Location" icon="terp-go-home" domain="[]" context="{'group_by':'location_id'}"/> </group> </search> </field> diff --git a/addons/mrp_repair/mrp_repair_view.xml b/addons/mrp_repair/mrp_repair_view.xml index 47e80be3e31..4c655099386 100644 --- a/addons/mrp_repair/mrp_repair_view.xml +++ b/addons/mrp_repair/mrp_repair_view.xml @@ -183,10 +183,10 @@ <field name="product_id" /> </group> <newline/> - <group expand="1" string="Group By" colspan="10" col="8" groups="base.group_extended"> - <filter string="Product" icon="terp-mrp" domain="[]" context="{'group_by':'product_id'}"/> - <filter string="State" icon="terp-mrp" domain="[]" context="{'group_by':'state'}"/> - <filter string="Partner" icon="terp-mrp" domain="[]" context="{'group_by':'partner_id'}"/> + <group expand="0" string="Group By..." colspan="10" col="8" groups="base.group_extended"> + <filter string="Product" icon="terp-accessories-archiver" domain="[]" context="{'group_by':'product_id'}"/> + <filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/> + <filter string="Partner" icon="terp-personal" domain="[]" context="{'group_by':'partner_id'}"/> </group> </search> </field> diff --git a/addons/point_of_sale/pos_view.xml b/addons/point_of_sale/pos_view.xml index ef8ae334810..62b15db0234 100644 --- a/addons/point_of_sale/pos_view.xml +++ b/addons/point_of_sale/pos_view.xml @@ -153,19 +153,19 @@ <field name="type">search</field> <field name="arch" type="xml"> <search string="Search Sales Order"> - <filter icon="terp-sale" string="Quotations" domain="[('state','=','draft')]"/> - <filter icon="terp-sale" string="Running" domain="[('state','in',('payment','advance'))]"/> + <filter icon="terp-document-new" string="Quotations" domain="[('state','=','draft')]"/> + <filter icon="terp-check" string="Running" domain="[('state','in',('payment','advance'))]"/> <separator orientation="vertical"/> <field name="name" select="1"/> <field name="partner_id" select="1"/> <field name="user_id" select="1" widget="selection"/> <field name="date_order" select="1" string="Order date" /> <newline/> - <group expand="1" string="Group By..." colspan="11" col="11" groups="base.group_extended"> - <filter string="Customer" icon="terp-sale" domain="[]" context="{'group_by':'partner_id'}"/> - <filter string="State" icon="terp-sale" domain="[]" context="{'group_by':'state'}"/> - <filter string="Order Date" icon="terp-sale" domain="[]" context="{'group_by':'date_order'}"/> - <filter string="Salesman" icon="terp-sale" domain="[]" context="{'group_by':'user_id'}"/> + <group expand="0" string="Group By..." colspan="11" col="11" groups="base.group_extended"> + <filter string="Customer" icon="terp-personal" domain="[]" context="{'group_by':'partner_id'}"/> + <filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/> + <filter string="Order Date" icon="terp-go-month" domain="[]" context="{'group_by':'date_order'}"/> + <filter string="Salesman" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/> </group> </search> </field> diff --git a/addons/product/product_view.xml b/addons/product/product_view.xml index aa73cdd0e63..11ed4bfba65 100644 --- a/addons/product/product_view.xml +++ b/addons/product/product_view.xml @@ -1,29 +1,30 @@ <?xml version="1.0" encoding="utf-8"?> <openerp> <data> - <menuitem groups="base.group_extended" id="prod_config_main" name="Product" parent="base.menu_base_config" sequence="50"/> + <menuitem groups="base.group_extended" id="prod_config_main" name="Product" parent="base.menu_base_config" sequence="40"/> + <record id="product_search_form_view" model="ir.ui.view"> <field name="name">product.search.form</field> <field name="model">product.product</field> <field name="type">search</field> <field name="arch" type="xml"> <search string="Product"> - <filter string="Services" icon="terp-stock" domain="[('type','=','service')]"/> - <filter string="Stockable" icon="terp-stock" domain="['|',('type','=','product'),('type','=','consu')]"/> + <filter string="Services" icon="terp-accessories-archiver" domain="[('type','=','service')]"/> + <filter string="Stockable" icon="terp-accessories-archiver" domain="['|',('type','=','product'),('type','=','consu')]"/> <separator orientation="vertical"/> - <filter string="Can be sold" icon="terp-stock" domain="[('sale_ok','=',1)]"/> - <filter string="Can be Purchased" icon="terp-stock" domain="[('purchase_ok', '=', 1)]" /> + <filter string="Can be sold" icon="terp-accessories-archiver-minus" domain="[('sale_ok','=',1)]"/> + <filter string="Can be Purchased" icon="terp-accessories-archiver+" domain="[('purchase_ok', '=', 1)]" /> <separator orientation="vertical"/> <field name="default_code"/> <field name="name"/> <field name="categ_id" widget="selection" operator="child_of"/> <newline/> - <group expand='1' string='Group by...' groups="base.group_extended"> - <filter string='Category' icon="terp-stock" domain="[]" context="{'group_by' : 'categ_id'}" /> + <group expand='0' string='Group by...' groups="base.group_extended"> + <filter string='Category' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'categ_id'}" /> <separator orientation="vertical"/> - <filter string='Default UOM' icon="terp-stock" domain="[]" context="{'group_by' : 'uom_id'}" /> + <filter string='Default UOM' icon="terp-mrp" domain="[]" context="{'group_by' : 'uom_id'}" /> <separator orientation="vertical"/> - <filter string='Type' icon="terp-stock" domain="[]" context="{'group_by' : 'type'}" /> + <filter string='Type' icon="terp-stock_symbol-selection" domain="[]" context="{'group_by' : 'type'}" /> </group> <newline/> <group expand="0" string="Extended options..." groups="base.group_extended"> @@ -260,7 +261,7 @@ <menuitem action="product_category_action_form" groups="base.group_extended" id="menu_product_category_action_form" - parent="prod_config_main" sequence="60"/> + parent="prod_config_main" sequence="2"/> <record id="product_normal_action_tree" model="ir.actions.act_window"> @@ -374,7 +375,7 @@ <field name="view_mode">tree,form</field> </record> <menuitem - action="product_ul_form_action" groups="base.group_extended" id="menu_product_ul_form_action" parent="prod_config_main" sequence="65"/> + action="product_ul_form_action" groups="base.group_extended" id="menu_product_ul_form_action" parent="prod_config_main" sequence="3"/> <record id="product_packaging_tree_view" model="ir.ui.view"> <field name="name">product.packaging.tree.view</field> diff --git a/addons/profile_accounting/__openerp__.py b/addons/profile_accounting/__openerp__.py index 4e3e2e10481..9e02bd3e275 100644 --- a/addons/profile_accounting/__openerp__.py +++ b/addons/profile_accounting/__openerp__.py @@ -26,7 +26,7 @@ 'category': 'Profile', 'description': """Profile for Accounting""", 'author': 'Tiny', - 'depends': ['account', 'report_analytic', 'board_account', 'account_followup'], + 'depends': ['account', 'board_account', 'account_followup'], 'update_xml': ['security/ir.model.access.csv', 'profile_accounting.xml'], 'demo_xml': [], 'installable': True, diff --git a/addons/project/project_demo.xml b/addons/project/project_demo.xml index f668d82bf5c..973194e0e31 100644 --- a/addons/project/project_demo.xml +++ b/addons/project/project_demo.xml @@ -256,5 +256,15 @@ <field name="project_id" ref="project_project_22"/> <field name="name">Latest in house tests</field> </record> + <record id="project_message_1" model="project.message"> + <field name="date">2010-05-27</field> + <field name="project_id" ref="project.project_project_23"/> + <field name="user_id" ref="base.user_root"/> + <field name="description">Follow the procedure of Configuration wizard. +- Add all required modules +- Add chat of accounts +- Create Users</field> + <field name="subject">Configuration steps</field> + </record> </data> </openerp> diff --git a/addons/project/project_view.xml b/addons/project/project_view.xml index d7a7ff0e8d4..e979632bab4 100644 --- a/addons/project/project_view.xml +++ b/addons/project/project_view.xml @@ -93,7 +93,7 @@ <field name="type">tree</field> <field name="priority" eval="5"/> <field name="arch" type="xml"> - <tree string="Projects"> + <tree colors="blue:state in ('pending');black:state in ('open','template','close');gray:state in ('cancelled') " string="Projects"> <field name="complete_name" string="Project Name"/> <field name="user_id" string="Project Manager"/> <field name="partner_id" string="Partner"/> @@ -111,22 +111,20 @@ <field name="arch" type="xml"> <search string="Search Project"> <group col='15' colspan='4'> - <filter icon="terp-project" string="Open" domain="[('state', 'in',('open','draft'))]" help="Open and Draft Projects" default="1"/> - <filter icon="terp-project" string="Pending" domain="[('state', '=', 'pending')]" help="Pending Projects"/> + <filter icon="terp-document-new" string="Draft" domain="[('state', 'in',('draft'))]" help="Draft Projects" default="1"/> + <filter icon="terp-check" string="Current" name="Current" domain="[('state', 'in',('open','pending'))]" help="Open and Pending Projects" default="1"/> <separator orientation="vertical"/> - <filter icon="terp-project" string="Manager" domain="[('user_id', '=', uid)]" help="Projects in which I am a manager."/> - <filter icon="terp-project" string="Member" domain="['|',('user_id', '=', uid),('members', '=', uid)]" help="Projects in which I am a member." default="1"/> - <separator orientation="vertical"/> - <filter icon="terp-project" string="Templates" domain="[('state','=','template')]" help="Template Projects"/> + <filter icon="terp-personal" string="Manager" name="Manager" domain="[('user_id', '=', uid)]" help="Projects in which I am a manager."/> + <filter icon="terp-personal-" string="Member" domain="['|',('user_id', '=', uid),('members', '=', uid)]" help="Projects in which I am a member." default="1"/> <separator orientation="vertical"/> <field name="name" string="Project Name"/> <field name="user_id" string="Project Manager" default="1"/> <field name="partner_id" string="Partner"/> </group> <newline /> - <group expand="1" string="Group By..." colspan="4" col="20" groups="base.group_extended"> - <filter string="Users" name="Users" icon="terp-project" domain = "[]" context="{'group_by':'user_id'}"/> - <filter string="Partner" name="Partner" icon="terp-project" domain = "[]" context="{'group_by':'partner_id'}"/> + <group expand="0" string="Group By..." colspan="4" col="20" groups="base.group_extended"> + <filter string="Users" name="Users" icon="terp-personal" domain = "[]" context="{'group_by':'user_id'}"/> + <filter string="Partner" name="Partner" icon="terp-personal" domain = "[]" context="{'group_by':'partner_id'}"/> </group> </search> </field> @@ -159,6 +157,7 @@ <field name="domain">[]</field> <field name="view_id" ref="view_project"/> <field name="search_view_id" ref="view_project_project_filter"/> + <field name="context">{'search_default_Current':1}</field> </record> <menuitem action="open_view_project_all" id="menu_open_view_project_all" parent="menu_project_management" sequence="1"/> @@ -169,8 +168,8 @@ <field name="domain">[('state','=','template')]</field> <field name="view_id" ref="view_project"/> </record> - <menuitem id="menu_template_project_specification" parent="project.menu_definitions" name="Specification" sequence="1"/> - <menuitem action="open_view_template_project" id="menu_template_project" parent="project.menu_template_project_specification" name="Specification Template"/> +<!-- <menuitem id="menu_template_project_specification" parent="project.menu_definitions" name="Specification" sequence="1"/>--> +<!-- <menuitem action="open_view_template_project" id="menu_template_project" parent="project.menu_template_project_specification" name="Specification Template"/>--> <record id="view_task_work_form" model="ir.ui.view"> <field name="name">project.task.work.form</field> @@ -213,7 +212,7 @@ <separator string="" colspan="4"/> <group col="4" colspan="4"> <button icon="gtk-cancel" special="cancel" string="Cancel"/> - <button icon="gtk-refresh" name="compute_hours" string="Update" type="object" default_focus="1"/> + <button icon="gtk-apply" name="compute_hours" string="Update" type="object" default_focus="1"/> </group> </form> </field> @@ -277,7 +276,7 @@ <button name="%(action_config_compute_remaining)d" states="done,cancelled" string="Reactivate" type="action" icon="gtk-convert" context="{'button_reactivate':True}" /> <button name="do_pending" states="open" string="Pending" type="object" icon="gtk-media-pause"/> <button groups="base.group_extended" name="%(action_project_task_delegate)d" states="pending,open" string="Delegate" type="action" icon="gtk-sort-descending"/> - <button name="do_close" states="pending,open" string="Done" type="object" icon="gtk-jump-to"/> + <button name="do_close" states="pending,open" string="Done" type="object" icon="gtk-apply"/> <button name="do_cancel" states="draft,open,pending" string="Cancel" type="object" icon="gtk-cancel"/> </group> </page> @@ -332,8 +331,8 @@ <field name="type">tree</field> <field eval="2" name="priority"/> <field name="arch" type="xml"> - <tree colors="grey:state in ('cancelled','done');blue:remaining_hours<0;red:bool(date_deadline) and (date_deadline<current_date) and (state in ('draft','open'));black:state not in ('cancelled','done')" string="Tasks"> - <field name="sequence" invisible="1"/> + <tree colors="grey:state in ('cancelled','done');blue:remaining_hours<0 and state in ('pending');red:bool(date_deadline) and (date_deadline<current_date) and (state in ('draft','open'));black:state not in ('cancelled','done')" string="Tasks"> + <field name="sequence" /> <field name="name"/> <field name="project_id" icon="gtk-indent" domain="['|',('user_id','=',uid),('members','=',uid)]"/> <field name="user_id"/> @@ -355,8 +354,8 @@ <field name="progress" widget="progressbar" invisible="context.get('set_visible',False)"/> <field name="state" invisible="context.get('set_visible',False)"/> <button name="do_open" states="pending,draft,done,cancel" string="Start Task" type="object" icon="gtk-execute" help="For changing to open state" invisible="context.get('set_visible',False)"/> - <button groups="base.group_extended" name="%(action_project_task_delegate)d" states="pending,open,draft" string="Delegate" type="action" icon="gtk-execute" help="For changing to delegate state"/> - <button name="do_close" states="draft,pending,open" string="Done" type="object" icon="gtk-jump-to" help="For changing to done state"/> + <button groups="base.group_extended" name="%(action_project_task_delegate)d" states="pending,open,draft" string="Delegate" type="action" icon="gtk-sort-descending" help="For changing to delegate state"/> + <button name="do_close" states="draft,pending,open" string="Done" type="object" icon="gtk-apply" help="For changing to done state"/> <button name="do_cancel" states="draft,open,pending" string="Cancel" type="object" icon="gtk-cancel" help="For cancelling the task"/> </tree> </field> @@ -409,30 +408,30 @@ <field name="arch" type="xml"> <search string="Task Edition"> <group col="20" colspan="4"> - <filter name="current" string="Current" domain="[('state','in',('open','draft'))]" help="Draft, Open and Pending Tasks" icon="terp-project" default="1"/> - <filter string="In Progress" domain="[('state','=','open')]" help="Open Tasks" icon="terp-project"/> - <filter string="Pending" domain="[('state','=','pending')]" context="{'show_delegated':False}" help="Pending Tasks" icon="terp-project"/> + <filter string="Current" domain="[('state','in',('open','draft'))]" help="Draft, Open and Pending Tasks" icon="terp-check" default="1"/> + <filter string="In Progress" domain="[('state','=','open')]" help="Open Tasks" icon="terp-camera_test"/> + <filter string="Pending" domain="[('state','=','pending')]" context="{'show_delegated':False}" help="Pending Tasks" icon="terp-gtk-media-pause"/> <separator orientation="vertical"/> - <filter string="Deadlines" domain="[('date_deadline','<>',False)]" help="Show only tasks having a deadline" icon="terp-project"/> + <filter string="Deadlines" domain="[('date_deadline','<>',False)]" help="Show only tasks having a deadline" icon="terp-emblem-important"/> <separator orientation="vertical"/> <field name="name" select="1"/> <field name="project_id" select="1" widget="selection"> - <filter domain="[('project_id.user_id','=',uid)]" help="My Projects" icon="terp-project"/> + <filter domain="[('project_id.user_id','=',uid)]" help="My Projects" icon="terp-folder-blue"/> </field> <field name="user_id" select="1" widget="selection"> <filter domain="[('user_id','=',False)]" help="Unassigned Tasks" icon="gtk-execute" separator="1"/> </field> </group> <newline/> - <group expand="1" string="Group By..." colspan="4" col="20"> - <filter string="Users" name="group_user_id" icon="terp-project" domain="[]" context="{'group_by':'user_id'}"/> - <filter string="Project" name="group_project_id" icon="terp-project" domain="[]" context="{'group_by':'project_id'}" default = "1"/> - <filter string="Stage" name="group_stage_id" icon="terp-project" domain="[]" context="{'group_by':'type'}"/> - <filter string="State" name="group_state" icon="terp-project" domain="[]" context="{'group_by':'state'}"/> + <group expand="0" string="Group By..." colspan="4" col="20"> + <filter string="Users" name="group_user_id" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/> + <filter string="Project" name="group_project_id" icon="terp-folder-blue" domain="[]" context="{'group_by':'project_id'}" default = "1"/> + <filter string="Stage" name="group_stage_id" icon="terp-stage" domain="[]" context="{'group_by':'type'}"/> + <filter string="State" name="group_state" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/> <separator orientation="vertical"/> - <filter string="Deadline" icon="terp-project" domain="[]" context="{'group_by':'date_deadline'}"/> - <filter string="Start Date" icon="terp-project" domain="[]" context="{'group_by':'date_start'}"/> - <filter string="End Date" icon="terp-project" domain="[]" context="{'group_by':'date_end'}"/> + <filter string="Deadline" icon="terp-gnome-cpu-frequency-applet+" domain="[]" context="{'group_by':'date_deadline'}"/> + <filter string="Start Date" icon="terp-gtk-jump-to-ltr" domain="[]" context="{'group_by':'date_start'}"/> + <filter string="End Date" icon="terp-gtk-jump-to-rtl" domain="[]" context="{'group_by':'date_end'}"/> </group> </search> </field> @@ -591,10 +590,10 @@ <field name="type">tree</field> <field name="arch" type="xml"> <tree string="Messages"> + <field name="date" select="1"/> <field name="subject" select="1"/> <field name="project_id" select="1"/> <field name="user_id" select="1"/> - <field name="date" select="1"/> </tree> </field> </record> @@ -606,8 +605,8 @@ <field name="arch" type="xml"> <search string="Messages"> <group col="20" colspan="4"> - <filter domain="[('date','>=',time.strftime('%%Y-%%m-01'))]" icon="terp-project" string="This Month" /> - <filter domain="[('date', '=', time.strftime('%%Y-%%m-%%d'))]" icon="terp-project" string="Today" /> + <filter domain="[('date','>=',time.strftime('%%Y-%%m-01'))]" icon="terp-go-month" string="This Month" /> + <filter domain="[('date', '=', time.strftime('%%Y-%%m-%%d'))]" icon="terp-go-today" string="Today" /> <separator orientation="vertical"/> <field name="subject"/> <field name="project_id" select="1" widget="selection"/> @@ -615,10 +614,10 @@ </field> </group> <newline/> - <group expand="1" string="Group By..." colspan="4" col="20"> - <filter string="Project" icon="terp-project" domain="[]" context="{'group_by':'project_id'}"/> - <filter string="User" icon="terp-project" domain="[]" context="{'group_by':'user_id'}"/> - <filter string="Date" icon="terp-project" domain="[]" context="{'group_by':'date'}"/> + <group expand="0" string="Group By..." colspan="4" col="20"> + <filter string="Project" icon="terp-folder-blue" domain="[]" context="{'group_by':'project_id'}"/> + <filter string="User" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/> + <filter string="Date" icon="terp-go-month" domain="[]" context="{'group_by':'date'}"/> </group> </search> </field> diff --git a/addons/project/report/project_report.py b/addons/project/report/project_report.py index 7984441b460..1cd452d736e 100644 --- a/addons/project/report/project_report.py +++ b/addons/project/report/project_report.py @@ -42,11 +42,13 @@ class report_project_task_user(osv.osv): 'hours_effective': fields.float('Effective Hours', readonly=True), 'hours_delay': fields.float('Avg. Plan.-Eff.', readonly=True), 'remaining_hours': fields.float('Remaining Hours', readonly=True), + 'progress': fields.float('Progress', readonly=True), 'total_hours': fields.float('Total Hours', readonly=True), 'closing_days': fields.float('Days to Close', digits=(16,2), readonly=True, group_operator="avg", help="Number of Days to close the task"), 'opening_days': fields.float('Days to Open', digits=(16,2), readonly=True, group_operator="avg", help="Number of Days to Open the task"), + 'delay_endings_days': fields.float('Overpass Delay', digits=(16,2), readonly=True, group_operator="avg"), 'nbr': fields.integer('# of tasks', readonly=True), 'priority' : fields.selection([('4','Very Low'), ('3','Low'), @@ -63,7 +65,7 @@ class report_project_task_user(osv.osv): ('cancelled', 'Cancelled'), ('done', 'Done')], 'State', readonly=True), - 'company_id': fields.many2one('res.company', 'Company',readonly=True), + 'company_id': fields.many2one('res.company', 'Company',readonly=True, groups="base.group_multi_company"), 'partner_id': fields.many2one('res.partner', 'Partner',readonly=True), 'type': fields.many2one('project.task.type', 'Stage',readonly=True), @@ -84,6 +86,7 @@ class report_project_task_user(osv.osv): to_date(to_char(t.date_deadline, 'dd-MM-YYYY'),'dd-MM-YYYY') as date_deadline, sum(cast(to_char(date_trunc('day',t.date_end) - date_trunc('day',t.date_start),'DD') as int)) as no_of_days, t.user_id, + sum(progress) as progress, t.project_id, t.state, t.priority, @@ -97,6 +100,7 @@ class report_project_task_user(osv.osv): sum(planned_hours) as hours_planned, avg(extract('epoch' from (t.date_end-t.create_date)))/(3600*24) as closing_days, avg(extract('epoch' from (t.date_start-t.create_date)))/(3600*24) as opening_days, + avg(extract('epoch' from (t.date_deadline-t.date_end)))/(3600*24) as delay_endings_days, sum(w.hours) as hours_effective, ((sum(planned_hours)-sum(w.hours))/count(distinct t.id))::decimal(16,2) as hours_delay from project_task t diff --git a/addons/project/report/project_report_view.xml b/addons/project/report/project_report_view.xml index f40fc218a9e..26488eae254 100644 --- a/addons/project/report/project_report_view.xml +++ b/addons/project/report/project_report_view.xml @@ -12,7 +12,7 @@ <field name="name" invisible="1"/> <field name="project_id" invisible="1"/> <field name="user_id" invisible="1"/> - <field name="done_by"/> + <field name="done_by" invisible="1"/> <field name="date_deadline" invisible="1"/> <field name="state" invisible="1"/> <field name="date_start" invisible="1"/> @@ -31,7 +31,9 @@ <field name="hours_effective" sum='Effective Hours'/> <field name="hours_delay" sum='Avg. Plan.-Eff.'/> <field name="opening_days" sum='Days to Open'/> + <field name="delay_endings_days" sum='OverPass delay'/> <field name="closing_days" sum='Days to Close'/> + <field name="progress" sum='Progress' widget='progressbar'/> </tree> </field> </record> @@ -55,71 +57,71 @@ <field name="type">search</field> <field name="arch" type="xml"> <search string="Tasks Analysis"> - <group> - <filter icon="gtk-media-rewind" string=" 365 Days " + <group colspan="10" col="12"> + <filter icon="terp-go-year" string=" 365 Days " domain="[('date_start','<=', time.strftime('%%Y-%%m-%%d')),('date_start','>',(datetime.date.today()-datetime.timedelta(days=365)).strftime('%%Y-%%m-%%d'))]" help="Tasks performed in last 365 Days"/> - <filter icon="gtk-media-rewind" string=" 30 Days " + <filter icon="terp-go-month" string=" 30 Days " name="month" domain="[('date_start','<=', time.strftime('%%Y-%%m-%%d')), ('date_start','>',(datetime.date.today()-datetime.timedelta(days=30)).strftime('%%Y-%%m-%%d'))]" help="Tasks performed in last 30 days"/> - <filter icon="gtk-media-rewind" + <filter icon="terp-go-week" string=" 7 Days " separator="1" domain="[('date_start','<=', time.strftime('%%Y-%%m-%%d')), ('date_start','>',(datetime.date.today()-datetime.timedelta(days=7)).strftime('%%Y-%%m-%%d'))]" help="Tasks during last 7 days"/> <separator orientation="vertical"/> <filter string="Draft" - icon="terp-project" + icon="terp-document-new" domain="[('state','=','draft')]" help = "Draft tasks"/> <filter string="Current" - icon="terp-project" + icon="terp-check" domain="[('state', '=' ,'open')]" help = "In progress tasks"/> <filter string="Pending" - icon="terp-project" + icon="terp-gtk-media-pause" domain="[('state','=','pending')]" help = "Pending tasks"/> <filter string="Done" - icon="terp-project" + icon="terp-dialog-close" name="done" domain="[('state','=','done')]"/> <separator orientation="vertical"/> <field name="partner_id" /> <field name="user_id" widget="selection"> - <filter icon="terp-project" + <filter icon="terp-personal" string="My Task" help = "My tasks" domain="[('user_id','=',uid)]" /> - <filter icon="terp-project" + <filter icon="terp-personal-" string="Non Assigned Tasks to users" help="Non Assigned Tasks to users" domain="[('user_id','=',False)]"/> </field> <field name="project_id"> - <filter icon="terp-project" + <filter icon="terp-folder-blue" string="My Projects" help="My Projects" domain="[('project_id','=',context.get('project_id', False)]"/> </field> </group> <newline/> - <group expand="1" string="Group By..." colspan="10" col="11"> - <filter string="User" name="User" icon="terp-project" context="{'group_by':'user_id'}" /> - <filter string="Project" icon="terp-project" context="{'group_by':'project_id'}"/> + <group expand="0" string="Group By..." colspan="10" col="12"> + <filter string="User" name="User" icon="terp-personal" context="{'group_by':'user_id'}" /> + <filter string="Project" icon="terp-folder-blue" context="{'group_by':'project_id'}"/> <separator orientation="vertical"/> - <filter string="Partner" icon="terp-project" context="{'group_by':'partner_id'}" /> - <filter string="Task" icon="terp-project" context="{'group_by':'name'}" /> - <filter string="Done By" icon="terp-project" context="{'group_by':'done_by'}" /> + <filter string="Partner" icon="terp-personal" context="{'group_by':'partner_id'}" /> + <filter string="Task" icon="terp-stock_align_left_24" context="{'group_by':'name'}" /> + <filter string="Done By" icon="terp-personal" context="{'group_by':'done_by'}" /> <separator orientation="vertical"/> - <filter string="State" icon="terp-project" context="{'group_by':'state'}"/> - <filter string="Company" icon="terp-project" context="{'group_by':'company_id'}" groups="base.group_multi_company"/> - <filter string="Stage" icon="terp-project" context="{'group_by':'type'}" /> + <filter string="State" icon="terp-stock_effects-object-colorize" context="{'group_by':'state'}"/> + <filter string="Company" icon="terp-go-home" context="{'group_by':'company_id'}" groups="base.group_multi_company"/> + <filter string="Stage" icon="terp-stage" context="{'group_by':'type'}" /> <separator orientation="vertical"/> - <filter string="Day" icon="terp-project" context="{'group_by':'day'}"/> - <filter string="Month" icon="terp-project" context="{'group_by':'month'}"/> - <filter string="Year" icon="terp-project" context="{'group_by':'year'}"/> + <filter string="Day" icon="terp-go-month" context="{'group_by':'day'}"/> + <filter string="Month" icon="terp-go-month" context="{'group_by':'month'}"/> + <filter string="Year" icon="terp-go-year" context="{'group_by':'year'}"/> </group> <newline/> <group expand="0" string="Extended options..." colspan="10" col="12" groups="base.group_extended"> @@ -128,6 +130,7 @@ <separator orientation="vertical"/> <field name="date_start"/> <field name="date_deadline"/> + <field name="date_end"/> <separator orientation="vertical"/> <field name="priority"/> <field name="company_id" groups="base.group_multi_company" widget="selection"/> diff --git a/addons/project_gtd/project_gtd.py b/addons/project_gtd/project_gtd.py index 059c19e0f40..d680e533505 100644 --- a/addons/project_gtd/project_gtd.py +++ b/addons/project_gtd/project_gtd.py @@ -120,8 +120,8 @@ project_gtd_timebox() class project_task(osv.osv): _inherit = "project.task" _columns = { - 'timebox_id': fields.many2one('project.gtd.timebox', "Timebox"), - 'context_id': fields.many2one('project.gtd.context', "Context"), + 'timebox_id': fields.many2one('project.gtd.timebox', "Timebox",help="Time-laps during which task has to be treated"), + 'context_id': fields.many2one('project.gtd.context', "Context",help="The context place where user has to treat task"), } def copy_data(self, cr, uid, id, default=None, context=None): @@ -169,7 +169,7 @@ class project_task(osv.osv): timebox_obj = self.pool.get('project.gtd.timebox') if res['type'] == 'search': tt = timebox_obj.browse(cr, uid, timebox_obj.search(cr,uid,[])) - search_extended ='''<newline/><group col="%d" expand="1" string="%s" groups="project_gtd.group_project_getting">''' % (len(tt)+7,_('Getting Things Done')) + search_extended ='''<newline/><group col="%d" expand="0" string="%s" groups="project_gtd.group_project_getting">''' % (len(tt)+7,_('Getting Things Done')) search_extended += '''<filter domain="[('timebox_id','=', False)]" context="{'set_editable':True,'set_visible':True}" icon="gtk-new" string="%s"/>''' % (_('Inbox'),) search_extended += '''<filter domain="[('state', 'in', ('draft','open','pending'))]" context="{'set_editable':True,'set_visible':True}" icon="gtk-new" string="%s"/>''' % (_('All'),) search_extended += '''<separator orientation="vertical"/>''' diff --git a/addons/project_gtd/project_gtd_view.xml b/addons/project_gtd/project_gtd_view.xml index 1615319c7b9..64f6bcdfbd1 100644 --- a/addons/project_gtd/project_gtd_view.xml +++ b/addons/project_gtd/project_gtd_view.xml @@ -8,7 +8,8 @@ <field name="arch" type="xml"> <tree string="Context"> <field name="sequence" invisible="1"/> - <field name="name"/> + <field name="name" select="1"/> + <field name="project_default_id" select="1"/> </tree> </field> </record> @@ -75,7 +76,7 @@ <field name="inherit_id" ref="project.view_task_tree2" /> <field name="arch" type="xml"> <field name="remaining_hours" position="after"> - <field string="xxxxxx" name="timebox_id" groups="project_gtd.group_project_getting" invisible=" not context.get('set_visible',True)"/> + <field string="Timebox" name="timebox_id" groups="project_gtd.group_project_getting" invisible=" not context.get('set_visible',True)"/> <button name="prev_timebox" type="object" icon="gtk-go-back" string="Previous" states="draft,pending,open" groups="project_gtd.group_project_getting" invisible=" not context.get('set_visible',True)"/> <button name="next_timebox" type="object" icon="gtk-go-forward" string="Next" states="draft,pending,open" groups="project_gtd.group_project_getting" invisible=" not context.get('set_visible',False)"/> <button name="do_reopen" states="done,cancelled" string="Reactivate" type="object" icon="gtk-convert" help="For reopening the tasks" invisible="not context.get('set_visible',False)"/> diff --git a/addons/project_issue/project_issue_view.xml b/addons/project_issue/project_issue_view.xml index c7a420aa845..dd3ed036691 100644 --- a/addons/project_issue/project_issue_view.xml +++ b/addons/project_issue/project_issue_view.xml @@ -2,6 +2,8 @@ <openerp> <data> + <menuitem id="menu_project_confi" name="Project Issue" parent="project.menu_definitions" sequence="1"/> + <record id="project_issue_categ_action" model="ir.actions.act_window"> <field name="name">Issue Categories</field> <field name="res_model">crm.case.categ</field> @@ -19,7 +21,8 @@ <field name="domain">[('object_id.model', '=', 'project.issue')]</field> <field name="context">{'object_id':'project.issue'}</field> </record> - <menuitem action="project_issue_stage_act" id="menu_project_issue_stage_act" parent="crm.menu_crm_case_stage"/> + + <menuitem action="project_issue_stage_act" name="Stages" id="menu_project_issue_stage_act" parent="menu_project_confi"/> <record model="ir.ui.view" id="project_issue_form_view"> <field name="name">Project Issue Tracker Form</field> @@ -184,18 +187,18 @@ <field name="arch" type="xml"> <search string="Issue Tracker Search"> <group colspan="4" col="20"> - <filter string="Current" domain="[('state','in',('open','draft'))]" help="Draft and Open Issues" icon="terp-project" default="1"/> - <filter string="In Progress" domain="[('state','=','open')]" help="Open Issues" icon="terp-project"/> - <filter string="Pending" domain="[('state','=','pending')]" help="Pending Issues" icon="terp-project"/> - + <filter string="Current" domain="[('state','in',('open','draft'))]" help="Draft and Open Issues" icon="terp-check" default="1"/> + <filter string="In Progress" domain="[('state','=','open')]" help="Open Issues" icon="terp-camera_test"/> + <filter string="Pending" domain="[('state','=','pending')]" help="Pending Issues" icon="terp-gtk-media-pause"/> + <separator orientation="vertical"/> - - <filter icon="gtk-home" string=" Today " + + <filter icon="terp-go-today" string=" Today " separator="1" domain="[('date','=',time.strftime('%%Y-%%m-%%d'))]" help="Today's bugs" /> - <filter icon="gtk-media-rewind" + <filter icon="terp-go-week" string=" 7 Days " separator="1" domain="[('date','<', time.strftime('%%Y-%%m-%%d')), ('date','>=',(datetime.date.today()-datetime.timedelta(days=7)).strftime('%%Y-%%m-%%d'))]" help="Bugs during last 7 days" @@ -204,26 +207,26 @@ <field name="name" select='1' string="Subject"/> <field name="user_id" select="1" widget="selection"/> <field name="state" select="1"> - <filter icon="gtk-new" domain="[('state','in',('open','draft'))]" help="Current Bugs" name="current_bugs"/> - <filter icon="gtk-yes" domain="[('state','=','open')]" help="Open Bugs"/> + <filter icon="terp-check" domain="[('state','in',('open','draft'))]" help="Current Bugs" name="current_bugs"/> + <filter icon="terp-camera_test" domain="[('state','=','open')]" help="Open Bugs"/> </field> <field name="project_id" select="1" widget="selection" string="Project"/> </group> <newline/> - <group expand="1" string="Group By..." colspan="4" col="20" groups="base.group_extended"> - <filter string="Stage" icon="terp-crm" domain="[]" + <group expand="0" string="Group By..." colspan="4" col="20" groups="base.group_extended"> + <filter string="Stage" icon="terp-stage" domain="[]" context="{'group_by':'stage_id'}" /> - <filter string="Priority" icon="terp-crm" domain="[]" + <filter string="Priority" icon="terp-rating-rated" domain="[]" context="{'group_by':'priority'}" /> - <filter string="Campaign" icon="terp-crm" + <filter string="Campaign" icon="terp-gtk-jump-to-rtl" domain="[]" context="{'group_by':'type_id'}" /> <separator orientation="vertical" /> - <filter string="Partner" icon="terp-crm" domain="[]" + <filter string="Partner" icon="terp-personal" domain="[]" context="{'group_by':'partner_id'}" /> - <filter string="Salesman" icon="terp-crm" + <filter string="Salesman" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}" /> <separator orientation="vertical" /> - <filter string="Month" icon="terp-crm" + <filter string="Month" icon="terp-go-month" domain="[]" context="{'group_by':'create_date'}" /> <separator orientation="vertical" /> </group> @@ -285,12 +288,12 @@ <field name="arch" type="xml"> <search string="Feature Tracker Search"> <group> - <filter icon="gtk-home" string=" Today " + <filter icon="terp-go-today" string=" Today " separator="1" domain="[('date','=',time.strftime('%%Y-%%m-%%d'))]" help="Today's features" /> - <filter icon="gtk-media-rewind" + <filter icon="terp-go-week" string=" 7 Days " separator="1" domain="[('date','<', time.strftime('%%Y-%%m-%%d')), ('date','>=',(datetime.date.today()-datetime.timedelta(days=7)).strftime('%%Y-%%m-%%d'))]" help="Features during last 7 days" @@ -301,8 +304,8 @@ <field name="name" select='1' string="Feature description"/> <field name="user_id" select="1" widget="selection"/> <field name="state" select="1"> - <filter icon="gtk-new" domain="[('state','in',('open','draft'))]" help="Current Features" name="current_feature"/> - <filter icon="gtk-yes" domain="[('state','=','open')]" help="Open Features"/> + <filter icon="terp-check" domain="[('state','in',('open','draft'))]" help="Current Features" name="current_feature"/> + <filter icon="terp-camera_test" domain="[('state','=','open')]" help="Open Features"/> </field> <field name="project_id" select="1" widget="selection" string="Project"/> diff --git a/addons/project_issue/report/project_issue_report_view.xml b/addons/project_issue/report/project_issue_report_view.xml index 5694d33993b..adc1b3c662f 100644 --- a/addons/project_issue/report/project_issue_report_view.xml +++ b/addons/project_issue/report/project_issue_report_view.xml @@ -53,25 +53,25 @@ <group col="16" colspan="8"> <!-- <filter string="This Year" name="This Year" icon="terp-hr" domain="[('name','=',time.localtime()[0])]"/>--> - <filter string="This Year" icon="terp-hr" + <filter string="This Year" icon="terp-go-year" domain="[('create_date','<=', time.strftime('%%Y-%%m-%%d')), ('create_date','>',(datetime.date.today()-datetime.timedelta(days=365)).strftime('%%Y-%%m-%%d'))]"/> <!-- <filter string="This Month" name="This Year" icon="terp-hr" domain="[('month','=',time.strftime('%%m'))]" />--> - <filter string="This Month" icon="terp-hr" name="This Month" + <filter string="This Month" icon="terp-go-month" name="This Month" domain="[('create_date','<=', time.strftime('%%Y-%%m-%%d')), ('create_date','>',(datetime.date.today()-datetime.timedelta(days=30)).strftime('%%Y-%%m-%%d'))]"/> - <filter icon="gtk-media-rewind" string="7 Days" separator="1" + <filter icon="terp-go-week" string="7 Days" separator="1" domain="[('create_date','<=', time.strftime('%%Y-%%m-%%d')), ('create_date','>',(datetime.date.today()-datetime.timedelta(days=7)).strftime('%%Y-%%m-%%d'))]"/> <separator orientation="vertical" /> - <filter icon="terp-hr" + <filter icon="terp-document-new" string="Draft" domain="[('state','=','draft')]"/> - <filter icon="terp-hr" + <filter icon="terp-camera_test" string="Open" domain="[('state','=','open')]"/> - <filter icon="terp-hr" + <filter icon="terp-gtk-media-pause" string="Pending" domain="[('state','=','pending')]"/> @@ -88,7 +88,7 @@ </field> <field name="company_id" widget="selection"> - <filter icon="terp-crm" + <filter icon="terp-go-home" context="{'invisible_section': False}" domain="[('section_id.user_id.company_id','=',uid)]" help="My company"/> @@ -96,11 +96,11 @@ <field name="user_id" select="1" widget="selection"/> </group> <newline/> - <group expand="1" string="Group By..." colspan="4" col="8"> - <filter string="User" name="User" icon="terp-sale" + <group expand="0" string="Group By..." colspan="4" col="8"> + <filter string="User" name="User" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}" /> - <filter string="Company" icon="terp-sale" + <filter string="Company" icon="terp-go-home" domain="[]" context="{'group_by':'company_id'}" /> @@ -109,42 +109,42 @@ context="{'group_by':'section_id'}" /> <separator orientation="vertical" /> - <filter string="State" icon="terp-sale" + <filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}" /> - <filter string="Category" icon="terp-sale" + <filter string="Category" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by':'categ_id'}" /> - <filter string="Stage" icon="terp-sale" domain="[]" context="{'group_by':'stage_id'}"/> + <filter string="Stage" icon="terp-stage" domain="[]" context="{'group_by':'stage_id'}"/> <separator orientation="vertical"/> - <filter string="Project" icon="terp-sale" domain="[]" context="{'group_by':'project_id'}" /> - <filter string="Priority" icon="terp-sale" domain="[]" context="{'group_by':'priority'}" /> + <filter string="Project" icon="terp-folder-blue" domain="[]" context="{'group_by':'project_id'}" /> + <filter string="Priority" icon="terp-rating-rated" domain="[]" context="{'group_by':'priority'}" /> <separator orientation="vertical"/> - <filter string="Type" icon="terp-sale" domain="[]" context="{'group_by':'type_id'}"/> - <filter string="Task" icon="terp-sale" domain="[]" context="{'group_by':'task_id'}"/> + <filter string="Type" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by':'type_id'}"/> + <filter string="Task" icon="terp-stock_align_left_24" domain="[]" context="{'group_by':'task_id'}"/> <newline/> - <filter string="Assigned To" icon="terp-sale" domain="[]" context="{'group_by':'assigned_to'}"/> - <filter string="Partner" icon="terp-sale" domain="[]" context="{'group_by':'partner_id'}"/> - <filter string="Channel" icon="terp-sale" domain="[]" context="{'group_by':'canal_id'}"/> + <filter string="Assigned To" icon="terp-personal" domain="[]" context="{'group_by':'assigned_to'}"/> + <filter string="Partner" icon="terp-personal" domain="[]" context="{'group_by':'partner_id'}"/> + <filter string="Channel" icon="terp-call-start" domain="[]" context="{'group_by':'canal_id'}"/> <separator orientation="vertical" /> <filter string="Day" icon="terp-sale" domain="[]" context="{'group_by':'day'}"/> - <filter string="Month" icon="terp-sale" + <filter string="Month" icon="terp-go-month" domain="[]" context="{'group_by':'month'}" /> - <filter string="Year" icon="terp-sale" + <filter string="Year" icon="terp-go-year" domain="[]" context="{'group_by':'name'}" /> </group> <newline/> <group expand="0" string="Extended options..." colspan="10" col="12" groups="base.group_extended"> - <filter icon="terp-sale" + <filter icon="terp-dialog-close" string="Done" domain="[('state','=','done')]"/> - <filter icon="terp-sale" + <filter icon="terp-gtk-stop" string="Cancel" domain="[('state','=','cancel')]"/> <group> @@ -156,8 +156,8 @@ <field name="task_id"/> <separator orientation="vertical"/> <field name="assigned_to" widget="selection"> - <filter icon="terp-crm" help = "Project Issue Assigned To Me" domain="[('assigned_to','=',uid)]" /> - <filter icon="terp-crm" help="Non Assigned Project Issue" domain="[('assigned_to','=',False)]"/> + <filter icon="terp-personal" help = "Project Issue Assigned To Me" domain="[('assigned_to','=',uid)]" /> + <filter icon="terp-personal-" help="Non Assigned Project Issue" domain="[('assigned_to','=',False)]"/> </field> <newline/> <field name="categ_id" widget="selection" domain="[('object_id.model', '=', 'project.issue')]"/> diff --git a/addons/project_long_term/project_long_term.py b/addons/project_long_term/project_long_term.py index 95e9099f549..212af8a30dc 100644 --- a/addons/project_long_term/project_long_term.py +++ b/addons/project_long_term/project_long_term.py @@ -93,7 +93,7 @@ class project_phase(osv.osv): 'next_phase_ids': fields.many2many('project.phase', 'project_phase_rel', 'prv_phase_id', 'next_phase_id', 'Next Phases'), 'previous_phase_ids': fields.many2many('project.phase', 'project_phase_rel', 'next_phase_id', 'prv_phase_id', 'Previous Phases'), 'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of phases."), - 'duration': fields.float('Duration', required=True), + 'duration': fields.float('Duration', required=True, help="By default in days"), 'product_uom': fields.many2one('product.uom', 'Duration UoM', required=True, help="UoM (Unit of Measure) is the unit of measurement for Duration"), 'task_ids': fields.one2many('project.task', 'phase_id', "Project Tasks"), 'resource_ids': fields.one2many('project.resource.allocation', 'phase_id', "Project Resources"), diff --git a/addons/project_long_term/project_long_term_view.xml b/addons/project_long_term/project_long_term_view.xml index a2ecc604ebe..e681b0da57f 100644 --- a/addons/project_long_term/project_long_term_view.xml +++ b/addons/project_long_term/project_long_term_view.xml @@ -47,7 +47,7 @@ </group> <newline/> <group expand="1" string="Group By..." colspan="4" col="20"> - <filter name="resource" string="Resource" icon="terp-project" domain="[]" context="{'group_by':'resource_id'}"/> + <filter name="resource" string="Resource" icon="terp-folder-blue" domain="[]" context="{'group_by':'resource_id'}"/> <filter string="Phase" icon="terp-project" domain="[]" context="{'group_by':'phase_id'}"/> </group> </search> @@ -102,7 +102,7 @@ <field name="state" select="1"/> <button string="Draft" name="set_draft" states="open" icon="gtk-indent"/> <button string="Start Phase" name="set_open" states="pending,draft" icon="gtk-execute"/> - <button string="Done" name="set_done" states="draft,pending,open" icon="gtk-jump-to"/> + <button string="Done" name="set_done" states="draft,pending,open" icon="gtk-apply"/> <button string="Pending" name="set_pending" states="open" icon="gtk-media-pause"/> <button string="Cancel" name="set_cancel" states="draft,open,pending" icon="gtk-cancel"/> </group> @@ -218,23 +218,23 @@ <field name="arch" type="xml"> <search string="Project Phases"> <group colspan="4" col="20"> - <filter string="Current" domain="[('state','in',('open','draft'))]" help="Draft, Open and Pending Phases" icon="terp-project" default="1"/> - <filter string="In Progress" domain="[('state','=','open')]" help="Open Phases" icon="terp-project"/> - <filter string="Pending" domain="[('state','=','pending')]" help="Pending Phases" icon="terp-project"/> + <filter string="Draft" domain="[('state','=','draft')]" help="Draft Phases" icon="terp-check" default="1"/> + <filter string="In Progress" name="Progress" domain="[('state','=','open')]" help="Open Phases" icon="terp-camera_test"/> + <filter string="Pending" domain="[('state','=','pending')]" help="Pending Phases" icon="terp-gtk-media-pause"/> <separator orientation="vertical"/> <field name="name"/> <field name="project_id" widget="selection"> - <filter domain="[('project_id.user_id','=',uid)]" help="My Projects" icon="terp-project"/> + <filter domain="[('project_id.user_id','=',uid)]" help="My Projects" icon="terp-folder-blue"/> </field> <field name="responsible_id" widget="selection"/> <field name="date_start"/> </group> <newline/> <group expand="1" string="Group By..." colspan="4" col="20" groups="base.group_extended"> - <filter string="Project" icon="terp-project" domain="[]" context="{'group_by':'project_id'}"/> - <filter string="State" icon="terp-project" domain="[]" context="{'group_by':'state'}"/> - <filter string="User" icon="terp-project" domain="[]" context="{'group_by':'responsible_id'}"/> - <filter string="Start Date" icon="terp-project" domain="[]" context="{'group_by':'date_start'}"/> + <filter string="Project" icon="terp-folder-blue" domain="[]" context="{'group_by':'project_id'}"/> + <filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/> + <filter string="User" icon="terp-personal" domain="[]" context="{'group_by':'responsible_id'}"/> + <filter string="Start Date" icon="terp-gtk-jump-to-ltr" domain="[]" context="{'group_by':'date_start'}"/> </group> </search> </field> diff --git a/addons/project_long_term/wizard/project_compute_tasks_view.xml b/addons/project_long_term/wizard/project_compute_tasks_view.xml index c89c83b3058..eff475b4f11 100644 --- a/addons/project_long_term/wizard/project_compute_tasks_view.xml +++ b/addons/project_long_term/wizard/project_compute_tasks_view.xml @@ -8,15 +8,13 @@ <field name="type">form</field> <field name="arch" type="xml"> <form string="Compute Scheduling of Phases"> - <group colspan="4" col="4"> - <label colspan="4" string="This wizard will schedule start date, end date, and assign user to tasks for specified project" /> - <newline /> - <field colspan="4" name="project_id"/> - </group> - <group colspan="4" col="6"> - <button icon="gtk-cancel" special="cancel" string="_Cancel"/> - <button icon="gtk-ok" name="compute_date" string="Compute" type="object"/> + <group colspan="4" height="100" width="500"> + <field name="project_id"/> + <group colspan="4" col="6"> + <button icon="gtk-cancel" special="cancel" string="_Cancel"/> + <button icon="gtk-ok" name="compute_date" string="Compute" type="object"/> </group> + </group> </form> </field> </record> diff --git a/addons/project_mrp/mrp.py b/addons/project_mrp/mrp.py index 350d6b006b7..6287ca3ad30 100644 --- a/addons/project_mrp/mrp.py +++ b/addons/project_mrp/mrp.py @@ -55,10 +55,11 @@ class mrp_procurement(osv.osv): break # Creating a project for task.Project is created from Procurement. + project_obj = self.pool.get('project.project') proj_name = tools.ustr(so_ref) - proj_exist_id = self.pool.get('project.project').search(cr, uid, [('name','=',proj_name)], context=context) + proj_exist_id = project_obj.search(cr, uid, [('name','=',proj_name)], context=context) if not proj_exist_id: - project_id = self.pool.get('project.project').create(cr, uid, {'name':proj_name,'category_id':analytic_account_id, 'partner_id':partner_id}) + project_id = project_obj.create(cr, uid, {'name':proj_name, 'partner_id':partner_id}) else: project_id = proj_exist_id[0] diff --git a/addons/project_planning/project_planning_view.xml b/addons/project_planning/project_planning_view.xml index 0ebbcd8e519..fd9d586f21e 100644 --- a/addons/project_planning/project_planning_view.xml +++ b/addons/project_planning/project_planning_view.xml @@ -162,7 +162,7 @@ <field name="arch" type="xml"> <search string="Planning by Account"> <group col="8" colspan="4"> - <filter icon="terp-project" string="Current Plannings" domain="[('date_from','<=',time.strftime('%%Y-%%m-%%d')),('date_to','>=',time.strftime('%%Y-%%m-%%d'))]" help="Current Plannings"/> + <filter icon="terp-check" string="Current Plannings" domain="[('date_from','<=',time.strftime('%%Y-%%m-%%d')),('date_to','>=',time.strftime('%%Y-%%m-%%d'))]" help="Current Plannings"/> <separator orientation="vertical"/> <field name="name" select="1"/> <field name="code" select="1"/> diff --git a/addons/project_timesheet/report/task_report_view.xml b/addons/project_timesheet/report/task_report_view.xml index 35a7c9f3de6..5a653985a20 100644 --- a/addons/project_timesheet/report/task_report_view.xml +++ b/addons/project_timesheet/report/task_report_view.xml @@ -148,16 +148,16 @@ <field name="arch" type="xml"> <search string="Tasks by User"> <group colspan="4" col="3"> - <filter icon="terp-project" string="This Year" domain="[('year','=',time.strftime('%%Y'))]" /> - <filter icon="terp-project" string="This Month" domain="[('month','=',time.strftime('%%m'))]" /> + <filter icon="terp-go-year" string="This Year" domain="[('year','=',time.strftime('%%Y'))]" /> + <filter icon="terp-go-month" string="This Month" domain="[('month','=',time.strftime('%%m'))]" /> <separator orientation="vertical"/> <field name="user_id" select="1" widget="selection"/> </group> <newline/> <group expand="1" string="Group By..." colspan="4" col="3"> - <filter string="User" icon="terp-project" context="{'group_by':'user_id'}" default="1" /> - <filter string="Year" icon="terp-project" context="{'group_by':'year'}" /> - <filter string="Month" icon="terp-project" context="{'group_by':'month'}" /> + <filter string="User" icon="terp-personal" context="{'group_by':'user_id'}" default="1" /> + <filter string="Year" icon="terp-go-year" context="{'group_by':'year'}" /> + <filter string="Month" icon="terp-go-month" context="{'group_by':'month'}" /> </group> </search> </field> diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index b886dc60a0e..c2e871f685a 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -223,7 +223,7 @@ class purchase_order(osv.osv): else: raise osv.except_osv(_('Invalid action !'), _('Cannot delete Purchase Order(s) which are in %s State!' % s['state'])) - # TODO: temporary fix in 5.0, to remove in 5.2 when subflows support + # TODO: temporary fix in 5.0, to remove in 5.2 when subflows support # automatically sending subflow.delete upon deletion wf_service = netsvc.LocalService("workflow") for id in unlink_ids: @@ -248,7 +248,7 @@ class purchase_order(osv.osv): return {'value':{'location_id': res, 'dest_address_id': False}} def onchange_partner_id(self, cr, uid, ids, part): - + if not part: return {'value':{'partner_address_id': False, 'fiscal_position': False}} addr = self.pool.get('res.partner').address_get(cr, uid, [part], ['default']) @@ -264,12 +264,12 @@ class purchase_order(osv.osv): #TODO: implement messages system def wkf_confirm_order(self, cr, uid, ids, context={}): todo = [] - for po in self.browse(cr, uid, ids): + for po in self.browse(cr, uid, ids): if not po.order_line: raise osv.except_osv(_('Error !'),_('You can not confirm purchase order without Purchase Order Lines.')) - for line in po.order_line: + for line in po.order_line: if line.state=='draft': - todo.append(line.id) + todo.append(line.id) current_name = self.name_get(cr, uid, ids)[0][1] self.pool.get('purchase.order.line').action_confirm(cr, uid, todo, context) for id in ids: @@ -313,13 +313,13 @@ class purchase_order(osv.osv): wf_service = netsvc.LocalService("workflow") for p_id in ids: # Deleting the existing instance of workflow for PO - wf_service.trg_delete(uid, 'purchase.order', p_id, cr) + wf_service.trg_delete(uid, 'purchase.order', p_id, cr) wf_service.trg_create(uid, 'purchase.order', p_id, cr) return True def action_invoice_create(self, cr, uid, ids, *args): res = False - + journal_obj = self.pool.get('account.journal') for o in self.browse(cr, uid, ids): il = [] @@ -437,7 +437,7 @@ class purchase_order(osv.osv): }) if order_line.move_dest_id: self.pool.get('stock.move').write(cr, uid, [order_line.move_dest_id.id], {'location_id':order.location_id.id}) - todo_moves.append(move) + todo_moves.append(move) self.pool.get('stock.move').action_confirm(cr, uid, todo_moves) self.pool.get('stock.move').force_assign(cr, uid, todo_moves) wf_service = netsvc.LocalService("workflow") @@ -459,26 +459,26 @@ class purchase_order(osv.osv): def do_merge(self, cr, uid, ids, context): - """ - To merge similar type of purchase orders. - Orders will only be merged if: - * Purchase Orders are in draft - * Purchase Orders belong to the same partner + """ + To merge similar type of purchase orders. + Orders will only be merged if: + * Purchase Orders are in draft + * Purchase Orders belong to the same partner * Purchase Orders are have same stock location, same pricelist - Lines will only be merged if: - * Order lines are exactly the same except for the quantity and unit + Lines will only be merged if: + * Order lines are exactly the same except for the quantity and unit @param self: The object pointer. @param cr: A database cursor @param uid: ID of the user currently logged in - @param ids: the ID or list of IDs - @param context: A standard dictionary - + @param ids: the ID or list of IDs + @param context: A standard dictionary + @return: new purchase order id - - """ - wf_service = netsvc.LocalService("workflow") - def make_key(br, fields): + + """ + wf_service = netsvc.LocalService("workflow") + def make_key(br, fields): list_key = [] for field in fields: field_val = getattr(br, field) @@ -496,9 +496,9 @@ class purchase_order(osv.osv): return tuple(list_key) # compute what the new orders should contain - + new_orders = {} - + for porder in [order for order in self.browse(cr, uid, ids) if order.state == 'draft']: order_key = make_key(porder, ('partner_id', 'location_id', 'pricelist_id')) new_order = new_orders.setdefault(order_key, ({}, [])) @@ -541,7 +541,7 @@ class purchase_order(osv.osv): o_line[field] = field_val o_line['uom_factor'] = order_line.product_uom and order_line.product_uom.factor or 1.0 - + allorders = [] for order_key, (order_data, old_ids) in new_orders.iteritems(): @@ -601,7 +601,7 @@ class purchase_order_line(osv.osv): 'invoiced': fields.boolean('Invoiced', readonly=True), 'partner_id': fields.related('order_id','partner_id',string='Partner',readonly=True,type="many2one", relation="res.partner"), 'date_order': fields.related('order_id','date_order',string='Order Date',readonly=True,type="date") - + } _defaults = { 'product_qty': lambda *a: 1.0, @@ -621,7 +621,7 @@ class purchase_order_line(osv.osv): partner_id, date_order=False, fiscal_position=False, date_planned=False, name=False, price_unit=False, notes=False): if not pricelist: - raise osv.except_osv(_('No Pricelist !'), _('You have to select a pricelist in the purchase form !\nPlease set one before choosing a product.')) + raise osv.except_osv(_('No Pricelist !'), _('You have to select a pricelist or a supplier in the purchase form !\nPlease set one before choosing a product.')) if not partner_id: raise osv.except_osv(_('No Partner!'), _('You have to select a partner in the purchase form !\nPlease set one partner before choosing a product.')) if not product: @@ -692,7 +692,7 @@ class purchase_order_line(osv.osv): return res def action_confirm(self, cr, uid, ids, context={}): self.write(cr, uid, ids, {'state': 'confirmed'}, context) - return True + return True purchase_order_line() class mrp_procurement(osv.osv): @@ -700,7 +700,7 @@ class mrp_procurement(osv.osv): _columns = { 'purchase_id': fields.many2one('purchase.order', 'Latest Requisition'), } - + def action_po_assign(self, cr, uid, ids, context={}): """ This is action which call from workflow to assign purchase order to procurements @return: True diff --git a/addons/purchase/purchase_view.xml b/addons/purchase/purchase_view.xml index 8aa643d1c43..10c5ccd9749 100644 --- a/addons/purchase/purchase_view.xml +++ b/addons/purchase/purchase_view.xml @@ -150,12 +150,12 @@ <field name="arch" type="xml"> <search string="Search Purchase Order"> <group col='10' colspan='4'> - <filter icon="terp-purchase" name="draft" string="Quotations" domain="[('state','=','draft')]" separator="1"/> - <filter icon="terp-purchase" name="confirmed" string="To Approve" domain="[('state','in',('wait','confirmed'))]" separator="1"/> - <filter icon="terp-purchase" name="approved" string="Approved" domain="[('state','in',('approved','done'))]" separator="1"/> - <filter icon="terp-purchase" name="exception" string="Exception" domain="[('state','in',('except_invoice','except_picking'))]" separator="1"/> + <filter icon="terp-document-new" name="draft" string="Quotations" domain="[('state','=','draft')]" separator="1"/> + <filter icon="terp-camera_test" name="confirmed" string="To Approve" domain="[('state','in',('wait','confirmed'))]" separator="1"/> + <filter icon="terp-check" name="approved" string="Approved" domain="[('state','in',('approved','done'))]" separator="1"/> + <filter icon="terp-emblem-important" name="exception" string="Exception" domain="[('state','in',('except_invoice','except_picking'))]" separator="1"/> <separator orientation="vertical"/> - <filter icon="terp-purchase" string="To Invoice" domain="[('invoiced','=',1)]" separator="1"/> + <filter icon="terp-gtk-go-back-rtl" string="To Invoice" domain="[('invoiced','=',1)]" separator="1"/> <separator orientation="vertical"/> <field name="name" select="1" string="Reference"/> <field name="partner_id" select="1"/> @@ -163,10 +163,13 @@ <field name="create_uid" select="1" widget="selection"/> </group> <newline/> - <group expand="1" string="Group By..." colspan="4" col="10" groups="base.group_extended"> - <filter string="Supplier" icon="terp-purchase" domain="[]" context="{'group_by':'partner_id'}"/> - <filter string="State" icon="terp-sale" domain="[]" context="{'group_by':'state'}"/> - <filter string="Order Date" icon="terp-purchase" domain="[]" context="{'group_by':'date_order'}"/> + <group expand="0" string="Group By..." colspan="4" col="10" groups="base.group_extended"> + <filter string="Supplier" icon="terp-personal" domain="[]" context="{'group_by':'partner_id'}"/> + <filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/> + <filter string="Order Date" icon="terp-go-month" domain="[]" context="{'group_by':'date_order'}"/> + <separator orientation="vertical"/> + <filter string="Expected Date" icon="terp-go-month" domain="[]" context="{'group_by':'minimum_planned_date'}"/> + <filter string="Source Document" icon="terp-gtk-jump-to-rtl" domain="[]" context="{'group_by':'origin'}"/> </group> </search> </field> @@ -176,7 +179,7 @@ <field name="model">purchase.order</field> <field name="type">tree</field> <field name="arch" type="xml"> - <tree string="Purchase Order"> + <tree colors="grey:state in ('approved','done');blue:state in ('wait','confirmed');red:state in ('except_invoice','except_picking')" string="Purchase Order"> <field name="name" string="Reference"/> <field name="date_order" string="Order Date"/> <field name="partner_id"/> @@ -265,7 +268,7 @@ <tree colors="red:date_planned<=current_date;black:date_planned>current_date" string="Purchase Order Lines"> <field name="order_id"/> <field name="name"/> - <field name="date_planned" widget="date"/> + <field name="date_planned" widget="date" width="135"/> <field name="product_id"/> <field name="product_qty"/> <field name="product_uom"/> @@ -276,6 +279,25 @@ </field> </record> + <record id="purchase_order_line_search" model="ir.ui.view"> + <field name="name">purchase.order.line.search</field> + <field name="model">purchase.order.line</field> + <field name="type">search</field> + <field name="arch" type="xml"> + <search string="Search Purchase Order"> + <group> + <field name='order_id'/> + <field name="product_id" widget="selection" /> + </group> + <newline/> + <group expand="0" string="Group By..."> + <filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by' : 'state'}" /> + <filter string="Order Reference" icon="terp-gtk-jump-to-rtl" domain="[]" context="{'group_by' : 'product_id'}" /> + </group> + </search> + </field> + </record> + <act_window context="{'partner_id': active_id}" domain="[('partner_id', '=', active_id)]" @@ -309,6 +331,7 @@ <field name="domain">[('state','in',('confirmed','done')), ('invoiced','=',False)]</field> <field name="view_type">form</field> <field name="view_mode">tree,form</field> + <field name="search_view_id" ref="purchase_order_line_search"/> </record> <record id="purchase_line_form_action_tree2" model="ir.actions.act_window.view"> <field eval="1" name="sequence"/> diff --git a/addons/purchase/report/purchase_report_view.xml b/addons/purchase/report/purchase_report_view.xml index 0cfc357b51f..00c1c62f0ff 100644 --- a/addons/purchase/report/purchase_report_view.xml +++ b/addons/purchase/report/purchase_report_view.xml @@ -53,26 +53,26 @@ <field name="arch" type="xml"> <search string="Purchase Orders"> <group colspan="10" col="12"> - <filter icon="terp-purchase" string="This Year" + <filter icon="terp-go-year" string="This Year" domain="[('date','<=', time.strftime('%%Y-%%m-%%d')),('date','>',(datetime.date.today()-datetime.timedelta(days=365)).strftime('%%Y-%%m-%%d'))]" help="Tasks performed in this year"/> - <filter icon="terp-purchase" string="This Month" + <filter icon="terp-go-month" string="This Month" name="month" domain="[('date','<=', time.strftime('%%Y-%%m-%%d')), ('date','>',(datetime.date.today()-datetime.timedelta(days=30)).strftime('%%Y-%%m-%%d'))]" help="Tasks performed in this month"/> - <filter icon="gtk-media-rewind" + <filter icon="terp-go-week" string=" 7 Days " separator="1" domain="[('date','<=', time.strftime('%%Y-%%m-%%d')), ('date','>',(datetime.date.today()-datetime.timedelta(days=7)).strftime('%%Y-%%m-%%d'))]" help="Tasks during last 7 days"/> <separator orientation="vertical"/> - <filter icon="terp-purchase" + <filter icon="terp-document-new" string="Quotations" domain="[('state','=','draft')]"/> - <filter icon="terp-purchase" + <filter icon="terp-gtk-media-pause" string="Waiting Schedule" domain="[('state','=','waiting_date')]"/> - <filter icon="terp-purchase" + <filter icon="terp-camera_test" string="Manual in progress" domain="[('state','=','manual')]"/> @@ -80,7 +80,7 @@ <field name="partner_id" string="Supplier"/> <field name="product_id"/> <field name="user_id" widget="selection"> - <filter icon="terp-purchase" + <filter icon="terp-personal-" string="Purchase Non User" help="Purchase Non User" domain="[('user_id','=',False)]"/> @@ -88,31 +88,31 @@ <field name="company_id" groups="base.group_multi_company" widget="selection"/> </group> <newline/> - <group expand="1" string="Group By..." colspan="10" col="12"> - <filter string="Company" icon="terp-purchase" context="{'group_by':'company_id'}" groups="base.group_multi_company"/> - <filter string="Warehouse" icon="terp-purchase" context="{'group_by':'warehouse_id'}"/> - <filter string="Location" icon="terp-purchase" context="{'group_by':'location_id'}"/> + <group expand="0" string="Group By..." colspan="10" col="12"> + <filter string="Company" icon="terp-go-home" context="{'group_by':'company_id'}" groups="base.group_multi_company"/> + <filter string="Warehouse" icon="terp-go-home" context="{'group_by':'warehouse_id'}"/> + <filter string="Location" icon="terp-go-home" context="{'group_by':'location_id'}"/> <separator orientation="vertical"/> - <filter string="Responsible" name="Responsible" icon="terp-purchase" context="{'group_by':'user_id'}"/> - <filter string="Pricelist" icon="terp-purchase" context="{'group_by':'pricelist_id'}"/> - <filter string="Validated by" icon="terp-purchase" context="{'group_by':'validator'}"/> + <filter string="Responsible" name="Responsible" icon="terp-personal" context="{'group_by':'user_id'}"/> + <filter string="Pricelist" icon="terp-dolar" context="{'group_by':'pricelist_id'}"/> + <filter string="Validated by" icon="terp-personal" context="{'group_by':'validator'}"/> <separator orientation="vertical"/> - <filter string="Address Contact Name" icon="terp-purchase" context="{'group_by':'partner_address_id'}"/> - <filter string="Dest. Contact Name" icon="terp-purchase" context="{'group_by':'dest_address_id'}"/> - <filter string="Product" icon="terp-purchase" context="{'group_by':'product_id'}"/> + <filter string="Address Contact Name" icon="terp-personal" context="{'group_by':'partner_address_id'}"/> + <filter string="Dest. Contact Name" icon="terp-gtk-jump-to-ltr" context="{'group_by':'dest_address_id'}"/> + <filter string="Product" icon="terp-accessories-archiver" context="{'group_by':'product_id'}"/> <separator orientation="vertical"/> - <filter string="Supplier" name="partner_id" icon="terp-purchase" context="{'group_by':'partner_id'}"/> - <filter string="State" icon="terp-purchase" context="{'group_by':'state'}"/> - <filter string="Fiscal Position" icon="terp-purchase" context="{'group_by':'fiscal_position'}"/> + <filter string="Supplier" name="partner_id" icon="terp-personal" context="{'group_by':'partner_id'}"/> + <filter string="State" icon="terp-stock_effects-object-colorize" context="{'group_by':'state'}"/> + <filter string="Fiscal Position" icon="terp-go-year" context="{'group_by':'fiscal_position'}"/> <newline/> - <filter string="Day" icon="terp-purchase" context="{'group_by':'day'}"/> - <filter string="Month" icon="terp-purchase" context="{'group_by':'month'}"/> - <filter string="Year" icon="terp-purchase" context="{'group_by':'name'}"/> + <filter string="Day" icon="terp-go-month" context="{'group_by':'day'}"/> + <filter string="Month" icon="terp-go-month" context="{'group_by':'month'}"/> + <filter string="Year" icon="terp-go-year" context="{'group_by':'name'}"/> </group> <newline/> <group expand="0" string="Extended filters..." colspan="10" col="12" groups="base.group_extended"> - <filter icon="terp-purchase" string="Shipping Exception" domain="[('state','=','shipping_except')]"/> - <filter icon="terp-purchase" string="Done" domain="[('state','=','done')]"/> + <filter icon="terp-emblem-important" string="Shipping Exception" domain="[('state','=','shipping_except')]"/> + <filter icon="terp-dialog-close" string="Done" domain="[('state','=','done')]"/> <separator orientation="vertical"/> <field name="date_approve"/> <separator orientation="vertical"/> @@ -122,8 +122,8 @@ <field name="validator" widget="selection"/> <newline/> - <filter icon="terp-purchase" string="Invoice Exception " domain="[('state','=','invoice_except')]"/> - <filter icon="terp-purchase" string="Cancel" domain="[('state','=','cancel')]"/> + <filter icon="terp-emblem-important" string="Invoice Exception " domain="[('state','=','invoice_except')]"/> + <filter icon="terp-gtk-stop" string="Cancel" domain="[('state','=','cancel')]"/> <separator orientation="vertical"/> <field name="expected_date"/> <separator orientation="vertical"/> diff --git a/addons/purchase_requisition/purchase_requisition_view.xml b/addons/purchase_requisition/purchase_requisition_view.xml index 4a4587f5f04..186815c9bc3 100644 --- a/addons/purchase_requisition/purchase_requisition_view.xml +++ b/addons/purchase_requisition/purchase_requisition_view.xml @@ -39,7 +39,7 @@ <field name="date_start"/> <field name="date_end"/> <field name="origin"/> - <field name="company_id" groups="base.group_multi_company" widget="selection"/> + <field name="company_id" groups="base.group_multi_company" widget="selection"/> </group> <notebook colspan="4"> @@ -65,7 +65,7 @@ <button name="tender_reset" states="done,cancel" string="Reset to Draft" type="object" icon="gtk-convert" /> <button name="tender_done" states="in_progress" string="Done" type="object" icon="gtk-jump-to" /> <button name="tender_cancel" states="draft,in_progress" string="Cancel" type="object" icon="gtk-cancel" /> - </group> + </group> </page> <page string="Quotations"> <field colspan="4" name="purchase_ids" nolabel="1" mode="tree,form"> @@ -77,8 +77,8 @@ <field name="location_id"/> <field name="minimum_planned_date"/> <field name="origin"/> - <field name="state"/> - </tree> + <field name="state"/> + </tree> </field> <separator colspan="4" string=""/> <group col="8" colspan="4"> @@ -117,8 +117,8 @@ <field name="arch" type="xml"> <search string="Search Purchase Requisition"> <group col='10' colspan='4'> - <filter icon="terp-purchase" string="Current" domain="[('state','=','draft,in_progress')]" separator="1" help="Current Purchaes Requisition"/> - <filter icon="terp-purchase" string="Done" domain="[('state','=','done')]" separator="1" help="Current Purchaes Requisition"/> + <filter icon="terp-check" string="Current" domain="[('state','=','draft,in_progress')]" separator="1" help="Current Purchaes Requisition"/> + <filter icon="terp-dialog-close" string="Done" domain="[('state','=','done')]" separator="1" help="Current Purchaes Requisition"/> <separator orientation="vertical"/> <field name="name" select="1" string="Requisition Reference"/> <field name="purchase_ids" select="1"/> @@ -127,13 +127,13 @@ <field name="company_id" select="1" groups="base.group_multi_company" widget="selection"/> </group> <newline/> - <group expand="1" string="Group By..." colspan="4" col="10" groups="base.group_extended"> - <filter string="State" icon="terp-sale" domain="[]" context="{'group_by':'state'}"/> - <separator orientation="vertical"/> - <filter string="Date Start" icon="terp-purchase" domain="[]" context="{'group_by':'date_start'}"/> - <filter string="Date End" icon="terp-purchase" domain="[]" context="{'group_by':'date_end'}"/> - <separator orientation="vertical"/> - <filter string="Origin" icon="terp-purchase" domain="[]" context="{'group_by':'origin'}"/> + <group expand="0" string="Group By..." colspan="4" col="10" groups="base.group_extended"> + <filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/> + <separator orientation="vertical"/> + <filter string="Date Start" icon="terp-gtk-jump-to-ltr" domain="[]" context="{'group_by':'date_start'}"/> + <filter string="Date End" icon="terp-gtk-jump-to-rtl" domain="[]" context="{'group_by':'date_end'}"/> + <separator orientation="vertical"/> + <filter string="Origin" icon="terp-gtk-jump-to-rtl" domain="[]" context="{'group_by':'origin'}"/> </group> </search> </field> diff --git a/addons/report_intrastat/report_intrastat_view.xml b/addons/report_intrastat/report_intrastat_view.xml index e7a12e8ac5e..0449b097ec4 100644 --- a/addons/report_intrastat/report_intrastat_view.xml +++ b/addons/report_intrastat/report_intrastat_view.xml @@ -97,8 +97,8 @@ <field name="arch" type="xml"> <search string="Intrastat Data"> <group col="10" colspan="4"> - <filter string="This Year" icon="terp-stock" domain="[('name','=',time.localtime()[0])]"/> - <filter string="This Month" icon="terp-stock" domain="[('month','=',time.localtime()[1])]"/> + <filter string="This Year" icon="terp-go-year" domain="[('name','=',time.localtime()[0])]"/> + <filter string="This Month" icon="terp-go-month" domain="[('month','=',time.localtime()[1])]"/> <separator orientation="vertical"/> <field name="name" select="1"/> <field name="month" select="1"/> diff --git a/addons/resource/resource_view.xml b/addons/resource/resource_view.xml index 861b577ddff..df0974fd9ed 100644 --- a/addons/resource/resource_view.xml +++ b/addons/resource/resource_view.xml @@ -17,10 +17,10 @@ <field name="company_id" widget="selection" groups="base.group_multi_company"/> </group> <newline/> - <group expand="1" string="Group By..." colspan="4" col="20" groups="base.group_extended"> - <filter string="Type" icon="terp-project" domain="[]" context="{'group_by':'resource_type'}"/> - <filter string="Company" icon="terp-project" domain="[]" context="{'group_by':'company_id'}"/> - <filter string="User" icon="terp-project" domain="[]" context="{'group_by':'user_id'}"/> + <group expand="0" string="Group By..." colspan="4" col="20" groups="base.group_extended"> + <filter string="Type" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by':'resource_type'}"/> + <filter string="Company" icon="terp-go-home" domain="[]" context="{'group_by':'company_id'}"/> + <filter string="User" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/> </group> </search> </field> @@ -55,9 +55,9 @@ <field name="resource_id" string="Resource" widget="selection"/> </group> <newline/> - <group expand="1" string="Group By..." colspan="4" col="20"> - <filter string="Resource" icon="terp-project" domain="[]" context="{'group_by':'resource_id'}"/> - <filter string="Company" icon="terp-project" domain="[]" context="{'group_by':'company_id'}" groups="base.group_multi_company"/> + <group expand="0" string="Group By..." colspan="4" col="20"> + <filter string="Resource" icon="terp-personal" domain="[]" context="{'group_by':'resource_id'}"/> + <filter string="Company" icon="terp-go-home" domain="[]" context="{'group_by':'company_id'}" groups="base.group_multi_company"/> </group> </search> </field> @@ -162,12 +162,12 @@ <field name="arch" type="xml"> <form string="Resource"> <field name="name" /> - <field name="active"/> + <field name="user_id" attrs="{'required':[('resource_type','=','user')]}"/> <field name="company_id" widget="selection" groups="base.group_multi_company"/> - <field name="calendar_id" widget="selection"/> <field name="resource_type" /> - <field name="user_id" attrs="{'required':[('resource_type','=','user')]}"/> + <field name="calendar_id" widget="selection"/> <field name="time_efficiency" groups="base.group_extended"/> + <field name="active"/> </form> </field> </record> diff --git a/addons/sale/report/sale_report.py b/addons/sale/report/sale_report.py index cad05c8dcc8..d9be5f49274 100644 --- a/addons/sale/report/sale_report.py +++ b/addons/sale/report/sale_report.py @@ -29,7 +29,12 @@ class sale_report(osv.osv): _auto = False _rec_name = 'date' _columns = { - 'date': fields.date('Date', readonly=True), + 'date': fields.date('Date Order', readonly=True), + 'date_confirm': fields.date('Date Confirm', readonly=True), + 'shipped':fields.boolean('Shipped', readonly=True), + 'paid':fields.float('Picked', readonly=True), + 'shipped_qty_1':fields.integer('Shipped Qty', readonly=True), + 'paid_qty':fields.float('Paid Qty', readonly=True), 'year': fields.char('Year', size=4, readonly=True), 'month':fields.selection([('01','January'), ('02','February'), ('03','March'), ('04','April'), ('05','May'), ('06','June'), ('07','July'), ('08','August'), ('09','September'), @@ -65,45 +70,39 @@ class sale_report(osv.osv): tools.drop_view_if_exists(cr, 'sale_report') cr.execute(""" create or replace view sale_report as ( - select - min(l.id) as id, + select el.*, + (select count(1) from sale_order_line where order_id = s.id) as nbr, s.date_order as date, + s.date_confirm as date_confirm, to_char(s.date_order, 'YYYY') as year, to_char(s.date_order, 'MM') as month, to_char(s.date_order, 'YYYY-MM-DD') as day, - l.product_id as product_id, - u.name as uom_name, - sum(l.product_uom_qty * u.factor) as product_uom_qty, s.partner_id as partner_id, s.user_id as user_id, s.shop_id as shop_id, s.company_id as company_id, - extract(epoch from avg(s.date_confirm-s.create_date))/(24*60*60)::decimal(16,2) as delay, - sum(l.product_uom_qty*l.price_unit) as price_total, - (sum(l.product_uom_qty*l.price_unit)/sum(l.product_uom_qty * u.factor))::decimal(16,2) as price_average, - count(*) as nbr, + extract(epoch from (s.date_confirm-s.create_date))/(24*60*60)::decimal(16,2) as delay, s.state, - pt.categ_id, + s.shipped, + s.shipped::integer as shipped_qty_1, s.pricelist_id as pricelist_id, s.project_id as analytic_account_id - from + from + sale_order s, + ( + select l.id as id, + l.product_id as product_id, + u.name as uom_name, + sum(l.product_uom_qty * u.factor) as product_uom_qty, + sum(l.product_uom_qty*l.price_unit) as price_total, + (sum(l.product_uom_qty*l.price_unit)/sum(l.product_uom_qty * u.factor))::decimal(16,2) as price_average, + pt.categ_id, l.order_id + from sale_order_line l - left join sale_order s on (s.id=l.order_id) left join product_uom u on (u.id=l.product_uom) left join product_template pt on (pt.id=l.product_id) - group by - s.date_order, - s.partner_id, - l.product_id, - l.product_uom, - s.user_id, - pt.categ_id, - u.name, - s.state, - s.shop_id, - s.company_id, - s.pricelist_id, - s.project_id + group by l.id, l.order_id, l.product_id, u.name, pt.categ_id) el + where s.id = el.order_id ) """) sale_report() diff --git a/addons/sale/report/sale_report_view.xml b/addons/sale/report/sale_report_view.xml index 98ae326fc14..75dd9d55642 100644 --- a/addons/sale/report/sale_report_view.xml +++ b/addons/sale/report/sale_report_view.xml @@ -20,12 +20,12 @@ <field name="categ_id" invisible="1"/> <field name="nbr" sum="# of Lines"/> <field name="product_uom_qty" sum="# of Qty"/> + <field name="shipped_qty_1"/> <field name="uom_name" invisible="not context.get('set_visible',False)"/> <field name="price_average" avg="Average Price"/> <field name="price_total" sum="Total Price"/> <field name="delay" avg="Days to Close"/> <field name="state" invisible="1"/> - <field name="pricelist_id" invisible="1"/> <field name="analytic_account_id" invisible="1"/> </tree> </field> @@ -51,57 +51,62 @@ <field name="arch" type="xml"> <search string="Sales Analysis"> <group> - <filter icon="gtk-media-rewind" string=" 365 Days " + <filter icon="terp-go-year" string=" 365 Days " domain="[('date','<=', time.strftime('%%Y-%%m-%%d')),('date','>',(datetime.date.today()-datetime.timedelta(days=365)).strftime('%%Y-%%m-%%d'))]" help="Tasks performed in last 365 days"/> - <filter icon="gtk-media-rewind" string=" 30 Days " + <filter icon="terp-go-month" string=" 30 Days " name="month" domain="[('date','<=', time.strftime('%%Y-%%m-%%d')), ('date','>',(datetime.date.today()-datetime.timedelta(days=30)).strftime('%%Y-%%m-%%d'))]" help="Tasks performed in last 30 days"/> - <filter icon="gtk-media-rewind" + <filter icon="terp-go-week" string=" 7 Days " separator="1" domain="[('date','<=', time.strftime('%%Y-%%m-%%d')), ('date','>',(datetime.date.today()-datetime.timedelta(days=7)).strftime('%%Y-%%m-%%d'))]" help="Tasks during last 7 days"/> <separator orientation="vertical"/> - <filter icon="terp-sale" + <filter icon="terp-document-new" string="Quotations" domain="[('state','=','draft')]"/> - <filter icon="terp-sale" + <filter icon="terp-dolar" string="Sales" domain="[('state','not in',('draft','done','cancel'))]"/> <separator orientation="vertical"/> + <filter icon="terp-sale" + string="Picked" + domain="[('shipped','=',True)]"/> + <separator orientation="vertical"/> <field name="partner_id"/> <field name="product_id"/> <field name="user_id" widget="selection"> - <filter icon="terp-sale" + <filter icon="terp-dolar" string="My Sales" help="My Sales" domain="[('user_id','=',uid)]"/> </field> </group> <newline/> - <group expand="1" string="Group By..." colspan="10" col="12"> - <filter string="Salesman" icon="terp-sale" name="User" context="{'group_by':'user_id'}"/> - <filter string="Shop" icon="terp-sale" context="{'group_by':'shop_id'}"/> - <filter string="Company" icon="terp-sale" groups="base.group_multi_company" context="{'group_by':'company_id'}"/> + <group expand="0" string="Group By..." colspan="10" col="12"> + <filter string="Salesman" icon="terp-personal" name="User" context="{'group_by':'user_id'}"/> + <filter string="Shop" icon="terp-go-home" context="{'group_by':'shop_id'}"/> + <filter string="Company" icon="terp-go-home" groups="base.group_multi_company" context="{'group_by':'company_id'}"/> <separator orientation="vertical"/> - <filter string="Product" icon="terp-sale" context="{'group_by':'product_id','set_visible':True}"/> - <filter string="Default UoM" icon="terp-sale" context="{'group_by':'uom_name'}"/> - <filter string="Partner" icon="terp-sale" context="{'group_by':'partner_id'}"/> - <filter string="State" icon="terp-sale" context="{'group_by':'state'}"/> + <filter string="Product" icon="terp-accessories-archiver" context="{'group_by':'product_id','set_visible':True}"/> + <filter string="Default UoM" icon="terp-mrp" context="{'group_by':'uom_name'}"/> + <filter string="Partner" icon="terp-personal" context="{'group_by':'partner_id'}"/> + <filter string="State" icon="terp-stock_effects-object-colorize" context="{'group_by':'state'}"/> <separator orientation="vertical"/> - <filter string="Pricelist" icon="terp-sale" context="{'group_by':'pricelist_id'}"/> - <filter string="Analytic Account" icon="terp-sale" context="{'group_by':'analytic_account_id'}"/> - <filter string="Category of Product" icon="terp-sale" context="{'group_by':'categ_id'}"/> + <filter string="Pricelist" icon="terp-dolar" context="{'group_by':'pricelist_id'}"/> + <filter string="Analytic Account" icon="terp-folder-green" context="{'group_by':'analytic_account_id'}"/> + <filter string="Category of Product" icon="terp-stock_symbol-selection" context="{'group_by':'categ_id'}"/> <separator orientation="vertical"/> - <filter string="Day" icon="terp-sale" context="{'group_by':'day'}"/> - <filter string="Month" icon="terp-sale" context="{'group_by':'month'}"/> - <filter string="Year" icon="terp-sale" context="{'group_by':'year'}"/> + <filter string="Day" icon="terp-go-month" context="{'group_by':'day'}"/> + <filter string="Month" icon="terp-go-month" context="{'group_by':'month'}"/> + <filter string="Year" icon="terp-go-year" context="{'group_by':'year'}"/> </group> <newline/> <group expand="0" string="Extended options..." groups="base.group_extended"> <field name="date"/> + <field name="date_confirm"/> <separator orientation="vertical"/> <field name="shop_id" widget="selection"/> <field name="state"/> diff --git a/addons/sale/sale.py b/addons/sale/sale.py index 356bd69f679..e684a1a6c1d 100644 --- a/addons/sale/sale.py +++ b/addons/sale/sale.py @@ -510,12 +510,12 @@ class sale_order(osv.osv): def action_invoice_end(self, cr, uid, ids, context=None): if context is None: context = {} - + for order in self.browse(cr, uid, ids, context=context): for line in order.order_line: if line.state == 'exception': self.pool.get('sale.order.line').write(cr, uid, [line.id], {'state': 'confirmed'}, context=context) - + if order.state == 'invoice_except': self.write(cr, uid, [order.id], {'state' : 'progress'}, context=context) @@ -1085,7 +1085,7 @@ class sale_order_line(osv.osv): warning = { 'title': 'No Pricelist !', 'message': - 'You have to select a pricelist in the sale form !\n' + 'You have to select a pricelist or a customer in the sale form !\n' 'Please set one before choosing a product.' } else: diff --git a/addons/sale/sale_view.xml b/addons/sale/sale_view.xml index 1d49c105f18..4d82e8595ad 100644 --- a/addons/sale/sale_view.xml +++ b/addons/sale/sale_view.xml @@ -43,8 +43,9 @@ <field name="view_mode">tree,form</field> <field name="view_id" ref="view_shop_tree"/> </record> + <menuitem action="action_shop_form" id="menu_action_shop_form" - parent="base.menu_base_config" sequence="70" + parent="product.prod_config_main" sequence="0" groups="base.group_extended"/> <record id="view_sale_order_calendar" model="ir.ui.view"> @@ -252,21 +253,21 @@ <field name="type">search</field> <field name="arch" type="xml"> <search string="Search Sales Order"> - <filter icon="terp-sale" string="Quotations" domain="[('state','=','draft')]"/> - <filter icon="terp-sale" string="Running" domain="[('state','in',('manual','progress'))]"/> - <filter icon="terp-sale" string="Sales To Invoice" domain="[('state','=','manual')]"/> + <filter icon="terp-document-new" string="Quotations" domain="[('state','=','draft')]"/> + <filter icon="terp-check" string="Running" domain="[('state','in',('manual','progress'))]"/> + <filter icon="terp-gtk-go-back-rtl" string="Sales To Invoice" domain="[('state','=','manual')]"/> <separator orientation="vertical"/> <field name="name" select="1"/> <field name="partner_id" select="1"/> <field name="user_id" select="1" widget="selection"/> <field name="date_order" select="1" string="Order date" /> <newline/> - <group expand="1" string="Group By..." colspan="11" col="11" groups="base.group_extended"> - <filter string="Customer" icon="terp-sale" domain="[]" context="{'group_by':'partner_id'}"/> - <filter string="Salesman" icon="terp-sale" domain="[]" context="{'group_by':'user_id'}"/> + <group expand="0" string="Group By..." colspan="11" col="11" groups="base.group_extended"> + <filter string="Customer" icon="terp-personal" domain="[]" context="{'group_by':'partner_id'}"/> + <filter string="Salesman" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/> <separator orientation="vertical"/> - <filter string="Order Date" icon="terp-sale" domain="[]" context="{'group_by':'date_order'}"/> - <filter string="State" icon="terp-sale" domain="[]" context="{'group_by':'state'}"/> + <filter string="Order Date" icon="terp-go-month" domain="[]" context="{'group_by':'date_order'}"/> + <filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/> </group> </search> </field> @@ -421,21 +422,21 @@ <field name="type">search</field> <field name="arch" type="xml"> <search string="Search Sales Order"> - <filter icon="terp-purchase" string="To Invoice" domain="[('invoiced','<>', 1),('state','=','done')]" separator="1"/> + <filter icon="terp-gtk-go-back-rtl" string="To Invoice" domain="[('invoiced','<>', 1),('state','=','done')]" separator="1"/> <separator orientation="vertical"/> <field name="order_id"/> <field name="order_partner_id"/> <field name="product_id"/> <field name="salesman_id" widget="selection"> - <filter icon="terp-sale" domain="[('salesman_id','=',uid)]" help="My Sale Order Lines"/> - <filter icon="terp-sale" domain="[('salesman_id','child_of',[uid])]" help="My Departments Sale Order Lines"/> + <filter icon="terp-dolar" domain="[('salesman_id','=',uid)]" help="My Sale Order Lines"/> + <filter icon="terp-personal+" domain="[('salesman_id','child_of',[uid])]" help="My Departments Sale Order Lines"/> </field> <newline/> <group expand="context.get('report',False)" string="Group By..." colspan="9" col="8"> - <filter string="Product" icon="terp-sale" domain="[]" context="{'group_by':'product_id'}"/> + <filter string="Product" icon="terp-accessories-archiver" domain="[]" context="{'group_by':'product_id'}"/> <filter string="Order" icon="terp-sale" domain="[]" context="{'group_by':'order_id'}"/> - <filter string="Salesman" icon="terp-sale" domain="[]" context="{'group_by':'salesman_id'}"/> - <filter string="State" icon="terp-sale" domain="[]" context="{'group_by':'state'}"/> + <filter string="Salesman" icon="terp-personal" domain="[]" context="{'group_by':'salesman_id'}"/> + <filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/> </group> </search> </field> @@ -447,14 +448,14 @@ <field name="type">search</field> <field name="arch" type="xml"> <search string="Search Uninvoiced Lines"> - <filter icon="terp-purchase" string="Shipped" + <filter icon="terp-accessories-archiver" string="Shipped" domain="[('state','=','done')]" name="unshipped" /> - <filter icon="terp-purchase" string="Uninvoiced" name="uninvoiced" + <filter icon="terp-dolar_ok!" string="Uninvoiced" name="uninvoiced" domain="[('invoiced','<>', 1),('state','<>','draft'),('state','<>','cancel')]" /> - <filter icon="terp-purchase" string="Sale Order" + <filter icon="terp-dolar" string="Sale Order" domain="[('state','=','confirmed')]" name="sale order" /> @@ -464,10 +465,10 @@ <field name="product_id"/> <field name="state"/> <newline /> - <group expand="1" string="Group By..." colspan="9" col="8"> - <filter string="Product" icon="terp-sale" domain="[]" context="{'group_by':'product_id'}"/> - <filter string="Order" icon="terp-sale" domain="[]" context="{'group_by':'order_id'}"/> - <filter string="State" icon="terp-sale" domain="[]" context="{'group_by':'state'}"/> + <group expand="0" string="Group By..." colspan="9" col="8"> + <filter string="Product" icon="terp-accessories-archiver" domain="[]" context="{'group_by':'product_id'}"/> + <filter string="Order" icon="terp-gtk-jump-to-rtl" domain="[]" context="{'group_by':'order_id'}"/> + <filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/> </group> </search> </field> diff --git a/addons/sale_crm/sale_crm_view.xml b/addons/sale_crm/sale_crm_view.xml index 3a703d1b5ca..bf5f1aaac52 100644 --- a/addons/sale_crm/sale_crm_view.xml +++ b/addons/sale_crm/sale_crm_view.xml @@ -35,7 +35,7 @@ <field name="arch" type="xml"> <field name="date_order" position="after"> <field name="section_id" default="context.get('section_id', False)" widget="selection" string="Sale Team" groups="base.group_extended"> - <filter icon="terp-crm" + <filter icon="terp-personal+" domain="[('section_id','=',context.get('section_id',False))]" groups="base.group_extended" help="My Sales Team"/> diff --git a/addons/sale_journal/report/sale_journal_report_view.xml b/addons/sale_journal/report/sale_journal_report_view.xml index 9d4cdf3e368..aa0a9cf06fe 100644 --- a/addons/sale_journal/report/sale_journal_report_view.xml +++ b/addons/sale_journal/report/sale_journal_report_view.xml @@ -1,8 +1,8 @@ <openerp> <data> - + <!-- Sales by journal's view --> - + <record model="ir.ui.view" id="view_sale_journal_report_tree"> <field name="name">sale.journal.report.tree</field> <field name="model">sale.journal.report</field> @@ -19,9 +19,9 @@ </tree> </field> </record> - + <!-- sales journal graph view --> - + <record id="view_sale_journal_graph" model="ir.ui.view"> <field name="name">sale.journal.report.graph</field> <field name="model">sale.journal.report</field> @@ -33,9 +33,9 @@ </graph> </field> </record> - - <!-- sales by journal search view --> - + + <!-- sales by journal search view --> + <record model="ir.ui.view" id="view_sale_journal_report_search"> <field name="name">sale.journal.report.search</field> <field name="model">sale.journal.report</field> @@ -43,16 +43,16 @@ <field name="arch" type="xml"> <search string="Sales by Journal"> <group col="8" colspan="4"> - <filter icon="terp-sale" string="This Year" domain="[('name','!=','')]" help="Sale journal in this year"/> - <filter icon="terp-sale" string="This Month" domain="[('name','=',time.strftime('%%Y-%%m-01'))]" help="Sale journal in this month"/> + <filter icon="terp-go-year" string="This Year" domain="[('name','!=','')]" help="Sale journal in this year"/> + <filter icon="terp-go-month" string="This Month" domain="[('name','=',time.strftime('%%Y-%%m-01'))]" help="Sale journal in this month"/> <separator orientation="vertical"/> - <filter icon="terp-sale" + <filter icon="terp-document-new" string="Quotations" domain="[('state','=','draft')]"/> - <filter icon="terp-sale" + <filter icon="terp-gtk-media-pause" string="Waiting Schedule" domain="[('state','=','waiting_date')]"/> - <filter icon="terp-sale" + <filter icon="terp-camera_test" string="In progress" domain="[('state','=','progress')]"/> <separator orientation="vertical"/> @@ -62,15 +62,15 @@ </group> <newline/> <group expand="1" string="Group By..." colspan="4" col="12"> - <filter string="journal" name="journal" icon="terp-sale" context="{'group_by':'journal_id'}"/> - <filter string="State" icon="terp-sale" context="{'group_by':'state'}"/> + <filter string="journal" name="journal" icon="terp-folder-orange" context="{'group_by':'journal_id'}"/> + <filter string="State" icon="terp-stock_effects-object-colorize" context="{'group_by':'state'}"/> </group> </search> </field> </record> - + <!-- Action of sales by journal view--> - + <record model="ir.actions.act_window" id="action_sale_journal_report_open_menu_all"> <field name="name">Sales by Journal</field> <field name="res_model">sale.journal.report</field> @@ -82,10 +82,10 @@ </record> <menuitem name="Sales by Journal" id="menu_sale_journal_report_open_all" parent="base.next_id_64" action="action_sale_journal_report_open_menu_all"/> - + <!-- picking by journal and invoice's tree view--> - + <record model="ir.ui.view" id="view_sale_journal_picking_report_tree"> <field name="name">sale.journal.picking.report.tree</field> <field name="model">sale.journal.picking.report</field> @@ -105,9 +105,9 @@ </tree> </field> </record> - + <!-- picking journal's graph view --> - + <record id="view_sale_journal_picking_graph" model="ir.ui.view"> <field name="name">sale.journal.picking.report.graph</field> <field name="model">sale.journal.picking.report</field> @@ -120,9 +120,9 @@ </graph> </field> </record> - + <!-- Picking journal search view --> - + <record model="ir.ui.view" id="view_sale_journal_picking_report_search"> <field name="name">sale.journal.picking.report.search</field> <field name="model">sale.journal.picking.report</field> @@ -130,16 +130,16 @@ <field name="arch" type="xml"> <search string="Picking journal"> <group col="8" colspan="4"> - <filter icon="terp-sale" string="This Year" name="year" domain="[('name','=',time.strftime('%%Y'))]" help="Picking by invoice or by journal method in this year"/> - <filter icon="terp-sale" string="This Month" name="month" domain="[('month','=',time.strftime('%%m'))]" help="Picking by invoice or by journal method in this month"/> + <filter icon="terp-go-year" string="This Year" name="year" domain="[('name','=',time.strftime('%%Y'))]" help="Picking by invoice or by journal method in this year"/> + <filter icon="terp-go-month" string="This Month" name="month" domain="[('month','=',time.strftime('%%m'))]" help="Picking by invoice or by journal method in this month"/> <separator orientation="vertical"/> - <filter icon="terp-stock" + <filter icon="terp-document-new" string="Draft" domain="[('state','=','draft')]"/> - <filter icon="terp-stock" + <filter icon="terp-gtk-media-pause" string="Pending" domain="[('state','=','waiting')]"/> - <filter icon="terp-stock" + <filter icon="terp-camera_test" string="Confirmed" domain="[('state','=','confirmed')]"/> <separator orientation="vertical"/> @@ -147,19 +147,19 @@ <field name="month" select="1"/> <field name="invoice_state" select="1"/> <field name="state" select="1"/> - </group> + </group> <newline/> <group expand="1" string="Group By..." colspan="4" col="12"> - <filter string="Journal" icon="terp-stock" context="{'group_by':'journal_id'}"/> - <filter string="Invoice" icon="terp-stock" context="{'group_by':'invoice_type_id'}"/> + <filter string="Journal" icon="terp-folder-orange" context="{'group_by':'journal_id'}"/> + <filter string="Invoice" icon="terp-dolar" context="{'group_by':'invoice_type_id'}"/> <separator orientation="vertical"/> - <filter string="Invoice state" icon="terp-stock" context="{'group_by':'invoice_state'}"/> - <filter string="state" icon="terp-stock" context="{'group_by':'state'}"/> + <filter string="Invoice state" icon="terp-stock_effects-object-colorize" context="{'group_by':'invoice_state'}"/> + <filter string="state" icon="terp-stock_effects-object-colorize" context="{'group_by':'state'}"/> </group> </search> </field> </record> - + <record model="ir.actions.act_window" id="action_sale_journal_picking_report_open"> <field name="name">Statistics on picking to invoice</field> <field name="res_model">sale.journal.picking.report</field> @@ -168,9 +168,9 @@ <field name="view_mode">tree,form</field> <field name="domain">[('invoice_state','=','2binvoiced'),('invoice_type_id','=',active_id)]</field> </record> - + <!-- Action for picking journal view --> - + <record model="ir.actions.act_window" id="action_sale_journal_picking_report_open_menu_all"> <field name="name">Picking Journal</field> <field name="res_model">sale.journal.picking.report</field> @@ -180,8 +180,8 @@ <field name="search_view_id" ref="view_sale_journal_picking_report_search"/> <field name="context">{'search_default_month':1, 'group_by_no_leaf':1,'group_by':[]}</field> </record> - + <menuitem name="Picking journal" id="menu_invoice_type_picking_stats_open_all" parent="stock.next_id_61" action="action_sale_journal_picking_report_open_menu_all"/> - + </data> </openerp> diff --git a/addons/sale_journal/sale_journal_view.xml b/addons/sale_journal/sale_journal_view.xml index 60161a1b2bf..7e4cc33b283 100644 --- a/addons/sale_journal/sale_journal_view.xml +++ b/addons/sale_journal/sale_journal_view.xml @@ -1,8 +1,8 @@ <openerp> <data> - + <!-- sale journal invoice Type's Form view --> - + <record model="ir.ui.view" id="view_sale_journal_invoice_type_form"> <field name="name">sale_journal.invoice.type.form</field> <field name="model">sale_journal.invoice.type</field> @@ -17,9 +17,9 @@ </form> </field> </record> - - <!-- sale journal invoice Type's tree view --> - + + <!-- sale journal invoice Type's tree view --> + <record model="ir.ui.view" id="view_sale_journal_invoice_type_tree"> <field name="name">sale_journal.invoice.type.tree</field> <field name="model">sale_journal.invoice.type</field> @@ -31,19 +31,19 @@ </tree> </field> </record> - - <!-- Action for sale journal invoice Type --> - + + <!-- Action for sale journal invoice Type --> + <record model="ir.actions.act_window" id="action_definition_journal_invoice_type"> <field name="res_model">sale_journal.invoice.type</field> <field name="view_type">form</field> <field name="view_mode">tree,form</field> </record> - + <!-- <menuitem name="Invoicing Methods" id="menu_definition_journal_invoice_type" parent="sale.menu_shop_configuration" action="action_definition_journal_invoice_type"/> --> - + <!-- sale journal Form view --> - + <record model="ir.ui.view" id="view_sale_journal_form"> <field name="name">sale_journal.sale.journal.form</field> <field name="model">sale_journal.sale.journal</field> @@ -57,7 +57,7 @@ <field name="date" select="1"/> <field name="date_created" select="1"/> <field name="date_validation" select="1"/> - </group> + </group> <notebook colspan="4"> <page string="Sales"> <field name="sale_stats_ids" colspan="4" nolabel="1"> @@ -86,9 +86,9 @@ </form> </field> </record> - - <!-- Sale journal tree view --> - + + <!-- Sale journal tree view --> + <record model="ir.ui.view" id="view_sale_journal_tree"> <field name="name">sale_journal.sale.journal.tree</field> <field name="model">sale_journal.sale.journal</field> @@ -103,9 +103,9 @@ </tree> </field> </record> - - <!-- Sale journal search view --> - + + <!-- Sale journal search view --> + <record model="ir.ui.view" id="view_sale_journal_search"> <field name="name">sale_journal.sale.journal.search</field> <field name="model">sale_journal.sale.journal</field> @@ -113,8 +113,8 @@ <field name="arch" type="xml"> <search string="Sales by Journal"> <group col="8" colspan="4"> - <filter icon="terp-sale" string="My Sale Journals" domain="[('user_id','=',uid)]" help="My Sale Journals"/> - <filter icon="terp-sale" string="Open" domain="[('state','=','open')]" help="Open Sale Journals"/> + <filter icon="terp-personal" string="My Sale Journals" domain="[('user_id','=',uid)]" help="My Sale Journals"/> + <filter icon="terp-camera_test" string="Open" domain="[('state','=','open')]" help="Open Sale Journals"/> <separator orientation="vertical"/> <field name="name" select="1"/> <field name="code" select="1"/> @@ -124,20 +124,20 @@ </search> </field> </record> - - <!-- Action for sale journal view --> - + + <!-- Action for sale journal view --> + <record model="ir.actions.act_window" id="action_definition_journal"> <field name="res_model">sale_journal.sale.journal</field> <field name="view_type">form</field> <field name="view_mode">tree,form</field> <field name="search_view_id" ref="view_sale_journal_search"/> </record> - + <menuitem id="menu_definition_journal" name="Sales Journals" parent="base.menu_base_config" action="action_definition_journal" sequence="60" /> - - <!-- Inherit sales order form view --> - + + <!-- Inherit sales order form view --> + <record model="ir.ui.view" id="sale_journal_sale_order"> <field name="name">sale.order.journal.view.form</field> <field name="type">form</field> @@ -151,9 +151,9 @@ </field> </field> </record> - + <!-- Inherit sales order tree view--> - + <record model="ir.ui.view" id="sale_journal_sale_order_tree"> <field name="name">sale.order.journal.view.tree</field> <field name="type">tree</field> @@ -167,8 +167,8 @@ </field> </record> -<!-- Inherit stock picking's form view --> - +<!-- Inherit stock picking's form view --> + <record model="ir.ui.view" id="sale_journal_picking_order"> <field name="name">stock.picking.journal.view.form</field> <field name="type">form</field> @@ -183,8 +183,8 @@ </field> </record> -<!-- Inherit stock picking's tree view --> - +<!-- Inherit stock picking's tree view --> + <record model="ir.ui.view" id="sale_journal_picking_order_tree"> <field name="name">stock.picking.journal.view.tree</field> <field name="type">tree</field> @@ -198,9 +198,9 @@ </field> </field> </record> - + <!-- Inherit stock picking delivery's form view.--> - + <record model="ir.ui.view" id="sale_journal_picking_order_del"> <field name="name">stock.picking.journal.view.form</field> <field name="type">form</field> @@ -214,9 +214,9 @@ </field> </field> </record> - + <!-- Inherit stock picking delivery's tree view.--> - + <record model="ir.ui.view" id="sale_journal_picking_order_tree_del"> <field name="name">stock.picking.journal.view.tree</field> <field name="type">tree</field> @@ -230,7 +230,7 @@ </field> </field> </record> - + <record model="ir.ui.view" id="sale_journal_picking_order_in"> <field name="name">stock.picking.journal.view.form</field> <field name="type">form</field> @@ -244,7 +244,7 @@ </field> </field> </record> - + <record model="ir.ui.view" id="sale_journal_picking_order_tree_in"> <field name="name">stock.picking.journal.view.tree</field> <field name="type">tree</field> @@ -258,7 +258,7 @@ </field> </field> </record> - + <record model="ir.ui.view" id="sale_journal_picking_order_out"> <field name="name">stock.picking.journal.view.form</field> <field name="type">form</field> @@ -272,7 +272,7 @@ </field> </field> </record> - + <record model="ir.ui.view" id="sale_journal_picking_order_tree_out"> <field name="name">stock.picking.journal.view.tree</field> <field name="type">tree</field> @@ -286,33 +286,33 @@ </field> </field> </record> - - <!-- Action of sale journal report in sale journal --> - + + <!-- Action of sale journal report in sale journal --> + <act_window name="Monthly sales" domain="[('journal_id', '=', active_id)]" res_model="sale.journal.report" src_model="sale_journal.sale.journal" id="act_sale_journal_sale_journal_2_sale_journal_sale_stats"/> - - <!-- Action of stock picking in picking journal --> - + + <!-- Action of stock picking in picking journal --> + <act_window name="Assigned picking" domain="[('journal_id', '=', active_id),('state', '=', 'assigned')]" res_model="stock.picking" src_model="sale_journal.picking.journal" id="act_sale_journal_picking_journal_2_stock_picking_assigned"/> - - <!-- Action of stock picking in picking journal --> - + + <!-- Action of stock picking in picking journal --> + <act_window name="Confirmed picking" domain="[('journal_id', '=', active_id),('state', '=', 'confirmed')]" res_model="stock.picking" src_model="sale_journal.picking.journal" id="act_sale_journal_picking_journal_2_stock_picking_confirmed"/> - - <!-- Action of stock picking in sale journal --> - + + <!-- Action of stock picking in sale journal --> + <act_window name="Assigned picking" domain="[('sale_journal_id', '=', active_id),('state', '=', 'assigned')]" res_model="stock.picking" @@ -328,21 +328,21 @@ id="act_sale_journal_sale_journal_2_stock_picking_confirmed"/> <!-- Action of sale order in sale journal --> - + <act_window name="Draft sales" domain="[('journal_id', '=', active_id),('state', '=', 'draft')]" res_model="sale.order" src_model="sale_journal.sale.journal" id="act_sale_journal_sale_journal_2_sale_order_draft"/> - - <!-- Action of sale order in sale journal --> - + + <!-- Action of sale order in sale journal --> + <act_window name="Approved sales" domain="[('journal_id', '=', active_id),('state', '=', 'approved')]" res_model="sale.order" src_model="sale_journal.sale.journal" id="act_sale_journal_sale_journal_2_sale_order_approved"/> - + <record id="view_partner_property_form" model="ir.ui.view"> <field name="name">res.partner.journal.property.form.inherit</field> <field name="model">res.partner</field> @@ -354,11 +354,11 @@ </page> </field> </record> - + <!--=====================================================--> <!-- picking journal view--> <!--===================================================== --> - + <record model="ir.ui.view" id="view_picking_journal_form"> <field name="name">sale_journal.picking.journal.form</field> <field name="model">sale_journal.picking.journal</field> @@ -373,7 +373,7 @@ <field name="date" select="1"/> <field name="date_created" select="1"/> <field name="date_validation" select="1"/> - </group> + </group> <notebook colspan="4"> <page string="Picking"> <field name="picking_stats_ids" colspan="4" nolabel="1"/> @@ -392,7 +392,7 @@ </form> </field> </record> - + <record model="ir.ui.view" id="view_picking_journal_tree"> <field name="name">sale_journal.picking.journal.tree</field> <field name="model">sale_journal.picking.journal</field> @@ -408,8 +408,8 @@ </field> </record> - <!-- Picking journal tree view --> - + <!-- Picking journal tree view --> + <record model="ir.ui.view" id="view_picking_journal_search"> <field name="name">sale_journal.picking.journal.search</field> <field name="model">sale_journal.picking.journal</field> @@ -417,8 +417,8 @@ <field name="arch" type="xml"> <search string="Picking Journals"> <group col="8" colspan="4"> - <filter icon="terp-hr" string="My Picking Journals" domain="[('user_id','=',uid)]" help="My Picking Journals"/> - <filter icon="terp-hr" string="Open" domain="[('state','=','open')]" help="Open Picking Journals"/> + <filter icon="terp-personal" string="My Picking Journals" domain="[('user_id','=',uid)]" help="My Picking Journals"/> + <filter icon="terp-camera_test" string="Open" domain="[('state','=','open')]" help="Open Picking Journals"/> <separator orientation="vertical"/> <field name="name" select="1"/> <field name="code" select="1"/> @@ -428,9 +428,9 @@ </search> </field> </record> - -<!-- Action of Picking journals --> - + +<!-- Action of Picking journals --> + <record model="ir.actions.act_window" id="action_definition_picking_journal"> <field name="name">Picking Journals</field> <field name="res_model">sale_journal.picking.journal</field> @@ -438,16 +438,16 @@ <field name="view_mode">tree,form</field> <field name="search_view_id" ref="view_picking_journal_search"/> </record> - + <menuitem name="Picking Journals" id="menu_definition_journal_picking" parent="stock.menu_stock_configuration" action="action_definition_picking_journal"/> - + <record model="ir.actions.act_window" id="action_invoice_type_tree"> <field name="name">Picking by invoice_method</field> <field name="res_model">sale_journal.invoice.type</field> <field name="type">ir.actions.act_window</field> <field name="view_type">tree</field> </record> - + <record model="ir.actions.act_window" id="action_invoice_type_picking_open"> <field name="name">Picking to invoice</field> <field name="res_model">stock.picking</field> @@ -456,7 +456,7 @@ <field name="view_mode">tree,form</field> <field name="domain">[('state','=','done'),('invoice_state','=','2binvoiced'),('invoice_type_id','=',active_id)]</field> </record> - + <record model="ir.values" id="ir_open_invoice_type"> <field name="key2">tree_but_open</field> <field name="model">sale_journal.invoice.type</field> diff --git a/addons/scrum/scrum.py b/addons/scrum/scrum.py index bccc991565f..2e3a0ca3fcb 100644 --- a/addons/scrum/scrum.py +++ b/addons/scrum/scrum.py @@ -29,7 +29,7 @@ class scrum_project(osv.osv): _inherit = 'project.project' _columns = { 'product_owner_id': fields.many2one('res.users', 'Product Owner'), - 'sprint_size': fields.integer('Sprint Days'), + 'sprint_size': fields.integer('Sprint Days',help="Number of days allocated for sprint"), 'scrum': fields.integer('Is a Scrum Project'), } _defaults = { @@ -105,7 +105,7 @@ class scrum_sprint(osv.osv): 'date_start': fields.date('Starting Date', required=True), 'date_stop': fields.date('Ending Date', required=True), 'project_id': fields.many2one('project.project', 'Project', required=True, domain=[('scrum','=',1)], help="If you have [?] in the project name, it means there are no analytic account linked to this project."), - 'product_owner_id': fields.many2one('res.users', 'Product Owner', required=True), + 'product_owner_id': fields.many2one('res.users', 'Product Owner', required=True,help="The person who is responsible for the product"), 'scrum_master_id': fields.many2one('res.users', 'Scrum Manager', required=True), 'meeting_ids': fields.one2many('scrum.meeting', 'sprint_id', 'Daily Scrum'), 'review': fields.text('Sprint Review'), @@ -189,7 +189,7 @@ class scrum_product_backlog(osv.osv): for bl in self.browse(cr, uid, ids): res.setdefault(bl.id, 0.0) for task in bl.tasks_id: - res[bl.id] += task.planned_hours + res[bl.id] += task.total_hours return res def button_cancel(self, cr, uid, ids, context={}): @@ -251,7 +251,7 @@ class scrum_task(osv.osv): result[task.id] = True return result.keys() _columns = { - 'product_backlog_id': fields.many2one('scrum.product.backlog', 'Product Backlog'), + 'product_backlog_id': fields.many2one('scrum.product.backlog', 'Product Backlog',help="Related product backlog that contains this task. Used in SCRUM methodology"), 'sprint_id': fields.related('product_backlog_id','sprint_id', type='many2one', relation='scrum.sprint', string='Sprint', store={ 'project.task': (lambda self, cr, uid, ids, c={}: ids, ['product_backlog_id'], 10), diff --git a/addons/scrum/scrum_view.xml b/addons/scrum/scrum_view.xml index dc015c3f38a..be16ecfa7e5 100644 --- a/addons/scrum/scrum_view.xml +++ b/addons/scrum/scrum_view.xml @@ -33,7 +33,7 @@ <field name="model">scrum.product.backlog</field> <field name="type">tree</field> <field name="arch" type="xml"> - <tree string="Product Backlog"> + <tree colors="grey:state in ('cancel','done');blue:state in ('pending')" string="Product Backlog"> <field name="sequence" invisible="1"/> <field name="name"/> <field name="project_id"/> @@ -127,14 +127,14 @@ <search string="Product Backlogs"> <group col="10" colspan="4"> <filter default="1" - icon="terp-project" + icon="terp-check" string="Current" name="current" domain="['|','&',('sprint_id.date_start','<=',time.strftime('%%Y-%%m-%%d')), ('sprint_id.date_stop','>=',time.strftime('%%Y-%%m-%%d')), ('state','in',['draft','open'])]" help="Current Backlogs"/> <separator orientation="vertical"/> - <filter icon="terp-project" string="Draft" domain="[('state','=','draft')]" help="Draft Backlogs"/> - <filter icon="terp-project" string="Open" domain="[('state','=','open')]" help="Open Backlogs"/> + <filter icon="terp-document-new" string="Draft" domain="[('state','=','draft')]" help="Draft Backlogs"/> + <filter icon="terp-camera_test" string="Open" domain="[('state','=','open')]" help="Open Backlogs"/> <separator orientation="vertical"/> <field name="name"/> <field name="project_id" widget="selection"/> @@ -151,11 +151,11 @@ <field name="user_id" widget="selection"/> </group> <newline/> - <group expand="1" string="Group By..." colspan="4" col="20" groups="base.group_extended"> - <filter string="Project" icon="terp-project" domain="[]" context="{'group_by':'project_id'}"/> - <filter string="Sprint" icon="terp-project" domain="[]" context="{'group_by':'sprint_id'}"/> - <filter string="Responsible" icon="terp-project" domain="[]" context="{'group_by':'user_id'}"/> - <filter string="State" icon="terp-project" domain="[]" context="{'group_by':'state'}"/> + <group expand="0" string="Group By..." colspan="4" col="20" groups="base.group_extended"> + <filter string="Project" icon="terp-folder-blue" domain="[]" context="{'group_by':'project_id'}"/> + <filter string="Sprint" icon="terp-gtk-jump-to-ltr" domain="[]" context="{'group_by':'sprint_id'}"/> + <filter string="Responsible" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/> + <filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/> </group> </search> @@ -184,7 +184,7 @@ <field name="model">scrum.sprint</field> <field name="type">tree</field> <field name="arch" type="xml"> - <tree string="Scrum Sprint"> + <tree colors="blue:state in ('pending');grey:state in ('cancel','done')" string="Scrum Sprint"> <field name="name"/> <field name="project_id"/> <field name="scrum_master_id"/> @@ -260,9 +260,10 @@ <field name="arch" type="xml"> <search string="Sprints"> <group col="10" colspan="4"> - <filter name="filter_current" icon="terp-project" string="Current" domain="[('state','in',('draft','open'))]" help="Draft and open Sprints"/> - <filter icon="terp-project" string="Draft" domain="[('state','=','draft')]" help="Draft Sprints"/> - <filter icon="terp-project" string="Open" domain="[('state','=','open')]" help="Open Sprints"/> + <filter name="terp-check" icon="terp-check" string="Current" domain="[('state','in',('draft','open'))]" help="Draft and open Sprints"/> + <separator orientation="vertical"/> + <filter icon="terp-document-new" string="Draft" domain="[('state','=','draft')]" help="Draft Sprints"/> + <filter icon="terp-camera_test" string="Open" domain="[('state','=','open')]" help="Open Sprints"/> <separator orientation="vertical"/> <field name="name"/> <field name="project_id" widget="selection"/> @@ -270,13 +271,13 @@ <field name="date_start"/> </group> <newline/> - <group expand="1" string="Group By..." colspan="4" col="20"> - <filter string="Project" icon="terp-project" domain="[]" context="{'group_by':'project_id'}"/> - <filter string="Masters" icon="terp-project" domain="[]" context="{'group_by':'scrum_master_id'}"/> - <filter string="Product owner" icon="terp-project" domain="[]" context="{'group_by':'product_owner_id'}"/> - <filter string="State" icon="terp-project" domain="[]" context="{'group_by':'state'}"/> + <group expand="0" string="Group By..." colspan="4" col="20"> + <filter string="Project" icon="terp-folder-blue" domain="[]" context="{'group_by':'project_id'}"/> + <filter string="Managers" icon="terp-personal" domain="[]" context="{'group_by':'scrum_master_id'}"/> + <filter string="Product owner" icon="terp-personal" domain="[]" context="{'group_by':'product_owner_id'}"/> + <filter string="State" icon="terp-stock_effects-object-colorize" domain="[]" context="{'group_by':'state'}"/> <separator orientation="vertical"/> - <filter string="Start Date" icon="terp-project" domain="[]" context="{'group_by':'date_start'}"/> + <filter string="Start Date" icon="terp-gtk-jump-to-ltr" domain="[]" context="{'group_by':'date_start'}"/> </group> </search> </field> @@ -349,18 +350,18 @@ <field name="arch" type="xml"> <search string="Scrum Sprint"> <group col="10" colspan="4"> - <filter name="scrum_daily" icon="terp-project" string="Daily" domain="[('date','=',time.strftime('%%Y-%%m-%%d'))]" help="Daily Meetings"/> + <filter name="scrum_daily" icon="terp-go-today" string="Daily" domain="[('date','=',time.strftime('%%Y-%%m-%%d'))]" help="Daily Meetings"/> <separator orientation="vertical"/> <field name="sprint_id" widget="selection"> - <filter icon="terp-project" string="Current" domain="[('sprint_id.state','in',('draft','open'))]" help="Current Sprints" default="1"/> + <filter icon="terp-check" string="Current" domain="[('sprint_id.state','in',('draft','open'))]" help="Current Sprints" default="1"/> </field> <field name="project_id" widget="selection"/> <field name="date"/> </group> <newline/> - <group expand="1" string="Group By..." colspan="4" col="20"> - <filter string="Sprint" icon="terp-project" domain="[]" context="{'group_by':'sprint_id'}"/> - <filter string="Date" icon="terp-project" domain="[]" context="{'group_by':'date'}"/> + <group expand="0" string="Group By..." colspan="4" col="20"> + <filter string="Sprint" icon="terp-gtk-jump-to-ltr" domain="[]" context="{'group_by':'sprint_id'}"/> + <filter string="Date" icon="terp-go-month" domain="[]" context="{'group_by':'date'}"/> </group> </search> </field> @@ -493,7 +494,7 @@ <field name="arch" type="xml"> <field name="project_id" position="after"> <field name="sprint_id" context="{'sprint_invisible':False}"> - <filter icon="terp-project" string="Current" context="{'sprint_invisible':False}" domain="[('sprint_id.state','in',('draft','open'))]" help="Current Sprints"/> + <filter icon="terp-check" string="Current" context="{'sprint_invisible':False}" domain="[('sprint_id.state','in',('draft','open'))]" help="Current Sprints"/> </field> </field> </field> @@ -506,8 +507,8 @@ <field name="inherit_id" ref="project.view_task_search_form"/> <field name="arch" type="xml"> <xpath expr="/search/group[@string='Group By...']/filter[@string='End Date']" position="after"> - <filter string="Sprint" icon="terp-project" domain="[]" context="{'group_by':'sprint_id'}"/> - <filter string="Backlog" icon="terp-project" domain="[]" context="{'group_by':'product_backlog_id'}"/> + <filter string="Sprint" icon="terp-gtk-jump-to-ltr" domain="[]" context="{'group_by':'sprint_id'}"/> + <filter string="Backlog" icon="terp-gtk-jump-to-rtl" domain="[]" context="{'group_by':'product_backlog_id'}"/> <separator orientation="vertical"/> </xpath> </field> diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 94d20f7a95e..6c3d09f2895 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -350,7 +350,7 @@ stock_location() class stock_tracking(osv.osv): _name = "stock.tracking" _description = "Stock Tracking Lots" - + def get_create_tracking_lot(self, cr, uid, ids, tracking_lot): tracking_lot_list = self.search(cr, uid, [('name', '=', tracking_lot)], limit=1) @@ -893,7 +893,7 @@ class stock_picking(osv.osv): move_obj = self.pool.get('stock.move') if not context: context = {} - + for pick in self.browse(cr, uid, ids, context=context): if pick.state in ['done','cancel']: raise osv.except_osv(_('Error'), _('You cannot remove the picking which is in %s state !')%(pick.state,)) @@ -906,7 +906,7 @@ class stock_picking(osv.osv): move_obj.action_cancel(cr, uid, ids2, ctx) #Removing the move move_obj.unlink(cr, uid, ids2, ctx) - + return super(stock_picking, self).unlink(cr, uid, ids, context=context) def do_partial(self, cr, uid, ids, partial_datas, context={}): @@ -1219,7 +1219,7 @@ class stock_move(osv.osv): 'product_id': fields.many2one('product.product', 'Product', required=True, select=True), 'product_qty': fields.float('Quantity', required=True), - 'product_uom': fields.many2one('product.uom', 'Product UOM', required=True), + 'product_uom': fields.many2one('product.uom', 'Unit of Measure', required=True), 'product_uos_qty': fields.float('Quantity (UOS)'), 'product_uos': fields.many2one('product.uom', 'Product UOS'), 'product_packaging': fields.many2one('product.packaging', 'Packaging', help="It specifies attributes of packaging like type, quantity of packaging,etc."), @@ -1294,7 +1294,7 @@ class stock_move(osv.osv): 'date_planned': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'), 'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'), 'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'stock.move', context=c), - 'date_expected': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'), + 'date_expected': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'), } def copy(self, cr, uid, id, default=None, context={}): @@ -1648,14 +1648,14 @@ class stock_move(osv.osv): 'line_id': lines, 'ref': ref, }) - tracking_lot = False + tracking_lot = False if context: tracking_lot = context.get('tracking_lot', False) if tracking_lot: rec_id = context and context.get('active_id', False) tracking = self.pool.get('stock.tracking') - tracking_lot = tracking.get_create_tracking_lot(cr, uid,[rec_id], tracking_lot) - + tracking_lot = tracking.get_create_tracking_lot(cr, uid,[rec_id], tracking_lot) + self.write(cr, uid, ids, {'state': 'done', 'date_planned': time.strftime('%Y-%m-%d %H:%M:%S'), 'tracking_id': tracking_lot or False}) picking_obj = self.pool.get('stock.picking') for pick in picking_obj.browse(cr, uid, picking_ids): @@ -1669,7 +1669,7 @@ class stock_move(osv.osv): def unlink(self, cr, uid, ids, context=None): if context is None: - context = {} + context = {} for move in self.browse(cr, uid, ids, context=context): if move.state != 'draft': raise osv.except_osv(_('UserError'), @@ -1877,7 +1877,7 @@ class stock_move(osv.osv): address_id = partial_datas.get('address_id', False) delivery_date = partial_datas.get('delivery_date', False) tracking_lot = context.get('tracking_lot', False) - + new_moves = [] complete, too_many, too_few = [], [], [] diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml index 8eca73792a1..92653501ed3 100644 --- a/addons/stock/stock_view.xml +++ b/addons/stock/stock_view.xml @@ -341,7 +341,7 @@ <field name="location_dest_id" /> <field name="date" /> <field name="date_planned" string="Date"/> - <field name="date_expected" string="Date Expected"/> + <field name="date_expected" string="Date Expected"/> <field name="state"/> </tree> </field> @@ -653,7 +653,7 @@ <field colspan="4" invisible="1" name="name"/> <field invisible="1" name="date"/> <field name="date_planned"/> - <field name="date_expected" string="Date Expected"/> + <field name="date_expected" string="Date Expected"/> <field name="address_id" context="{'contact_display':'partner'}"/> <field groups="base.group_extended" name="product_packaging" domain="[('product_id','=',product_id)]"/> <field name="prodlot_id" groups="base.group_extended" @@ -778,7 +778,7 @@ <field name="location_id"/> <field name="location_dest_id"/> <field name="date_planned"/> - <field name="date_expected" string="Date Expected"/> + <field name="date_expected" string="Date Expected"/> <field name="state"/> <button name="%(stock.track_line)d" @@ -805,7 +805,7 @@ <field colspan="4" invisible="1" name="name"/> <field invisible="1" name="date"/> <field name="date_planned"/> - <field name="date_expected" string="Date Expected"/> + <field name="date_expected" string="Date Expected"/> <field groups="base.group_extended" name="product_packaging" domain="[('product_id','=',product_id)]"/> <field name="prodlot_id" groups="base.group_extended" context="{'location_id':location_id, 'product_id':product_id}" @@ -958,7 +958,7 @@ <field name="location_id"/> <field name="location_dest_id"/> <field name="date_planned"/> - <field name="date_expected" string="Date Expected"/> + <field name="date_expected" string="Date Expected"/> <field name="state"/> <button name="%(stock.track_line)d" @@ -985,7 +985,7 @@ <field colspan="4" invisible="1" name="name"/> <field invisible="1" name="date"/> <field name="date_planned"/> - <field name="date_expected" string="Date Expected"/> + <field name="date_expected" string="Date Expected"/> <field groups="base.group_extended" name="product_packaging" domain="[('product_id','=',product_id)]"/> <field name="prodlot_id" groups="base.group_extended" context="{'location_id':location_id, 'product_id':product_id}" @@ -1160,7 +1160,7 @@ <field groups="product.group_uos" name="product_uos_qty"/> <field colspan="4" invisible="1" name="name" /> <field groups="base.group_extended" name="date_planned"/> - <field name="date_expected" groups="base.group_extended" string="Date Expected"/> + <field name="date_expected" groups="base.group_extended" string="Date Expected"/> <newline/> <newline/> <field groups="base.group_extended" name="product_packaging" domain="[('product_id','=',product_id)]"/> @@ -1222,6 +1222,7 @@ <separator orientation="vertical"/> <field name="name"/> <field name="address_id"/> + <field name="origin"/> <field name="company_id" widget="selection" groups="base.group_multi_company" /> </group> <newline/> @@ -1232,8 +1233,6 @@ <separator orientation="vertical" /> <filter string="Order Date" icon="terp-stock" domain="[]" context="{'group_by':'date'}"/> <filter string="Expected Date" icon="terp-stock" domain="[]" context="{'group_by':'min_date'}"/> - <separator orientation="vertical" /> - <filter string="Origin" icon="terp-stock" domain="[]" context="{'group_by':'origin'}"/> </group> </search> </field> @@ -1361,7 +1360,7 @@ <separator string="Dates & Priority" colspan="2" /> <field name="date"/> <field name="date_planned"/> - <field name="date_expected"/> + <field name="date_expected"/> <field name="priority"/> </group> @@ -1475,12 +1474,12 @@ <notebook colspan="4"> <page string="General Information"> <separator colspan="4" string="Move Information"/> - <field name="location_id"/> - <field name="location_dest_id"/> + <field name="location_id" widget="selection"/> + <field name="location_dest_id" widget="selection"/> <field colspan="4" name="product_id" on_change="onchange_product_id(product_id, location_id, location_dest_id, parent.address_id)"/> <field name="product_qty" on_change="onchange_quantity(product_id, product_qty, product_uom, product_uos)"/> - <field name="product_uom"/> - <field name="product_uos"/> + <field name="product_uom" widget="selection"/> + <field name="product_uos" widget="selection" groups="base.group_extended"/> <field colspan="4" name="name"/> <field name="date"/> <field name="company_id" groups="base.group_multi_company" widget="selection"/> @@ -1497,8 +1496,10 @@ on_change="onchange_lot_id(prodlot_id,product_qty, location_id, product_id)"/> <field name="tracking_id"/> <newline/> - <label/> - <button name="%(track_line)d" string="Split in production lots" type="action" icon="gtk-justify-fill"/> + <group col="2" colspan="2"> + <label/> + <button name="%(track_line)d" string="Split in production lots" type="action" icon="gtk-justify-fill"/> + </group> <separator colspan="4" string="Move State"/> <field name="state"/> <group col="5" colspan="2"> @@ -1541,7 +1542,9 @@ <group expand="1" string="Group By..." colspan="4" col="8"> <filter string="Product" icon="terp-stock" domain="[]" context="{'group_by':'product_id'}"/> <filter string="State" icon="terp-stock" domain="[]" context="{'group_by':'state'}"/> - <filter string="Date" icon="terp-stock" domain="[]" context="{'group_by':'date'}"/> + <separator orientation="vertical"/> + <filter string="Order Date" icon="terp-stock" domain="[]" context="{'group_by':'date'}"/> + <filter string="Expected Date" icon="terp-stock" domain="[]" context="{'group_by':'date_expected'}" /> </group> </search> </field> |
