[MERGE] merge from trunk addons

bzr revid: mra@mra-laptop-20100625041328-8rymp929ui5rg5hb
This commit is contained in:
Mustufa Rangwala
2010-06-25 09:43:28 +05:30
84 changed files with 1642 additions and 1324 deletions
+1 -1
View File
@@ -17,7 +17,7 @@
</separator>
<xpath expr="//label[@string='description']"
position="attributes">
<attribute name="string">You can enhance OpenERP's basic accounting support with a few additional OpenERP applications.</attribute>
<attribute name="string">From this screen, you can configure your accounting system. Choose a Chart of Account matched to your accounting system or the Generic Chart of Account which allows you to configure which suit your needs.</attribute>
</xpath>
<xpath expr="//button[@string='Install Modules']" position="attributes">
<attribute name="string">Configure</attribute>
+9 -1
View File
@@ -801,15 +801,19 @@ class account_move_line(osv.osv):
ids = journal_pool.search(cr, uid, [])
journals = journal_pool.browse(cr, uid, ids)
all_journal = [None]
common_fields = {}
total = len(journals)
for journal in journals:
all_journal.append(journal.id)
for field in journal.view_id.columns_id:
if not field.field in fields:
fields[field.field] = [None, journal.id]
fields[field.field] = [journal.id]
fld.append((field.field, field.sequence))
flds.append(field.field)
common_fields[field.field] = 1
else:
fields.get(field.field).append(journal.id)
common_fields[field.field] = common_fields[field.field] + 1
fld.append(('period_id', 3))
fld.append(('journal_id', 10))
@@ -831,6 +835,10 @@ class account_move_line(osv.osv):
for field_it in fld:
field = field_it[0]
if common_fields.get(field) == total:
fields.get(field).append(None)
if field=='state':
state = 'colors="red:state==\'draft\'"'
+5 -6
View File
@@ -7,14 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2010-06-23 17:24+0000\n"
"Last-Translator: Jordi Esteve (www.zikzakmedia.com) "
"<jesteve@zikzakmedia.com>\n"
"PO-Revision-Date: 2010-06-24 10:03+0000\n"
"Last-Translator: Borja López Soilán (Pexego) <borjals@pexego.es>\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-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: account
@@ -806,7 +805,7 @@ msgstr "Cuenta de la empresa"
#. module: account
#: wizard_view:account.subscription.generate,init:0
msgid "Generate entries before:"
msgstr "Generar asientos antes:"
msgstr "Generar asientos hasta:"
#. module: account
#: rml:account.analytic.account.cost_ledger:0
@@ -3680,7 +3679,7 @@ msgstr ""
#: wizard_field:account.invoice.pay,addendum,comment:0
#: wizard_field:account.invoice.pay,init,name:0
msgid "Entry Name"
msgstr "Núm. asiento"
msgstr "Descripción"
#. module: account
#: help:account.invoice,account_id:0
+5 -5
View File
@@ -8,13 +8,13 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2010-05-14 17:04+0000\n"
"PO-Revision-Date: 2010-06-24 09:57+0000\n"
"Last-Translator: Borja López Soilán (Pexego) <borjals@pexego.es>\n"
"Language-Team: Galician <gl@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-22 04:04+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: account
@@ -2047,7 +2047,7 @@ msgstr ""
#. module: account
#: field:account.journal,invoice_sequence_id:0
msgid "Invoice Sequence"
msgstr ""
msgstr "Secuencia de factura"
#. module: account
#: wizard_view:account.automatic.reconcile,init:0
@@ -3597,7 +3597,7 @@ msgstr ""
#: wizard_field:account.invoice.pay,addendum,comment:0
#: wizard_field:account.invoice.pay,init,name:0
msgid "Entry Name"
msgstr ""
msgstr "Descripción"
#. module: account
#: help:account.invoice,account_id:0
@@ -5064,7 +5064,7 @@ msgstr ""
#. module: account
#: model:ir.model,name:account.model_fiscalyear_seq
msgid "Maintains Invoice sequences with Fiscal Year"
msgstr ""
msgstr "Mantén secuencias de facturas con exercicio fiscal"
#. module: account
#: selection:account.account.balance.report,checktype,display_account:0
+1 -1
View File
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: account
+1 -1
View File
@@ -26,7 +26,7 @@ from osv import fields,osv
#----------------------------------------------------------
class stock_picking(osv.osv):
_inherit = "stock.picking"
_description = "Packing List"
_description = "Picking List"
def action_invoice_create(self, cr, uid, ids, journal_id=False,
group=False, type='out_invoice', context=None):
+1 -1
View File
@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: account_budget
+167
View File
@@ -0,0 +1,167 @@
# Spanish translation for openobject-addons
# Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2009-11-24 13:11+0000\n"
"PO-Revision-Date: 2010-06-24 09:42+0000\n"
"Last-Translator: Borja López Soilán (Pexego) <borjals@pexego.es>\n"
"Language-Team: Spanish <es@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: account_coda
#: field:account.coda,journal_id:0
#: wizard_field:account.coda_import,init,journal_id:0
msgid "Bank Journal"
msgstr "Diario bancario"
#. module: account_coda
#: constraint:ir.model:0
msgid ""
"The Object name must start with x_ and not contain any special character !"
msgstr ""
"¡El objeto debe empezar con x_ y no puede contener ningún carácter especial!"
#. module: account_coda
#: wizard_field:account.coda_import,extraction,note:0
msgid "Log"
msgstr "Registro"
#. module: account_coda
#: wizard_button:account.coda_import,extraction,open:0
msgid "_Open Statement"
msgstr ""
#. module: account_coda
#: model:ir.module.module,shortdesc:account_coda.module_meta_information
msgid "Account CODA"
msgstr ""
#. module: account_coda
#: field:account.coda,name:0
msgid "Coda file"
msgstr ""
#. module: account_coda
#: wizard_view:account.coda_import,init:0
msgid "Clic on 'New' to select your file :"
msgstr ""
#. module: account_coda
#: model:ir.actions.wizard,name:account_coda.wizard_account_coda_import
msgid "Import Coda File"
msgstr ""
#. module: account_coda
#: constraint:ir.actions.act_window:0
msgid "Invalid model name in the action definition."
msgstr "Nombre de modelo inválido en la definición de acción."
#. module: account_coda
#: field:account.coda,note:0
msgid "Import log"
msgstr "Registro de importación"
#. module: account_coda
#: wizard_field:account.coda_import,init,def_receivable:0
msgid "Default receivable Account"
msgstr "Cuenta a recibir por defecto"
#. module: account_coda
#: model:ir.module.module,description:account_coda.module_meta_information
msgid ""
"Module provides functionality to import\n"
" bank statements from .csv file.\n"
" Import coda file wizard is used to import bank statements."
msgstr ""
#. module: account_coda
#: wizard_button:account.coda_import,extraction,end:0
msgid "_Close"
msgstr "_Cerrar"
#. module: account_coda
#: field:account.coda,statement_id:0
msgid "Generated Bank Statement"
msgstr "Extracto bancario generado"
#. module: account_coda
#: view:account.coda:0
#: model:ir.actions.act_window,name:account_coda.act_account_payment_account_bank_statement
#: model:ir.actions.act_window,name:account_coda.action_account_coda
msgid "Coda import"
msgstr ""
#. module: account_coda
#: field:account.coda,user_id:0
msgid "User"
msgstr "Usuario"
#. module: account_coda
#: constraint:ir.ui.view:0
msgid "Invalid XML for View Architecture!"
msgstr "¡XML inválido para la estructura de la vista!"
#. module: account_coda
#: model:ir.model,name:account_coda.model_account_coda
msgid "coda for an Account"
msgstr ""
#. module: account_coda
#: wizard_field:account.coda_import,init,def_payable:0
msgid "Default Payable Account"
msgstr "Cuenta a pagar por defecto"
#. module: account_coda
#: model:ir.ui.menu,name:account_coda.menu_account_coda
msgid "Coda Statements"
msgstr ""
#. module: account_coda
#: model:ir.ui.menu,name:account_coda.menu_account_coda_wizard
msgid "Import Coda Statements"
msgstr ""
#. module: account_coda
#: wizard_button:account.coda_import,init,extraction:0
msgid "_Ok"
msgstr "_Aceptar"
#. module: account_coda
#: wizard_view:account.coda_import,extraction:0
#: wizard_view:account.coda_import,init:0
msgid "Import Coda Statement"
msgstr ""
#. module: account_coda
#: field:account.bank.statement,coda_id:0
msgid "Coda"
msgstr ""
#. module: account_coda
#: wizard_view:account.coda_import,extraction:0
msgid "Results :"
msgstr "Resultados :"
#. module: account_coda
#: wizard_field:account.coda_import,init,coda:0
msgid "Coda File"
msgstr ""
#. module: account_coda
#: field:account.coda,date:0
msgid "Import Date"
msgstr "Fecha de importación"
#. module: account_coda
#: wizard_view:account.coda_import,init:0
msgid "Select your bank journal :"
msgstr "Seleccione su diario bancario :"
+1 -1
View File
@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: account_payment
+98 -89
View File
@@ -8,13 +8,13 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2010-06-24 02:48+0000\n"
"PO-Revision-Date: 2010-06-24 22:06+0000\n"
"Last-Translator: Panayiotis Konstantinidis <Unknown>\n"
"Language-Team: Greek <el@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: auction
@@ -182,7 +182,7 @@ msgstr "ΦΠΑ"
#. module: auction
#: view:auction.lots:0
msgid "Statements"
msgstr ""
msgstr "Καταστάσεις"
#. module: auction
#: xsl:flagey.huissier:0
@@ -244,33 +244,34 @@ msgstr "Σύγχρονη Τέχνη"
#: view:auction.lots:0
#: view:report.unclassified.objects:0
msgid "Ref"
msgstr ""
msgstr "Αναφορά"
#. module: auction
#: field:report.auction.view,nseller:0
msgid "No of sellers"
msgstr ""
msgstr "Αριθμός πωλητών"
#. module: auction
#: selection:auction.lots.send.aie,date_ask,lang:0
msgid "ned"
msgstr ""
msgstr "Κανονική ισοδύναμη απόκλιση"
#. module: auction
#: constraint:hr.attendance:0
msgid "Error: Sign in (resp. Sign out) must follow Sign out (resp. Sign in)"
msgstr ""
"Σφάλμα: Η Είσοδος (ή Έξοδος) πρέπει να ακολουθείται από Έξοδο (Είσοδο)"
#. module: auction
#: view:auction.lots:0
#: field:report.buyer.auction,total_price:0
msgid "Total Adj."
msgstr ""
msgstr "Συνολική προσαρμογή"
#. module: auction
#: field:report.auction.view2,obj_margin_procent:0
msgid "Net margin (%)"
msgstr ""
msgstr "Καθαρό περιθώριο (%)"
#. module: auction
#: selection:auction.lots,state:0
@@ -278,28 +279,28 @@ msgstr ""
#: selection:report.seller.auction,state:0
#: selection:report.unclassified.objects,state:0
msgid "Unsold"
msgstr ""
msgstr "Αδιάθετο"
#. module: auction
#: view:auction.dates:0
msgid "Dates"
msgstr ""
msgstr "Ημερομηνίες"
#. module: auction
#: constraint:product.template:0
msgid "Error: UOS must be in a different category than the UOM"
msgstr ""
msgstr "Error: UOS must be in a different category than the UOM"
#. module: auction
#: rml:auction.total.rml:0
msgid "Items"
msgstr ""
msgstr "Αντικείμενα"
#. module: auction
#: model:account.tax,name:auction.auction_tax5
#: field:auction.dates,seller_costs:0
msgid "Seller Costs"
msgstr ""
msgstr "Έξοδα πωλητών"
#. module: auction
#: view:auction.bid:0
@@ -309,75 +310,75 @@ msgstr ""
#: model:ir.actions.report.xml,name:auction.bid_auction
#: model:ir.ui.menu,name:auction.menu_action_bid_open
msgid "Bids"
msgstr ""
msgstr "Προσφορές"
#. module: auction
#: model:ir.ui.menu,name:auction.auction_all_objects_menu
msgid "All objects"
msgstr ""
msgstr "Όλα τα αντικείμενα"
#. module: auction
#: model:ir.actions.act_window,name:auction.action_auction_buyer_reporting_all2
msgid "Buyer's auction for all months"
msgstr ""
msgstr "Πληστηριασμοί αγοραστή για όλους τους μήνες"
#. module: auction
#: field:auction.bid,contact_tel:0
msgid "Contact"
msgstr ""
msgstr "Επικοινωνία"
#. module: auction
#: field:report.auction.view,obj_ret:0
#: field:report.object.encoded,obj_ret:0
#: field:report.object.encoded.manager,obj_ret:0
msgid "# obj ret"
msgstr ""
msgstr "Αριθμός αντικειμένων που επεστράφησαν"
#. module: auction
#: wizard_button:auction.lots.sms_send,init,send:0
msgid "Send SMS"
msgstr ""
msgstr "Αποστολή SMS"
#. module: auction
#: selection:auction.lot.category,aie_categ:0
msgid "Cont. Art/Painting"
msgstr ""
msgstr "Cont. Τέχνη/Ζωγραφική"
#. module: auction
#: field:auction.lots,sel_inv_id:0
msgid "Seller Invoice"
msgstr ""
msgstr "Τιμολόγιο πωλητή"
#. module: auction
#: view:auction.dates:0
msgid "Commissions"
msgstr ""
msgstr "Προμήθειες"
#. module: auction
#: wizard_button:auction.lots.numerotate,search,init:0
msgid "Back"
msgstr ""
msgstr "Πίσω"
#. module: auction
#: model:ir.actions.act_window,name:auction.action_all_objects_unsold
msgid "Unsold objects"
msgstr ""
msgstr "Αδιάθετα αντικείμενα"
#. module: auction
#: model:ir.ui.menu,name:auction.menu_all_objects_sold1
msgid "Sold Objects"
msgstr ""
msgstr "Πουλημένα αντικείμενα"
#. module: auction
#: view:report.buyer.auction2:0
#: view:report.seller.auction2:0
msgid "Sum net margin"
msgstr ""
msgstr "Σύνολο καθαρού περιθωρίου"
#. module: auction
#: view:auction.deposit:0
msgid "Deposit Border Form"
msgstr ""
msgstr "Κατάθεση φόρμας συνόρων"
#. module: auction
#: field:auction.bid,bid_lines:0
@@ -385,12 +386,12 @@ msgstr ""
#: rml:bids.lots:0
#: model:ir.model,name:auction.model_auction_bid_line
msgid "Bid"
msgstr ""
msgstr "Προσφορά"
#. module: auction
#: wizard_field:auction.lots.send.aie,date_ask,lang:0
msgid "Langage"
msgstr ""
msgstr "Γλώσσα"
#. module: auction
#: field:auction.bid_line,lot_id:0
@@ -398,17 +399,17 @@ msgstr ""
#: view:auction.lots:0
#: model:ir.model,name:auction.model_auction_lots
msgid "Object"
msgstr ""
msgstr "Αντικείμενο"
#. module: auction
#: model:ir.actions.wizard,name:auction.wizard_map_user
msgid "Map buyer username to Partners"
msgstr ""
msgstr "Καταγραφή του ονόματος χρήστη στους 'Συνεργάτες'"
#. module: auction
#: wizard_field:auction.lots.numerotate,search,lot_num:0
msgid "Inventory Number"
msgstr ""
msgstr "Αριθμός απογραφής"
#. module: auction
#: wizard_button:auction.lots.buyer_map,check,end:0
@@ -416,17 +417,17 @@ msgstr ""
#: wizard_button:auction.lots.numerotate,search,end:0
#: wizard_button:auction.lots.numerotate_cont,init,end:0
msgid "Exit"
msgstr ""
msgstr "Έξοδος"
#. module: auction
#: field:report.buyer.auction2,net_revenue:0
msgid "Net Revenue"
msgstr ""
msgstr "Καθαρό έσοδο"
#. module: auction
#: view:report.buyer.auction:0
msgid "Auction buyer reporting form view"
msgstr ""
msgstr "Έντυπο έκθεσης άποψης των αγοραστών δημοπρασιών"
#. module: auction
#: field:auction.dates,state:0
@@ -436,17 +437,17 @@ msgstr ""
#: field:report.seller.auction,state:0
#: field:report.unclassified.objects,state:0
msgid "Status"
msgstr ""
msgstr "Κατάσταση"
#. module: auction
#: model:ir.actions.wizard,name:auction.wizard_sms
msgid "SMS Send"
msgstr ""
msgstr "Αποστολή γραπτού μηνύματος"
#. module: auction
#: selection:auction.lot.category,aie_categ:0
msgid "Antique/Cartoons"
msgstr ""
msgstr "Αντίκες/Γελοιογραφίες"
#. module: auction
#: view:auction.lots:0
@@ -454,42 +455,43 @@ msgstr ""
#: selection:report.seller.auction,state:0
#: selection:report.unclassified.objects,state:0
msgid "Sold"
msgstr ""
msgstr "Πουλημένο"
#. module: auction
#: constraint:hr.employee:0
msgid "Error ! You cannot create recursive Hierarchy of Employees."
msgstr ""
"Σφάλμα! Δε μπορείται να δημιουργήσετε αναδρομική ιεραρχία στους εργαζομένους"
#. module: auction
#: field:auction.bid_line,name:0
msgid "Bid date"
msgstr ""
msgstr "Ημερομηνία προσφορών"
#. module: auction
#: field:auction.dates,acc_expense:0
msgid "Expense Account"
msgstr ""
msgstr "Λογαριασμός Εξόδων"
#. module: auction
#: model:ir.ui.menu,name:auction.menu_wizard_emporte
msgid "Deliveries Management"
msgstr ""
msgstr "Διαχείριση Παραδόσεων"
#. module: auction
#: field:auction.lots,obj_desc:0
msgid "Object Description"
msgstr ""
msgstr "Περιγραφή αντικειμένου"
#. module: auction
#: selection:auction.deposit,method:0
msgid "Contact the Seller"
msgstr ""
msgstr "Επικοινωνήστε με τον πωλητή"
#. module: auction
#: view:auction.lots:0
msgid "Auction Objects"
msgstr ""
msgstr "Δημοπρατημένα αντικείμενα"
#. module: auction
#: field:auction.lots,gross_revenue:0
@@ -497,60 +499,60 @@ msgstr ""
#: field:report.object.encoded.manager,gross_revenue:0
#: field:report.seller.auction2,gross_revenue:0
msgid "Gross revenue"
msgstr ""
msgstr "Μικτό έσοδο"
#. module: auction
#: view:report.seller.auction2:0
msgid "Auction reporting2 form view"
msgstr ""
msgstr "Έντυπο αναφοράς άποψης Δημοπρασίας"
#. module: auction
#: model:ir.actions.wizard,name:auction.wizard_pay
msgid "Pay objects of the buyer"
msgstr ""
msgstr "Πληρωμή αντικειμένων του αγοραστή"
#. module: auction
#: view:report.deposit.border:0
msgid "Depositer's statistics"
msgstr ""
msgstr "Στατιστικά αποταμιευτή"
#. module: auction
#: view:auction.lots:0
msgid "Buyer information"
msgstr ""
msgstr "Πληροφορίες Αγοραστή"
#. module: auction
#: model:ir.model,name:auction.model_report_seller_auction
msgid "Auction Reporting on seller view"
msgstr ""
msgstr "Έντυπο αναφοράς άποψης των πωλητών για τη δημοπρασία"
#. module: auction
#: field:auction.lots,name2:0
msgid "Short Description (2)"
msgstr ""
msgstr "Σύντομη περιγραφή (2)"
#. module: auction
#: model:ir.model,name:auction.model_auction_dates
msgid "auction.dates"
msgstr ""
msgstr "Δημοπρασίες.Ημερομηνίες"
#. module: auction
#: rml:auction.total.rml:0
#: model:ir.ui.menu,name:auction.auction_buyers_menu
msgid "Buyers"
msgstr ""
msgstr "Αγοραστές"
#. module: auction
#: wizard_field:auction.pay.buy,init,amount:0
#: wizard_field:auction.pay.buy,init,amount2:0
#: wizard_field:auction.pay.buy,init,amount3:0
msgid "Amount paid"
msgstr ""
msgstr "Ποσό που πληρώθηκε"
#. module: auction
#: model:ir.ui.menu,name:auction.menu_report_latest_doposit_tree
msgid "My Latest Deposits"
msgstr ""
msgstr "Οι Τελευταίες Καταθέσεις μου"
#. module: auction
#: field:auction.lots,lot_est1:0
@@ -559,105 +561,105 @@ msgstr ""
#: field:report.auction.view,min_est:0
#: field:report.unclassified.objects,lot_est1:0
msgid "Minimum Estimation"
msgstr ""
msgstr "Ελάχιστος υπολογισμός"
#. module: auction
#: view:auction.dates:0
msgid "Accounting"
msgstr ""
msgstr "Λογιστική"
#. module: auction
#: model:ir.ui.menu,name:auction.menu_buyer_allmonth_view2
msgid "Buyer's Revenues"
msgstr ""
msgstr "Έσοδα του Αγοραστή"
#. module: auction
#: model:ir.model,name:auction.model_report_auction_adjudication
msgid "report_auction_adjudication"
msgstr ""
msgstr "Αναφορά_δημοπρασίες_Διαγωνισμοί"
#. module: auction
#: field:auction.bid_line,price:0
msgid "Maximum Price"
msgstr ""
msgstr "Μέγιστη τιμή"
#. module: auction
#: selection:auction.lots.send.aie,date_ask,lang:0
msgid "eng"
msgstr ""
msgstr "Αγγλική"
#. module: auction
#: view:report.buyer.auction2:0
msgid "Auction buyer reporting tree view2"
msgstr ""
msgstr "Προβολή δέντρου εκθέσεων αγοραστή δημοπρασιών"
#. module: auction
#: wizard_view:auction.lots.sms_send,init:0
msgid "Bulk SMS send"
msgstr ""
msgstr "Μαζική αποστολή γραπτών μηνυμάτων"
#. module: auction
#: wizard_view:auction.taken,init:0
msgid "Select lots which are Sold"
msgstr ""
msgstr "Επιλέξτε παρτίδες που έχουν πουληθεί"
#. module: auction
#: field:auction.lots,statement_id:0
msgid "Payment"
msgstr ""
msgstr "Πληρωμή"
#. module: auction
#: selection:auction.lots.send.aie,date_ask,lang:0
msgid "fr"
msgstr ""
msgstr "Γαλλική"
#. module: auction
#: selection:auction.lot.category,aie_categ:0
msgid "Antique/Old weapons and militaria"
msgstr ""
msgstr "Αντίκες/ παλαιά όπλα και στρατιωτικά είδη"
#. module: auction
#: selection:auction.lot.category,aie_categ:0
msgid "Antique/Oriental Arts/Chineese furnitures"
msgstr ""
msgstr "Αντίκεςς/Ανατολίτικη τέχνη/Κινέζικα έπιπλα"
#. module: auction
#: selection:auction.deposit,method:0
msgid "Keep until sold"
msgstr ""
msgstr "Διατήρηση μέχρι να πουληθεί"
#. module: auction
#: wizard_button:auction.lots.numerotate,init,choice:0
#: wizard_button:auction.lots.send.aie,init,date_ask:0
#: wizard_button:auction.lots.send.aie.results,init,date_ask:0
msgid "Continue"
msgstr ""
msgstr "Συνεχίστε"
#. module: auction
#: field:report.object.encoded,obj_num:0
#: field:report.object.encoded.manager,obj_num:0
msgid "# of Encoded obj."
msgstr ""
msgstr "Πλήθος κωδικοποιημένων αντικειμένων"
#. module: auction
#: xsl:report.auction.vnd_bordereau:0
msgid "List N."
msgstr ""
msgstr "Λίστα Ν."
#. module: auction
#: field:report.deposit.border,moy_est:0
msgid "Avg. Est"
msgstr ""
msgstr "Μέσος υπολογισμός"
#. module: auction
#: rml:auction.total.rml:0
msgid "# of sellers:"
msgstr ""
msgstr "Πλήθος πωλητών:"
#. module: auction
#: constraint:product.product:0
msgid "Error: Invalid ean code"
msgstr ""
msgstr "Σφάλμα: Άκυρος κωδικός EAN"
#. module: auction
#: model:ir.module.module,description:auction.module_meta_information
@@ -668,26 +670,33 @@ msgid ""
" Delivery Management. \n"
" "
msgstr ""
"Αυτή η μονάδα παρέχει λειτουργικότητα στη \n"
" Διαχείριση καλλιτεχνών, αντικειμένων, πωλητών, αγοραστών και "
"δημοπρασίας.\n"
" Διαχείριση προσφορών, ιχνηλάτιση πουλημένων, πληρωμένων και απλήρωτων "
"αντικειμένων.\n"
" Διαχείριση παραδόσεων. \n"
" "
#. module: auction
#: rml:auction.total.rml:0
msgid "# of items taken away:"
msgstr ""
msgstr "πλήθος αντικειμένων που παραδόθηκαν:"
#. module: auction
#: model:ir.ui.menu,name:auction.menu_auction_allmonth_view1
msgid "Auction's Summary"
msgstr ""
msgstr "Περίληψη Δημοπρασίας"
#. module: auction
#: rml:buyer.list:0
msgid "%)"
msgstr ""
msgstr "%)"
#. module: auction
#: wizard_view:auction.lots.able,init:0
msgid "Confirmation set taken away"
msgstr ""
msgstr "Επιβεβαίωση αυτών που έχουν σταλθεί"
#. module: auction
#: wizard_field:auction.lots.make_invoice,init,objects:0
@@ -696,7 +705,7 @@ msgstr ""
#: wizard_field:auction.lots.send.aie.results,date_ask,objects:0
#: field:report.deposit.border,nb_obj:0
msgid "# of objects"
msgstr ""
msgstr "ΠΛήθος αντικειμένων"
#. module: auction
#: field:auction.lots,lot_est2:0
@@ -705,42 +714,42 @@ msgstr ""
#: field:report.auction.view,max_est:0
#: field:report.unclassified.objects,lot_est2:0
msgid "Maximum Estimation"
msgstr ""
msgstr "Μέγιστος υπολογισμός"
#. module: auction
#: field:auction.lots,buyer_price:0
msgid "Buyer price"
msgstr ""
msgstr "Τιμή αγοραστή"
#. module: auction
#: model:ir.actions.wizard,name:auction.auction_wizard_payer_sel
msgid "Mark as paid for seller"
msgstr ""
msgstr "Σημειώστε το ως πληρωμένο για τον πωλητή"
#. module: auction
#: model:ir.actions.report.xml,name:auction.seller_form_id
msgid "Seller List"
msgstr ""
msgstr "Λίστα πωλητών"
#. module: auction
#: field:auction.lots,is_ok:0
msgid "Buyer's payment"
msgstr ""
msgstr "ΠΛηρωμή αγοραστή"
#. module: auction
#: view:auction.dates:0
msgid "Close + Create all invoices"
msgstr ""
msgstr "Κλείσιμο + Δημιουργεία όλων των τιμολογίων"
#. module: auction
#: model:ir.actions.wizard,name:auction.auction_catalog_flagy
msgid "Auction Catalog Flagey"
msgstr ""
msgstr "Κατάλογος δημοπρασιών Flagey"
#. module: auction
#: field:auction.lot.history,price:0
msgid "Withdrawn price"
msgstr ""
msgstr "Απόσυρση τιμής"
#. module: auction
#: model:account.tax,name:auction.auction_tax4
+36 -32
View File
@@ -8,13 +8,13 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2010-06-24 02:58+0000\n"
"PO-Revision-Date: 2010-06-24 21:17+0000\n"
"Last-Translator: Panayiotis Konstantinidis <Unknown>\n"
"Language-Team: Greek <el@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: audittrail
@@ -159,153 +159,157 @@ msgid ""
" Subscribe Rules for read, write, create and delete on objects and check "
"logs"
msgstr ""
"Επιστρέπει στον Διαχειριστή να ακολουθεί τα ίχνη κάθε λειτουργίας του χρήστη "
"σε όλα τα αντικείμενα του συστήματος.\n"
" Εισάγεται κανόνες για ανάγνωση, εγγραφή, δημιουργία και διαγραφή στα "
"αντικείμενα και τα ημερολόγια ελέγχου."
#. module: audittrail
#: field:audittrail.log,timestamp:0
msgid "Date"
msgstr ""
msgstr "Ημερομηνία"
#. module: audittrail
#: field:audittrail.log,user_id:0
msgid "User"
msgstr ""
msgstr "Χρήστης"
#. module: audittrail
#: view:audittrail.log:0
msgid "Old Value Text : "
msgstr ""
msgstr "Παλιά τιμή κειμένου: "
#. module: audittrail
#: constraint:ir.ui.view:0
msgid "Invalid XML for View Architecture!"
msgstr ""
msgstr "Λανθασμένο XML για αρχιτεκτονική όψης!"
#. module: audittrail
#: field:audittrail.log,name:0
msgid "Name"
msgstr ""
msgstr "Όνομα"
#. module: audittrail
#: field:audittrail.log,line_ids:0
msgid "Log lines"
msgstr ""
msgstr "Γραμμές ημερολογίου"
#. module: audittrail
#: model:ir.ui.menu,name:audittrail.menu_action_audittrail_rule_tree_sub
msgid "Subscribed Rules"
msgstr ""
msgstr "Εγγεγραμμένοι Κανόνες"
#. module: audittrail
#: field:audittrail.log.line,field_id:0
msgid "Fields"
msgstr ""
msgstr "Πεδία"
#. module: audittrail
#: view:audittrail.rule:0
msgid "AuditTrail Rules"
msgstr ""
msgstr "Κανόνες διαδρομής ελέγχου"
#. module: audittrail
#: model:ir.model,name:audittrail.model_audittrail_rule
msgid "audittrail.rule"
msgstr ""
msgstr "ελεγκτική ιχνηλάτηση.κανόνες"
#. module: audittrail
#: view:audittrail.rule:0
msgid "UnSubscribe"
msgstr ""
msgstr "Διαγραφείτε"
#. module: audittrail
#: field:audittrail.rule,log_write:0
msgid "Log writes"
msgstr ""
msgstr "Εγγραφές ημερολογίου"
#. module: audittrail
#: model:ir.model,name:audittrail.model_audittrail_log
msgid "audittrail.log"
msgstr ""
msgstr "ελεγκτική ιχνηλάτηση.ημερολόγιο"
#. module: audittrail
#: field:audittrail.log.line,field_description:0
msgid "Field Description"
msgstr ""
msgstr "Περιγραφή πεδίου"
#. module: audittrail
#: selection:audittrail.log,method:0
msgid "Delete"
msgstr ""
msgstr "Διαγραφή"
#. module: audittrail
#: wizard_button:audittrail.view.log,init,open:0
msgid "Open Logs"
msgstr ""
msgstr "Άνοιγμα ημερολογίων"
#. module: audittrail
#: field:audittrail.log.line,new_value_text:0
msgid "New value Text"
msgstr ""
msgstr "Νέα τιμή κειμένου"
#. module: audittrail
#: field:audittrail.rule,name:0
msgid "Rule Name"
msgstr ""
msgstr "Όνομα Κανόνα"
#. module: audittrail
#: field:audittrail.rule,log_read:0
msgid "Log reads"
msgstr ""
msgstr "Αναγνώσεις ημερολογίων"
#. module: audittrail
#: model:ir.ui.menu,name:audittrail.menu_action_audittrail_log_tree
msgid "Logs"
msgstr ""
msgstr "Αρχεία καταγραφής"
#. module: audittrail
#: field:audittrail.log.line,new_value:0
msgid "New Value"
msgstr ""
msgstr "Νέα τιμή"
#. module: audittrail
#: model:ir.ui.menu,name:audittrail.menu_action_log_tree2
msgid "View Logs"
msgstr ""
msgstr "Δείτε τα αρχεία καταγραφής"
#. module: audittrail
#: field:audittrail.rule,log_create:0
msgid "Log creates"
msgstr ""
msgstr "Δημιουργία αρχείων καταγραφής"
#. module: audittrail
#: view:audittrail.log:0
msgid "AuditTrail Logs"
msgstr ""
msgstr "παρακολούθηση της πόρειας των αρχείων καταγραφής"
#. module: audittrail
#: model:ir.ui.menu,name:audittrail.menu_action_audittrail_rule_tree
msgid "Rules"
msgstr ""
msgstr "Κανόνες"
#. module: audittrail
#: view:audittrail.log:0
msgid "New Value : "
msgstr ""
msgstr "Νέα τιμή : "
#. module: audittrail
#: field:audittrail.rule,user_id:0
msgid "Users"
msgstr ""
msgstr "Χρήστες"
#. module: audittrail
#: field:audittrail.log.line,old_value_text:0
msgid "Old value Text"
msgstr ""
msgstr "Παλιά τιμή κειμένου"
#. module: audittrail
#: wizard_button:audittrail.view.log,init,end:0
msgid "Cancel"
msgstr ""
msgstr "Ακύρωση"
#. module: audittrail
#: field:audittrail.rule,log_unlink:0
msgid "Log deletes"
msgstr ""
msgstr "Διαγραφή αρχείων καταγραφής"
+1 -1
View File
@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base_module_quality
+1 -1
View File
@@ -15,7 +15,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base_module_quality
+1 -1
View File
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"X-Poedit-Country: GREECE\n"
"X-Poedit-Language: Greek\n"
+1 -3
View File
@@ -13,9 +13,7 @@
<xpath expr="//label[@string='description']"
position="attributes">
<attribute name="string"
>Now that OpenERP is installed, We have selected applications commonly useful to users which you can install directly, as well as sets of applications for more specific types or groups of businesses (the vertical modules).
If you don't think you need any of these right now, you can easily install them later on.</attribute>
>The most common applications have been pre selected. You can directly install them. You can either choose generic modules, or select modules for specific business sectors and industries. If you do not think you need any of these right now, you can easily install them later.</attribute>
</xpath>
<xpath expr='//separator[@string="vsep"]' position='attributes'>
<attribute name='string'></attribute>
+1 -1
View File
@@ -26,9 +26,9 @@
<field name="company_id" invisible="1"/>
<field name="name" required="True"/><field name="account_no"/>
<field name="currency" widget="selection"/><field name="street"/>
<field name="zip"/>
<field name="street2"/>
<field name="country_id"/>
<field name="zip"/>
<field name="state_id"/>
<field name="city"/>
<field name="email"/>
+1 -1
View File
@@ -11,7 +11,7 @@
<attribute name="string">Contact Information</attribute>
</form>
<xpath expr="//label[@string='description']" position="attributes">
<attribute name="string">Information about you and the company you are related too. The Basic information related to the company has already been collected and some more information required by you to fill.</attribute>
<attribute name="string">To receive more information, please fill in the form about you and your company. Documentation and/or information will be sent to you as soon as possible.</attribute>
</xpath>
<xpath expr='//separator[@string="title"]' position='attributes'>
<attribute name='string'>Would you like more information or documentation ?</attribute>
+1 -1
View File
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:46+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:46+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"X-Poedit-Country: GREECE\n"
"X-Poedit-Language: Greek\n"
+1 -1
View File
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:46+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:46+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"X-Poedit-Country: GREECE\n"
"X-Poedit-Language: Greek\n"
+1 -1
View File
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:46+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:46+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"X-Poedit-Country: GREECE\n"
"X-Poedit-Language: Greek\n"
+1 -1
View File
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"X-Poedit-Country: GREECE\n"
"X-Poedit-Language: Greek\n"
+1 -1
View File
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:46+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:46+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"X-Poedit-Country: GREECE\n"
"X-Poedit-Language: Greek\n"
-1
View File
@@ -20,7 +20,6 @@
##############################################################################
import crm
import crm_mailgate
import crm_action_rule
import crm_segmentation
import crm_meeting
+9 -10
View File
@@ -25,26 +25,25 @@
<xpath expr="//button[@string='Install Modules']" position="attributes">
<attribute name="string">Configure</attribute>
</xpath>
<group colspan="8">
<group colspan="8">
<group colspan="4" col="4" groups="base.group_extended" name="other">
<field name="crm_claim" />
<field name="crm_helpdesk" />
<field name="crm_fundraising" />
<field name="wiki_sale_faq"/>
<field name="sale_crm" invisible="1"/>
</group>
<group colspan="2" col="2">
<separator string="Synchronization" colspan="4" />
<field name="crm_caldav" />
<field name="fetchmail" />
</group>
<group colspan="2" col="2">
<separator string="Plugins" colspan="4" />
<separator string="Plugins" colspan="4" />
<field name="thunderbird" />
<label string="*Outlook*" />
<!-- TODO <field name="outlook" />-->
</group>
<group colspan="4" col="4" groups="base.group_extended" name="other">
<separator string="Additional features" colspan="4" />
<field name="crm_claim" />
<field name="crm_helpdesk" />
<field name="crm_fundraising" />
<field name="wiki_sale_faq"/>
<field name="sale_crm" invisible="1"/>
</group>
</group>
</data>
</field>
+133 -2
View File
@@ -27,6 +27,9 @@ import time
import mx.DateTime
from tools.translate import _
from crm import crm_case
import collections
import binascii
import tools
class crm_lead(osv.osv, crm_case):
""" CRM Lead Case """
@@ -117,6 +120,8 @@ and users by email"),
domain="[('section_id','=',section_id),\
('object_id.model', '=', 'crm.lead')]"),
'partner_name': fields.char("Partner Name", size=64),
'optin': fields.selection([('yes','Yes'),('no','No'),('unknown','/')],'Opt-In'),
'optout': fields.selection([('yes','Yes'),('no','No'),('unknown','/')],'Opt-Out'),
'type':fields.selection([
('lead','Lead'),
('opportunity','Opportunity'),
@@ -139,8 +144,8 @@ and users by email"),
\nIf the case is in progress the state is set to \'Open\'.\
\nWhen the case is over, the state is set to \'Done\'.\
\nIf the case needs to be reviewed then the state is set to \'Pending\'.'),
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('history', '=', True),('res_model','=',_name)]),
'log_ids': fields.one2many('mailgate.message', 'res_id', 'Logs', domain=[('history', '=', False),('res_model','=',_name)]),
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('history', '=', True),('model','=',_name)]),
'log_ids': fields.one2many('mailgate.message', 'res_id', 'Logs', domain=[('history', '=', False),('model','=',_name)]),
}
_defaults = {
@@ -148,6 +153,8 @@ and users by email"),
'user_id': crm_case._get_default_user,
'email_from': crm_case._get_default_email,
'state': lambda *a: 'draft',
'optin': lambda *a: 'unknown',
'optout': lambda *a: 'unknown',
'section_id': crm_case._get_section,
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.lead', context=c),
'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0],
@@ -231,6 +238,130 @@ and users by email"),
}
return value
def message_new(self, cr, uid, msg, context):
"""
Automatically calls when new email message arrives
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks
"""
mailgate_pool = self.pool.get('email.server.tools')
subject = msg.get('subject')
body = msg.get('body')
msg_from = msg.get('from')
priority = msg.get('priority')
vals = {
'name': subject,
'email_from': msg_from,
'email_cc': msg.get('cc'),
'description': body,
'user_id': False,
}
if msg.get('priority', False):
vals['priority'] = priority
res = mailgate_pool.get_partner(cr, uid, msg.get('from'))
if res:
vals.update(res)
res = self.create(cr, uid, vals, context)
attachents = msg.get('attachments', [])
for attactment in attachents or []:
data_attach = {
'name': attactment,
'datas':binascii.b2a_base64(str(attachents.get(attactment))),
'datas_fname': attactment,
'description': 'Mail attachment',
'res_model': self._name,
'res_id': res,
}
self.pool.get('ir.attachment').create(cr, uid, data_attach)
return res
def message_update(self, cr, uid, ids, vals={}, msg="", default_act='pending', context={}):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@param ids: List of update mail’s IDs
"""
if isinstance(ids, (str, int, long)):
ids = [ids]
msg_from = msg['from']
vals.update({
'description': msg['body']
})
if msg.get('priority', False):
vals['priority'] = msg.get('priority')
maps = {
'cost':'planned_cost',
'revenue': 'planned_revenue',
'probability':'probability'
}
vls = { }
for line in msg['body'].split('\n'):
line = line.strip()
res = tools.misc.command_re.match(line)
if res and maps.get(res.group(1).lower(), False):
key = maps.get(res.group(1).lower())
vls[key] = res.group(2).lower()
vals.update(vls)
res = self.write(cr, uid, ids, vals)
return res
def emails_get(self, cr, uid, ids, context=None):
"""
Get Emails
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@param ids: List of email’s IDs
@param context: A standard dictionary for contextual values
"""
res = {}
if isinstance(ids, (str, int, long)):
select = [long(ids)]
else:
select = ids
for thread in self.browse(cr, uid, select, context=context):
values = collections.defaultdict(set)
for message in thread.message_ids:
user_email = (message.user_id and message.user_id.address_id and message.user_id.address_id.email) or False
values['user_email'].add(user_email)
values['email_from'].add(message.email_from)
values['email_cc'].add(message.email_cc or False)
values['priority'] = thread.priority
res[thread.id] = dict((key,list(values[key])) for key, value in values.iteritems())
return res
def msg_send(self, cr, uid, id, *args, **argv):
""" Send The Message
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@param ids: List of email’s IDs
@param *args: Return Tuple Value
@param **args: Return Dictionary of Keyword Value
"""
return True
crm_lead()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+8 -4
View File
@@ -146,6 +146,11 @@
<field name="date_open"/>
<field name="date_closed"/>
</group>
<group colspan="2" col="2">
<separator string="Mailings" colspan="2" col="2"/>
<field name="optin"/>
<field name="optout"/>
</group>
<group colspan="2" col="2">
<separator string="Statistics" colspan="2" col="2"/>
<field name="day_open"/>
@@ -256,12 +261,11 @@
<field name="type">calendar</field>
<field name="priority" eval="2"/>
<field name="arch" type="xml">
<calendar string="Meeting For Leads Generation"
date_start="create_date" color="user_id"
date_delay="duration">
<calendar string="Leads Generation"
date_start="create_date" color="user_id">
<field name="name" />
<field name="partner_name" />
<field name="partner_contact" />
<field name="partner_address_id" />
</calendar>
</field>
</record>
-172
View File
@@ -1,172 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import time
import re
import os
import binascii
import mx.DateTime
import base64
from tools.translate import _
import tools
from osv import fields,osv,orm
from osv.orm import except_orm
import collections
from tools import command_re
class mailgate_thread(osv.osv):
""" mailgate_thread """
_name = "mailgate.thread"
_inherit = "mailgate.thread"
def message_new(self, cr, uid, msg, context):
"""
Automatically calls when new email message arrives
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks
"""
mailgate_pool = self.pool.get('email.server.tools')
subject = msg.get('subject')
body = msg.get('body')
msg_from = msg.get('from')
priority = msg.get('priority')
vals = {
'name': subject,
'email_from': msg_from,
'email_cc': msg.get('cc'),
'description': body,
'user_id': False,
}
if msg.get('priority', False):
vals['priority'] = priority
res = mailgate_pool.get_partner(cr, uid, msg.get('from'))
if res:
vals.update(res)
res = self.create(cr, uid, vals, context)
cases = self.browse(cr, uid, [res])
self._history(cr, uid, cases, _('Receive'), history=True, details=body, email_from=msg_from, message_id=msg.get('id'))
attachents = msg.get('attachments', [])
for attactment in attachents or []:
data_attach = {
'name': attactment,
'datas':binascii.b2a_base64(str(attachents.get(attactment))),
'datas_fname': attactment,
'description': 'Mail attachment',
'res_model': self._name,
'res_id': res,
}
self.pool.get('ir.attachment').create(cr, uid, data_attach)
return res
def message_update(self, cr, uid, ids, vals={}, msg="", default_act='pending', context={}):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@param ids: List of update mail’s IDs
"""
if isinstance(ids, (str, int, long)):
ids = [ids]
msg_from = msg['from']
vals.update({
'description': msg['body']
})
if msg.get('priority', False):
vals['priority'] = msg.get('priority')
maps = {
'cost':'planned_cost',
'revenue': 'planned_revenue',
'probability':'probability'
}
vls = { }
for line in msg['body'].split('\n'):
line = line.strip()
res = command_re.match(line)
if res and maps.get(res.group(1).lower(), False):
key = maps.get(res.group(1).lower())
vls[key] = res.group(2).lower()
vals.update(vls)
res = self.write(cr, uid, ids, vals)
cases = self.browse(cr, uid, ids)
message_id = context.get('references_id', False)
self._history(cr, uid, cases, _('Receive'), history=True, details=msg['body'], email_from=msg_from, message_id=message_id)
#getattr(self, act)(cr, uid, select)
return res
def emails_get(self, cr, uid, ids, context=None):
"""
Get Emails
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@param ids: List of email’s IDs
@param context: A standard dictionary for contextual values
"""
res = {}
if isinstance(ids, (str, int, long)):
select = [long(ids)]
else:
select = ids
for thread in self.browse(cr, uid, select, context=context):
values = collections.defaultdict(set)
for message in thread.message_ids:
user_email = (message.user_id and message.user_id.address_id and message.user_id.address_id.email) or False
values['user_email'].add(user_email)
values['email_from'].add(message.email_from)
values['email_cc'].add(message.email_cc or False)
res[str(thread.id)] = dict((key,list(values[key])) for key, value in values.iteritems())
return res
def msg_send(self, cr, uid, id, *args, **argv):
""" Send The Message
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@param ids: List of email’s IDs
@param *args: Return Tuple Value
@param **args: Return Dictionary of Keyword Value
"""
return True
mailgate_thread()
+34 -2
View File
@@ -148,6 +148,7 @@
<button string="Invite People"
name="%(base_calendar.action_view_calendar_invite_attendee_wizard)d"
icon="terp-partner" type="action"
attrs="{'readonly': [('state', '=', 'done')]}"
context="{'model' : 'crm.meeting', 'attendee_field':'attendee_ids'}" colspan="2"/>
<field name="attendee_ids" colspan="4"
nolabel="1" widget="one2many" mode="tree,form">
@@ -214,10 +215,27 @@
<tree string="Meetings"
colors="red:state=='open';black:state in ('draft', 'cancel','done','pending')">
<field name="name" string="Subject" />
<field name="partner_id" string="Partner" />
<field name="date" string="Meeting Date" />
<field name="date" string="Start Date" />
<field name="duration" />
<field name="partner_id" string="Partner" />
<field name="location" />
<field name="categ_id" string="Meeting Type"/>
<field name="class" string="Privacy"/>
<field name="state"/>
<field name="user_id" invisible="1"/>
<field name="show_as" invisible="1" string="Show time as"/>
<button name="case_reset" string="Reset to Unconfirmed"
states="open,done,cancel" type="object"
icon="gtk-convert" />
<button name="case_open" string="Confirm"
states="draft" type="object"
icon="gtk-go-forward" />
<button name="case_close" string="Done"
states="open" type="object"
icon="gtk-jump-to" />
<button name="case_cancel" string="Cancel"
states="draft,open" type="object"
icon="gtk-cancel" />
</tree>
</field>
</record>
@@ -268,6 +286,10 @@
help="Current Meetings"/>
<separator orientation="vertical"/>
<field name="name" select="1" string="Subject"/>
<field name="categ_id" select="1"
string="Meeting Type" widget="selection"
domain="[('object_id.model', '=', 'crm.meeting')]" />
<separator orientation="vertical"/>
<field name="partner_id" select="1" />
<field name="section_id" select="1" widget="selection">
<filter icon="terp-personal+"
@@ -282,16 +304,26 @@
domain="[]" context="{'group_by':'date'}" />
<filter string="Privacy" icon="terp-locked"
domain="[]" context="{'group_by':'class'}" />
<filter string="Show time as" icon="terp-project"
domain="[]" context="{'group_by':'show_as'}" />
<separator orientation="vertical" />
<filter string="Responsible" icon="terp-personal" domain="[]"
context="{'group_by':'user_id'}" />
<filter string="Partner" icon="terp-personal" domain="[]"
context="{'group_by':'partner_id'}" />
<separator orientation="vertical" />
<filter string="Meeting Type" help="Meeting Type"
icon="terp-stock_symbol-selection" domain="[]"
context="{'group_by':'categ_id'}" />
<filter string="State" icon="terp-stock_effects-object-colorize" domain="[]"
context="{'group_by':'state'}" />
<separator orientation="vertical" />
</group>
<newline/>
<group expand="0" string="Extended Options...">
<field name="class" select="1" string="Privacy"/>
<field name="show_as" string="Show time as" select="1"/>
</group>
</search>
</field>
</record>
+2 -1
View File
@@ -143,9 +143,10 @@ class crm_opportunity(osv.osv):
context = {
'default_opportunity_id': opp.id,
'default_partner_id': opp.partner_id and opp.partner_id.id or False,
'default_user_id': uid,
'default_section_id': opp.section_id and opp.section_id.id or False,
'default_email_from': opp.email_from,
'default_state': 'open',
'default_state': 'open',
'default_name': opp.name
}
value = {
+3 -3
View File
@@ -7,9 +7,9 @@
name="Phone calls"
res_model="crm.phonecall"
src_model="crm.lead"
view_mode="calendar,tree,form"
view_mode="tree,calendar,form"
context="{'default_duration': 1.0 ,'default_opportunity_id': active_id}"
domain="[('user_id','=',uid),('opportunity_id', '=', active_id)]"
domain="[('opportunity_id', '=', active_id)]"
view_type="form"/>
<act_window
@@ -19,7 +19,7 @@
src_model="crm.lead"
view_mode="tree,form,calendar,"
context="{'default_duration': 4.0, 'default_opportunity_id': active_id}"
domain="[('user_id','=',uid), ('opportunity_id', '=', active_id)]"
domain="[('opportunity_id', '=', active_id)]"
view_type="form"/>
<record model="ir.actions.act_window" id="crm_case_category_act_oppor11">
+9 -5
View File
@@ -258,6 +258,8 @@
<field name="section_id"
invisible="context.get('invisible_section', True)" />
<field name="user_id"/>
<field name="priority" invisible="1"/>
<field name="categ_id" invisible="1"/>
<field name="state"/>
<button name="case_open" string="Open"
states="draft,pending" type="object"
@@ -299,14 +301,14 @@
<field name="arch" type="xml">
<search string="Search Opportunities">
<filter icon="terp-check"
string="Current"
string="Current" help="Current Opportunities"
name="current"
domain="[('state','in',('draft','open'))]"/>
<filter icon="terp-camera_test"
string="Open"
string="Open" help="Open Opportunities"
domain="[('state','=','open')]"/>
<filter icon="terp-gtk-media-pause"
string="Pending"
string="Pending" help="Pending Opportunities"
domain="[('state','=','pending')]"/>
<separator orientation="vertical"/>
<filter icon="terp-go-today" string="Today"
@@ -352,8 +354,10 @@
<separator orientation="vertical" />
<filter string="Creation" icon="terp-go-month"
domain="[]" context="{'group_by':'create_date'}" />
<filter string="Exp.Closing" icon="terp-go-month"
domain="[]" context="{'group_by':'date_deadline'}" />
<filter string="Exp.Closing"
icon="terp-go-month"
help="Expected Closing" domain="[]"
context="{'group_by':'date_deadline'}" />
</group>
</search>
</field>
+2 -2
View File
@@ -82,8 +82,8 @@ class crm_phonecall(osv.osv, crm_case):
'date_closed': fields.datetime('Closed', readonly=True),
'date': fields.datetime('Date'),
'opportunity_id': fields.many2one ('crm.lead', 'Opportunity'),
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('history', '=', True),('res_model','=',_name)]),
'log_ids': fields.one2many('mailgate.message', 'res_id', 'Logs', domain=[('history', '=', False),('res_model','=',_name)]),
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('history', '=', True),('model','=',_name)]),
'log_ids': fields.one2many('mailgate.message', 'res_id', 'Logs', domain=[('history', '=', False),('model','=',_name)]),
}
_defaults = {
+1 -1
View File
@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:46+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:46+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: crm
+1 -1
View File
@@ -147,7 +147,7 @@ class crm_lead_report(osv.osv):
0 as avg_answers,
0.0 as perc_done,
0.0 as perc_cancel,
(select count(id) from mailgate_message where res_id=c.id and res_model='crm.lead') as email,
(select count(id) from mailgate_message where res_id=c.id and model='crm.lead') as email,
date_trunc('day',c.create_date) as create_date,
avg(extract('epoch' from (c.date_closed-c.create_date)))/(3600*24) as delay_close,
avg(extract('epoch' from (c.date_deadline - c.date_closed)))/(3600*24) as delay_expected,
+1 -2
View File
@@ -30,9 +30,8 @@
"access_crm_lead2opportunity_partner","crm.lead2opportunity.partner","model_crm_lead2opportunity_partner","crm.group_crm_user",1,1,1,1
"access_crm_installer","crm.installer.rule","model_crm_installer","base.group_system",1,1,1,1
"access_crm_lead_forward_to_partner","crm.lead.forward.to.partner","model_crm_lead_forward_to_partner","crm.group_crm_user",1,1,1,1
"access_mailgate_thread","mailgate.thread","model_mailgate_thread","crm.group_crm_user",1,1,1,1
"access_res_partner","res.partner.crm.user","base.model_res_partner","crm.group_crm_user",1,0,0,0
"access_res_partner_address","res.partner.address.crm.user","base.model_res_partner_address","crm.group_crm_user",1,0,0,0
"access_res_partner_category","res.partner.category.crm.user","base.model_res_partner_category","crm.group_crm_user",1,0,0,0
"mail_gateway_mailgate_message","mail_gateway.mailgate.message","mail_gateway.model_mailgate_message","crm.group_crm_user",1,1,1,1
"mail_gateway_mailgate_thread","mail_gateway.mailgate.thread","model_mailgate_thread","crm.group_crm_user",1,1,1,1
"mail_gateway_mailgate_thread","mail_gateway.mailgate.thread","mail_gateway.model_mailgate_thread","crm.group_crm_user",1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
30 access_crm_lead2opportunity_partner crm.lead2opportunity.partner model_crm_lead2opportunity_partner crm.group_crm_user 1 1 1 1
31 access_crm_installer crm.installer.rule model_crm_installer base.group_system 1 1 1 1
32 access_crm_lead_forward_to_partner crm.lead.forward.to.partner model_crm_lead_forward_to_partner crm.group_crm_user 1 1 1 1
access_mailgate_thread mailgate.thread model_mailgate_thread crm.group_crm_user 1 1 1 1
33 access_res_partner res.partner.crm.user base.model_res_partner crm.group_crm_user 1 0 0 0
34 access_res_partner_address res.partner.address.crm.user base.model_res_partner_address crm.group_crm_user 1 0 0 0
35 access_res_partner_category res.partner.category.crm.user base.model_res_partner_category crm.group_crm_user 1 0 0 0
36 mail_gateway_mailgate_message mail_gateway.mailgate.message mail_gateway.model_mailgate_message crm.group_crm_user 1 1 1 1
37 mail_gateway_mailgate_thread mail_gateway.mailgate.thread model_mailgate_thread mail_gateway.model_mailgate_thread crm.group_crm_user 1 1 1 1
@@ -9,13 +9,15 @@
<field name="model">crm.opportunity2phonecall</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Schedule Other Call">
<form string="Schedule a PhoneCall">
<separator string="Schedule a PhoneCall" colspan="4"/>
<group colspan="2" >
<field name="name"/>
<field name="date" string="Planned Date"/>
<newline/>
<field name="user_id" />
<field name="section_id"/>
<separator string="" colspan="4"/>
<label string ="" colspan="2"/>
<button name="action_cancel" string="_Cancel"
icon="gtk-cancel" special="cancel" />
+40 -3
View File
@@ -21,7 +21,7 @@
from osv import fields, osv
from crm import crm
import time
class crm_claim(osv.osv, crm.crm_case):
"""
Crm claim
@@ -88,8 +88,8 @@ class crm_claim(osv.osv, crm.crm_case):
\nIf the case is in progress the state is set to \'Open\'.\
\nWhen the case is over, the state is set to \'Done\'.\
\nIf the case needs to be reviewed then the state is set to \'Pending\'.'),
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('history', '=', True),('res_model','=',_name)]),
'log_ids': fields.one2many('mailgate.message', 'res_id', 'Logs', domain=[('history', '=', False),('res_model','=',_name)]),
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('history', '=', True),('model','=',_name)]),
'log_ids': fields.one2many('mailgate.message', 'res_id', 'Logs', domain=[('history', '=', False),('model','=',_name)]),
}
_defaults = {
@@ -100,9 +100,46 @@ class crm_claim(osv.osv, crm.crm_case):
'email_from':crm.crm_case. _get_default_email,
'state': lambda *a: 'draft',
'section_id':crm.crm_case. _get_section,
'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.case', context=c),
'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0],
}
def onchange_partner_id(self, cr, uid, ids, part, email=False):
"""This function returns value of partner address based on partner
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@param ids: List of case IDs
@param part: Partner's id
@email: Partner's email ID
"""
if not part:
return {'value': {'partner_address_id': False,
'email_from': False,
'partner_phone': False,
'partner_mobile': False
}}
addr = self.pool.get('res.partner').address_get(cr, uid, [part], ['contact'])
data = {'partner_address_id': addr['contact']}
data.update(self.onchange_partner_address_id(cr, uid, ids, addr['contact'])['value'])
print data
return {'value': data}
def onchange_partner_address_id(self, cr, uid, ids, add, email=False):
"""This function returns value of partner email based on Partner Address
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@param ids: List of case IDs
@param add: Id of Partner's address
@email: Partner's email ID
"""
if not add:
return {'value': {'email_from': False}}
address = self.pool.get('res.partner.address').browse(cr, uid, add)
return {'value': {'email_from': address.email, 'partner_phone': address.phone, 'partner_mobile': address.mobile}}
crm_claim()
+36 -9
View File
@@ -58,7 +58,6 @@
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Claims" colors="blue:state=='pending';black:state=='open';grey:state in ('close', 'cancel')">
<field name="id"/>
<field name="name"/>
<field name="partner_id"/>
<field name="user_id" />
@@ -67,6 +66,8 @@
<field name="date_deadline" string="Deadline"/>
<field name="date_closed" string="Closure Date"/>
<field name="categ_id" string="Type" select="1"/>
<field name="stage_id" invisible="1"/>
<field name="som" invisible="1"/>
<field name="state"/>
<button name="case_open" string="Open"
states="draft,pending" type="object"
@@ -123,8 +124,9 @@
<field name="user_id" string="Responsible"/>
<field name="section_id" widget="selection"/>
<label string="Stage: " align="1.0"/>
<group colspan="1" col="2">
<group colspan="1" col="3">
<field name="stage_id" select="1" nolabel="1"/>
<button name="stage_previous" string="" type="object" icon="gtk-go-back" />
<button icon="gtk-go-forward" string="" name="stage_next" type="object"/>
</group>
<field name="categ_id" select="1" widget="selection"
@@ -143,18 +145,18 @@
<separator colspan="4" string=""/>
<group col="8" colspan="4">
<field name="state" select="1"/>
<button name="case_close" string="Done"
states="open,draft,pending" type="object"
icon="gtk-jump-to" />
<button name="case_open" string="Open"
states="draft,pending" type="object"
icon="gtk-go-forward" />
<button name="case_cancel" string="Cancel"
states="draft,open,pending" type="object"
icon="gtk-cancel" />
<button name="case_pending" string="Pending"
states="draft,open" type="object"
icon="gtk-media-pause" />
<button name="case_close" string="Done"
states="open,draft,pending" type="object"
icon="gtk-jump-to" />
<button name="case_cancel" string="Cancel"
states="draft,open,pending" type="object"
icon="gtk-cancel" />
<button name="case_reset"
string="Reset to Draft" states="done,cancel"
type="object" icon="gtk-convert" />
@@ -291,12 +293,37 @@
widget="selection"/>
<newline/>
<group expand="0" string="Group By...">
<filter string="Partner" icon="terp-partner"
domain="[]" help="Partner"
context="{'group_by':'partner_id'}" />
<filter string="Responsible" icon="terp-personal"
domain="[]" help="Responsible User"
context="{'group_by':'user_id'}" />
<filter string="Sales Team" icon="terp-personal+"
domain="[]" help="Sales Team"
context="{'group_by':'section_id'}" />
<separator orientation="vertical"/>
<filter string="Stage" icon="terp-stage"
domain="[]" context="{'group_by':'stage_id'}" />
<filter string="Type" icon="terp-stock_symbol-selection"
domain="[]" context="{'group_by':'categ_id'}" />
<filter string="State"
icon="terp-stock_effects-object-colorize"
domain="[]" context="{'group_by':'state'}" />
<separator orientation="vertical"/>
<filter string="Claim Date" icon="terp-go-month"
domain="[]" help="Claim Date"
context="{'group_by':'date'}" />
<filter string="Deadline" icon="terp-go-month"
domain="[]"
context="{'group_by':'date_deadline'}" />
<filter string="Closure" icon="terp-go-month"
domain="[]"
domain="[]" help="Date Closed"
context="{'group_by':'date_closed'}" />
<separator orientation="vertical"/>
<filter string="State of Mind"
icon="terp-face-plain"
domain="[]" context="{'group_by':'som'}" />
</group>
</search>
</field>
+2 -2
View File
@@ -85,8 +85,8 @@ class crm_fundraising(osv.osv, crm.crm_case):
\nIf the case is in progress the state is set to \'Open\'.\
\nWhen the case is over, the state is set to \'Done\'.\
\nIf the case needs to be reviewed then the state is set to \'Pending\'.'),
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('history', '=', True),('res_model','=',_name)]),
'log_ids': fields.one2many('mailgate.message', 'res_id', 'Logs', domain=[('history', '=', False),('res_model','=',_name)]),
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('history', '=', True),('model','=',_name)]),
'log_ids': fields.one2many('mailgate.message', 'res_id', 'Logs', domain=[('history', '=', False),('model','=',_name)]),
}
_defaults = {
+20 -14
View File
@@ -72,21 +72,21 @@
<field name="user_id" />
<field name="state" />
<field name="partner_id" invisible="1"/>
<button name="case_close" string="Done"
states="open,draft,pending" type="object"
icon="gtk-close" />
<button name="case_open" string="Open"
states="draft,pending" type="object"
icon="gtk-go-forward" />
<button name="case_cancel" string="Cancel"
states="draft,open,pending" type="object"
icon="gtk-cancel" />
<button name="case_pending" string="Pending"
states="draft,open" type="object" icon="gtk-media-pause" />
<button name="case_escalate" string="Escalate"
states="open,draft,pending" type="object"
groups="base.group_extended"
icon="gtk-go-up" />
<button name="case_close" string="Done"
states="open,draft,pending" type="object"
icon="gtk-close" />
<button name="case_cancel" string="Cancel"
states="draft,open,pending" type="object"
icon="gtk-cancel" />
<button name="case_reset" string="Reset to Draft"
states="done,cancel" type="object" icon="gtk-convert" />
</tree>
@@ -133,15 +133,9 @@
<separator colspan="4"/>
<group col="8" colspan="4">
<field name="state"/>
<button name="case_close" string="Done"
states="open,draft,pending" type="object"
icon="gtk-close" />
<button name="case_open" string="Open"
states="draft,pending" type="object"
icon="gtk-go-forward" />
<button name="case_cancel" string="Cancel"
states="draft,open,pending" type="object"
icon="gtk-cancel" />
<button name="case_pending" string="Pending"
states="draft,open" type="object"
icon="gtk-media-pause" />
@@ -149,6 +143,12 @@
states="open,draft,pending" type="object"
groups="base.group_extended"
icon="gtk-go-up" />
<button name="case_close" string="Done"
states="open,draft,pending" type="object"
icon="gtk-close" />
<button name="case_cancel" string="Cancel"
states="draft,open,pending" type="object"
icon="gtk-cancel" />
<button name="case_reset"
string="Reset to Draft" states="done,cancel"
type="object" icon="gtk-convert" />
@@ -304,9 +304,15 @@
domain="[]"
context="{'group_by':'user_id'}" />
<separator orientation="vertical" />
<filter string="Type" icon="terp-stock_symbol-selection"
domain="[]"
<filter string="Category" help="Fund Category"
icon="terp-stock_symbol-selection" domain="[]"
context="{'group_by':'categ_id'}" />
<filter string="Payment Mode" help="Payment Mode"
icon="terp-dolar" domain="[]"
context="{'group_by':'type_id'}" />
<separator orientation="vertical" />
<filter string="State" icon="terp-stock_effects-object-colorize" domain="[]"
context="{'group_by':'state'}" />
</group>
</search>
</field>
+2
View File
@@ -21,6 +21,7 @@
from crm import crm
from osv import fields, osv
import time
class crm_helpdesk(osv.osv, crm.crm_case):
""" Helpdesk Cases """
@@ -85,6 +86,7 @@ class crm_helpdesk(osv.osv, crm.crm_case):
'partner_address_id': crm.crm_case._get_default_partner_address,
'email_from': crm.crm_case. _get_default_email,
'state': lambda *a: 'draft',
'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
'section_id': crm.crm_case. _get_section,
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.helpdesk', context=c),
'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0],
+45 -27
View File
@@ -29,7 +29,7 @@
<field name="arch" type="xml">
<form string="Helpdesk Support">
<group colspan="4" col="7">
<field name="name" select="1"/>
<field name="name" select="1" string="Query"/>
<field name="section_id" widget="selection"/>
<field name="user_id" select="1"/>
<button name="remind_user"
@@ -71,26 +71,26 @@
<separator colspan="4"/>
<group col="8" colspan="4">
<field name="state" select="1"/>
<button name="case_close"
states="open,draft,pending" string="Close"
type="object" icon="gtk-close" />
<button name="case_open"
states="draft,pending" string="Open"
type="object" icon="gtk-go-forward" />
<button name="case_cancel"
states="draft,open,pending" string="Cancel"
type="object" icon="gtk-cancel" />
states="draft,pending" string="Open"
type="object" icon="gtk-go-forward" />
<button name="case_pending"
states="draft,open" string="Pending"
type="object" icon="gtk-media-pause" />
states="draft,open" string="Pending"
type="object" icon="gtk-media-pause" />
<button name="case_escalate"
states="open,draft,pending"
string="Escalate" type="object"
icon="gtk-go-up" />
states="open,draft,pending"
string="Escalate" type="object"
icon="gtk-go-up" />
<button name="case_close"
states="open,draft,pending" string="Close"
type="object" icon="gtk-jump-to" />
<button name="case_cancel"
states="draft,open,pending" string="Cancel"
type="object" icon="gtk-cancel" />
<button name="case_reset"
states="done,cancel"
string="Reset to Draft" type="object"
icon="gtk-convert" />
states="done,cancel"
string="Reset to Draft" type="object"
icon="gtk-convert" />
</group>
</page>
<page string="History" groups="base.group_extended">
@@ -179,24 +179,18 @@
<field name="arch" type="xml">
<tree string="Helpdesk Support Tree"
colors="black:state=='open';blue:state=='pending';grey:state in ('cancel','close')">
<field name="id"/>
<field name="name" string="Query Description" />
<field name="name" string="Query" />
<field name="partner_id" string="Partner"/>
<field name="date" string="Date"/>
<field name="date_deadline"/>
<field name="user_id"/>
<field name="section_id"/>
<field name="priority"/>
<field name="som" invisible="1"/>
<field name="state"/>
<button name="case_close" string="Done"
states="open,draft,pending" type="object"
icon="gtk-close" />
<button name="case_open" string="Open"
states="draft,pending" type="object"
icon="gtk-go-forward" />
<button name="case_cancel" string="Cancel"
states="draft,open,pending" type="object"
icon="gtk-cancel" />
<button name="case_pending" string="Pending"
states="draft,open" type="object"
icon="gtk-media-pause" />
@@ -204,6 +198,12 @@
groups="base.group_extended"
states="open,draft,pending" type="object"
icon="gtk-go-up" />
<button name="case_close" string="Done"
states="open,draft,pending" type="object"
icon="gtk-close" />
<button name="case_cancel" string="Cancel"
states="draft,open,pending" type="object"
icon="gtk-cancel" />
<button name="case_reset" string="Reset to Draft"
states="done,cancel" type="object" icon="gtk-convert" />
</tree>
@@ -255,12 +255,30 @@
</field>
<newline/>
<group expand="0" string="Group By...">
<filter string="Customer" icon="terp-personal"
domain="[]" context="{'group_by':'partner_id'}" />
<filter string="Partner" icon="terp-partner"
domain="[]" help="Partner"
context="{'group_by':'partner_id'}" />
<filter string="Responsible" icon="terp-personal"
domain="[]" help="Responsible User"
context="{'group_by':'user_id'}" />
<filter string="Sales Team" icon="terp-personal+"
domain="[]" help="Sales Team"
context="{'group_by':'section_id'}" />
<separator orientation="vertical"/>
<filter string="State" icon="terp-stock_effects-object-colorize" domain="[]"
context="{'group_by':'state'}" />
<filter string="Priority" icon="terp-rating-rated"
domain="[]" context="{'group_by':'priority'}" />
<filter string="State of Mind"
icon="terp-face-plain"
domain="[]" context="{'group_by':'som'}" />
<separator orientation="vertical"/>
<filter string="Date" icon="terp-go-month"
domain="[]" help="Request Date"
context="{'group_by':'date'}" />
<filter string="Deadline" icon="terp-go-month"
domain="[]"
context="{'group_by':'date_deadline'}" />
</group>
</search>
</field>
+1 -1
View File
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"X-Poedit-Country: GREECE\n"
"X-Poedit-Language: Greek\n"
-2
View File
@@ -28,8 +28,6 @@ import decimal_precision as dp
# Overloaded stock_picking to manage carriers :
class stock_picking(osv.osv):
_name = "stock.picking"
_description = "Packing List"
_inherit = 'stock.picking'
def _cal_weight(self, cr, uid, ids, name, args, context=None):
+1 -1
View File
@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: document
+1 -1
View File
@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: document
+1 -1
View File
@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: document_webdav_old
+1 -2
View File
@@ -108,8 +108,7 @@ class email_template(osv.osv):
'enforce_from_account':fields.many2one(
'email_template.account',
string="Enforce From Account",
help="Emails will be sent only from this account(which are approved).",
domain=[('state','=','approved')]),
help="Emails will be sent only from this account(which are approved)."),
'from_email' : fields.related('enforce_from_account', 'email_id',
type='char', string='From',),
'def_to':fields.char(
@@ -97,9 +97,12 @@ class email_template_account(osv.osv):
context
)['name'],
'state':lambda * a:'draft',
'smtpport':lambda *a:25,
'smtpserver':lambda *a:'localhost',
'company':lambda *a:'yes',
'user':lambda self, cursor, user, context:user,
'send_pref':lambda * a: 'html',
'smtptls':lambda * a:True,
'send_pref':lambda *a: 'html',
'smtptls':lambda *a:True,
}
_sql_constraints = [
@@ -56,14 +56,16 @@
<field name="model_int_name" invisible="1" />
<notebook colspan="4">
<page string="Mail Details">
<field name="enforce_from_account" required= "1"/>
<group col="4" colspan="2">
<group col="2" colspan="2">
<separator string="Addresses" colspan="2"/>
<field name="from_email"/>
<field name="def_to" colspan="4" required="1" />
<field name="def_cc" colspan="4" />
<field name="def_bcc" colspan="4" />
<field name="def_to" required="1"/>
<field name="def_cc"/>
<field name="def_bcc"/>
</group>
<group col="2" colspan="2">
<separator string="Email Data" colspan="2"/>
<field name="enforce_from_account" required= "1"/>
<field name="def_subject" colspan="4" required="1" />
<field name="use_sign" colspan="4" />
<field name="lang" colspan="4" />
+88
View File
@@ -0,0 +1,88 @@
# Greek translation for openobject-addons
# Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2010-06-24 22:21+0000\n"
"Last-Translator: Panayiotis Konstantinidis <Unknown>\n"
"Language-Team: Greek <el@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: event_project
#: constraint:ir.ui.view:0
msgid "Invalid XML for View Architecture!"
msgstr "Λανθασμένο XML για προβολή αρχιτεκτονικής!"
#. module: event_project
#: model:ir.actions.wizard,name:event_project.wizard_event_task
msgid "Tasks"
msgstr "Εργασίες"
#. module: event_project
#: wizard_button:event.project,init,done:0
msgid "Ok"
msgstr "Εντάξει"
#. module: event_project
#: model:ir.module.module,description:event_project.module_meta_information
msgid ""
"Organization and management of events.\n"
"\n"
" This module allow you to create retro planning for managing your "
"events.\n"
msgstr ""
"Οργάνωση και διαχείριση συμβάντων.\n"
"\n"
" Αυτή το τμήμα του προγράμματος σας επιτρέπει να κάνετε ανασχεδιασμό για "
"τη διαχείριση των συμβάντων σας.\n"
#. module: event_project
#: view:event.event:0
msgid "Remaining Tasks"
msgstr "Εργασίες που παραμένουν"
#. module: event_project
#: model:ir.module.module,shortdesc:event_project.module_meta_information
msgid "Event - Project"
msgstr "Συμβάν - Έργο"
#. module: event_project
#: field:event.event,project_id:0
#: wizard_field:event.project,init,project_id:0
#: model:ir.actions.wizard,name:event_project.event_wiz
msgid "Project"
msgstr "Έργο"
#. module: event_project
#: field:event.event,task_ids:0
msgid "Project tasks"
msgstr "Εργασίες Έργου"
#. module: event_project
#: wizard_button:event.project,init,end:0
msgid "Cancel"
msgstr "Ακύρωση"
#. module: event_project
#: view:event.event:0
msgid "Create Retro-Planning"
msgstr "Δημιουργία προγραμματισμού"
#. module: event_project
#: wizard_view:event.project,init:0
msgid "Event"
msgstr "Συμβάν"
#. module: event_project
#: view:event.event:0
msgid "Tasks management"
msgstr "Διαχείριση εργασιών"
+1 -1
View File
@@ -24,7 +24,7 @@
{
"name" : "Fetchmail Server",
"version" : "1.0",
"depends" : ["base"],
"depends" : ["base", 'mail_gateway'],
"author" : "Tiny",
"description": """Fetchmail:
* Fetch email from Pop / IMAP server
+65 -345
View File
@@ -19,140 +19,57 @@
#
##############################################################################
import os
import re
import time
import email
import binascii
import mimetypes
from imaplib import IMAP4
from imaplib import IMAP4_SSL
from imaplib import IMAP4_SSL
from poplib import POP3
from poplib import POP3_SSL
from email.header import Header
from email.header import decode_header
import netsvc
from osv import osv
from osv import fields
from tools.translate import _
from osv import osv, fields
logger = netsvc.Logger()
def html2plaintext(html, body_id=None, encoding='utf-8'):
## (c) Fry-IT, www.fry-it.com, 2007
## <peter@fry-it.com>
## download here: http://www.peterbe.com/plog/html2plaintext
""" from an HTML text, convert the HTML to plain text.
If @body_id is provided then this is the tag where the
body (not necessarily <body>) starts.
"""
try:
from BeautifulSoup import BeautifulSoup, SoupStrainer, Comment
except:
return html
urls = []
if body_id is not None:
strainer = SoupStrainer(id=body_id)
else:
strainer = SoupStrainer('body')
soup = BeautifulSoup(html, parseOnlyThese=strainer, fromEncoding=encoding)
for link in soup.findAll('a'):
title = link.renderContents()
for url in [x[1] for x in link.attrs if x[0]=='href']:
urls.append(dict(url=url, tag=str(link), title=title))
html = soup.__str__()
url_index = []
i = 0
for d in urls:
if d['title'] == d['url'] or 'http://'+d['title'] == d['url']:
html = html.replace(d['tag'], d['url'])
else:
i += 1
html = html.replace(d['tag'], '%s [%s]' % (d['title'], i))
url_index.append(d['url'])
html = html.replace('<strong>','*').replace('</strong>','*')
html = html.replace('<b>','*').replace('</b>','*')
html = html.replace('<h3>','*').replace('</h3>','*')
html = html.replace('<h2>','**').replace('</h2>','**')
html = html.replace('<h1>','**').replace('</h1>','**')
html = html.replace('<em>','/').replace('</em>','/')
# the only line breaks we respect is those of ending tags and
# breaks
html = html.replace('\n',' ')
html = html.replace('<br>', '\n')
html = html.replace('<tr>', '\n')
html = html.replace('</p>', '\n\n')
html = re.sub('<br\s*/>', '\n', html)
html = html.replace(' ' * 2, ' ')
# for all other tags we failed to clean up, just remove then and
# complain about them on the stderr
def desperate_fixer(g):
#print >>sys.stderr, "failed to clean up %s" % str(g.group())
return ' '
html = re.sub('<.*?>', desperate_fixer, html)
# lstrip all lines
html = '\n'.join([x.lstrip() for x in html.splitlines()])
for i, url in enumerate(url_index):
if i == 0:
html += '\n\n'
html += '[%s] %s\n' % (i+1, url)
return html
class email_server(osv.osv):
_name = 'email.server'
_description = "POP/IMAP Server"
_columns = {
'name':fields.char('Name', size=256, required=True, readonly=False),
'active':fields.boolean('Active', required=False),
'name':fields.char('Name', size=256, required=True, readonly=False),
'active':fields.boolean('Active', required=False),
'state':fields.selection([
('draft','Not Confirmed'),
('wating','Waiting for Verification'),
('done','Confirmed'),
],'State', select=True, readonly=True),
'server' : fields.char('Server', size=256, required=True, readonly=True, states={'draft':[('readonly',False)]}),
'port' : fields.integer('Port', required=True, readonly=True, states={'draft':[('readonly',False)]}),
('draft', 'Not Confirmed'),
('wating', 'Waiting for Verification'),
('done', 'Confirmed'),
], 'State', select=True, readonly=True),
'server' : fields.char('Server', size=256, required=True, readonly=True, states={'draft':[('readonly', False)]}),
'port' : fields.integer('Port', required=True, readonly=True, states={'draft':[('readonly', False)]}),
'type':fields.selection([
('pop','POP Server'),
('imap','IMAP Server'),
],'State', select=True, readonly=False),
'is_ssl':fields.boolean('SSL ?', required=False),
'attach':fields.boolean('Add Attachments ?', required=False),
'date': fields.date('Date', readonly=True, states={'draft':[('readonly',False)]}),
'user' : fields.char('User Name', size=256, required=True, readonly=True, states={'draft':[('readonly',False)]}),
'password' : fields.char('Password', size=1024, invisible=True, required=True, readonly=True, states={'draft':[('readonly',False)]}),
'note': fields.text('Description'),
'action_id':fields.many2one('ir.actions.server', 'Reply Email', required=False, domain="[('state','=','email')]"),
'object_id': fields.many2one('ir.model',"Model", required=True),
'priority': fields.integer('Server Priority', readonly=True, states={'draft':[('readonly',False)]}, help="Priority between 0 to 10, select define the order of Processing"),
'user_id':fields.many2one('res.users', 'User', required=False),
('pop', 'POP Server'),
('imap', 'IMAP Server'),
], 'State', select=True, readonly=False),
'is_ssl':fields.boolean('SSL ?', required=False),
'attach':fields.boolean('Add Attachments ?', required=False),
'date': fields.date('Date', readonly=True, states={'draft':[('readonly', False)]}),
'user' : fields.char('User Name', size=256, required=True, readonly=True, states={'draft':[('readonly', False)]}),
'password' : fields.char('Password', size=1024, invisible=True, required=True, readonly=True, states={'draft':[('readonly', False)]}),
'note': fields.text('Description'),
'action_id':fields.many2one('ir.actions.server', 'Reply Email', required=False, domain="[('state','=','email')]"),
'object_id': fields.many2one('ir.model', "Model", required=True),
'priority': fields.integer('Server Priority', readonly=True, states={'draft':[('readonly', False)]}, help="Priority between 0 to 10, select define the order of Processing"),
'user_id':fields.many2one('res.users', 'User', required=False),
}
_defaults = {
'state': lambda *a: "draft",
'active': lambda *a: True,
'priority': lambda *a: 5,
'date': lambda *a: time.strftime('%Y-%m-%d'),
'user_id': lambda self, cr, uid, ctx: uid,
'state': lambda *a: "draft",
'active': lambda *a: True,
'priority': lambda *a: 5,
'date': lambda *a: time.strftime('%Y-%m-%d'),
'user_id': lambda self, cr, uid, ctx: uid,
}
def check_duplicate(self, cr, uid, ids):
vals = self.read(cr, uid, ids, ['user', 'password'])[0]
cr.execute("select count(id) from email_server where user='%s' and password='%s'" % (vals['user'], vals['password']))
@@ -160,201 +77,41 @@ class email_server(osv.osv):
if res:
if res[0] > 1:
return False
return True
return True
_constraints = [
(check_duplicate, 'Warning! Can\'t have duplicate server configuration!', ['user', 'password'])
]
def onchange_server_type(self, cr, uid, ids, server_type=False, ssl=False):
port = 0
if server_type == 'pop':
port = ssl and 995 or 110
elif server_type == 'imap':
port = ssl and 993 or 143
return {'value':{'port':port}}
def _process_email(self, cr, uid, server, message, context={}):
context.update({
'server_id':server.id
})
history_pool = self.pool.get('mail.server.history')
msg_txt = email.message_from_string(message)
message_id = msg_txt.get('Message-ID', False)
msg = {}
if not message_id:
return False
fields = msg_txt.keys()
msg['id'] = message_id
msg['message-id'] = message_id
def _decode_header(txt):
txt = txt.replace('\r', '')
return ' '.join(map(lambda (x, y): unicode(x, y or 'ascii'), decode_header(txt)))
if 'Subject' in fields:
msg['subject'] = _decode_header(msg_txt.get('Subject'))
if 'Content-Type' in fields:
msg['content-type'] = msg_txt.get('Content-Type')
if 'From' in fields:
msg['from'] = _decode_header(msg_txt.get('From'))
if 'Delivered-To' in fields:
msg['to'] = _decode_header(msg_txt.get('Delivered-To'))
if 'Cc' in fields:
msg['cc'] = _decode_header(msg_txt.get('Cc'))
if 'Reply-To' in fields:
msg['reply'] = _decode_header(msg_txt.get('Reply-To'))
if 'Date' in fields:
msg['date'] = msg_txt.get('Date')
if 'Content-Transfer-Encoding' in fields:
msg['encoding'] = msg_txt.get('Content-Transfer-Encoding')
if 'References' in fields:
msg['references'] = msg_txt.get('References')
if 'X-openerp-caseid' in fields:
msg['caseid'] = msg_txt.get('X-openerp-caseid')
if 'X-Priority' in fields:
msg['priority'] = msg_txt.get('X-priority', '3 (Normal)').split(' ')[0]
if not msg_txt.is_multipart() or 'text/plain' in msg.get('content-type', None):
encoding = msg_txt.get_content_charset()
msg['body'] = msg_txt.get_payload(decode=True)
if encoding:
msg['body'] = msg['body'].decode(encoding).encode('utf-8')
attachents = {}
if msg_txt.is_multipart() or 'multipart/alternative' in msg.get('content-type', None):
body = ""
counter = 1
for part in msg_txt.walk():
if part.get_content_maintype() == 'multipart':
continue
encoding = part.get_content_charset()
if part.get_content_maintype()=='text':
content = part.get_payload(decode=True)
filename = part.get_filename()
if filename :
attachents[filename] = content
else:
if encoding:
content = unicode(content, encoding)
if part.get_content_subtype() == 'html':
body = html2plaintext(content)
elif part.get_content_subtype() == 'plain':
body = content
elif part.get_content_maintype()=='application' or part.get_content_maintype()=='image' or part.get_content_maintype()=='text':
filename = part.get_filename();
if filename :
attachents[filename] = part.get_payload(decode=True)
else:
res = part.get_payload(decode=True)
if encoding:
res = res.decode(encoding).encode('utf-8')
body += res
msg['body'] = body
msg['attachments'] = attachents
res_id = False
if msg.get('references', False):
id = False
ref = msg.get('references')
if '\r\n' in ref:
ref = msg.get('references').split('\r\n')
else:
ref = msg.get('references').split(' ')
if ref:
hids = history_pool.search(cr, uid, [('name','=',ref[0].strip())])
if hids:
id = hids[0]
history = history_pool.browse(cr, uid, id)
model_pool = self.pool.get(server.object_id.model)
context.update({
'references_id':ref[0]
})
vals = {
}
if hasattr(model_pool, 'message_update'):
model_pool.message_update(cr, uid, [history.res_id], vals, msg, context=context)
else:
logger.notifyChannel('imap', netsvc.LOG_WARNING, 'method def message_update is not define in model %s' % (model_pool._name))
return False
res_id = id
else:
model_pool = self.pool.get(server.object_id.model)
if hasattr(model_pool, 'message_new'):
res_id = model_pool.message_new(cr, uid, msg, context)
else:
logger.notifyChannel('imap', netsvc.LOG_WARNING, 'method def message_new is not define in model %s' % (model_pool._name))
return False
if server.attach:
for attactment in attachents or []:
data_attach = {
'name': attactment,
'datas':binascii.b2a_base64(str(attachents.get(attactment))),
'datas_fname': attactment,
'description': 'Mail attachment',
'res_model': server.object_id.model,
'res_id': res_id,
}
self.pool.get('ir.attachment').create(cr, uid, data_attach)
if server.action_id:
action_pool = self.pool.get('ir.actions.server')
action_pool.run(cr, uid, [server.action_id.id], {'active_id':res_id, 'active_ids':[res_id]})
res = {
'name': message_id,
'res_id': res_id,
'server_id': server.id,
'note': msg.get('body', msg.get('from')),
'ref_id':msg.get('references', msg.get('id')),
'type':server.type
}
his_id = history_pool.create(cr, uid, res)
return res_id
def set_draft(self, cr, uid, ids, context={}):
self.write(cr, uid, ids , {'state':'draft'})
return True
def button_fetch_mail(self, cr, uid, ids, context={}):
self.fetch_mail(cr, uid, ids)
# sendmail_thread = threading.Thread(target=self.fetch_mail, args=(cr, uid, ids))
# sendmail_thread.start()
return True
def _fetch_mails(self, cr, uid, ids=False, context={}):
if not ids:
ids = self.search(cr, uid, [])
return self.fetch_mail(cr, uid, ids, context)
def fetch_mail(self, cr, uid, ids, context={}):
def fetch_mail(self, cr, uid, ids, context={}):
email_tool = self.pool.get('email.server.tools')
for server in self.browse(cr, uid, ids, context):
logger.notifyChannel('imap', netsvc.LOG_INFO, 'fetchmail start checking for new emails on %s' % (server.name))
count = 0
try:
if server.type == 'imap':
@@ -363,17 +120,21 @@ class email_server(osv.osv):
imap_server = IMAP4_SSL(server.server, int(server.port))
else:
imap_server = IMAP4(server.server, int(server.port))
imap_server.login(server.user, server.password)
imap_server.select()
result, data = imap_server.search(None, '(UNSEEN)')
for num in data[0].split():
result, data = imap_server.fetch(num, '(RFC822)')
if self._process_email(cr, uid, server, data[0][1], context):
res_id = email_tool.process_email(cr, uid, server.object_id.model, data[0][1], attach=server.attach, server_id=server.id, server_type=server.type, context=context)
if res_id and server.action_id:
action_pool = self.pool.get('ir.actions.server')
action_pool.run(cr, uid, [server.action_id.id], {'active_id': res_id, 'active_ids':[res_id]})
imap_server.store(num, '+FLAGS', '\\Seen')
count += 1
count += 1
logger.notifyChannel('imap', netsvc.LOG_INFO, 'fetchmail fetch/process %s email(s) from %s' % (count, server.name))
imap_server.close()
imap_server.logout()
elif server.type == 'pop':
@@ -382,7 +143,7 @@ class email_server(osv.osv):
pop_server = POP3_SSL(server.server, int(server.port))
else:
pop_server = POP3(server.server, int(server.port))
#TODO: use this to remove only unread messages
#pop_server.user("recent:"+server.user)
pop_server.user(server.user)
@@ -393,79 +154,38 @@ class email_server(osv.osv):
for num in range(1, numMsgs + 1):
(header, msges, octets) = pop_server.retr(num)
msg = '\n'.join(msges)
self._process_email(cr, uid, server, msg, context)
res_id = email_tool.process_email(cr, uid, server.object_id.model, data[0][1], attach=server.attach, server_id=server.id, server_type=server.type, context=context)
if res_id and server.action_id:
action_pool = self.pool.get('ir.actions.server')
action_pool.run(cr, uid, [server.action_id.id], {'active_id': res_id, 'active_ids':[res_id]})
pop_server.dele(num)
pop_server.quit()
logger.notifyChannel('imap', netsvc.LOG_INFO, 'fetchmail fetch %s email(s) from %s' % (numMsgs, server.name))
self.write(cr, uid, [server.id], {'state':'done'})
except Exception, e:
logger.notifyChannel(server.type, netsvc.LOG_WARNING, '%s' % (e))
return True
email_server()
class mail_server_history(osv.osv):
class mailgate_message(osv.osv):
_inherit = "mailgate.message"
_name = "mail.server.history"
_description = "Mail Server History"
_columns = {
'name': fields.char('Message Id', size=256, readonly=True, help="Message Id in Email Server.", select=True),
'ref_id': fields.char('Referance Id', size=256, readonly=True, help="Message Id in Email Server.", select=True),
'res_id': fields.integer("Resource ID", readonly=True, select=True),
'server_id': fields.many2one('email.server',"Mail Server", readonly=True, select=True),
'model_id':fields.related('server_id', 'object_id', type='many2one', relation='ir.model', string='Model', readonly=True, select=True),
'note': fields.text('Notes', readonly=True),
'create_date': fields.datetime('Created Date', readonly=True),
'server_id': fields.many2one('email.server', "Mail Server", readonly=True, select=True),
'type':fields.selection([
('pop','POP Server'),
('imap','IMAP Server'),
],'State', select=True, readonly=True),
('pop', 'POP Server'),
('imap', 'IMAP Server'),
], 'State', select=True, readonly=True),
}
_order = 'id desc'
mail_server_history()
class fetchmail_tool(osv.osv):
mailgate_message()
_name = 'email.server.tools'
_description = "Email Tools"
_auto = False
def to_email(self, text):
_email = re.compile(r'.*<.*@.*\..*>', re.UNICODE)
def record(path):
eml = path.group()
index = eml.index('<')
eml = eml[index:-1].replace('<','').replace('>','')
return eml
bits = _email.sub(record, text)
return bits
def get_partner(self, cr, uid, from_email, context=None):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks
@param from_email: email address based on that function will search for the correct
"""
res = {
'partner_address_id': False,
'partner_id': False
}
from_email = self.to_email(from_email)
address_ids = self.pool.get('res.partner.address').search(cr, uid, [('email', '=', from_email)])
if address_ids:
address = self.pool.get('res.partner.address').browse(cr, uid, address_ids[0])
res['partner_address_id'] = address_ids[0]
res['partner_id'] = address.partner_id.id
return res
fetchmail_tool()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+22 -50
View File
@@ -103,82 +103,54 @@
action="action_email_server_tree_imap"
/>
<record model="ir.ui.view" id="view_mail_server_history_tree">
<field name="name">mail.server.history.tree</field>
<field name="model">mail.server.history</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Received Mail History">
<field name="server_id" select="1"/>
<field name="create_date" select="1"/>
<field name="model_id"/>
<field name="name" select="1"/>
<field name="ref_id"/>
</tree>
</field>
</record>
<record model="ir.ui.view" id="view_email_server_history_form">
<field name="name">mail.server.history.form</field>
<field name="model">mail.server.history</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Email History">
<group col="6" colspan="4">
<record model="ir.ui.view" id="mailgate_message_tree_view">
<field name="name">mailgate.message.tree</field>
<field name="model">mailgate.message</field>
<field name="type">tree</field>
<field name="inherit_id" ref="mail_gateway.view_mailgate_message_tree"/>
<field name="arch" type="xml">
<field name="user_id" position="after">
<field name="server_id" select="1"/>
<field name="create_date" select="1"/>
</group>
<group col="2" colspan="2">
<separator string="Resource Information" colspan="2"/>
<field name="model_id" select="1"/>
<field name="res_id"/>
</group>
<group col="2" colspan="2">
<separator string="Meta Information" colspan="2"/>
<field name="name" select="1"/>
<field name="ref_id"/>
</group>
<newline/>
<separator string="Description" colspan="4"/>
<field name="note" colspan="4" nolabel="1"/>
</form>
</field>
</record>
</field>
</field>
</record>
<act_window
context="{'server_id': active_id}"
domain="[('server_id', '=', active_id)]"
id="act_server_history" name="Email History"
res_model="mail.server.history" src_model="email.server"/>
res_model="mailgate.message" src_model="email.server"/>
<record model="ir.actions.act_window" id="action_email_server_history_tree">
<record model="ir.actions.act_window" id="action_mailgate_message_tree">
<field name="name">Received Email History</field>
<field name="res_model">mail.server.history</field>
<field name="res_model">mailgate.message</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_mail_server_history_tree"/>
<field name="view_id" ref="mailgate_message_tree_view"/>
<field name="context">{'type':'imap'}</field>
<field name="domain">[('type','=','imap')]</field>
</record>
<menuitem
parent="menu_action_email_server_tree_imap"
id="menu_action_email_server_history_tree"
action="action_email_server_history_tree"/>
id="menu_action_mailgate_message_tree"
action="action_mailgate_message_tree"/>
<record model="ir.actions.act_window" id="action_email_server_history_tree_pop">
<record model="ir.actions.act_window" id="action_mailgate_message_tree_pop">
<field name="name">Received Email History</field>
<field name="res_model">mail.server.history</field>
<field name="res_model">mailgate.message</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_mail_server_history_tree"/>
<field name="view_id" ref="mailgate_message_tree_view"/>
<field name="context">{'type':'pop'}</field>
<field name="domain">[('type','=','pop')]</field>
</record>
<menuitem
parent="menu_action_email_server_tree"
id="menu_action_email_server_history_tree_pop"
action="action_email_server_history_tree_pop"/>
id="menu_action_mailgate_message_tree_pop"
action="action_mailgate_message_tree_pop"/>
</data>
</openerp>
@@ -1,4 +1,2 @@
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
"access_email_server","email.server","model_email_server",,1,1,1,1
"access_mail_server_history","mail.server.history","model_mail_server_history",,1,1,1,1
"access_email_server_tools","email.server.tools","model_email_server_tools",,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_email_server email.server model_email_server 1 1 1 1
access_mail_server_history mail.server.history model_mail_server_history 1 1 1 1
access_email_server_tools email.server.tools model_email_server_tools 1 1 1 1
+1 -1
View File
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"X-Poedit-Country: GREECE\n"
"X-Poedit-Language: Greek\n"
+1 -1
View File
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"X-Poedit-Country: GREECE\n"
"X-Poedit-Language: Greek\n"
+1 -1
View File
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"X-Poedit-Country: GREECE\n"
"X-Poedit-Language: Greek\n"
+1 -1
View File
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"X-Poedit-Country: GREECE\n"
"X-Poedit-Language: Greek\n"
+132 -2
View File
@@ -21,6 +21,11 @@
from osv import fields, osv
from crm import crm
import tools
import collections
import binascii
import tools
from tools.translate import _
AVAILABLE_STATES = [
('draft', 'New'),
@@ -60,8 +65,8 @@ class hr_applicant(osv.osv, crm.crm_case):
_inherit = ['mailgate.thread']
_columns = {
'name': fields.char('Name', size=128, required=True),
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('history', '=', True),('res_model','=',_name)]),
'log_ids': fields.one2many('mailgate.message', 'res_id', 'Logs', domain=[('history', '=', False),('res_model','=',_name)]),
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('history', '=', True),('model','=',_name)]),
'log_ids': fields.one2many('mailgate.message', 'res_id', 'Logs', domain=[('history', '=', False),('model','=',_name)]),
'active': fields.boolean('Active', help="If the active field is set to false, it will allow you to hide the case without removing it."),
'description': fields.text('Description'),
'section_id': fields.many2one('crm.case.section', 'Sales Team', \
@@ -240,6 +245,131 @@ class hr_applicant(osv.osv, crm.crm_case):
context.update({'survey_id': record.survey.id, 'response_id' : [record.response], 'response_no':0, })
value = self.pool.get("survey").action_print_survey(cr, uid, ids, context)
return value
def message_new(self, cr, uid, msg, context):
"""
Automatically calls when new email message arrives
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks
"""
mailgate_pool = self.pool.get('email.server.tools')
subject = msg.get('subject')
body = msg.get('body')
msg_from = msg.get('from')
priority = msg.get('priority')
vals = {
'name': subject,
'email_from': msg_from,
'email_cc': msg.get('cc'),
'description': body,
'user_id': False,
}
if msg.get('priority', False):
vals['priority'] = priority
res = mailgate_pool.get_partner(cr, uid, msg.get('from'))
if res:
vals.update(res)
res = self.create(cr, uid, vals, context)
attachents = msg.get('attachments', [])
for attactment in attachents or []:
data_attach = {
'name': attactment,
'datas':binascii.b2a_base64(str(attachents.get(attactment))),
'datas_fname': attactment,
'description': 'Mail attachment',
'res_model': self._name,
'res_id': res,
}
self.pool.get('ir.attachment').create(cr, uid, data_attach)
return res
def message_update(self, cr, uid, ids, vals={}, msg="", default_act='pending', context={}):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@param ids: List of update mail’s IDs
"""
if isinstance(ids, (str, int, long)):
ids = [ids]
msg_from = msg['from']
vals.update({
'description': msg['body']
})
if msg.get('priority', False):
vals['priority'] = msg.get('priority')
maps = {
'cost':'planned_cost',
'revenue': 'planned_revenue',
'probability':'probability'
}
vls = { }
for line in msg['body'].split('\n'):
line = line.strip()
res = tools.misc.command_re.match(line)
if res and maps.get(res.group(1).lower(), False):
key = maps.get(res.group(1).lower())
vls[key] = res.group(2).lower()
vals.update(vls)
res = self.write(cr, uid, ids, vals)
return res
def emails_get(self, cr, uid, ids, context=None):
"""
Get Emails
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@param ids: List of email’s IDs
@param context: A standard dictionary for contextual values
"""
res = {}
if isinstance(ids, (str, int, long)):
select = [long(ids)]
else:
select = ids
for thread in self.browse(cr, uid, select, context=context):
values = collections.defaultdict(set)
for message in thread.message_ids:
user_email = (message.user_id and message.user_id.address_id and message.user_id.address_id.email) or False
values['user_email'].add(user_email)
values['email_from'].add(message.email_from)
values['email_cc'].add(message.email_cc or False)
values['priority'] = thread.priority
res[thread.id] = dict((key,list(values[key])) for key, value in values.iteritems())
return res
def msg_send(self, cr, uid, id, *args, **argv):
""" Send The Message
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@param ids: List of email’s IDs
@param *args: Return Tuple Value
@param **args: Return Dictionary of Keyword Value
"""
return True
hr_applicant()
class hr_job(osv.osv):
+1 -1
View File
@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: hr_timesheet_invoice
+1 -1
View File
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"X-Poedit-Country: GREECE\n"
"X-Poedit-Language: Greek\n"
+339 -9
View File
@@ -27,6 +27,7 @@ import email
from email.header import decode_header
import base64
import re
from tools.translate import _
class mailgate_thread(osv.osv):
'''
@@ -37,14 +38,24 @@ class mailgate_thread(osv.osv):
_rec_name = 'thread'
_columns = {
'thread': fields.char('Thread', size=32, required=False),
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('history', '=', True)], readonly=True),
'log_ids': fields.one2many('mailgate.message', 'res_id', 'Logs', domain=[('history', '=', False)], readonly=True),
'model': fields.char('Model Name', size=64, required=False),
'res_id': fields.integer('Resource ID'),
}
def _history(self, cr, uid, cases, keyword, history=False, subject=None, email=False, details=None, email_from=False, message_id=False, attach=None, context=None):
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('history', '=', True)]),
'log_ids': fields.one2many('mailgate.message', 'res_id', 'Logs', domain=[('history', '=', False)]),
}
def message_new(self, cr, uid, msg, context):
raise Exception, _('Method is not implemented')
def message_update(self, cr, uid, ids, vals={}, msg="", default_act='pending', context={}):
raise Exception, _('Method is not implemented')
def emails_get(self, cr, uid, ids, context=None):
raise Exception, _('Method is not implemented')
def msg_send(self, cr, uid, id, *args, **argv):
raise Exception, _('Method is not implemented')
def _history(self, cr, uid, cases, keyword, history=False, subject=None, email=False, details=None, \
email_from=False, message_id=False, references=None, attach=None, context=None):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@@ -98,6 +109,7 @@ class mailgate_thread(osv.osv):
(hasattr(case, 'user_id') and case.user_id and case.user_id.address_id and \
case.user_id.address_id.email) or tools.config.get('email_from', False),
'partner_id': hasattr(case, 'partner_id') and (case.partner_id and case.partner_id.id or False) or False,
'references': references,
'message_id': message_id,
'attachment_ids': [(6, 0, attachments)]
}
@@ -125,7 +137,8 @@ class mailgate_message(osv.osv):
'email_to': fields.char('Email To', size=84),
'email_cc': fields.char('Email CC', size=84),
'email_bcc': fields.char('Email BCC', size=84),
'message_id': fields.char('Message Id', size=1024, readonly=True, help="Message Id on Email Server.", select=True),
'message_id': fields.char('Message Id', size=1024, readonly=True, help="Message Id on Email.", select=True),
'references': fields.text('References', readonly=True, help="Referencess emails."),
'description': fields.text('Description'),
'partner_id': fields.many2one('res.partner', 'Partner', required=False),
'attachment_ids': fields.many2many('ir.attachment', 'message_attachment_rel', 'message_id', 'attachment_id', 'Attachments'),
@@ -133,3 +146,320 @@ class mailgate_message(osv.osv):
mailgate_message()
class mailgate_tool(osv.osv_memory):
_name = 'email.server.tools'
_description = "Email Server Tools"
def _to_decode(self, s, charsets):
for charset in charsets:
if charset:
try:
return s.decode(charset)
except UnicodeError:
pass
return s.decode('latin1')
def _decode_header(self, text):
if text:
text = decode_header(text.replace('\r', ''))
return ''.join(map(lambda x:self._to_decode(x[0], [x[1]]), text or []))
def to_email(self, text):
_email = re.compile(r'.*<.*@.*\..*>', re.UNICODE)
def record(path):
eml = path.group()
index = eml.index('<')
eml = eml[index:-1].replace('<', '').replace('>', '')
return eml
bits = _email.sub(record, text)
return bits
def history(self, cr, uid, model, res_ids, msg, attach):
"""This function creates history for mails fetched
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@param model: OpenObject Model
@param res_ids: Ids of the record of OpenObject model created
@param msg: Email details
@param attach: Email attachments
"""
if isinstance(res_ids, (int, long)):
res_ids = [res_ids]
msg_pool = self.pool.get('mailgate.message')
for res_id in res_ids:
msg_data = {
'name': msg.get('subject', 'No subject'),
'date': msg.get('date') ,
'description': msg.get('body', msg.get('from')),
'history': True,
'res_model': model,
'email_cc': msg.get('cc'),
'email_from': msg.get('from'),
'email_to': msg.get('to'),
'message_id': msg.get('message-id'),
'references': msg.get('references'),
'res_id': res_id,
'user_id': uid,
'attachment_ids': [(6, 0, attach)]
}
msg_id = msg_pool.create(cr, uid, msg_data)
return True
def email_send(self, cr, uid, model, res_id, msg, from_email=False, email_default=False):
"""This function Sends return email on submission of Fetched email in OpenERP database
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@param model: OpenObject Model
@param res_id: Id of the record of OpenObject model created from the Email details
@param msg: Email details
@param email_default: Default Email address in case of any Problem
"""
history_pool = self.pool.get('mailgate.message')
model_pool = self.pool.get(model)
from_email = from_email or tools.config.get('email_from', None)
message = email.message_from_string(str(msg))
subject = "[%s] %s" %(res_id, self._decode_header(message['Subject']))
#msg_mails = []
#mails = [self._decode_header(message['From']), self._decode_header(message['To'])]
#mails += self._decode_header(message.get('Cc', '')).split(',')
values = {}
if hasattr(model_pool, 'emails_get'):
values = model_pool.emails_get(cr, uid, [res_id])
emails = values.get(res_id, {})
priority = emails.get('priority', [3])[0]
em = emails['user_email'] + emails['email_from'] + emails['email_cc']
msg_mails = map(self.to_email, filter(None, em))
#mm = [self._decode_header(message['From']), self._decode_header(message['To'])]
#mm += self._decode_header(message.get('Cc', '')).split(',')
#msg_mails = map(self.to_email, filter(None, mm))
encoding = message.get_content_charset()
message['body'] = message.get_payload(decode=True)
if encoding:
message['body'] = tools.ustr(message['body'].decode(encoding))
body = _("""
Hello %s,
Your Request ID: %s
Thanks
-------- Original Message --------
%s
""") %(self._decode_header(message['From']), res_id, message['body'])
res = None
try:
res = tools.email_send(from_email, msg_mails, subject, body, openobject_id=res_id)
except Exception, e:
if email_default:
temp_msg = '[%s] %s'%(res_id, self._decode_header(message['Subject']))
del message['Subject']
message['Subject'] = '[OpenERP-FetchError] %s' %(temp_msg)
tools.email_send(from_email, email_default, message.get('Subject'), message.get('body'), openobject_id=res_id)
return res
def process_email(self, cr, uid, model, message, attach=True, context=None):
"""This function Processes email and create record for given OpenERP model
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@param model: OpenObject Model
@param message: Email details
@param attach: Email attachments
@param context: A standard dictionary for contextual values"""
model_pool = self.pool.get(model)
if not context:
context = {}
res_id = False
# Create New Record into particular model
def create_record(msg):
if hasattr(model_pool, 'message_new'):
res_id = model_pool.message_new(cr, uid, msg, context)
else:
data = {
'name': msg.get('subject'),
'email_from': msg.get('from'),
'email_cc': msg.get('cc'),
'user_id': False,
'description': msg.get('body'),
'state' : 'draft',
}
data.update(self.get_partner(cr, uid, msg.get('from'), context=context))
res_id = model_pool.create(cr, uid, data, context=context)
att_ids = []
if attach:
for attachment in msg.get('attachments', []):
data_attach = {
'name': attachment,
'datas': binascii.b2a_base64(str(attachments.get(attachment))),
'datas_fname': attachment,
'description': 'Mail attachment',
'res_model': model,
'res_id': res_id,
}
att_ids.append(self.pool.get('ir.attachment').create(cr, uid, data_attach))
return res_id
history_pool = self.pool.get('mailgate.message')
msg_txt = email.message_from_string(message)
message_id = msg_txt.get('Message-ID', False)
msg = {}
if not message_id:
return False
fields = msg_txt.keys()
msg['id'] = message_id
msg['message-id'] = message_id
if 'Subject' in fields:
msg['subject'] = self._decode_header(msg_txt.get('Subject'))
if 'Content-Type' in fields:
msg['content-type'] = msg_txt.get('Content-Type')
if 'From' in fields:
msg['from'] = self._decode_header(msg_txt.get('From'))
if 'Delivered-To' in fields:
msg['to'] = self._decode_header(msg_txt.get('Delivered-To'))
if 'Cc' in fields:
msg['cc'] = self._decode_header(msg_txt.get('Cc'))
if 'Reply-To' in fields:
msg['reply'] = self._decode_header(msg_txt.get('Reply-To'))
if 'Date' in fields:
msg['date'] = msg_txt.get('Date')
if 'Content-Transfer-Encoding' in fields:
msg['encoding'] = msg_txt.get('Content-Transfer-Encoding')
if 'References' in fields:
msg['references'] = msg_txt.get('References')
if 'X-Priority' in fields:
msg['priority'] = msg_txt.get('X-priority', '3 (Normal)').split(' ')[0]
if not msg_txt.is_multipart() or 'text/plain' in msg.get('content-type', None):
encoding = msg_txt.get_content_charset()
msg['body'] = msg_txt.get_payload(decode=True)
if encoding:
msg['body'] = tools.ustr(msg['body'])
attachments = {}
if msg_txt.is_multipart() or 'multipart/alternative' in msg.get('content-type', None):
body = ""
counter = 1
for part in msg_txt.walk():
if part.get_content_maintype() == 'multipart':
continue
encoding = part.get_content_charset()
if part.get_content_maintype()=='text':
content = part.get_payload(decode=True)
filename = part.get_filename()
if filename :
attachments[filename] = content
else:
if encoding:
content = unicode(content, encoding)
if part.get_content_subtype() == 'html':
body = tools.html2plaintext(content)
elif part.get_content_subtype() == 'plain':
body = content
elif part.get_content_maintype()=='application' or part.get_content_maintype()=='image' or part.get_content_maintype()=='text':
filename = part.get_filename();
if filename :
attachments[filename] = part.get_payload(decode=True)
else:
res = part.get_payload(decode=True)
if encoding:
res = tools.ustr(res)
body += res
msg['body'] = body
msg['attachments'] = attachments
res_ids = []
new_res_id = False
if msg.get('references', False):
references = msg.get('references')
if '\r\n' in references:
references = msg.get('references').split('\r\n')
else:
references = msg.get('references').split(' ')
for ref in references:
ref = ref.strip()
res_id = tools.misc.reference_re.search(ref)
if res_id:
res_id = res_id.group(1)
else:
res_id = tools.misc.res_re.search(msg['subject'])
if res_id:
res_id = res_id.group(1)
if res_id:
res_id = int(res_id)
res_ids.append(res_id)
model_pool = self.pool.get(model)
vals = {}
if hasattr(model_pool, 'message_update'):
model_pool.message_update(cr, uid, [res_id], vals, msg, context=context)
if not len(res_ids):
new_res_id = create_record(msg)
res_ids = [new_res_id]
# Store messages
if hasattr(model_pool, '_history'):
model_pool._history(cr, uid, res_ids, _('Receive'), history=True,
subject = msg.get('subject'),
email = msg.get('to'),
details = msg.get('body'),
email_from = msg.get('from'),
message_id = msg.get('message-id'),
references = msg.get('references', False),
attach = msg.get('attachments', {}).items(),
context = {'model' : model})
else:
self.history(cr, uid, model, res_ids, msg, att_ids)
return new_res_id
def get_partner(self, cr, uid, from_email, context=None):
"""This function returns partner Id based on email passed
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks
@param from_email: email address based on that function will search for the correct
"""
address_pool = self.pool.get('res.partner.address')
res = {
'partner_address_id': False,
'partner_id': False
}
from_email = self.to_email(from_email)
address_ids = address_pool.search(cr, uid, [('email', '=', from_email)])
if address_ids:
address = address_pool.browse(cr, uid, address_ids[0])
res['partner_address_id'] = address_ids[0]
res['partner_id'] = address.partner_id.id
return res
mailgate_tool()
+49 -24
View File
@@ -29,7 +29,7 @@
<field name="message_id" />
<field name="ref_id" />
</group>
<separator string="Description" colspan="4"/>
<separator string="Description" colspan="4"/>
<field name="description" nolabel="1" colspan="4" />
</page>
<page string="Attachments">
@@ -76,28 +76,30 @@
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Mailgateway Thread">
<field name="thread" select="1"/>
<group col="6" colspan="4">
<field name="thread" select="1" colspan="3"/>
</group>
<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">
@@ -163,10 +165,33 @@
</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="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>
<!-- Mailgateway message action-->
<record model="ir.actions.act_window" id="action_view_mailgate_message">
<field name="name">Mailgateway Messages</field>
<field name="res_model">mailgate.message</field>
<field name="view_mode">tree,form</field>
<field name="view_type">form</field>
<field name="domain">[('history', '=', True)]</field>
<field name="view_id" ref="view_mailgate_thread_tree"/>
</record>
@@ -195,4 +220,4 @@
/>
</data>
</openerp>
</openerp>
@@ -21,104 +21,15 @@
#
###########################################################################################
import re
import smtplib
import email
import mimetypes
from email.Header import decode_header
from email.MIMEText import MIMEText
import xmlrpclib
import os
import binascii
import time
import socket
import logging
import sys
import optparse
email_re = re.compile(r"([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6})")
case_re = re.compile(r"\[([0-9]+)\]", re.UNICODE)
command_re = re.compile("^Set-([a-z]+) *: *(.+)$", re.I + re.UNICODE)
reference_re = re.compile("<.*-openobject-(\\d+)@(.*)>", re.UNICODE)
priorities = {
'1': '1 (Highest)',
'2': '2 (High)',
'3': '3 (Normal)',
'4': '4 (Low)',
'5': '5 (Lowest)',
}
def html2plaintext(html, body_id=None, encoding='utf-8'):
## (c) Fry-IT, www.fry-it.com, 2007
## <peter@fry-it.com>
## download here: http://www.peterbe.com/plog/html2plaintext
""" from an HTML text, convert the HTML to plain text.
If @body_id is provided then this is the tag where the
body (not necessarily <body>) starts.
"""
try:
from BeautifulSoup import BeautifulSoup, SoupStrainer, Comment
except:
return html
urls = []
if body_id is not None:
strainer = SoupStrainer(id=body_id)
else:
strainer = SoupStrainer('body')
soup = BeautifulSoup(html, parseOnlyThese=strainer, fromEncoding=encoding)
for link in soup.findAll('a'):
title = unicode(link)
for url in [x[1] for x in link.attrs if x[0]=='href']:
urls.append(dict(url=url, tag=unicode(link), title=title))
html = unicode(soup)
url_index = []
i = 0
for d in urls:
if d['title'] == d['url'] or 'http://'+d['title'] == d['url']:
html = html.replace(d['tag'], d['url'])
else:
i += 1
html = html.replace(d['tag'], '%s [%s]' % (d['title'], i))
url_index.append(d['url'])
html = html.replace('<strong>', '*').replace('</strong>', '*')
html = html.replace('<b>', '*').replace('</b>', '*')
html = html.replace('<h3>', '*').replace('</h3>', '*')
html = html.replace('<h2>', '**').replace('</h2>', '**')
html = html.replace('<h1>', '**').replace('</h1>', '**')
html = html.replace('<em>', '/').replace('</em>', '/')
# the only line breaks we respect is those of ending tags and
# breaks
html = html.replace('\n', ' ')
html = html.replace('<br>', '\n')
html = html.replace('<tr>', '\n')
html = html.replace('</p>', '\n\n')
html = re.sub('<br\s*/>', '\n', html)
html = html.replace(' ' * 2, ' ')
html = re.sub('<.*?>', ' ', html)
# lstrip all lines
html = '\n'.join([x.lstrip() for x in html.splitlines()])
for i, url in enumerate(url_index):
if i == 0:
html += '\n\n'
html += '[%s] %s\n' % (i+1, url)
return html
import sys
import xmlrpclib
import email
class rpc_proxy(object):
def __init__(self, uid, passwd, host='localhost', port=8069, path='object', dbname='terp'):
self.rpc = xmlrpclib.ServerProxy('http://%s:%s/xmlrpc/%s' % (host, port, path))
def __init__(self, uid, passwd, host='localhost', port=8069, path='object', dbname='terp'):
self.rpc = xmlrpclib.ServerProxy('http://%s:%s/xmlrpc/%s' % (host, port, path), allow_none=True)
self.user_id = uid
self.passwd = passwd
self.dbname = dbname
@@ -130,296 +41,28 @@ class email_parser(object):
def __init__(self, uid, password, model, email, email_default, dbname, host, port):
self.rpc = rpc_proxy(uid, password, host=host, port=port, dbname=dbname)
try:
self.model_id = int(model)
self.model = str(model)
except:
self.model_id = self.rpc('ir.model', 'search', [('model', '=', model)])[0]
self.model = str(model)
self.email = email
self.email_default = email_default
self.canal_id = False
def email_get(self, email_from):
res = email_re.search(email_from)
return res and res.group(1)
def partner_get(self, email):
mail = self.email_get(email)
adr_ids = self.rpc('res.partner.address', 'search', [('email', '=', mail)])
if not adr_ids:
return {}
adr = self.rpc('res.partner.address', 'read', adr_ids, ['partner_id'])
return {
'partner_address_id': adr[0]['id'],
'partner_id': adr[0].get('partner_id', False) and adr[0]['partner_id'][0] or False
}
def _to_decode(self, s, charsets):
for charset in charsets:
if charset:
try:
return s.decode(charset)
except UnicodeError:
pass
return s.decode('latin1')
def _decode_header(self, text):
if text:
text = decode_header(text.replace('\r', ''))
return ''.join(map(lambda x:self._to_decode(x[0], [x[1]]), text or []))
def msg_new(self, msg):
message = self.msg_body_get(msg)
msg_subject = self._decode_header(msg['Subject'])
msg_from = self._decode_header(msg['From'])
msg_to = self._decode_header(msg['To'])
msg_cc = self._decode_header(msg['Cc'] or '')
data = {
'name': msg_subject,
'email_from': msg_from,
'email_cc': msg_cc,
'user_id': False,
'description': message['body'],
'state' : 'draft',
}
data.update(self.partner_get(msg_from))
values = {
'message_ids' : [
(0, 0, {
'res_model' : self.model,
'date' : time.strftime('%Y-%m-%d %H:%M:%S'),
'description' : message['body'],
'email_from' : msg_from,
'email_to' : msg_to,
'name' : 'Receive',
'history' : True,
'user_id' : self.rpc.user_id,
}
)
]
}
oid = self.rpc(self.model, 'create', data)
attachments = message['attachment']
for attach in attachments or []:
data_attach = {
'name': str(attach),
'datas': binascii.b2a_base64(str(attachments[attach])),
'datas_fname': str(attach),
'description': 'Mail attachment',
'res_model': self.model,
'res_id': oid
}
self.rpc('ir.attachment', 'create', data_attach)
return (oid, )
def msg_body_get(self, msg):
message = {
'body' : '',
'attachment' : {},
}
attachment = message['attachment'];
counter = 1;
for part in msg.walk():
if part.get_content_maintype() == 'multipart':
continue
if part.get_content_maintype()=='text':
buf = part.get_payload(decode=True)
if buf:
txt = self._to_decode(buf, part.get_charsets())
txt = re.sub("<\/?(\w)>", '', txt)
if txt and part.get_content_subtype() == 'plain':
message['body'] += txt
elif txt and part.get_content_subtype() == 'html':
message['body'] += html2plaintext(txt)
filename = part.get_filename();
if filename :
attachment[filename] = part.get_payload(decode=True);
elif part.get_content_maintype() in ('application', 'image', 'text'):
filename = part.get_filename();
if not filename :
filename = 'attach_file'+str(counter);
counter += 1;
attachment[filename] = part.get_payload(decode=True);
message['attachment'] = attachment
#end for
return message
def msg_user(self, msg, id):
body = self.msg_body_get(msg)
# handle email body commands (ex: Set-State: Draft)
actions = {}
body_data=''
for line in body['body'].split('\n'):
res = command_re.match(line)
if res:
actions[res.group(1).lower()] = res.group(2).lower()
else:
body_data += line+'\n'
body['body'] = body_data
data = {
# 'description': body['body'],
}
act = 'case_open'
if 'state' in actions:
if actions['state'] in ['draft', 'close', 'cancel', 'open', 'pending']:
act = 'case_' + actions['state']
for k1, k2 in [('cost', 'planned_cost'), ('revenue', 'planned_revenue'), ('probability', 'probability')]:
try:
data[k2] = float(actions[k1])
except:
pass
if 'priority' in actions:
if actions['priority'] in ('1', '2', '3', '4', '5'):
data['priority'] = actions['priority']
if 'partner' in actions:
data['email_from'] = actions['partner'][:128]
if 'user' in actions:
uids = self.rpc('res.users', 'name_search', actions['user'])
if uids:
data['user_id'] = uids[0][0]
self.rpc(self.model, act, [id])
self.rpc(self.model, 'write', [id], data)
attachments = body['attachment']
for attach in attachments or []:
data_attach = {
'name': str(attach),
'datas': binascii.b2a_base64(str(attachments[attach])),
'datas_fname': str(attach),
'description': 'Mail attachment',
'res_model': self.model,
'res_id': id
}
self.rpc('ir.attachment', 'create', data_attach)
self.create_message(id, msg['From'], msg['To'], 'Send', message['body'])
return id
def create_message(self, oid, email_from, email_to, name, body):
"""
This functions creates a message in the thread
> create_message(id, msg['From'], msg['To'], 'Send', message['body'])
"""
values = {
'res_model' : self.model,
'res_id' : oid,
'date' : time.strftime('%Y-%m-%d %H:%M:%S'),
'description' : body,
'email_from' : self._decode_header(email_from),
'email_to' : self._decode_header(email_to),
'name' : name,
'history' : True,
'user_id' : self.rpc.user_id,
}
return self.rpc('mailgate.message', 'create', values)
def msg_send(self, msg, emails, priority=None):
if not emails:
return False
msg['To'] = emails[0]
if len(emails) > 1:
msg['Cc'] = ','.join(emails[1:])
msg['Reply-To'] = self.email
if priority:
msg['X-Priority'] = priorities.get(priority, '3 (Normal)')
s = smtplib.SMTP()
s.connect()
s.sendmail(self.email, emails, msg.as_string())
s.close()
return True
def msg_partner(self, msg, id):
message = self.msg_body_get(msg)
body = message['body']
act = 'case_open'
self.rpc(self.model, act, [id])
attachments = message['attachment']
for attach in attachments or []:
data_attach = {
'name': str(attach),
'datas': binascii.b2a_base64(str(attachments[attach])),
'datas_fname': str(attach),
'description': 'Mail attachment',
'res_model': self.model,
'res_id': id
}
self.rpc('ir.attachment', 'create', data_attach)
self.create_message(id, msg['From'], msg['To'], 'Send', message['body'])
return id
def msg_test(self, msg, case_str):
if not case_str:
return (False, False)
case_id = int(case_str)
emails = self.rpc(self.model, 'emails_get', [case_id])
return (case_id, emails)
def parse(self, msg):
case_str = reference_re.search(msg.get('References', ''))
if case_str:
case_str = case_str.group(1)
else:
case_str = case_re.search(msg.get('Subject', ''))
if case_str:
case_str = case_str.group(1)
logging.info("email: %s -> %s -- %s", msg['From'], self.email, msg['Subject'])
(case_id, emails) = self.msg_test(msg, case_str)
if case_id:
user_email = filter(None, emails['user_email'])[0]
if user_email and self.email_get(user_email) == self.email_get(self._decode_header(msg['From'])):
self.msg_user(msg, case_id)
else:
self.msg_partner(msg, case_id)
else:
case_id = self.msg_new(msg)
subject = self._decode_header(msg['Subject'])
msg['Subject'] = "[%s] %s" % (case_id, subject,)
msg['Message-Id'] = "<%s-openerpcrm-%s@%s>" % (time.time(), case_id, socket.gethostname(),)
logging.info(" case: %r", case_id)
values = self.rpc(self.model, 'emails_get', [case_id])
emails = values[str(thread_id)]
priority = emails.get('piority', [3])[0]
em = emails['user_email'] + emails['email_from'] + emails['email_cc']
emails = map(self.email_get, filter(None, em))
mm = [self._decode_header(msg['From']), self._decode_header(msg['To'])]+self._decode_header(msg.get('Cc', '')).split(',')
msg_mails = map(self.email_get, filter(None, mm))
emails = filter(lambda m: m and m not in msg_mails, emails)
def parse(self, message):
try:
self.msg_send(msg, emails, priority)
except:
if self.email_default:
a = self._decode_header(msg['Subject'])
msg['Subject'] = '[OpenERP-CaseError] ' + a
self.msg_send(msg, self.email_default.split(','))
return case_id, emails
res_id = self.rpc('email.server.tools', 'process_email', self.model, message)
except Exception, e:
res_id = False
# Reply mail
if res_id:
self.rpc('email.server.tools', 'email_send', self.model, res_id, message, self.email, self.email_default)
return res_id
if __name__ == '__main__':
parser = optparse.OptionParser(usage='usage: %prog [options]', version='%prog v1.0')
@@ -442,7 +85,7 @@ if __name__ == '__main__':
parser = email_parser(options.userid, options.password, options.model, options.email, options.default, dbname=options.dbname, host=options.host, port=options.port)
msg_txt = email.message_from_file(sys.stdin)
msg_txt = sys.stdin.read()
parser.parse(msg_txt)
+7 -1
View File
@@ -28,9 +28,15 @@
"document",
"email_template"
],
"author" : "Tiny",
"author" : "OpenERP SA",
"category": 'Generic Modules/Marketing',
"description": """
Allows you to setup leads automation through marketing campaigns. The campaigns
are dynamic and multi-channels. The process:
* Design marketing campaigns that incluces mail templates, reports to print,
miscelleanous actions, etc.
* Define segments that are selections of target people
* Launch your campaign to automate communications.
""",
'website': 'http://www.openerp.com',
'init_xml': [],
@@ -79,7 +79,7 @@ you required for the campaign"),
('start', '=', True)])
if not act_ids :
raise osv.except_osv("Error", "There is no starting activitity in the campaign")
act_ids = act_obj.search(cr, uid, [('id', 'in', actvity_idsf),
act_ids = act_obj.search(cr, uid, [('id', 'in', actvity_ids),
('type', '=', 'email')])
for activity in act_obj.browse(cr, uid, act_ids):
if not activity.email_template_id.enforce_from_account :
@@ -451,7 +451,7 @@
<field name="context">{'group_by': [], 'search_default_todo': 1}</field>
</record>
<menuitem id="menu_action_marketing_campaign_workitem" parent="menu_marketing_campaign" action="action_marketing_campaign_workitem" sequence="30" groups="base.group_extended"/>
<menuitem id="menu_action_marketing_campaign_workitem" parent="menu_marketing_campaign" action="action_marketing_campaign_workitem" sequence="30"/>
<act_window name="All Segments"
res_model="marketing.campaign.segment"
+1 -1
View File
@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:46+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:46+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: mrp
+1 -1
View File
@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: mrp_operations
+1 -1
View File
@@ -15,7 +15,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: olap
+1 -1
View File
@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:46+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:46+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: point_of_sale
+1 -1
View File
@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:46+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:46+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: project
+129 -2
View File
@@ -31,6 +31,9 @@ from crm import crm
from osv import fields,osv,orm
from osv.orm import except_orm
from tools.translate import _
import collections
import binascii
import tools
class project_issue(osv.osv, crm.crm_case):
_name = "project.issue"
@@ -178,8 +181,8 @@ class project_issue(osv.osv, crm.crm_case):
method=True, multi='working_days_open', type="float", store=True),
'working_hours_close': fields.function(_compute_day, string='Working Hours to Close the Issue', \
method=True, multi='working_days_close', type="float", store=True),
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('history', '=', True),('res_model','=',_name)]),
'log_ids': fields.one2many('mailgate.message', 'res_id', 'Logs', domain=[('history', '=', False),('res_model','=',_name)]),
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('history', '=', True),('model','=',_name)]),
'log_ids': fields.one2many('mailgate.message', 'res_id', 'Logs', domain=[('history', '=', False),('model','=',_name)]),
}
def _get_project(self, cr, uid, context):
@@ -299,5 +302,129 @@ class project_issue(osv.osv, crm.crm_case):
self.write(cr, uid, [case.id], data)
return True
def message_new(self, cr, uid, msg, context):
"""
Automatically calls when new email message arrives
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks
"""
mailgate_pool = self.pool.get('email.server.tools')
subject = msg.get('subject')
body = msg.get('body')
msg_from = msg.get('from')
priority = msg.get('priority')
vals = {
'name': subject,
'email_from': msg_from,
'email_cc': msg.get('cc'),
'description': body,
'user_id': False,
}
if msg.get('priority', False):
vals['priority'] = priority
res = mailgate_pool.get_partner(cr, uid, msg.get('from'))
if res:
vals.update(res)
res = self.create(cr, uid, vals, context)
attachents = msg.get('attachments', [])
for attactment in attachents or []:
data_attach = {
'name': attactment,
'datas':binascii.b2a_base64(str(attachents.get(attactment))),
'datas_fname': attactment,
'description': 'Mail attachment',
'res_model': self._name,
'res_id': res,
}
self.pool.get('ir.attachment').create(cr, uid, data_attach)
return res
def message_update(self, cr, uid, ids, vals={}, msg="", default_act='pending', context={}):
"""
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@param ids: List of update mail’s IDs
"""
if isinstance(ids, (str, int, long)):
ids = [ids]
msg_from = msg['from']
vals.update({
'description': msg['body']
})
if msg.get('priority', False):
vals['priority'] = msg.get('priority')
maps = {
'cost':'planned_cost',
'revenue': 'planned_revenue',
'probability':'probability'
}
vls = { }
for line in msg['body'].split('\n'):
line = line.strip()
res = tools.misc.command_re.match(line)
if res and maps.get(res.group(1).lower(), False):
key = maps.get(res.group(1).lower())
vls[key] = res.group(2).lower()
vals.update(vls)
res = self.write(cr, uid, ids, vals)
return res
def emails_get(self, cr, uid, ids, context=None):
"""
Get Emails
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@param ids: List of email’s IDs
@param context: A standard dictionary for contextual values
"""
res = {}
if isinstance(ids, (str, int, long)):
select = [long(ids)]
else:
select = ids
for thread in self.browse(cr, uid, select, context=context):
values = collections.defaultdict(set)
for message in thread.message_ids:
user_email = (message.user_id and message.user_id.address_id and message.user_id.address_id.email) or False
values['user_email'].add(user_email)
values['email_from'].add(message.email_from)
values['email_cc'].add(message.email_cc or False)
values['priority'] = thread.priority
res[thread.id] = dict((key,list(values[key])) for key, value in values.iteritems())
return res
def msg_send(self, cr, uid, id, *args, **argv):
""" Send The Message
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@param ids: List of email’s IDs
@param *args: Return Tuple Value
@param **args: Return Dictionary of Keyword Value
"""
return True
project_issue()
+1 -1
View File
@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: project_timesheet
+1 -1
View File
@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:46+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:46+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: report_analytic_planning
+1 -1
View File
@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: report_task
+1 -1
View File
@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: sale
+60 -60
View File
@@ -50,41 +50,41 @@
<field name="type">search</field>
<field name="arch" type="xml">
<search string="Sales Analysis">
<group>
<filter icon="terp-go-year" string=" 365 Days "
domain="[('date','&lt;=', time.strftime('%%Y-%%m-%%d')),('date','&gt;',(datetime.date.today()-datetime.timedelta(days=365)).strftime('%%Y-%%m-%%d'))]"
help="Tasks performed in last 365 days"/>
<filter icon="terp-go-month" string=" 30 Days "
name="month"
domain="[('date','&lt;=', time.strftime('%%Y-%%m-%%d')), ('date','&gt;',(datetime.date.today()-datetime.timedelta(days=30)).strftime('%%Y-%%m-%%d'))]"
help="Tasks performed in last 30 days"/>
<filter icon="terp-go-week"
string=" 7 Days "
separator="1"
domain="[('date','&lt;=', time.strftime('%%Y-%%m-%%d')), ('date','&gt;',(datetime.date.today()-datetime.timedelta(days=7)).strftime('%%Y-%%m-%%d'))]"
help="Tasks during last 7 days"/>
<separator orientation="vertical"/>
<filter icon="terp-document-new"
string="Quotations"
domain="[('state','=','draft')]"/>
<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"/>
<group>
<filter icon="terp-go-year" string=" 365 Days "
domain="[('date','&lt;=', time.strftime('%%Y-%%m-%%d')),('date','&gt;',(datetime.date.today()-datetime.timedelta(days=365)).strftime('%%Y-%%m-%%d'))]"
help="Tasks performed in last 365 days"/>
<filter icon="terp-go-month" string=" 30 Days "
name="month"
domain="[('date','&lt;=', time.strftime('%%Y-%%m-%%d')), ('date','&gt;',(datetime.date.today()-datetime.timedelta(days=30)).strftime('%%Y-%%m-%%d'))]"
help="Tasks performed in last 30 days"/>
<filter icon="terp-go-week"
string=" 7 Days "
separator="1"
domain="[('date','&lt;=', time.strftime('%%Y-%%m-%%d')), ('date','&gt;',(datetime.date.today()-datetime.timedelta(days=7)).strftime('%%Y-%%m-%%d'))]"
help="Tasks during last 7 days"/>
<separator orientation="vertical"/>
<filter icon="terp-document-new"
string="Quotations"
domain="[('state','=','draft')]"/>
<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-personal"
<field name="user_id" widget="selection">
<filter icon="terp-personal"
string="My Sales"
help="My Sales"
domain="[('user_id','=',uid)]"/>
</field>
</group>
<newline/>
</field>
</group>
<newline/>
<group expand="1" string="Group By..." colspan="10" col="12">
<filter string="Salesman" icon="terp-personal" name="User" context="{'group_by':'user_id'}"/>
<filter string="Partner" icon="terp-personal" context="{'group_by':'partner_id'}"/>
@@ -103,7 +103,7 @@
<filter string="Month" icon="terp-go-month" context="{'group_by':'month'}"/>
<filter string="Year" icon="terp-go-year" context="{'group_by':'year'}"/>
</group>
<newline/>
<newline/>
<group expand="0" string="Extended options..." groups="base.group_extended">
<field name="date"/>
<field name="date_confirm"/>
@@ -171,7 +171,7 @@
<field name="domain">[('state','in',('manual','progress')),('date','&lt;=', time.strftime('%Y-%m-%d')),('date','&gt;',(datetime.date.today()-datetime.timedelta(days=90)).strftime('%Y-%m-%d'))]</field>
<field name="view_id" ref="view_sales_by_partner_graph"/>
</record>
<record id="open_view_sales_by_partner_graph" model="ir.actions.act_window.view">
<record id="open_view_sales_by_partner_graph" model="ir.actions.act_window.view">
<field eval="1" name="sequence"/>
<field name="view_mode">graph</field>
<field name="view_id" ref="view_sales_by_partner_graph"/>
@@ -233,7 +233,7 @@
<field name="model">sale.report</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Sold products and Total Price">
<tree string="Sales by Products">
<field name="product_id"/>
<field name="price_total"/>
</tree>
@@ -245,7 +245,7 @@
<field name="model">sale.report</field>
<field name="type">graph</field>
<field name="arch" type="xml">
<graph string="Sold products and Total Price" type="bar">
<graph string="Sales by Products" type="bar">
<field name="product_id" />
<field name="price_total" operator="+"/>
</graph>
@@ -253,11 +253,11 @@
</record>
<record id="action_sales_product_total_price" model="ir.actions.act_window">
<field name="name">Sold product and Total Price</field>
<field name="name">Sales by Products</field>
<field name="res_model">sale.report</field>
<field name="view_type">form</field>
<field name="view_mode">graph,tree</field>
<field name="domain">[('state','in',('manual','progress','done')),('date','&lt;=', time.strftime('%Y-%m-%d')),('date','&gt;',(datetime.date.today()-datetime.timedelta(days=90)).strftime('%Y-%m-%d'))]</field>
<field name="domain">[('state','in',('manual','progress','done')),('date','&gt;',(datetime.date.today()-datetime.timedelta(days=90)).strftime('%Y-%m-%d'))]</field>
<field name="view_id" ref="view_sales_product_total_price_graph"/>
</record>
<record id="open_view_sales_product_total_price_graph" model="ir.actions.act_window.view">
@@ -273,29 +273,29 @@
<field name="act_window_id" ref="action_sales_product_total_price"/>
</record>
<record id="view_sales_by_month_tree" model="ir.ui.view">
<field name="name">view.sales.by.month.tree</field>
<field name="model">sale.report</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Total Sales By Month">
<field name="month" />
<field name="price_total" />
</tree>
</field>
</record>
<record id="action_view_sales_by_month" model="ir.actions.act_window">
<field name="name">Sales By Month</field>
<field name="res_model">sale.report</field>
<field name="view_type">form</field>
<field name="view_mode">tree</field>
<field name="domain">[('state','in',('manual','progress','done')),('year','=', time.strftime('%Y'))]</field>
<field name="context">{'group_by_no_leaf':1,'group_by':['month']}</field>
<field name="view_id" ref="view_sales_by_month_tree"/>
<field name="search_view_id" ref="view_order_product_search"/>
</record>
<record id="view_sales_by_month_tree" model="ir.ui.view">
<field name="name">view.sales.by.month.tree</field>
<field name="model">sale.report</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Sales By Month">
<field name="month" />
<field name="product_id" />
<field name="price_total" />
</tree>
</field>
</record>
<record id="action_view_sales_by_month" model="ir.actions.act_window">
<field name="name">Sales By Month</field>
<field name="res_model">sale.report</field>
<field name="view_type">form</field>
<field name="view_mode">tree,graph</field>
<field name="domain">[('state','in',('manual','progress','done')),('year','=', time.strftime('%Y'))]</field>
<field name="context">{'group_by_no_leaf':1,'group_by':['month','product_id']}</field>
<field name="view_id" ref="view_sales_by_month_tree"/>
</record>
<record id="view_top_quotations_tree" model="ir.ui.view">
<record id="view_top_quotations_tree" model="ir.ui.view">
<field name="name">sale.top.quotations.tree</field>
<field name="model">sale.order</field>
<field name="type">tree</field>
@@ -317,7 +317,7 @@
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('state','=','draft')]</field>
<field name="view_id" ref="view_top_quotations_tree"/>
<field name="view_id" ref="view_top_quotations_tree"/>
</record>
</data>
+1 -1
View File
@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:46+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:46+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: stock
+4 -4
View File
@@ -535,10 +535,10 @@ class stock_picking(osv.osv):
seq_obj_name = 'stock.picking.' + vals['type']
vals['name'] = self.pool.get('ir.sequence').get(cr, user, seq_obj_name)
type_list = {
'out':_('Packing List'),
'out':_('Picking List'),
'in':_('Reception'),
'internal': _('Internal picking'),
'delivery': _('Delivery order')
'internal': _('Internal Picking'),
'delivery': _('Delivery Order')
}
new_id = super(stock_picking, self).create(cr, user, vals, context)
if not vals.get('auto_picking', False):
@@ -709,7 +709,7 @@ class stock_picking(osv.osv):
"""
for pick in self.browse(cr, uid, ids, context=context):
type_list = {
'out':'Packing List',
'out':'Picking List',
'in':'Reception',
'internal': 'Internal picking',
'delivery': 'Delivery order'
+1 -1
View File
@@ -1132,7 +1132,7 @@
</record>
<record id="action_picking_tree" model="ir.actions.act_window">
<field name="name">Outgoing Packings</field>
<field name="name">Outgoing Orders</field>
<field name="res_model">stock.picking</field>
<field name="type">ir.actions.act_window</field>
<field name="view_type">form</field>
+1 -1
View File
@@ -14,7 +14,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-06-24 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-06-25 03:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: stock_location
@@ -17,6 +17,9 @@
<xpath expr="//label[@string='description']" position="attributes">
<attribute name="string">This module is required for the thuderbird plug-in to work properly.This allows you to select an object that you had like to add to your email and its attachments. You can select a partner, a task, a project, an analytical account, or any other object and attach selected mail as .eml file in attachment of selected record.</attribute>
</xpath>
<xpath expr="//button[@string='Install Modules']" position="attributes">
<attribute name="string">Configure</attribute>
</xpath>
<xpath expr='//separator[@string="vsep"]' position='attributes'>
<attribute name='string'></attribute>
<attribute name='rowspan'>15</attribute>