diff --git a/addons/account/test/account_supplier_invoice.yml b/addons/account/test/account_supplier_invoice.yml
index 9c5ce2dea3e..02c3d367050 100644
--- a/addons/account/test/account_supplier_invoice.yml
+++ b/addons/account/test/account_supplier_invoice.yml
@@ -21,7 +21,7 @@
-
I create a supplier invoice
-
- !record {model: account.invoice, id: account_invoice_supplier0}:
+ !record {model: account.invoice, id: account_invoice_supplier0, view: invoice_supplier_form}:
account_id: account.a_pay
check_total: 3000.0
company_id: base.main_company
diff --git a/addons/account/wizard/account_invoice_refund.py b/addons/account/wizard/account_invoice_refund.py
index b7d278b8849..38a22baa9f1 100644
--- a/addons/account/wizard/account_invoice_refund.py
+++ b/addons/account/wizard/account_invoice_refund.py
@@ -32,11 +32,11 @@ class account_invoice_refund(osv.osv_memory):
_name = "account.invoice.refund"
_description = "Invoice Refund"
_columns = {
- 'date': fields.date('Operation Date', help='This date will be used as the invoice date for credit note and period will be chosen accordingly!'),
+ 'date': fields.date('Date', help='This date will be used as the invoice date for credit note and period will be chosen accordingly!'),
'period': fields.many2one('account.period', 'Force period'),
'journal_id': fields.many2one('account.journal', 'Refund Journal', help='You can select here the journal to use for the credit note that will be created. If you leave that field empty, it will use the same journal as the current invoice.'),
- 'description': fields.char('Description', size=128, required=True),
- 'filter_refund': fields.selection([('refund', 'Create a draft refund'), ('cancel', 'Cancel: create credit note and reconcile'),('modify', 'Modify: create credit note, reconcile and create a new draft invoice')], "Refund Method", required=True, help='Credit note base on this type. You can not Modify and Cancel if the invoice is already reconciled'),
+ 'description': fields.char('Reason', size=128, required=True),
+ 'filter_refund': fields.selection([('refund', 'Create a draft credit note'), ('cancel', 'Cancel: create credit note and reconcile'),('modify', 'Modify: create credit note, reconcile and create a new draft invoice')], "Refund Method", required=True, help='Credit note base on this type. You can not Modify and Cancel if the invoice is already reconciled'),
}
def _get_journal(self, cr, uid, context=None):
diff --git a/addons/account/wizard/account_invoice_refund_view.xml b/addons/account/wizard/account_invoice_refund_view.xml
index 78a9b085bf1..3945a6f57e6 100644
--- a/addons/account/wizard/account_invoice_refund_view.xml
+++ b/addons/account/wizard/account_invoice_refund_view.xml
@@ -7,19 +7,40 @@
account.invoice.refund
+
account.voucher.form
account.voucher
diff --git a/addons/account_voucher/invoice.py b/addons/account_voucher/invoice.py
index 14b725cbeca..91ba438756e 100644
--- a/addons/account_voucher/invoice.py
+++ b/addons/account_voucher/invoice.py
@@ -27,11 +27,12 @@ class invoice(osv.osv):
def invoice_pay_customer(self, cr, uid, ids, context=None):
if not ids: return []
+ mod,modid = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account_voucher', 'view_vendor_receipt_dialog_form')
inv = self.browse(cr, uid, ids[0], context=context)
return {
'name':_("Pay Invoice"),
'view_mode': 'form',
- 'view_id': False,
+ 'view_id': modid,
'view_type': 'form',
'res_model': 'account.voucher',
'type': 'ir.actions.act_window',
@@ -41,13 +42,13 @@ class invoice(osv.osv):
'context': {
'default_partner_id': inv.partner_id.id,
'default_amount': inv.type in ('out_refund', 'in_refund') and -inv.residual or inv.residual,
- 'default_name':inv.name,
+ 'default_number':inv.name,
'close_after_process': True,
- 'invoice_type':inv.type,
- 'invoice_id':inv.id,
+ 'invoice_type': inv.type,
+ 'invoice_id': inv.id,
'default_type': inv.type in ('out_invoice','out_refund') and 'receipt' or 'payment',
'type': inv.type in ('out_invoice','out_refund') and 'receipt' or 'payment'
- }
+ }
}
invoice()
diff --git a/addons/account_voucher/report/__init__.py b/addons/account_voucher/report/__init__.py
index caeb155adbe..862843352a8 100644
--- a/addons/account_voucher/report/__init__.py
+++ b/addons/account_voucher/report/__init__.py
@@ -23,4 +23,4 @@ import account_voucher
import account_voucher_print
import account_voucher_sales_receipt
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/account_voucher/test/account_voucher.yml b/addons/account_voucher/test/account_voucher.yml
index 2ea6c0b7890..f8e20f496e5 100644
--- a/addons/account_voucher/test/account_voucher.yml
+++ b/addons/account_voucher/test/account_voucher.yml
@@ -1,7 +1,8 @@
-
In order to check account voucher module in OpenERP I create a customer voucher
-
- !record {model: account.voucher, id: account_voucher_voucherforaxelor0}:
+ !record {model: account.voucher, id: account_voucher_voucherforaxelor0, view: view_sale_receipt_form}:
+ type: sale
account_id: account.cash
amount: 1000.0
company_id: base.main_company
@@ -47,7 +48,8 @@
-
Now I create a Vendor Voucher
-
- !record {model: account.voucher, id: account_voucher_voucheraxelor0, view: False}:
+ !record {model: account.voucher, id: account_voucher_voucheraxelor0, view: view_voucher_filter_vendor}:
+ type: purchase
account_id: account.cash
amount: 1000.0
company_id: base.main_company
diff --git a/addons/account_voucher/test/account_voucher_report.yml b/addons/account_voucher/test/account_voucher_report.yml
index 3996e0c27e4..60dc4103553 100644
--- a/addons/account_voucher/test/account_voucher_report.yml
+++ b/addons/account_voucher/test/account_voucher_report.yml
@@ -1,7 +1,8 @@
-
Demo for Account Voucher
-
- !record {model: account.voucher, id: account_voucher_voucheraxelor0again}:
+ !record {model: account.voucher, id: account_voucher_voucheraxelor0again, view: view_sale_receipt_form}:
+ type: sale
account_id: account.cash
company_id: base.main_company
journal_id: account.bank_journal
diff --git a/addons/account_voucher/test/case1_usd_usd.yml b/addons/account_voucher/test/case1_usd_usd.yml
index b706e6f0644..300d565f229 100644
--- a/addons/account_voucher/test/case1_usd_usd.yml
+++ b/addons/account_voucher/test/case1_usd_usd.yml
@@ -216,6 +216,10 @@
assert move_line.credit == 63.00, "Debtor account has wrong entry."
elif move_line.amount_currency == 10.00:
assert move_line.debit == 9.00, "Writeoff amount is wrong."
+ elif move_line.amount_currency == 240.00:
+ assert move_line.debit == 216.00, "Bank entry is wrong."
+ else:
+ assert False, "Unrecognized journal entry"
-
I check the residual amount of Invoice1, should be 20 in amount_currency
-
@@ -237,7 +241,7 @@
-
On the first April, I create the second voucher of payment with values 45 USD, journal USD,
-
- !record {model: account.voucher, id: account_voucher_2_case1}:
+ !record {model: account.voucher, id: account_voucher_2_case1, view: view_vendor_receipt_form}:
account_id: account.cash
amount: 45.0
company_id: base.main_company
@@ -323,8 +327,16 @@
assert move_line.debit == 4.75, "Writeoff amount is wrong."
elif move_line.debit == 11.5 and move_line.account_id.reconcile:
assert move_line.amount_currency == 0.0 and move_line.reconcile_id.id == reconcile_a, "Exchange difference entry for the invoice of 100$ is wrong"
+ elif move_line.credit == 11.5:
+ assert move_line.amount_currency == 0.0
elif move_line.debit == 31.0 and move_line.account_id.reconcile:
assert move_line.amount_currency == 0.0 and move_line.reconcile_id.id == reconcile_b, "Exchange difference entry for the invoice of 200$ is wrong"
+ elif move_line.credit == 31.0:
+ assert move_line.amount_currency == 0.0
+ elif move_line.amount_currency == 45.00:
+ assert move_line.debit == 42.75, "Bank entry is wrong."
+ else:
+ assert False, "Unrecognized journal entry"
-
I check the residual amount of Invoice1, should be 0 in residual currency and 0 in amount_residual and paid
-
diff --git a/addons/account_voucher/test/case4_cad_chf.yml b/addons/account_voucher/test/case4_cad_chf.yml
index a78669c95ef..a2b252497cd 100644
--- a/addons/account_voucher/test/case4_cad_chf.yml
+++ b/addons/account_voucher/test/case4_cad_chf.yml
@@ -164,7 +164,7 @@
-
I check that my currency rate difference is correct. 0 in debit with no amount_currency
-
- I check that my writeoff is correct. 11.05 credit and 13.26 amount_currency
+ I check that my writeoff is correct. 11.05 credit and -13.26 amount_currency
-
!python {model: account.voucher}: |
voucher = self.search(cr, uid, [('name', '=', 'First payment: Case 4'), ('partner_id', '=', ref('base.res_partner_19'))])
@@ -179,7 +179,7 @@
elif move_line.debit == 0.00 and move_line.credit == 0.00:
assert move_line.amount_currency == 0.00, "Incorrect Currency Difference."
elif move_line.credit == 10.61:
- assert move_line.amount_currency == 13.26, "Writeoff amount is wrong."
+ assert move_line.amount_currency == -13.26, "Writeoff amount is wrong."
else:
assert False, "Wrong entry"
-
diff --git a/addons/account_voucher/test/sales_receipt.yml b/addons/account_voucher/test/sales_receipt.yml
index f39d784bd42..7cd82eecaff 100644
--- a/addons/account_voucher/test/sales_receipt.yml
+++ b/addons/account_voucher/test/sales_receipt.yml
@@ -1,7 +1,7 @@
-
Creating a Voucher Receipt for partner Seagate with amount 30000.0
-
- !record {model: account.voucher, id: account_voucher_seagate_0}:
+ !record {model: account.voucher, id: account_voucher_seagate_0, view: view_sale_receipt_form}:
account_id: account.a_recv
amount: 30000.0
company_id: base.main_company
diff --git a/addons/account_voucher/voucher_payment_receipt_view.xml b/addons/account_voucher/voucher_payment_receipt_view.xml
index c41ed6d5577..78b76e5c9b7 100644
--- a/addons/account_voucher/voucher_payment_receipt_view.xml
+++ b/addons/account_voucher/voucher_payment_receipt_view.xml
@@ -71,6 +71,7 @@
+
+
+
+
+
+ account.voucher.receipt.dialog.form
+ account.voucher
+ 30
+
+
+
+
+
+
account.voucher.receipt.form
account.voucher
@@ -293,7 +402,7 @@
-
+
@@ -325,9 +434,9 @@
-
+
+
+
@@ -80,9 +81,9 @@
+
-
@@ -235,6 +236,7 @@
widget="selection"
on_change="onchange_journal(journal_id, line_dr_ids, tax_id, partner_id, date, amount, type, company_id, context)"
groups="account.group_account_user"/>
+
diff --git a/addons/analytic/__openerp__.py b/addons/analytic/__openerp__.py
index 10762a1d2be..6227cd369d3 100644
--- a/addons/analytic/__openerp__.py
+++ b/addons/analytic/__openerp__.py
@@ -38,11 +38,11 @@ that have no counterpart in the general financial accounts.
'security/analytic_security.xml',
'security/ir.model.access.csv',
'analytic_sequence.xml',
- 'analytic_view.xml'
+ 'analytic_view.xml',
+ 'analytic_data.xml'
],
'demo': [],
'installable': True,
'auto_install': False,
- 'certificate' : '00462253285027988541',
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/analytic/analytic.py b/addons/analytic/analytic.py
index 269bf24ed61..1ce483a26cd 100644
--- a/addons/analytic/analytic.py
+++ b/addons/analytic/analytic.py
@@ -125,7 +125,8 @@ class account_analytic_account(osv.osv):
if account.company_id:
if account.company_id.currency_id.id != value:
raise osv.except_osv(_('Error!'), _("If you set a company, the currency selected has to be the same as it's currency. \nYou can remove the company belonging, and thus change the currency, only on analytic account of type 'view'. This can be really usefull for consolidation purposes of several companies charts with different currencies, for example."))
- return cr.execute("""update account_analytic_account set currency_id=%s where id=%s""", (value, account.id, ))
+ if value:
+ return cr.execute("""update account_analytic_account set currency_id=%s where id=%s""", (value, account.id, ))
def _currency(self, cr, uid, ids, field_name, arg, context=None):
result = {}
@@ -163,7 +164,7 @@ class account_analytic_account(osv.osv):
'date': fields.date('Date End', select=True),
'company_id': fields.many2one('res.company', 'Company', required=False), #not required because we want to allow different companies to use the same chart of account, except for leaf accounts.
'state': fields.selection([('template', 'Template'),('draft','New'),('open','In Progress'), ('cancelled', 'Cancelled'),('pending','To Renew'),('close','Closed')], 'Status', required=True,),
- 'currency_id': fields.function(_currency, fnct_inv=_set_company_currency,
+ 'currency_id': fields.function(_currency, fnct_inv=_set_company_currency, #the currency_id field is readonly except if it's a view account and if there is no company
store = {
'res.company': (_get_analytic_account, ['currency_id'], 10),
}, string='Currency', type='many2one', relation='res.currency'),
@@ -284,7 +285,8 @@ class account_analytic_account(osv.osv):
def create_send_note(self, cr, uid, ids, context=None):
for obj in self.browse(cr, uid, ids, context=context):
- self.message_post(cr, uid, [obj.id], body=_("Contract for %s has been created.") % (obj.partner_id.name), context=context)
+ self.message_post(cr, uid, [obj.id], body=_("Contract for %s has been created.") % (obj.partner_id.name),
+ subtype="analytic.mt_account_status", context=context)
account_analytic_account()
diff --git a/addons/analytic/analytic_data.xml b/addons/analytic/analytic_data.xml
new file mode 100644
index 00000000000..67940fb2063
--- /dev/null
+++ b/addons/analytic/analytic_data.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ Status Change
+ account.analytic.account
+
+
+
+
diff --git a/addons/analytic/analytic_view.xml b/addons/analytic/analytic_view.xml
index 51f5428002f..0bb009e72b0 100644
--- a/addons/analytic/analytic_view.xml
+++ b/addons/analytic/analytic_view.xml
@@ -24,6 +24,7 @@
+
diff --git a/addons/analytic_user_function/__openerp__.py b/addons/analytic_user_function/__openerp__.py
index f23296012d2..d788342648c 100644
--- a/addons/analytic_user_function/__openerp__.py
+++ b/addons/analytic_user_function/__openerp__.py
@@ -45,6 +45,5 @@ compatible with older configurations.
'demo': [],
'installable': True,
'auto_install': False,
- 'certificate': '0082277138269',
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/analytic_user_function/i18n/nl_BE.po b/addons/analytic_user_function/i18n/nl_BE.po
index 979cef10b2c..04943a48f1d 100644
--- a/addons/analytic_user_function/i18n/nl_BE.po
+++ b/addons/analytic_user_function/i18n/nl_BE.po
@@ -1,63 +1,86 @@
-# Translation of OpenERP Server.
-# This file contains the translation of the following modules:
-# * analytic_user_function
+# Dutch (Belgium) translation for openobject-addons
+# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
+# This file is distributed under the same license as the openobject-addons package.
+# FIRST AUTHOR , 2012.
#
msgid ""
msgstr ""
-"Project-Id-Version: OpenERP Server 6.0dev\n"
-"Report-Msgid-Bugs-To: support@openerp.com\n"
-"POT-Creation-Date: 2009-08-28 15:34:14+0000\n"
-"PO-Revision-Date: 2009-08-28 15:34:14+0000\n"
-"Last-Translator: <>\n"
-"Language-Team: \n"
+"Project-Id-Version: openobject-addons\n"
+"Report-Msgid-Bugs-To: FULL NAME \n"
+"POT-Creation-Date: 2012-02-08 00:35+0000\n"
+"PO-Revision-Date: 2012-10-02 07:35+0000\n"
+"Last-Translator: Els Van Vossel (Agaplan) \n"
+"Language-Team: Dutch (Belgium) \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: \n"
-"Plural-Forms: \n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2012-10-03 05:09+0000\n"
+"X-Generator: Launchpad (build 16061)\n"
#. module: analytic_user_function
-#: constraint:ir.ui.view:0
-msgid "Invalid XML for View Architecture!"
-msgstr ""
+#: field:analytic.user.funct.grid,product_id:0
+msgid "Product"
+msgstr "Product"
#. module: analytic_user_function
#: model:ir.model,name:analytic_user_function.model_analytic_user_funct_grid
msgid "Relation table between users and products on a analytic account"
msgstr ""
+"Relatietabel tussen gebruikers en producten van een analytische rekening"
#. module: analytic_user_function
-#: field:analytic_user_funct_grid,product_id:0
-msgid "Product"
-msgstr ""
+#: constraint:hr.analytic.timesheet:0
+msgid "You cannot modify an entry in a Confirmed/Done timesheet !."
+msgstr "In een bevestigde/afgesloten uurrooster kunt u geen regels wijzigen."
#. module: analytic_user_function
-#: field:analytic_user_funct_grid,account_id:0
+#: field:analytic.user.funct.grid,account_id:0
+#: model:ir.model,name:analytic_user_function.model_account_analytic_account
msgid "Analytic Account"
-msgstr ""
+msgstr "Analytische rekening"
#. module: analytic_user_function
#: view:account.analytic.account:0
#: field:account.analytic.account,user_product_ids:0
msgid "Users/Products Rel."
-msgstr ""
+msgstr "Rel. gebruikers/producten"
#. module: analytic_user_function
-#: field:analytic_user_funct_grid,user_id:0
+#: field:analytic.user.funct.grid,user_id:0
msgid "User"
+msgstr "Gebruiker"
+
+#. module: analytic_user_function
+#: code:addons/analytic_user_function/analytic_user_function.py:96
+#: code:addons/analytic_user_function/analytic_user_function.py:131
+#, python-format
+msgid "There is no expense account define for this product: \"%s\" (id:%d)"
msgstr ""
+"Er is geen kostenrekening gedefinieerd voor dit product: \"%s\" (id:%d)"
#. module: analytic_user_function
-#: constraint:ir.model:0
-msgid "The Object name must start with x_ and not contain any special character !"
-msgstr "De objectnaam moet beginnen met x_ en mag geen speciale karakters bevatten !"
+#: code:addons/analytic_user_function/analytic_user_function.py:95
+#: code:addons/analytic_user_function/analytic_user_function.py:130
+#, python-format
+msgid "Error !"
+msgstr "Fout"
#. module: analytic_user_function
-#: model:ir.module.module,shortdesc:analytic_user_function.module_meta_information
-msgid "Analytic User Function"
-msgstr ""
+#: constraint:account.analytic.account:0
+msgid "Error! You can not create recursive analytic accounts."
+msgstr "U kunt niet dezelfde analytische rekeningen maken."
#. module: analytic_user_function
-#: view:analytic_user_funct_grid:0
+#: model:ir.model,name:analytic_user_function.model_hr_analytic_timesheet
+msgid "Timesheet Line"
+msgstr "Uurroosterlijn"
+
+#. module: analytic_user_function
+#: view:analytic.user.funct.grid:0
msgid "User's Product for this Analytic Account"
-msgstr ""
+msgstr "Product van gebruiker voor deze analytische rekening"
+#~ msgid ""
+#~ "The Object name must start with x_ and not contain any special character !"
+#~ msgstr ""
+#~ "De objectnaam moet beginnen met x_ en mag geen speciale karakters bevatten !"
diff --git a/addons/anonymization/__openerp__.py b/addons/anonymization/__openerp__.py
index 865fb19ea07..ac63d0e01f1 100644
--- a/addons/anonymization/__openerp__.py
+++ b/addons/anonymization/__openerp__.py
@@ -48,7 +48,6 @@ anonymization process to recover your previous data.
],
'installable': True,
'auto_install': False,
- 'certificate': '00719010980872226045',
'images': ['images/anonymization1.jpeg','images/anonymization2.jpeg','images/anonymization3.jpeg'],
}
diff --git a/addons/anonymization/anonymization.py b/addons/anonymization/anonymization.py
index 43d198b27e2..8834645c460 100644
--- a/addons/anonymization/anonymization.py
+++ b/addons/anonymization/anonymization.py
@@ -363,7 +363,7 @@ class ir_model_fields_anonymize_wizard(osv.osv_memory):
})
raise osv.except_osv(error_type, error_msg)
- def anonymize_database(self,cr, uid, ids, context=None):
+ def anonymize_database(self, cr, uid, ids, context=None):
"""Sets the 'anonymized' state to defined fields"""
# create a new history record:
@@ -498,7 +498,7 @@ class ir_model_fields_anonymize_wizard(osv.osv_memory):
'target':'new',
}
- def reverse_anonymize_database(self,cr, uid, ids, context=None):
+ def reverse_anonymize_database(self, cr, uid, ids, context=None):
"""Set the 'clear' state to defined fields"""
ir_model_fields_anonymization_model = self.pool.get('ir.model.fields.anonymization')
diff --git a/addons/association/__openerp__.py b/addons/association/__openerp__.py
index 665968c6613..35b520e06f8 100644
--- a/addons/association/__openerp__.py
+++ b/addons/association/__openerp__.py
@@ -37,7 +37,6 @@ membership products (schemes).
'demo': [],
'installable': True,
'auto_install': False,
- 'certificate': '0078696047261',
'images': ['images/association1.jpeg'],
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/audittrail/__openerp__.py b/addons/audittrail/__openerp__.py
index 3ba8c59a2f3..41958c84f66 100644
--- a/addons/audittrail/__openerp__.py
+++ b/addons/audittrail/__openerp__.py
@@ -42,7 +42,6 @@ and can check logs.
'demo': ['audittrail_demo.xml'],
'installable': True,
'auto_install': False,
- 'certificate': '0062572348749',
'images': ['images/audittrail1.jpeg','images/audittrail2.jpeg','images/audittrail3.jpeg'],
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/audittrail/audittrail.py b/addons/audittrail/audittrail.py
index 3dff7c1cb00..9232a696da8 100644
--- a/addons/audittrail/audittrail.py
+++ b/addons/audittrail/audittrail.py
@@ -202,7 +202,7 @@ class audittrail_objects_proxy(object_proxy):
res = value
return res
- def create_log_line(self, cr, uid, log_id, model, lines=[]):
+ def create_log_line(self, cr, uid, log_id, model, lines=None):
"""
Creates lines for changed fields with its old and new values
@@ -211,6 +211,8 @@ class audittrail_objects_proxy(object_proxy):
@param model: Object which values are being changed
@param lines: List of values for line is to be created
"""
+ if lines is None:
+ lines = []
pool = pooler.get_pool(cr.dbname)
obj_pool = pool.get(model.model)
model_pool = pool.get('ir.model')
@@ -349,9 +351,9 @@ class audittrail_objects_proxy(object_proxy):
data[(model.id, resource_id)] = {'text':values_text, 'value': values}
return data
- def prepare_audittrail_log_line(self, cr, uid, pool, model, resource_id, method, old_values, new_values, field_list=[]):
+ def prepare_audittrail_log_line(self, cr, uid, pool, model, resource_id, method, old_values, new_values, field_list=None):
"""
- This function compares the old data (i.e before the method was executed) and the new data
+ This function compares the old data (i.e before the method was executed) and the new data
(after the method was executed) and returns a structure with all the needed information to
log those differences.
@@ -375,9 +377,11 @@ class audittrail_objects_proxy(object_proxy):
(model.id, resource_id): []
}
- The reason why the structure returned is build as above is because when modifying an existing
+ The reason why the structure returned is build as above is because when modifying an existing
record, we may have to log a change done in a x2many field of that object
"""
+ if field_list is None:
+ field_list = []
key = (model.id, resource_id)
lines = {
key: []
@@ -416,7 +420,7 @@ class audittrail_objects_proxy(object_proxy):
lines[key].append(data)
return lines
- def process_data(self, cr, uid, pool, res_ids, model, method, old_values={}, new_values={}, field_list=[]):
+ def process_data(self, cr, uid, pool, res_ids, model, method, old_values=None, new_values=None, field_list=None):
"""
This function processes and iterates recursively to log the difference between the old
data (i.e before the method was executed) and the new data and creates audittrail log
@@ -435,6 +439,8 @@ class audittrail_objects_proxy(object_proxy):
on specific fields only.
:return: True
"""
+ if field_list is None:
+ field_list = []
# loop on all the given ids
for res_id in res_ids:
# compare old and new values and get audittrail log lines accordingly
@@ -442,11 +448,13 @@ class audittrail_objects_proxy(object_proxy):
# if at least one modification has been found
for model_id, resource_id in lines:
+ name = pool.get(model.model).name_get(cr, uid, [resource_id])[0][1]
vals = {
'method': method,
'object_id': model_id,
'user_id': uid,
'res_id': resource_id,
+ 'name': name,
}
if (model_id, resource_id) not in old_values and method not in ('copy', 'read'):
# the resource was not existing so we are forcing the method to 'create'
@@ -484,7 +492,7 @@ class audittrail_objects_proxy(object_proxy):
if len(rule['user_id']) == 0 or uid in rule['user_id']:
if rule.get('log_'+method,0):
return True
- elif method not in ('default_get','read','fields_view_get','fields_get','search','search_count','name_search','name_get','get','request_get', 'get_sc', 'unlink', 'write', 'create'):
+ elif method not in ('default_get','read','fields_view_get','fields_get','search','search_count','name_search','name_get','get','request_get', 'get_sc', 'unlink', 'write', 'create', 'read_group', 'import_data'):
if rule['log_action']:
return True
diff --git a/addons/auth_ldap/__openerp__.py b/addons/auth_ldap/__openerp__.py
index aa7c93e4146..844f6d9fa84 100644
--- a/addons/auth_ldap/__openerp__.py
+++ b/addons/auth_ldap/__openerp__.py
@@ -107,7 +107,6 @@ authentication if installed at the same time.
],
'auto_install': False,
'installable': True,
- 'certificate' : '001141446349334700221',
'external_dependencies' : {
'python' : ['ldap'],
}
diff --git a/addons/auth_ldap/users_ldap.py b/addons/auth_ldap/users_ldap.py
index 47fc41c3645..c2c0ac557bf 100644
--- a/addons/auth_ldap/users_ldap.py
+++ b/addons/auth_ldap/users_ldap.py
@@ -180,8 +180,8 @@ class CompanyLDAP(osv.osv):
"""
user_id = False
- login = tools.ustr(login)
- cr.execute("SELECT id, active FROM res_users WHERE login=%s", (login,))
+ login = tools.ustr(login.lower())
+ cr.execute("SELECT id, active FROM res_users WHERE lower(login)=%s", (login,))
res = cr.fetchone()
if res:
if res[1]:
diff --git a/addons/auth_ldap/users_ldap_view.xml b/addons/auth_ldap/users_ldap_view.xml
index c4fc7cebbbe..47c15badd7c 100644
--- a/addons/auth_ldap/users_ldap_view.xml
+++ b/addons/auth_ldap/users_ldap_view.xml
@@ -14,7 +14,7 @@
-
+
diff --git a/addons/auth_oauth/__openerp__.py b/addons/auth_oauth/__openerp__.py
index d43815e8018..1c29ca8c093 100644
--- a/addons/auth_oauth/__openerp__.py
+++ b/addons/auth_oauth/__openerp__.py
@@ -34,11 +34,15 @@ Allow users to login through Google OAuth2.
'depends': ['base', 'web', 'base_setup'],
'data': [
'auth_oauth_data.xml',
+ 'auth_oauth_data.yml',
'auth_oauth_view.xml',
'security/ir.model.access.csv'
],
'js': ['static/src/js/auth_oauth.js'],
- 'css': ['static/lib/zocial/css/zocial.css'],
+ 'css': [
+ 'static/lib/zocial/css/zocial.css',
+ 'static/src/css/auth_oauth.css',
+ ],
'qweb': ['static/src/xml/auth_oauth.xml'],
'installable': True,
'auto_install': False,
diff --git a/addons/auth_oauth/auth_oauth_data.xml b/addons/auth_oauth/auth_oauth_data.xml
index 7bb95192e5d..83e9df2e44d 100644
--- a/addons/auth_oauth/auth_oauth_data.xml
+++ b/addons/auth_oauth/auth_oauth_data.xml
@@ -2,6 +2,15 @@
+
+ OpenERP Accounts
+ https://accounts.openerp.com/oauth2/auth
+ userinfo
+ https://accounts.openerp.com/oauth2/tokeninfo
+
+ zocial openerp
+ Sign in with OpenERP account
+
Facebook Graph
https://www.facebook.com/dialog/oauth
diff --git a/addons/auth_oauth/auth_oauth_data.yml b/addons/auth_oauth/auth_oauth_data.yml
new file mode 100644
index 00000000000..af43811a560
--- /dev/null
+++ b/addons/auth_oauth/auth_oauth_data.yml
@@ -0,0 +1,6 @@
+-
+ Use database uuid as client_id for OpenERP oauth provider
+-
+ !python {model: ir.config_parameter}: |
+ oauth = self.pool.get('auth.oauth.provider')
+ oauth.write(cr, uid, [ref('provider_openerp')], {'client_id': self.get_param(cr, uid, 'database.uuid')})
diff --git a/addons/auth_oauth/controllers/main.py b/addons/auth_oauth/controllers/main.py
index 5d939f19db1..ae01df5f6f7 100644
--- a/addons/auth_oauth/controllers/main.py
+++ b/addons/auth_oauth/controllers/main.py
@@ -16,10 +16,13 @@ class OAuthController(openerpweb.Controller):
@openerpweb.jsonrequest
def list_providers(self, req, dbname):
- registry = openerp.modules.registry.RegistryManager.get(dbname)
- with registry.cursor() as cr:
- providers = registry.get('auth.oauth.provider')
- l = providers.read(cr, SUPERUSER_ID, providers.search(cr, SUPERUSER_ID, [('enabled','=',True)]))
+ try:
+ registry = openerp.modules.registry.RegistryManager.get(dbname)
+ with registry.cursor() as cr:
+ providers = registry.get('auth.oauth.provider')
+ l = providers.read(cr, SUPERUSER_ID, providers.search(cr, SUPERUSER_ID, [('enabled','=',True)]))
+ except Exception:
+ l = []
return l
@openerpweb.httprequest
diff --git a/addons/auth_oauth/res_users.py b/addons/auth_oauth/res_users.py
index b4f62612746..fd26e89c2e3 100644
--- a/addons/auth_oauth/res_users.py
+++ b/addons/auth_oauth/res_users.py
@@ -1,6 +1,7 @@
import logging
import urllib
+import urlparse
import urllib2
import simplejson
@@ -20,8 +21,11 @@ class res_users(osv.Model):
}
def auth_oauth_rpc(self, cr, uid, endpoint, access_token, context=None):
- params = urllib.urlencode({'access_token':access_token})
- url = endpoint + '?' + params
+ params = urllib.urlencode({ 'access_token': access_token })
+ if urlparse.urlparse(endpoint)[4]:
+ url = endpoint + '&' + params
+ else:
+ url = endpoint + '?' + params
f = urllib2.urlopen(url)
response = f.read()
return simplejson.loads(response)
@@ -38,26 +42,32 @@ class res_users(osv.Model):
validation = self.auth_oauth_rpc(cr, uid, p.validation_endpoint, access_token)
if validation.get("error"):
raise openerp.exceptions.AccessDenied
- login = validation['email']
+ if p.data_endpoint:
+ data = self.auth_oauth_rpc(cr, uid, p.data_endpoint, access_token)
+ validation.update(data)
+ # required
oauth_uid = validation['user_id']
- name = self.auth_oauth_rpc(cr, uid, p.data_endpoint, access_token)['name']
-
- credentials = (cr.dbname, login, access_token)
+ if not oauth_uid:
+ raise openerp.exceptions.AccessDenied
+ email = validation.get('email', 'provider_%d_user_%d' % (p.id, oauth_uid))
+ # optional
+ name = validation.get('name', email)
res = self.search(cr, uid, [("oauth_uid", "=", oauth_uid)])
if res:
- self.write(cr, uid, res[0], {'oauth_access_token':access_token})
+ self.write(cr, uid, res[0], { 'oauth_access_token': access_token })
else:
# New user
new_user = {
'name': name,
- 'login': login,
- 'user_email': login,
- 'oauth_provider_id': 1,
+ 'login': email,
+ 'user_email': email,
+ 'oauth_provider_id': p.id,
'oauth_uid': oauth_uid,
'oauth_access_token': access_token,
'active': True,
}
self.auth_signup_create(cr, uid, new_user)
+ credentials = (cr.dbname, email, access_token)
return credentials
def check_credentials(self, cr, uid, password):
diff --git a/addons/auth_oauth/static/src/css/auth_oauth.css b/addons/auth_oauth/static/src/css/auth_oauth.css
new file mode 100644
index 00000000000..ed6130e3123
--- /dev/null
+++ b/addons/auth_oauth/static/src/css/auth_oauth.css
@@ -0,0 +1,35 @@
+.openerp .oe_application .zocial {
+ font: white;
+}
+
+.openerp .zocial.openerp:before {
+ content: "\E02E";
+ font-style: italic;
+ text-shadow: 0 1px 1px black;
+}
+
+.openerp a.zocial.openerp {
+ float: right;
+ border: 1px solid #222222;
+ color: white;
+ margin: 0;
+ background-color: #b92020;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#b92020), to(#600606));
+ background-image: -webkit-linear-gradient(top, #b92020, #600606);
+ background-image: -moz-linear-gradient(top, #b92020, #600606);
+ background-image: -ms-linear-gradient(top, #b92020, #600606);
+ background-image: -o-linear-gradient(top, #b92020, #600606);
+ background-image: linear-gradient(to bottom, #b92020, #600606);
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
+ -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(155, 155, 155, 0.4) inset;
+ -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(155, 155, 155, 0.4) inset;
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(155, 155, 155, 0.4) inset;
+ text-shadow: none;
+ font-weight: normal;
+}
+
+.openerp .oe_login .oe_oauth_provider_login_button {
+ margin-top: 4px;
+}
diff --git a/addons/auth_oauth/static/src/js/auth_oauth.js b/addons/auth_oauth/static/src/js/auth_oauth.js
index 4a41e720726..5c80d29f4e9 100644
--- a/addons/auth_oauth/static/src/js/auth_oauth.js
+++ b/addons/auth_oauth/static/src/js/auth_oauth.js
@@ -1,8 +1,9 @@
openerp.auth_oauth = function(instance) {
var QWeb = instance.web.qweb;
- instance.web.Login = instance.web.Login.extend({
+ instance.web.Login.include({
start: function(parent, params) {
+ var self = this;
var d = this._super.apply(this, arguments);
this.$el.on('click', 'a.zocial', this.on_oauth_sign_in);
this.oauth_providers = [];
@@ -11,7 +12,13 @@ openerp.auth_oauth = function(instance) {
} else if(this.params.oauth_error === 2) {
this.do_warn("Authentication error","");
}
- return d.then(this.do_oauth_load);
+ return d.then(this.do_oauth_load).fail(function() {
+ self.do_oauth_load([]);
+ });
+ },
+ on_db_loaded: function(result) {
+ this._super.apply(this, arguments);
+ this.$("form [name=db]").change(this.do_oauth_load);
},
do_oauth_load: function() {
var db = this.$("form [name=db]").val();
@@ -21,6 +28,7 @@ openerp.auth_oauth = function(instance) {
},
on_oauth_loaded: function(result) {
this.oauth_providers = result;
+ this.$('.oe_oauth_provider_login_button').remove();
var buttons = QWeb.render("auth_oauth.Login.button",{"widget":this});
this.$(".oe_login_pane form ul").after(buttons);
},
@@ -33,7 +41,7 @@ openerp.auth_oauth = function(instance) {
var state_object = {
d: dbname,
p: p.id
- }
+ };
var state = JSON.stringify(state_object);
var params = {
response_type: 'token',
diff --git a/addons/auth_oauth/static/src/xml/auth_oauth.xml b/addons/auth_oauth/static/src/xml/auth_oauth.xml
index c2693804e59..76c71b83f10 100644
--- a/addons/auth_oauth/static/src/xml/auth_oauth.xml
+++ b/addons/auth_oauth/static/src/xml/auth_oauth.xml
@@ -2,8 +2,7 @@
-
-
+
diff --git a/addons/base_action_rule/__openerp__.py b/addons/base_action_rule/__openerp__.py
index c9483f00360..973567c613f 100644
--- a/addons/base_action_rule/__openerp__.py
+++ b/addons/base_action_rule/__openerp__.py
@@ -44,7 +44,6 @@ trigger an automatic reminder email.
'demo': [],
'installable': True,
'auto_install': False,
- 'certificate' : '001017908446466333429',
'images': ['images/base_action_rule1.jpeg','images/base_action_rule2.jpeg','images/base_action_rule3.jpeg'],
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/base_calendar/__init__.py b/addons/base_calendar/__init__.py
index ec4f5070d63..b6447567083 100644
--- a/addons/base_calendar/__init__.py
+++ b/addons/base_calendar/__init__.py
@@ -21,6 +21,5 @@
import base_calendar
import crm_meeting
-import wizard
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/addons/base_calendar/__openerp__.py b/addons/base_calendar/__openerp__.py
index 1e17a504919..313ddb8453a 100644
--- a/addons/base_calendar/__openerp__.py
+++ b/addons/base_calendar/__openerp__.py
@@ -23,7 +23,7 @@
'name': 'Calendar',
'version': '1.0',
'depends': ['base', 'base_status', 'mail', 'base_action_rule'],
- 'summary': 'Personnal & Shared Agenda',
+ 'summary': 'Personal & Shared Calendar',
'description': """
This is a full-featured calendar system.
========================================
@@ -32,7 +32,6 @@ It supports:
------------
- Calendar of events
- Recurring events
- - Invitations to people
If you need to manage your meetings, you should install the CRM module.
""",
@@ -43,7 +42,6 @@ If you need to manage your meetings, you should install the CRM module.
'data': [
'security/calendar_security.xml',
'security/ir.model.access.csv',
- 'wizard/base_calendar_invite_attendee_view.xml',
'base_calendar_view.xml',
'crm_meeting_view.xml',
'base_calendar_data.xml',
@@ -53,7 +51,6 @@ If you need to manage your meetings, you should install the CRM module.
'installable': True,
'application': True,
'auto_install': False,
- 'certificate': '00694071962960352821',
'images': ['images/base_calendar1.jpeg','images/base_calendar2.jpeg','images/base_calendar3.jpeg','images/base_calendar4.jpeg',],
}
diff --git a/addons/base_calendar/base_calendar.py b/addons/base_calendar/base_calendar.py
index 73811d5ba71..5b8c41787d4 100644
--- a/addons/base_calendar/base_calendar.py
+++ b/addons/base_calendar/base_calendar.py
@@ -971,8 +971,8 @@ class calendar_event(osv.osv):
event = datas['id']
if datas.get('interval', 0) < 0:
raise osv.except_osv(_('Warning!'), _('Interval cannot be negative.'))
- if datas.get('count', 0) < 0:
- raise osv.except_osv(_('Warning!'), _('Count cannot be negative.'))
+ if datas.get('count', 0) <= 0:
+ raise osv.except_osv(_('Warning!'), _('Count cannot be negative or 0.'))
if datas['recurrency']:
result[event] = self.compute_rule_string(datas)
else:
@@ -1058,8 +1058,40 @@ rule or repeating pattern of time to exclude from the recurring rule."),
'active': fields.boolean('Active', help="If the active field is set to \
true, it will allow you to hide the event alarm information without removing it."),
'recurrency': fields.boolean('Recurrent', help="Recurrent Meeting"),
+ 'partner_ids': fields.many2many('res.partner', string='Attendees', states={'done': [('readonly', True)]}),
}
+ def create_attendees(self, cr, uid, ids, context):
+ att_obj = self.pool.get('calendar.attendee')
+ user_obj = self.pool.get('res.users')
+ current_user = user_obj.browse(cr, uid, uid, context=context)
+ for event in self.browse(cr, uid, ids, context):
+ attendees = {}
+ for att in event.attendee_ids:
+ attendees[att.partner_id.id] = True
+ new_attendees = []
+ mail_to = []
+ for partner in event.partner_ids:
+ if partner.id in attendees:
+ continue
+ att_id = self.pool.get('calendar.attendee').create(cr, uid, {
+ 'partner_id': partner.id,
+ 'user_id': partner.user_ids and partner.user_ids[0].id or False,
+ 'ref': self._name+','+str(event.id),
+ 'email': partner.email
+ }, context=context)
+ if partner.email:
+ mail_to.append(partner.email)
+ self.write(cr, uid, [event.id], {
+ 'attendee_ids': [(4, att_id)]
+ }, context=context)
+ new_attendees.append(att_id)
+
+ if mail_to and current_user.email:
+ att_obj._send_mail(cr, uid, new_attendees, mail_to,
+ email_from = current_user.email)
+ return True
+
def default_organizer(self, cr, uid, context=None):
user_pool = self.pool.get('res.users')
user = user_pool.browse(cr, uid, uid, context=context)
@@ -1081,6 +1113,16 @@ rule or repeating pattern of time to exclude from the recurring rule."),
'user_id': lambda self, cr, uid, ctx: uid,
'organizer': default_organizer,
}
+
+ def _check_closing_date(self, cr, uid, ids, context=None):
+ for event in self.browse(cr, uid, ids, context=context):
+ if event.date_deadline < event.date:
+ return False
+ return True
+
+ _constraints = [
+ (_check_closing_date, 'Error ! End date cannot be set before start date.', ['date_deadline']),
+ ]
def get_recurrent_ids(self, cr, uid, select, domain, limit=100, context=None):
"""Gives virtual event ids for recurring events based on value of Recurrence Rule
@@ -1366,6 +1408,8 @@ rule or repeating pattern of time to exclude from the recurring rule."),
vals['vtimezone'] = vals['vtimezone'][40:]
res = super(calendar_event, self).write(cr, uid, ids, vals, context=context)
+ if vals.get('partner_ids', False):
+ self.create_attendees(cr, uid, ids, context)
if ('alarm_id' in vals or 'base_calendar_alarm_id' in vals)\
or ('date' in vals or 'duration' in vals or 'date_deadline' in vals):
@@ -1489,17 +1533,10 @@ rule or repeating pattern of time to exclude from the recurring rule."),
if vals.get('vtimezone', '') and vals.get('vtimezone', '').startswith('/freeassociation.sourceforge.net/tzfile/'):
vals['vtimezone'] = vals['vtimezone'][40:]
- #updated_vals = self.onchange_dates(cr, uid, [],
- # vals.get('date', False),
- # vals.get('duration', False),
- # vals.get('date_deadline', False),
- # vals.get('allday', False),
- # context=context)
- #vals.update(updated_vals.get('value', {}))
-
res = super(calendar_event, self).create(cr, uid, vals, context)
alarm_obj = self.pool.get('res.alarm')
alarm_obj.do_alarm_create(cr, uid, [res], self._name, 'date', context=context)
+ self.create_attendees(cr, uid, [res], context)
return res
def do_tentative(self, cr, uid, ids, context=None, *args):
diff --git a/addons/base_calendar/base_calendar_view.xml b/addons/base_calendar/base_calendar_view.xml
index 0ea2be4f37f..fe292a489ab 100644
--- a/addons/base_calendar/base_calendar_view.xml
+++ b/addons/base_calendar/base_calendar_view.xml
@@ -11,7 +11,6 @@
-
@@ -248,12 +243,6 @@
-
diff --git a/addons/base_calendar/crm_meeting.py b/addons/base_calendar/crm_meeting.py
index 0ee23ed1d0f..b87114f3a66 100644
--- a/addons/base_calendar/crm_meeting.py
+++ b/addons/base_calendar/crm_meeting.py
@@ -71,6 +71,34 @@ class crm_meeting(base_state, osv.Model):
default['attendee_ids'] = False
return super(crm_meeting, self).copy(cr, uid, id, default, context)
+ def onchange_partner_ids(self, cr, uid, ids, value, context=None):
+ """ The basic purpose of this method is to check that destination partners
+ effectively have email addresses. Otherwise a warning is thrown.
+ :param value: value format: [[6, 0, [3, 4]]]
+ """
+ res = {'value': {}}
+ if not value or not value[0] or not value[0][0] == 6:
+ return
+ res.update(self.check_partners_email(cr, uid, value[0][2], context=context))
+ return res
+
+ def check_partners_email(self, cr, uid, partner_ids, context=None):
+ """ Verify that selected partner_ids have an email_address defined.
+ Otherwise throw a warning. """
+ partner_wo_email_lst = []
+ for partner in self.pool.get('res.partner').browse(cr, uid, partner_ids, context=context):
+ if not partner.email:
+ partner_wo_email_lst.append(partner)
+ if not partner_wo_email_lst:
+ return {}
+ warning_msg = _('The following contacts have no email address :')
+ for partner in partner_wo_email_lst:
+ warning_msg += '\n- %s' % (partner.name)
+ return {'warning': {
+ 'title': _('Email addresses not found'),
+ 'message': warning_msg,
+ }
+ }
# ----------------------------------------
# OpenChatter
# ----------------------------------------
@@ -80,7 +108,7 @@ class crm_meeting(base_state, osv.Model):
return [('date','<=',time.strftime('%Y-%M-%D 23:59:59')), ('date_deadline','>=', time.strftime('%Y-%M-%D 00:00:00')), ('user_id','=',uid)]
def case_get_note_msg_prefix(self, cr, uid, id, context=None):
- return 'Meeting'
+ return _('Meeting')
def case_open_send_note(self, cr, uid, ids, context=None):
return self.message_post(cr, uid, ids, body=_("Meeting confirmed."), context=context)
diff --git a/addons/base_calendar/crm_meeting_view.xml b/addons/base_calendar/crm_meeting_view.xml
index fc936f416ad..adcfc23a520 100644
--- a/addons/base_calendar/crm_meeting_view.xml
+++ b/addons/base_calendar/crm_meeting_view.xml
@@ -80,7 +80,9 @@
-
+