diff --git a/addons/account/account.py b/addons/account/account.py index 9b728ff36e0..01a4d851de8 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -1023,7 +1023,10 @@ class account_period(osv.osv): if not result: result = self.search(cr, uid, args, context=context) if not result: - raise osv.except_osv(_('Error!'), _('There is no period defined for this date: %s.\nPlease create one.')%dt) + model, action_id = self.pool['ir.model.data'].get_object_reference(cr, uid, 'account', 'action_account_fiscalyear') + msg = _('There is no period defined for this date: %s.\nPlease, go to Configuration/Periods and configure a fiscal year.') % dt + raise openerp.exceptions.RedirectWarning(msg, action_id, _('Go to the configuration panel')) + return result def action_draft(self, cr, uid, ids, *args): diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py index cb242942656..b48e842caf5 100644 --- a/addons/account/account_move_line.py +++ b/addons/account/account_move_line.py @@ -849,18 +849,17 @@ class account_move_line(osv.osv): (tuple(ids), )) r = cr.fetchall() #TODO: move this check to a constraint in the account_move_reconcile object + if len(r) != 1: + raise osv.except_osv(_('Error'), _('Entries are not of the same account or already reconciled ! ')) if not unrec_lines: raise osv.except_osv(_('Error!'), _('Entry is already reconciled.')) account = account_obj.browse(cr, uid, account_id, context=context) + if not account.reconcile: + raise osv.except_osv(_('Error'), _('The account is not defined to be reconciled !')) if r[0][1] != None: raise osv.except_osv(_('Error!'), _('Some entries are already reconciled.')) - if context.get('fy_closing'): - # We don't want to generate any write-off when being called from the - # wizard used to close a fiscal year (and it doesn't give us any - # writeoff_acc_id). - pass - elif (not currency_obj.is_zero(cr, uid, account.company_id.currency_id, writeoff)) or \ + if (not currency_obj.is_zero(cr, uid, account.company_id.currency_id, writeoff)) or \ (account.currency_id and (not currency_obj.is_zero(cr, uid, account.currency_id, currency))): if not writeoff_acc_id: raise osv.except_osv(_('Warning!'), _('You have to provide an account for the write off/exchange difference entry.')) @@ -1199,7 +1198,7 @@ class account_move_line(osv.osv): break # Automatically convert in the account's secondary currency if there is one and # the provided values were not already multi-currency - if account.currency_id and (vals.get('amount_currency', False) is False) and account.currency_id.id != account.company_id.currency_id.id: + if account.currency_id and 'amount_currency' not in vals and account.currency_id.id != account.company_id.currency_id.id: vals['currency_id'] = account.currency_id.id ctx = {} if 'date' in vals: diff --git a/addons/account/demo/account_demo.xml b/addons/account/demo/account_demo.xml index 8a450c0b6aa..5ee0385f858 100644 --- a/addons/account/demo/account_demo.xml +++ b/addons/account/demo/account_demo.xml @@ -18,10 +18,18 @@ Fiscal Periods --> + + + + + + + + + - @@ -30,7 +38,6 @@ - @@ -40,7 +47,6 @@ - @@ -49,7 +55,6 @@ - @@ -58,7 +63,6 @@ - @@ -68,7 +72,6 @@ - @@ -76,7 +79,6 @@ - @@ -85,7 +87,6 @@ - @@ -94,7 +95,6 @@ - @@ -103,7 +103,6 @@ - @@ -112,7 +111,6 @@ - @@ -121,7 +119,6 @@ - diff --git a/addons/account/wizard/account_fiscalyear_close.py b/addons/account/wizard/account_fiscalyear_close.py index 928f0647084..266b8ccbc50 100644 --- a/addons/account/wizard/account_fiscalyear_close.py +++ b/addons/account/wizard/account_fiscalyear_close.py @@ -224,14 +224,6 @@ class account_fiscalyear_close(osv.osv_memory): query_2nd_part = "" query_2nd_part_args = [] for account in obj_acc_account.browse(cr, uid, account_ids, context={'fiscalyear': fy_id}): - balance_in_currency = 0.0 - if account.currency_id: - cr.execute('SELECT sum(COALESCE(amount_currency,0.0)) as balance_in_currency FROM account_move_line ' \ - 'WHERE account_id = %s ' \ - 'AND ' + query_line + ' ' \ - 'AND currency_id = %s', (account.id, account.currency_id.id)) - balance_in_currency = cr.dictfetchone()['balance_in_currency'] - company_currency_id = self.pool.get('res.users').browse(cr, uid, uid).company_id.currency_id if not currency_obj.is_zero(cr, uid, company_currency_id, abs(account.balance)): if query_2nd_part: @@ -246,7 +238,7 @@ class account_fiscalyear_close(osv.osv_memory): period.id, account.id, account.currency_id and account.currency_id.id or None, - balance_in_currency, + account.foreign_balance if account.currency_id else 0.0, account.company_id.id, 'draft') if query_2nd_part: diff --git a/addons/account_anglo_saxon/test/anglo_saxon.yml b/addons/account_anglo_saxon/test/anglo_saxon.yml index 7c3983223b0..042f35a5271 100644 --- a/addons/account_anglo_saxon/test/anglo_saxon.yml +++ b/addons/account_anglo_saxon/test/anglo_saxon.yml @@ -43,6 +43,7 @@ parent_id: account.cash type: other user_type: account.data_account_type_asset + reconcile: True - Configure Creditor Account Payable. - @@ -52,6 +53,7 @@ parent_id: account.a_pay type: other user_type: account.data_account_type_payable + reconcile: True - Configure Debtor Account Receivable. - @@ -61,6 +63,7 @@ parent_id: account.a_recv type: other user_type: account.data_account_type_receivable + reconcile: True - Configure Cost of Good sale Account. - diff --git a/addons/account_anglo_saxon/test/anglo_saxon_avg_fifo.yml b/addons/account_anglo_saxon/test/anglo_saxon_avg_fifo.yml index 93afc48eb11..92d331f97d7 100644 --- a/addons/account_anglo_saxon/test/anglo_saxon_avg_fifo.yml +++ b/addons/account_anglo_saxon/test/anglo_saxon_avg_fifo.yml @@ -43,6 +43,7 @@ parent_id: account.cash type: other user_type: account.data_account_type_asset + reconcile: True - Configure Creditor Account Payable. - @@ -52,6 +53,7 @@ parent_id: account.a_pay type: other user_type: account.data_account_type_payable + reconcile: True - Configure Debtor Account Receivable. - @@ -61,6 +63,7 @@ parent_id: account.a_recv type: other user_type: account.data_account_type_receivable + reconcile: True - Configure Cost of Good sale Account. - diff --git a/addons/account_payment/i18n/es_MX.po b/addons/account_payment/i18n/es_MX.po index f7f051ca3da..519b2222c71 100644 --- a/addons/account_payment/i18n/es_MX.po +++ b/addons/account_payment/i18n/es_MX.po @@ -1,84 +1,67 @@ -# Translation of OpenERP Server. -# This file contains the translation of the following modules: -# * account_payment +# Spanish (Mexico) translation for openobject-addons +# Copyright (c) 2014 Rosetta Contributors and Canonical Ltd 2014 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2014. # msgid "" msgstr "" -"Project-Id-Version: OpenERP Server 6.0dev\n" -"Report-Msgid-Bugs-To: support@openerp.com\n" -"POT-Creation-Date: 2011-01-11 11:14+0000\n" -"PO-Revision-Date: 2011-01-12 13:13+0000\n" -"Last-Translator: Borja López Soilán (NeoPolus) \n" -"Language-Team: \n" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2012-12-21 17:05+0000\n" +"PO-Revision-Date: 2014-01-10 21:52+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Spanish (Mexico) \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-09-05 05:26+0000\n" -"X-Generator: Launchpad (build 13830)\n" +"X-Launchpad-Export-Date: 2014-01-11 05:45+0000\n" +"X-Generator: Launchpad (build 16890)\n" #. module: account_payment -#: field:payment.order,date_scheduled:0 -msgid "Scheduled date if fixed" -msgstr "Fecha planificada si es fija" +#: model:ir.actions.act_window,help:account_payment.action_payment_order_tree +msgid "" +"

\n" +" Click to create a payment order.\n" +"

\n" +" A payment order is a payment request from your company to " +"pay a\n" +" supplier invoice or a customer refund.\n" +"

\n" +" " +msgstr "" #. module: account_payment #: field:payment.line,currency:0 msgid "Partner Currency" -msgstr "Moneda de la empresa" +msgstr "" #. module: account_payment #: view:payment.order:0 msgid "Set to draft" -msgstr "Cambiar a borrador" +msgstr "" #. module: account_payment #: help:payment.order,mode:0 msgid "Select the Payment Mode to be applied." -msgstr "Seleccione el modo de pago a aplicar." +msgstr "" #. module: account_payment #: view:payment.mode:0 #: view:payment.order:0 msgid "Group By..." -msgstr "Agrupar por..." - -#. module: account_payment -#: model:ir.module.module,description:account_payment.module_meta_information -msgid "" -"\n" -"This module provides :\n" -"* a more efficient way to manage invoice payment.\n" -"* a basic mechanism to easily plug various automated payment.\n" -" " msgstr "" -"\n" -"Este módulo proporciona:\n" -"* Una forma más eficiente para gestionar el pago de las facturas.\n" -"* Un mecanismo básico para conectar fácilmente varios pagos automatizados.\n" -" " #. module: account_payment #: field:payment.order,line_ids:0 msgid "Payment lines" -msgstr "Líneas de pago" +msgstr "" #. module: account_payment #: view:payment.line:0 #: field:payment.line,info_owner:0 #: view:payment.order:0 msgid "Owner Account" -msgstr "Cuenta propietario" - -#. module: account_payment -#: help:payment.order,state:0 -msgid "" -"When an order is placed the state is 'Draft'.\n" -" Once the bank is confirmed the state is set to 'Confirmed'.\n" -" Then the order is paid the state is 'Done'." msgstr "" -"Cuando se hace una orden, el estado es 'Borrador'.\n" -" Una vez se confirma el banco, el estado es \"Confirmada\".\n" -" Cuando la orden se paga, el estado es 'Realizada'." #. module: account_payment #: help:account.invoice,amount_to_pay:0 @@ -86,108 +69,109 @@ msgid "" "The amount which should be paid at the current date\n" "minus the amount which is already in payment order" msgstr "" -"El importe que se debería haber pagado en la fecha actual\n" -"menos el importe que ya está en la orden de pago" #. module: account_payment +#: field:payment.line,company_id:0 #: field:payment.mode,company_id:0 +#: field:payment.order,company_id:0 msgid "Company" -msgstr "Compañía" +msgstr "" #. module: account_payment -#: field:payment.order,date_prefered:0 -msgid "Preferred date" -msgstr "Fecha preferida" +#: model:res.groups,name:account_payment.group_account_payment +msgid "Accounting / Payments" +msgstr "" #. module: account_payment #: selection:payment.line,state:0 msgid "Free" -msgstr "Libre" +msgstr "" #. module: account_payment +#: view:payment.order.create:0 #: field:payment.order.create,entries:0 msgid "Entries" -msgstr "Asientos" +msgstr "" #. module: account_payment #: report:payment.order:0 msgid "Used Account" -msgstr "Cuenta utilizada" +msgstr "" #. module: account_payment #: field:payment.line,ml_maturity_date:0 #: field:payment.order.create,duedate:0 msgid "Due Date" -msgstr "Fecha de vencimiento" - -#. module: account_payment -#: constraint:account.move.line:0 -msgid "You can not create move line on closed account." -msgstr "No puede crear una línea de movimiento en una cuenta cerrada." - -#. module: account_payment -#: view:account.move.line:0 -msgid "Account Entry Line" -msgstr "Línea del asiento contable" +msgstr "" #. module: account_payment #: view:payment.order.create:0 msgid "_Add to payment order" -msgstr "_Añadir a la orden de pago" +msgstr "" #. module: account_payment #: model:ir.actions.act_window,name:account_payment.action_account_payment_populate_statement #: model:ir.actions.act_window,name:account_payment.action_account_populate_statement_confirm msgid "Payment Populate statement" -msgstr "Extracto generar pago" +msgstr "" + +#. module: account_payment +#: code:addons/account_payment/account_invoice.py:43 +#, python-format +msgid "" +"You cannot cancel an invoice which has already been imported in a payment " +"order. Remove it from the following payment order : %s." +msgstr "" + +#. module: account_payment +#: code:addons/account_payment/account_invoice.py:43 +#: code:addons/account_payment/account_move_line.py:110 +#, python-format +msgid "Error!" +msgstr "" #. module: account_payment #: report:payment.order:0 #: view:payment.order:0 msgid "Amount" -msgstr "Importe" - -#. module: account_payment -#: sql_constraint:account.move.line:0 -msgid "Wrong credit or debit value in accounting entry !" -msgstr "¡Valor haber o debe erróneo en el asiento contable!" +msgstr "" #. module: account_payment #: view:payment.order:0 msgid "Total in Company Currency" -msgstr "Total en moneda de la compañía" +msgstr "" #. module: account_payment #: selection:payment.order,state:0 msgid "Cancelled" -msgstr "Cancelado" +msgstr "" #. module: account_payment #: model:ir.actions.act_window,name:account_payment.action_payment_order_tree_new msgid "New Payment Order" -msgstr "Nueva orden de pago" +msgstr "" #. module: account_payment #: report:payment.order:0 #: field:payment.order,reference:0 msgid "Reference" -msgstr "Referencia" +msgstr "" #. module: account_payment #: sql_constraint:payment.line:0 msgid "The payment line name must be unique!" -msgstr "¡El nombre de la línea de pago debe ser única!" +msgstr "" #. module: account_payment #: model:ir.actions.act_window,name:account_payment.action_payment_order_tree #: model:ir.ui.menu,name:account_payment.menu_action_payment_order_form msgid "Payment Orders" -msgstr "Órdenes de pago" +msgstr "" #. module: account_payment #: selection:payment.order,date_prefered:0 msgid "Directly" -msgstr "Directamente" +msgstr "" #. module: account_payment #: model:ir.actions.act_window,name:account_payment.action_payment_line_form @@ -195,45 +179,52 @@ msgstr "Directamente" #: view:payment.line:0 #: view:payment.order:0 msgid "Payment Line" -msgstr "Línea de pago" +msgstr "" #. module: account_payment #: view:payment.line:0 msgid "Amount Total" -msgstr "Importe total" +msgstr "" + +#. module: account_payment +#: help:payment.order,state:0 +msgid "" +"When an order is placed the status is 'Draft'.\n" +" Once the bank is confirmed the status is set to 'Confirmed'.\n" +" Then the order is paid the status is 'Done'." +msgstr "" #. module: account_payment #: view:payment.order:0 #: selection:payment.order,state:0 msgid "Confirmed" -msgstr "Confirmada" +msgstr "" #. module: account_payment #: help:payment.line,ml_date_created:0 msgid "Invoice Effective Date" -msgstr "Fecha vencimiento factura" +msgstr "" #. module: account_payment #: report:payment.order:0 msgid "Execution Type" -msgstr "Tipo ejecución" +msgstr "" #. module: account_payment #: selection:payment.line,state:0 msgid "Structured" -msgstr "Estructurado" +msgstr "" #. module: account_payment -#: view:payment.order:0 -#: field:payment.order,state:0 -msgid "State" -msgstr "Estado" +#: view:account.bank.statement:0 +msgid "Import Payment Lines" +msgstr "" #. module: account_payment #: view:payment.line:0 #: view:payment.order:0 msgid "Transaction Information" -msgstr "Información de transacción" +msgstr "" #. module: account_payment #: model:ir.actions.act_window,name:account_payment.action_payment_mode_form @@ -241,18 +232,19 @@ msgstr "Información de transacción" #: model:ir.ui.menu,name:account_payment.menu_action_payment_mode_form #: view:payment.mode:0 #: view:payment.order:0 +#: field:payment.order,mode:0 msgid "Payment Mode" -msgstr "Modo de pago" +msgstr "" #. module: account_payment #: field:payment.line,ml_date_created:0 msgid "Effective Date" -msgstr "Fecha vencimiento" +msgstr "" #. module: account_payment #: field:payment.line,ml_inv_ref:0 msgid "Invoice Ref." -msgstr "Ref. factura" +msgstr "" #. module: account_payment #: help:payment.order,date_prefered:0 @@ -261,119 +253,99 @@ msgid "" "by you.'Directly' stands for the direct execution.'Due date' stands for the " "scheduled date of execution." msgstr "" -"Seleccione una opción para la orden de pago: 'Fecha fija' para una fecha " -"especificada por usted. 'Directamente' para la ejecución directa. 'Fecha " -"vencimiento' para la fecha programada de ejecución." #. module: account_payment -#: code:addons/account_payment/account_move_line.py:110 -#, python-format -msgid "Error !" -msgstr "¡Error!" - -#. module: account_payment -#: view:account.move.line:0 -msgid "Total debit" -msgstr "Total debe" - -#. module: account_payment -#: field:payment.order,date_done:0 -msgid "Execution date" -msgstr "Fecha ejecución" +#: field:payment.order,date_created:0 +msgid "Creation Date" +msgstr "" #. module: account_payment #: help:payment.mode,journal:0 msgid "Bank or Cash Journal for the Payment Mode" -msgstr "Diario de banco o caja para el modo de pago." +msgstr "" #. module: account_payment #: selection:payment.order,date_prefered:0 msgid "Fixed date" -msgstr "Fecha fija" +msgstr "" #. module: account_payment #: field:payment.line,info_partner:0 #: view:payment.order:0 msgid "Destination Account" -msgstr "Cuenta de destino" +msgstr "" #. module: account_payment #: view:payment.line:0 msgid "Desitination Account" -msgstr "Cuenta de destino" +msgstr "" #. module: account_payment #: view:payment.order:0 msgid "Search Payment Orders" -msgstr "Buscar órdenes de pago" - -#. module: account_payment -#: constraint:account.move.line:0 -msgid "" -"You can not create move line on receivable/payable account without partner" msgstr "" -"No puede crear una línea de movimiento en una cuenta a cobrar/a pagar sin " -"una empresa." #. module: account_payment #: field:payment.line,create_date:0 msgid "Created" -msgstr "Creado" +msgstr "" #. module: account_payment #: view:payment.order:0 msgid "Select Invoices to Pay" -msgstr "Seleccionar facturas a pagar" +msgstr "" #. module: account_payment #: view:payment.line:0 msgid "Currency Amount Total" -msgstr "Importe total monetario" +msgstr "" #. module: account_payment #: view:payment.order:0 msgid "Make Payments" -msgstr "Realizar pagos" +msgstr "" #. module: account_payment #: field:payment.line,state:0 msgid "Communication Type" -msgstr "Tipo de comunicación" +msgstr "" #. module: account_payment -#: model:ir.module.module,shortdesc:account_payment.module_meta_information -msgid "Payment Management" -msgstr "Gestión de pagos" +#: field:payment.line,partner_id:0 +#: field:payment.mode,partner_id:0 +#: report:payment.order:0 +msgid "Partner" +msgstr "" #. module: account_payment #: field:payment.line,bank_statement_line_id:0 msgid "Bank statement line" -msgstr "Línea extracto bancario" +msgstr "" #. module: account_payment #: selection:payment.order,date_prefered:0 msgid "Due date" -msgstr "Fecha vencimiento" +msgstr "" #. module: account_payment #: field:account.invoice,amount_to_pay:0 msgid "Amount to be paid" -msgstr "Importe a pagar" +msgstr "" #. module: account_payment #: report:payment.order:0 msgid "Currency" -msgstr "Moneda" +msgstr "" #. module: account_payment #: view:account.payment.make.payment:0 msgid "Yes" -msgstr "Sí" +msgstr "" #. module: account_payment #: help:payment.line,info_owner:0 msgid "Address of the Main Partner" -msgstr "Dirección de la empresa principal" +msgstr "" #. module: account_payment #: help:payment.line,date:0 @@ -381,92 +353,79 @@ msgid "" "If no payment date is specified, the bank will treat this payment line " "directly" msgstr "" -"Si no se indica fecha de pago, el banco procesará esta línea de pago " -"directamente" #. module: account_payment #: model:ir.model,name:account_payment.model_account_payment_populate_statement msgid "Account Payment Populate Statement" -msgstr "Contabilidad extracto generar pago" +msgstr "" + +#. module: account_payment +#: code:addons/account_payment/account_move_line.py:110 +#, python-format +msgid "There is no partner defined on the entry line." +msgstr "" #. module: account_payment #: help:payment.mode,name:0 msgid "Mode of Payment" -msgstr "Modo de pago" +msgstr "" #. module: account_payment #: report:payment.order:0 msgid "Value Date" -msgstr "Fecha valor" +msgstr "" #. module: account_payment #: report:payment.order:0 msgid "Payment Type" -msgstr "Tipo de Pago" +msgstr "" #. module: account_payment #: help:payment.line,amount_currency:0 msgid "Payment amount in the partner currency" -msgstr "Importe pagado en la moneda de la empresa" +msgstr "" #. module: account_payment #: view:payment.order:0 #: selection:payment.order,state:0 msgid "Draft" -msgstr "Borrador" +msgstr "" + +#. module: account_payment +#: view:payment.order:0 +#: field:payment.order,state:0 +msgid "Status" +msgstr "" #. module: account_payment #: help:payment.line,communication2:0 msgid "The successor message of Communication." -msgstr "El mensaje de pago realizado a comunicar." - -#. module: account_payment -#: code:addons/account_payment/account_move_line.py:110 -#, python-format -msgid "No partner defined on entry line" -msgstr "No se ha definido la empresa en la línea de entrada" +msgstr "" #. module: account_payment #: help:payment.line,info_partner:0 msgid "Address of the Ordering Customer." -msgstr "Dirección del cliente que ordena." +msgstr "" #. module: account_payment #: view:account.payment.populate.statement:0 msgid "Populate Statement:" -msgstr "Generar extracto:" - -#. module: account_payment -#: view:account.move.line:0 -msgid "Total credit" -msgstr "Total haber" +msgstr "" #. module: account_payment #: help:payment.order,date_scheduled:0 msgid "Select a date if you have chosen Preferred Date to be fixed." msgstr "" -"Seleccione una fecha si ha seleccionado que la fecha preferida sea fija." - -#. module: account_payment -#: field:payment.order,user_id:0 -msgid "User" -msgstr "Usuario" #. module: account_payment #: field:account.payment.populate.statement,lines:0 -#: model:ir.actions.act_window,name:account_payment.act_account_invoice_2_payment_line msgid "Payment Lines" -msgstr "Líneas de pago" +msgstr "" #. module: account_payment #: model:ir.model,name:account_payment.model_account_move_line msgid "Journal Items" -msgstr "Apuntes contables" - -#. module: account_payment -#: constraint:account.move.line:0 -msgid "Company must be same for its related account and period." -msgstr "La compañía debe ser la misma para la cuenta y periodo relacionados." +msgstr "" #. module: account_payment #: help:payment.line,move_line_id:0 @@ -474,202 +433,192 @@ msgid "" "This Entry Line will be referred for the information of the ordering " "customer." msgstr "" -"Esta línea se usará como referencia para la información del cliente que " -"ordena." #. module: account_payment #: view:payment.order.create:0 msgid "Search" -msgstr "Buscar" +msgstr "" #. module: account_payment -#: model:ir.actions.report.xml,name:account_payment.payment_order1 -#: model:ir.model,name:account_payment.model_payment_order -msgid "Payment Order" -msgstr "Orden de pago" +#: field:payment.order,user_id:0 +msgid "Responsible" +msgstr "" #. module: account_payment #: field:payment.line,date:0 msgid "Payment Date" -msgstr "Fecha de pago" +msgstr "" #. module: account_payment #: report:payment.order:0 msgid "Total:" -msgstr "Total:" +msgstr "" #. module: account_payment -#: field:payment.order,date_created:0 -msgid "Creation date" -msgstr "Fecha de creación" +#: field:payment.order,date_done:0 +msgid "Execution Date" +msgstr "" #. module: account_payment #: view:account.payment.populate.statement:0 msgid "ADD" -msgstr "Añadir" +msgstr "" #. module: account_payment -#: view:account.bank.statement:0 -msgid "Import payment lines" -msgstr "Importar líneas de pago" +#: model:ir.actions.act_window,name:account_payment.action_create_payment_order +msgid "Populate Payment" +msgstr "" #. module: account_payment #: field:account.move.line,amount_to_pay:0 msgid "Amount to pay" -msgstr "Importe a pagar" +msgstr "" #. module: account_payment #: field:payment.line,amount:0 msgid "Amount in Company Currency" -msgstr "Importe en la moneda de la compañía" +msgstr "" #. module: account_payment #: help:payment.line,partner_id:0 msgid "The Ordering Customer" -msgstr "El cliente que ordena" +msgstr "" #. module: account_payment #: model:ir.model,name:account_payment.model_account_payment_make_payment msgid "Account make payment" -msgstr "Contabilidad realizar pago" +msgstr "" #. module: account_payment #: report:payment.order:0 msgid "Invoice Ref" -msgstr "Ref. factura" +msgstr "" #. module: account_payment #: field:payment.line,name:0 msgid "Your Reference" -msgstr "Su referencia" - -#. module: account_payment -#: field:payment.order,mode:0 -msgid "Payment mode" -msgstr "Modo de pago" +msgstr "" #. module: account_payment #: view:payment.order:0 msgid "Payment order" -msgstr "Órdenes de pago" +msgstr "" #. module: account_payment #: view:payment.line:0 #: view:payment.order:0 msgid "General Information" -msgstr "Información General" +msgstr "" #. module: account_payment #: view:payment.order:0 #: selection:payment.order,state:0 msgid "Done" -msgstr "Realizado" +msgstr "" #. module: account_payment #: model:ir.model,name:account_payment.model_account_invoice msgid "Invoice" -msgstr "Factura" +msgstr "" #. module: account_payment #: field:payment.line,communication:0 msgid "Communication" -msgstr "Comunicación" +msgstr "" #. module: account_payment #: view:account.payment.make.payment:0 #: view:account.payment.populate.statement:0 -#: view:payment.order:0 #: view:payment.order.create:0 msgid "Cancel" -msgstr "Cancelar" +msgstr "" + +#. module: account_payment +#: field:payment.line,bank_id:0 +msgid "Destination Bank Account" +msgstr "" #. module: account_payment #: view:payment.line:0 #: view:payment.order:0 msgid "Information" -msgstr "Información" +msgstr "" #. module: account_payment -#: model:ir.actions.act_window,help:account_payment.action_payment_order_tree -msgid "" -"A payment order is a payment request from your company to pay a supplier " -"invoice or a customer credit note. Here you can register all payment orders " -"that should be done, keep track of all payment orders and mention the " -"invoice reference and the partner the payment should be done for." +#: model:ir.actions.report.xml,name:account_payment.payment_order1 +#: model:ir.model,name:account_payment.model_payment_order +#: view:payment.order:0 +msgid "Payment Order" msgstr "" -"Una órden de pago es una petición de pago que realiza su compañía para pagar " -"una factura de proveedor o un apunte de crédito de un cliente. Aquí puede " -"registrar todas las órdenes de pago pendientes y hacer seguimiento de las " -"órdenes e indicar la referencia de factura y la entidad a la cual pagar." #. module: account_payment #: help:payment.line,amount:0 msgid "Payment amount in the company currency" -msgstr "Importe pagado en la moneda de la compañía" +msgstr "" #. module: account_payment #: view:payment.order.create:0 msgid "Search Payment lines" -msgstr "Buscar líneas de pago" +msgstr "" #. module: account_payment #: field:payment.line,amount_currency:0 msgid "Amount in Partner Currency" -msgstr "Importe en la moneda de la empresa" +msgstr "" #. module: account_payment #: field:payment.line,communication2:0 msgid "Communication 2" -msgstr "Comunicación 2" +msgstr "" #. module: account_payment -#: field:payment.line,bank_id:0 -msgid "Destination Bank account" -msgstr "Cuenta bancaria destino" +#: field:payment.order,date_scheduled:0 +msgid "Scheduled Date" +msgstr "" #. module: account_payment #: view:account.payment.make.payment:0 msgid "Are you sure you want to make payment?" -msgstr "¿Está seguro que quiere realizar el pago?" +msgstr "" #. module: account_payment #: view:payment.mode:0 #: field:payment.mode,journal:0 msgid "Journal" -msgstr "Diario" +msgstr "" #. module: account_payment #: field:payment.mode,bank_id:0 msgid "Bank account" -msgstr "Cuenta bancaria" +msgstr "" #. module: account_payment #: view:payment.order:0 msgid "Confirm Payments" -msgstr "Confirmar pagos" +msgstr "" #. module: account_payment #: field:payment.line,company_currency:0 #: report:payment.order:0 msgid "Company Currency" -msgstr "Moneda de la compañía" +msgstr "" #. module: account_payment #: model:ir.ui.menu,name:account_payment.menu_main_payment #: view:payment.line:0 #: view:payment.order:0 msgid "Payment" -msgstr "Pago" +msgstr "" #. module: account_payment #: report:payment.order:0 msgid "Payment Order / Payment" -msgstr "Orden de pago / Pago" +msgstr "" #. module: account_payment #: field:payment.line,move_line_id:0 msgid "Entry line" -msgstr "Línea del asiento" +msgstr "" #. module: account_payment #: help:payment.line,communication:0 @@ -677,134 +626,57 @@ msgid "" "Used as the message between ordering customer and current company. Depicts " "'What do you want to say to the recipient about this order ?'" msgstr "" -"Se utiliza como mensaje entre el cliente que hace el pedido y la compañía " -"actual. Describe '¿Qué quiere decir al receptor sobre este pedido?'" #. module: account_payment #: field:payment.mode,name:0 msgid "Name" -msgstr "Nombre" +msgstr "" #. module: account_payment #: report:payment.order:0 msgid "Bank Account" -msgstr "Cuenta bancaria" +msgstr "" #. module: account_payment #: view:payment.line:0 #: view:payment.order:0 msgid "Entry Information" -msgstr "Información del asiento" +msgstr "" #. module: account_payment #: model:ir.model,name:account_payment.model_payment_order_create msgid "payment.order.create" -msgstr "pago.orden.crear" +msgstr "" #. module: account_payment #: field:payment.line,order_id:0 msgid "Order" -msgstr "Orden" +msgstr "" #. module: account_payment #: field:payment.order,total:0 msgid "Total" -msgstr "Total" +msgstr "" #. module: account_payment #: view:account.payment.make.payment:0 #: model:ir.actions.act_window,name:account_payment.action_account_payment_make_payment msgid "Make Payment" -msgstr "Realizar pago" +msgstr "" #. module: account_payment -#: field:payment.line,partner_id:0 -#: report:payment.order:0 -msgid "Partner" -msgstr "Empresa" +#: field:payment.order,date_prefered:0 +msgid "Preferred Date" +msgstr "" #. module: account_payment -#: model:ir.actions.act_window,name:account_payment.action_create_payment_order -msgid "Populate Payment" -msgstr "Generar pago" +#: view:account.payment.make.payment:0 +#: view:account.payment.populate.statement:0 +#: view:payment.order.create:0 +msgid "or" +msgstr "" #. module: account_payment #: help:payment.mode,bank_id:0 msgid "Bank Account for the Payment Mode" -msgstr "Cuenta bancaria para el modo de pago" - -#. module: account_payment -#: constraint:account.move.line:0 -msgid "You can not create move line on view account." -msgstr "No puede crear una línea de movimiento en una cuenta de tipo vista." - -#~ msgid "Execution date:" -#~ msgstr "Fecha de ejecución:" - -#~ msgid "Suitable bank types" -#~ msgstr "Tipos de banco adecuados" - -#~ msgid "Invalid XML for View Architecture!" -#~ msgstr "¡XML inválido para la definición de la vista!" - -#~ msgid "_Cancel" -#~ msgstr "_Cancelar" - -#~ msgid "Date" -#~ msgstr "Fecha" - -#~ msgid "Reference:" -#~ msgstr "Referencia:" - -#~ msgid "Maturity Date" -#~ msgstr "Fecha vencimiento" - -#~ msgid "Specify the Code for Payment Type" -#~ msgstr "Indique el código para el tipo de pago" - -#~ msgid "Code" -#~ msgstr "Código" - -#~ msgid "" -#~ "The Object name must start with x_ and not contain any special character !" -#~ msgstr "" -#~ "¡El nombre del objeto debe empezar con x_ y no contener ningún carácter " -#~ "especial!" - -#~ msgid "Pay" -#~ msgstr "Pagar" - -#~ msgid "Draft Payment Order" -#~ msgstr "Orden de pago borrador" - -#~ msgid "Cash Journal for the Payment Mode" -#~ msgstr "Diario de caja para el modo de pago" - -#~ msgid "_Search" -#~ msgstr "_Buscar" - -#, python-format -#~ msgid "Partner '+ line.partner_id.name+ ' has no bank account defined" -#~ msgstr "" -#~ "Empresa '+ line.partner_id.name+ ' no tiene una cuenta bancaria definida" - -#~ msgid "Payment Orders to Validate" -#~ msgstr "Órdenes de pago a validar" - -#~ msgid "Payment type" -#~ msgstr "Tipo de pago" - -#~ msgid "_Add" -#~ msgstr "_Añadir" - -#~ msgid "Select the Payment Type for the Payment Mode." -#~ msgstr "Seleccione el tipo de pago para el modo de pago." - -#~ msgid "Invalid model name in the action definition." -#~ msgstr "Nombre de modelo no válido en la definición de acción." - -#~ msgid "Populate payment" -#~ msgstr "Rellenar la orden" - -#~ msgid "Populate Statement with Payment lines" -#~ msgstr "Llenar un extracto con líneas de pago" +msgstr "" diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py index d6ad6efdd90..c9516b6135f 100644 --- a/addons/account_voucher/account_voucher.py +++ b/addons/account_voucher/account_voucher.py @@ -217,7 +217,7 @@ class account_voucher(osv.osv): if context.get('type', 'sale') in ('purchase', 'payment'): nodes = doc.xpath("//field[@name='partner_id']") for node in nodes: - node.set('context', "{'search_default_supplier': 1}") + node.set('context', "{'default_customer': 0, 'search_default_supplier': 1, 'default_supplier': 1}") if context.get('invoice_type','') in ('in_invoice', 'in_refund'): node.set('string', _("Supplier")) res['arch'] = etree.tostring(doc) @@ -1329,7 +1329,7 @@ class account_voucher(osv.osv): 'date': voucher.date, 'credit': diff > 0 and diff or 0.0, 'debit': diff < 0 and -diff or 0.0, - 'amount_currency': company_currency <> current_currency and (sign * -1 * voucher.writeoff_amount) or False, + 'amount_currency': company_currency <> current_currency and (sign * -1 * voucher.writeoff_amount) or 0.0, 'currency_id': company_currency <> current_currency and current_currency or False, 'analytic_account_id': voucher.analytic_id and voucher.analytic_id.id or False, } diff --git a/addons/analytic/analytic.py b/addons/analytic/analytic.py index 14c8f712e81..4f1de653ae1 100644 --- a/addons/analytic/analytic.py +++ b/addons/analytic/analytic.py @@ -194,7 +194,7 @@ class account_analytic_account(osv.osv): 'user_id': fields.many2one('res.users', 'Project Manager', track_visibility='onchange'), 'manager_id': fields.many2one('res.users', 'Account Manager', track_visibility='onchange'), 'date_start': fields.date('Start Date'), - 'date': fields.date('End Date', select=True, track_visibility='onchange'), + 'date': fields.date('Expiration Date', select=True, track_visibility='onchange'), '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'),('pending','To Renew'),('close','Closed'),('cancelled', 'Cancelled')], 'Status', required=True, track_visibility='onchange'), '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 diff --git a/addons/base_calendar/base_calendar.py b/addons/base_calendar/base_calendar.py deleted file mode 100644 index 769d4e2b358..00000000000 --- a/addons/base_calendar/base_calendar.py +++ /dev/null @@ -1,1765 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# 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 . -# -############################################################################## - -from datetime import datetime, timedelta, date -from dateutil import parser -from dateutil import rrule -from dateutil.relativedelta import relativedelta -from openerp.osv import fields, osv -from openerp.tools.translate import _ -import pytz -import re -import time - -from openerp import tools, SUPERUSER_ID -import openerp.service.report - -months = { - 1: "January", 2: "February", 3: "March", 4: "April", \ - 5: "May", 6: "June", 7: "July", 8: "August", 9: "September", \ - 10: "October", 11: "November", 12: "December" -} - -def get_recurrent_dates(rrulestring, exdate, startdate=None, exrule=None): - """ - Get recurrent dates based on Rule string considering exdate and start date. - @param rrulestring: rulestring - @param exdate: list of exception dates for rrule - @param startdate: startdate for computing recurrent dates - @return: list of Recurrent dates - """ - def todate(date): - val = parser.parse(''.join((re.compile('\d')).findall(date))) - return val - - if not startdate: - startdate = datetime.now() - - if not exdate: - exdate = [] - - rset1 = rrule.rrulestr(str(rrulestring), dtstart=startdate, forceset=True) - for date in exdate: - datetime_obj = todate(date) - rset1._exdate.append(datetime_obj) - - if exrule: - rset1.exrule(rrule.rrulestr(str(exrule), dtstart=startdate)) - - return list(rset1) - -def base_calendar_id2real_id(base_calendar_id=None, with_date=False): - """ - Convert a "virtual/recurring event id" (type string) into a real event id (type int). - E.g. virtual/recurring event id is 4-20091201100000, so it will return 4. - @param base_calendar_id: id of calendar - @param with_date: if a value is passed to this param it will return dates based on value of withdate + base_calendar_id - @return: real event id - """ - if base_calendar_id and isinstance(base_calendar_id, (str, unicode)): - res = base_calendar_id.split('-') - - if len(res) >= 2: - real_id = res[0] - if with_date: - real_date = time.strftime("%Y-%m-%d %H:%M:%S", \ - time.strptime(res[1], "%Y%m%d%H%M%S")) - start = datetime.strptime(real_date, "%Y-%m-%d %H:%M:%S") - end = start + timedelta(hours=with_date) - return (int(real_id), real_date, end.strftime("%Y-%m-%d %H:%M:%S")) - return int(real_id) - - return base_calendar_id and int(base_calendar_id) or base_calendar_id - -def get_real_ids(ids): - if isinstance(ids, (str, int, long)): - return base_calendar_id2real_id(ids) - - if isinstance(ids, (list, tuple)): - res = [] - for id in ids: - res.append(base_calendar_id2real_id(id)) - return res - -def real_id2base_calendar_id(real_id, recurrent_date): - """ - Convert a real event id (type int) into a "virtual/recurring event id" (type string). - E.g. real event id is 1 and recurrent_date is set to 01-12-2009 10:00:00, so - it will return 1-20091201100000. - @param real_id: real event id - @param recurrent_date: real event recurrent date - @return: string containing the real id and the recurrent date - """ - if real_id and recurrent_date: - recurrent_date = time.strftime("%Y%m%d%H%M%S", \ - time.strptime(recurrent_date, "%Y-%m-%d %H:%M:%S")) - return '%d-%s' % (real_id, recurrent_date) - return real_id - -html_invitation = """ - - - -%(name)s - - - - - - - - - - - - -
Hello,
You are invited for %(company)s Event.
Below are the details of event. Hours and dates expressed in %(timezone)s time.
- - - - - - - - -
-

%(name)s

-
- - - - - - - - - - - - - - - - - - - - - - - - -
-
Start Date
-
:%(start_date)s -
End Date
-
:%(end_date)s
Description:%(description)s
-
Location
-
:%(location)s
-
Event Attendees
-
: -
-
%(attendees)s
-
-
-
- - - - - - - - - - - - - -
From:
%(user)s
--------------------------
%(sign)s
- - -""" - -class calendar_attendee(osv.osv): - """ - Calendar Attendee Information - """ - _name = 'calendar.attendee' - _description = 'Attendee information' - _rec_name = 'cutype' - - __attribute__ = {} - - def _get_address(self, name=None, email=None): - """ - Gives email information in ical CAL-ADDRESS type format. - @param name: name for CAL-ADDRESS value - @param email: email address for CAL-ADDRESS value - """ - if name and email: - name += ':' - return (name or '') + (email and ('MAILTO:' + email) or '') - - def _compute_data(self, cr, uid, ids, name, arg, context=None): - """ - Compute data on function fields for attendee values. - @param cr: the current row, from the database cursor - @param uid: the current user's ID for security checks - @param ids: list of calendar attendee's IDs - @param name: name of field - @param context: a standard dictionary for contextual values - @return: dictionary of form {id: {'field Name': value'}} - """ - name = name[0] - result = {} - for attdata in self.browse(cr, uid, ids, context=context): - id = attdata.id - result[id] = {} - if name == 'sent_by': - if not attdata.sent_by_uid: - result[id][name] = '' - continue - else: - result[id][name] = self._get_address(attdata.sent_by_uid.name, \ - attdata.sent_by_uid.email) - - if name == 'cn': - if attdata.user_id: - result[id][name] = attdata.user_id.name - elif attdata.partner_id: - result[id][name] = attdata.partner_id.name or False - else: - result[id][name] = attdata.email or '' - - if name == 'delegated_to': - todata = [] - for child in attdata.child_ids: - if child.email: - todata.append('MAILTO:' + child.email) - result[id][name] = ', '.join(todata) - - if name == 'delegated_from': - fromdata = [] - for parent in attdata.parent_ids: - if parent.email: - fromdata.append('MAILTO:' + parent.email) - result[id][name] = ', '.join(fromdata) - - if name == 'event_date': - if attdata.ref: - result[id][name] = attdata.ref.date - else: - result[id][name] = False - - if name == 'event_end_date': - if attdata.ref: - result[id][name] = attdata.ref.date_deadline - else: - result[id][name] = False - - if name == 'sent_by_uid': - if attdata.ref: - result[id][name] = (attdata.ref.user_id.id, attdata.ref.user_id.name) - else: - result[id][name] = uid - - if name == 'language': - user_obj = self.pool.get('res.users') - lang = user_obj.read(cr, uid, uid, ['lang'], context=context)['lang'] - result[id][name] = lang.replace('_', '-') if lang else False - - return result - - def _lang_get(self, cr, uid, context=None): - """ - Get language for language selection field. - @param cr: the current row, from the database cursor - @param uid: the current user's id for security checks - @param context: a standard dictionary for contextual values - @return: list of dictionary which contain code and name and id - """ - obj = self.pool.get('res.lang') - ids = obj.search(cr, uid, []) - res = obj.read(cr, uid, ids, ['code', 'name'], context=context) - res = [((r['code']).replace('_', '-').lower(), r['name']) for r in res] - return res - - _columns = { - 'cutype': fields.selection([('individual', 'Individual'), \ - ('group', 'Group'), ('resource', 'Resource'), \ - ('room', 'Room'), ('unknown', 'Unknown') ], \ - 'Invite Type', help="Specify the type of Invitation"), - 'member': fields.char('Member', size=124, - help="Indicate the groups that the attendee belongs to"), - 'role': fields.selection([('req-participant', 'Participation required'), \ - ('chair', 'Chair Person'), \ - ('opt-participant', 'Optional Participation'), \ - ('non-participant', 'For information Purpose')], 'Role', \ - help='Participation role for the calendar user'), - 'state': fields.selection([('needs-action', 'Needs Action'), - ('tentative', 'Uncertain'), - ('declined', 'Declined'), - ('accepted', 'Accepted'), - ('delegated', 'Delegated')], 'Status', readonly=True, \ - help="Status of the attendee's participation"), - 'rsvp': fields.boolean('Required Reply?', - help="Indicats whether the favor of a reply is requested"), - 'delegated_to': fields.function(_compute_data, \ - string='Delegated To', type="char", size=124, store=True, \ - multi='delegated_to', help="The users that the original \ -request was delegated to"), - 'delegated_from': fields.function(_compute_data, string=\ - 'Delegated From', type="char", store=True, size=124, multi='delegated_from'), - 'parent_ids': fields.many2many('calendar.attendee', 'calendar_attendee_parent_rel', \ - 'attendee_id', 'parent_id', 'Delegrated From'), - 'child_ids': fields.many2many('calendar.attendee', 'calendar_attendee_child_rel', \ - 'attendee_id', 'child_id', 'Delegrated To'), - 'sent_by': fields.function(_compute_data, string='Sent By', \ - type="char", multi='sent_by', store=True, size=124, \ - help="Specify the user that is acting on behalf of the calendar user"), - 'sent_by_uid': fields.function(_compute_data, string='Sent By User', \ - type="many2one", relation="res.users", multi='sent_by_uid'), - 'cn': fields.function(_compute_data, string='Common name', \ - type="char", size=124, multi='cn', store=True), - 'dir': fields.char('URI Reference', size=124, help="Reference to the URI\ -that points to the directory information corresponding to the attendee."), - 'language': fields.function(_compute_data, string='Language', \ - type="selection", selection=_lang_get, multi='language', \ - store=True, help="To specify the language for text values in a\ -property or property parameter."), - 'user_id': fields.many2one('res.users', 'User'), - 'partner_id': fields.many2one('res.partner', 'Contact'), - 'email': fields.char('Email', size=124, help="Email of Invited Person"), - 'event_date': fields.function(_compute_data, string='Event Date', \ - type="datetime", multi='event_date'), - 'event_end_date': fields.function(_compute_data, \ - string='Event End Date', type="datetime", \ - multi='event_end_date'), - 'ref': fields.reference('Event Ref', selection=openerp.addons.base.res.res_request.referencable_models, size=128), - 'availability': fields.selection([('free', 'Free'), ('busy', 'Busy')], 'Free/Busy', readonly="True"), - } - _defaults = { - 'state': 'needs-action', - 'role': 'req-participant', - 'rsvp': True, - 'cutype': 'individual', - } - - - def copy(self, cr, uid, id, default=None, context=None): - raise osv.except_osv(_('Warning!'), _('You cannot duplicate a calendar attendee.')) - - def onchange_partner_id(self, cr, uid, ids, partner_id,context=None): - """ - Make entry on email and availbility on change of partner_id field. - @param cr: the current row, from the database cursor - @param uid: the current user's ID for security checks - @param ids: list of calendar attendee's IDs - @param partner_id: changed value of partner id - @param context: a standard dictionary for contextual values - @return: dictionary of values which put value in email and availability fields - """ - - if not partner_id: - return {'value': {'email': ''}} - partner = self.pool.get('res.partner').browse(cr, uid, partner_id, context=context) - return {'value': {'email': partner.email}} - - def get_ics_file(self, cr, uid, event_obj, context=None): - """ - Returns iCalendar file for the event invitation. - @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 event_obj: event object (browse record) - @param context: a standard dictionary for contextual values - @return: .ics file content - """ - res = None - def ics_datetime(idate, short=False): - if idate: - #returns the datetime as UTC, because it is stored as it in the database - return datetime.strptime(idate, '%Y-%m-%d %H:%M:%S').replace(tzinfo=pytz.timezone('UTC')) - return False - try: - # FIXME: why isn't this in CalDAV? - import vobject - except ImportError: - return res - cal = vobject.iCalendar() - event = cal.add('vevent') - if not event_obj.date_deadline or not event_obj.date: - raise osv.except_osv(_('Warning!'),_("First you have to specify the date of the invitation.")) - event.add('created').value = ics_datetime(time.strftime('%Y-%m-%d %H:%M:%S')) - event.add('dtstart').value = ics_datetime(event_obj.date) - event.add('dtend').value = ics_datetime(event_obj.date_deadline) - event.add('summary').value = event_obj.name - if event_obj.description: - event.add('description').value = event_obj.description - if event_obj.location: - event.add('location').value = event_obj.location - if event_obj.rrule: - event.add('rrule').value = event_obj.rrule - - if event_obj.user_id or event_obj.organizer_id: - event_org = event.add('organizer') - organizer = event_obj.organizer_id - if not organizer: - organizer = event_obj.user_id - event_org.params['CN'] = [organizer.name] - event_org.value = 'MAILTO:' + (organizer.email or organizer.name) - - if event_obj.alarm_id: - # computes alarm data - valarm = event.add('valarm') - alarm_object = self.pool.get('res.alarm') - alarm_data = alarm_object.read(cr, uid, event_obj.alarm_id.id, context=context) - # Compute trigger data - interval = alarm_data['trigger_interval'] - occurs = alarm_data['trigger_occurs'] - duration = (occurs == 'after' and alarm_data['trigger_duration']) \ - or -(alarm_data['trigger_duration']) - related = alarm_data['trigger_related'] - trigger = valarm.add('TRIGGER') - trigger.params['related'] = [related.upper()] - if interval == 'days': - delta = timedelta(days=duration) - if interval == 'hours': - delta = timedelta(hours=duration) - if interval == 'minutes': - delta = timedelta(minutes=duration) - trigger.value = delta - # Compute other details - valarm.add('DESCRIPTION').value = alarm_data['name'] or 'OpenERP' - - for attendee in event_obj.attendee_ids: - attendee_add = event.add('attendee') - attendee_add.params['CUTYPE'] = [str(attendee.cutype)] - attendee_add.params['ROLE'] = [str(attendee.role)] - attendee_add.params['RSVP'] = [str(attendee.rsvp)] - attendee_add.value = 'MAILTO:' + (attendee.email or '') - res = cal.serialize() - return res - - def _send_mail(self, cr, uid, ids, mail_to, email_from=tools.config.get('email_from', False), context=None): - """ - Send mail for event invitation to event attendees. - @param email_from: email address for user sending the mail - @return: True - """ - company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.name - for att in self.browse(cr, uid, ids, context=context): - sign = att.sent_by_uid and att.sent_by_uid.signature or '' - sign = '
'.join(sign and sign.split('\n') or []) - res_obj = att.ref - if res_obj: - att_infos = [] - sub = res_obj.name - other_invitation_ids = self.search(cr, uid, [('ref', '=', res_obj._name + ',' + str(res_obj.id))]) - - for att2 in self.browse(cr, uid, other_invitation_ids): - att_infos.append(((att2.user_id and att2.user_id.name) or \ - (att2.partner_id and att2.partner_id.name) or \ - att2.email) + ' - Status: ' + att2.state.title()) - #dates and times are gonna be expressed in `tz` time (local timezone of the `uid`) - tz = context.get('tz', pytz.timezone('UTC')) - #res_obj.date and res_obj.date_deadline are in UTC in database so we use context_timestamp() to transform them in the `tz` timezone - date_start = fields.datetime.context_timestamp(cr, uid, datetime.strptime(res_obj.date, tools.DEFAULT_SERVER_DATETIME_FORMAT), context=context) - date_stop = False - if res_obj.date_deadline: - date_stop = fields.datetime.context_timestamp(cr, uid, datetime.strptime(res_obj.date_deadline, tools.DEFAULT_SERVER_DATETIME_FORMAT), context=context) - body_vals = {'name': res_obj.name, - 'start_date': date_start, - 'end_date': date_stop, - 'timezone': tz, - 'description': res_obj.description or '-', - 'location': res_obj.location or '-', - 'attendees': '
'.join(att_infos), - 'user': res_obj.user_id and res_obj.user_id.name or 'OpenERP User', - 'sign': sign, - 'company': company - } - body = html_invitation % body_vals - if mail_to and email_from: - ics_file = self.get_ics_file(cr, uid, res_obj, context=context) - vals = {'email_from': email_from, - 'email_to': mail_to, - 'state': 'outgoing', - 'subject': sub, - 'body_html': body, - 'auto_delete': True} - if ics_file: - vals['attachment_ids'] = [(0,0,{'name': 'invitation.ics', - 'datas_fname': 'invitation.ics', - 'datas': str(ics_file).encode('base64')})] - self.pool.get('mail.mail').create(cr, uid, vals, context=context) - return True - - def onchange_user_id(self, cr, uid, ids, user_id, *args, **argv): - """ - Make entry on email and availbility on change of user_id field. - @param cr: the current row, from the database cursor - @param uid: the current user's ID for security checks - @param ids: list of calendar attendee's IDs - @param user_id: changed value of User id - @return: dictionary of values which put value in email and availability fields - """ - - if not user_id: - return {'value': {'email': ''}} - usr_obj = self.pool.get('res.users') - user = usr_obj.browse(cr, uid, user_id, *args) - return {'value': {'email': user.email, 'availability':user.availability}} - - def do_tentative(self, cr, uid, ids, context=None, *args): - """ - Makes event invitation as Tentative. - @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 calendar attendee's IDs - @param *args: get Tupple value - @param context: a standard dictionary for contextual values - """ - return self.write(cr, uid, ids, {'state': 'tentative'}, context) - - def do_accept(self, cr, uid, ids, context=None, *args): - """ - Marks event invitation as Accepted. - @param cr: the current row, from the database cursor - @param uid: the current user's ID for security checks - @param ids: list of calendar attendee's IDs - @param context: a standard dictionary for contextual values - @return: True - """ - if context is None: - context = {} - - return self.write(cr, uid, ids, {'state': 'accepted'}, context) - - def do_decline(self, cr, uid, ids, context=None, *args): - """ - Marks event invitation as Declined. - @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 calendar attendee's IDs - @param *args: get Tupple value - @param context: a standard dictionary for contextual values - """ - if context is None: - context = {} - return self.write(cr, uid, ids, {'state': 'declined'}, context) - - def create(self, cr, uid, vals, context=None): - """ - Overrides orm create method. - @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 vals: get Values - @param context: a standard dictionary for contextual values - """ - if context is None: - context = {} - if not vals.get("email") and vals.get("cn"): - cnval = vals.get("cn").split(':') - email = filter(lambda x:x.__contains__('@'), cnval) - vals['email'] = email and email[0] or '' - vals['cn'] = vals.get("cn") - res = super(calendar_attendee, self).create(cr, uid, vals, context=context) - return res - - -class res_alarm(osv.osv): - """Resource Alarm """ - _name = 'res.alarm' - _description = 'Basic Alarm Information' - - _columns = { - 'name':fields.char('Name', size=256, required=True), - 'trigger_occurs': fields.selection([('before', 'Before'), \ - ('after', 'After')], \ - 'Triggers', required=True), - 'trigger_interval': fields.selection([('minutes', 'Minutes'), \ - ('hours', 'Hours'), \ - ('days', 'Days')], 'Interval', \ - required=True), - 'trigger_duration': fields.integer('Duration', required=True), - 'trigger_related': fields.selection([('start', 'The event starts'), \ - ('end', 'The event ends')], \ - 'Related to', required=True), - 'duration': fields.integer('Duration', help="""Duration' and 'Repeat' \ -are both optional, but if one occurs, so MUST the other"""), - 'repeat': fields.integer('Repeat'), - '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.") - } - _defaults = { - 'trigger_interval': 'minutes', - 'trigger_duration': 5, - 'trigger_occurs': 'before', - 'trigger_related': 'start', - 'active': 1, - } - - def do_alarm_create(self, cr, uid, ids, model, date, context=None): - """ - Create Alarm for event. - @param cr: the current row, from the database cursor, - @param uid: the current user's ID for security checks, - @param ids: List of res alarm's IDs. - @param model: Model name. - @param date: Event date - @param context: A standard dictionary for contextual values - @return: True - """ - if context is None: - context = {} - alarm_obj = self.pool.get('calendar.alarm') - res_alarm_obj = self.pool.get('res.alarm') - ir_obj = self.pool.get('ir.model') - model_id = ir_obj.search(cr, uid, [('model', '=', model)])[0] - - model_obj = self.pool[model] - for data in model_obj.browse(cr, uid, ids, context=context): - - basic_alarm = data.alarm_id - cal_alarm = data.base_calendar_alarm_id - if (not basic_alarm and cal_alarm) or (basic_alarm and cal_alarm): - new_res_alarm = None - # Find for existing res.alarm - duration = cal_alarm.trigger_duration - interval = cal_alarm.trigger_interval - occurs = cal_alarm.trigger_occurs - related = cal_alarm.trigger_related - domain = [('trigger_duration', '=', duration), ('trigger_interval', '=', interval), ('trigger_occurs', '=', occurs), ('trigger_related', '=', related)] - alarm_ids = res_alarm_obj.search(cr, uid, domain, context=context) - if not alarm_ids: - val = { - 'trigger_duration': duration, - 'trigger_interval': interval, - 'trigger_occurs': occurs, - 'trigger_related': related, - 'name': str(duration) + ' ' + str(interval) + ' ' + str(occurs) - } - new_res_alarm = res_alarm_obj.create(cr, uid, val, context=context) - else: - new_res_alarm = alarm_ids[0] - cr.execute('UPDATE %s ' % model_obj._table + \ - ' SET base_calendar_alarm_id=%s, alarm_id=%s ' \ - ' WHERE id=%s', - (cal_alarm.id, new_res_alarm, data.id)) - - self.do_alarm_unlink(cr, uid, [data.id], model) - if basic_alarm: - vals = { - 'action': 'display', - 'description': data.description, - 'name': data.name, - 'attendee_ids': [(6, 0, map(lambda x:x.id, data.attendee_ids))], - 'trigger_related': basic_alarm.trigger_related, - 'trigger_duration': basic_alarm.trigger_duration, - 'trigger_occurs': basic_alarm.trigger_occurs, - 'trigger_interval': basic_alarm.trigger_interval, - 'duration': basic_alarm.duration, - 'repeat': basic_alarm.repeat, - 'state': 'run', - 'event_date': data[date], - 'res_id': data.id, - 'model_id': model_id, - 'user_id': uid - } - alarm_id = alarm_obj.create(cr, uid, vals) - cr.execute('UPDATE %s ' % model_obj._table + \ - ' SET base_calendar_alarm_id=%s, alarm_id=%s ' - ' WHERE id=%s', \ - ( alarm_id, basic_alarm.id, data.id) ) - return True - - def do_alarm_unlink(self, cr, uid, ids, model, context=None): - """ - Delete alarm specified in ids - @param cr: the current row, from the database cursor, - @param uid: the current user's ID for security checks, - @param ids: List of res alarm's IDs. - @param model: Model name for which alarm is to be cleared. - @return: True - """ - if context is None: - context = {} - alarm_obj = self.pool.get('calendar.alarm') - ir_obj = self.pool.get('ir.model') - model_id = ir_obj.search(cr, uid, [('model', '=', model)])[0] - model_obj = self.pool[model] - for data in model_obj.browse(cr, uid, ids, context=context): - alarm_ids = alarm_obj.search(cr, uid, [('model_id', '=', model_id), ('res_id', '=', data.id)]) - if alarm_ids: - alarm_obj.unlink(cr, uid, alarm_ids) - cr.execute('Update %s set base_calendar_alarm_id=NULL, alarm_id=NULL\ - where id=%%s' % model_obj._table,(data.id,)) - return True - - -class calendar_alarm(osv.osv): - _name = 'calendar.alarm' - _description = 'Event alarm information' - _inherit = 'res.alarm' - __attribute__ = {} - - _columns = { - 'alarm_id': fields.many2one('res.alarm', 'Basic Alarm', ondelete='cascade'), - 'name': fields.char('Summary', size=124, help="""Contains the text to be \ - used as the message subject for email \ - or contains the text to be used for display"""), - 'action': fields.selection([('audio', 'Audio'), ('display', 'Display'), \ - ('procedure', 'Procedure'), ('email', 'Email') ], 'Action', \ - required=True, help="Defines the action to be invoked when an alarm is triggered"), - 'description': fields.text('Description', help='Provides a more complete \ - description of the calendar component, than that \ - provided by the "SUMMARY" property'), - 'attendee_ids': fields.many2many('calendar.attendee', 'alarm_attendee_rel', \ - 'alarm_id', 'attendee_id', 'Attendees', readonly=True), - 'attach': fields.binary('Attachment', help="""* Points to a sound resource,\ - which is rendered when the alarm is triggered for audio, - * File which is intended to be sent as message attachments for email, - * Points to a procedure resource, which is invoked when\ - the alarm is triggered for procedure."""), - 'res_id': fields.integer('Resource ID'), - 'model_id': fields.many2one('ir.model', 'Model'), - 'user_id': fields.many2one('res.users', 'Owner'), - 'event_date': fields.datetime('Event Date'), - 'event_end_date': fields.datetime('Event End Date'), - 'trigger_date': fields.datetime('Trigger Date', readonly="True"), - 'state':fields.selection([ - ('draft', 'Draft'), - ('run', 'Run'), - ('stop', 'Stop'), - ('done', 'Done'), - ], 'Status', select=True, readonly=True), - } - - _defaults = { - 'action': 'email', - 'state': 'run', - } - - def create(self, cr, uid, vals, context=None): - """ - Overrides orm create method. - @param self: The object pointer - @param cr: the current row, from the database cursor, - @param vals: dictionary of fields value.{'name_of_the_field': value, ...} - @param context: A standard dictionary for contextual values - @return: new record id for calendar_alarm. - """ - if context is None: - context = {} - event_date = vals.get('event_date', False) - if event_date: - dtstart = datetime.strptime(vals['event_date'], "%Y-%m-%d %H:%M:%S") - if vals['trigger_interval'] == 'days': - delta = timedelta(days=vals['trigger_duration']) - if vals['trigger_interval'] == 'hours': - delta = timedelta(hours=vals['trigger_duration']) - if vals['trigger_interval'] == 'minutes': - delta = timedelta(minutes=vals['trigger_duration']) - trigger_date = dtstart + (vals['trigger_occurs'] == 'after' and delta or -delta) - vals['trigger_date'] = trigger_date - res = super(calendar_alarm, self).create(cr, uid, vals, context=context) - return res - - def do_run_scheduler(self, cr, uid, automatic=False, use_new_cursor=False, \ - context=None): - """Scheduler for event reminder - @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 calendar alarm's IDs. - @param use_new_cursor: False or the dbname - @param context: A standard dictionary for contextual values - """ - if context is None: - context = {} - current_datetime = datetime.now() - alarm_ids = self.search(cr, uid, [('state', '!=', 'done')], context=context) - - mail_to = "" - - for alarm in self.browse(cr, uid, alarm_ids, context=context): - next_trigger_date = None - update_vals = {} - model_obj = self.pool[alarm.model_id.model] - res_obj = model_obj.browse(cr, uid, alarm.res_id, context=context) - re_dates = [] - - if hasattr(res_obj, 'rrule') and res_obj.rrule: - event_date = datetime.strptime(res_obj.date, '%Y-%m-%d %H:%M:%S') - #exdate is a string and we need a list - exdate = res_obj.exdate and res_obj.exdate.split(',') or [] - recurrent_dates = get_recurrent_dates(res_obj.rrule, exdate, event_date, res_obj.exrule) - - trigger_interval = alarm.trigger_interval - if trigger_interval == 'days': - delta = timedelta(days=alarm.trigger_duration) - if trigger_interval == 'hours': - delta = timedelta(hours=alarm.trigger_duration) - if trigger_interval == 'minutes': - delta = timedelta(minutes=alarm.trigger_duration) - delta = alarm.trigger_occurs == 'after' and delta or -delta - - for rdate in recurrent_dates: - if rdate + delta > current_datetime: - break - if rdate + delta <= current_datetime: - re_dates.append(rdate.strftime("%Y-%m-%d %H:%M:%S")) - rest_dates = recurrent_dates[len(re_dates):] - next_trigger_date = rest_dates and rest_dates[0] or None - - else: - re_dates = [alarm.trigger_date] - - if re_dates: - if alarm.action == 'email': - sub = '[OpenERP Reminder] %s' % (alarm.name) - body = """
-Event: %s
-Event Date: %s
-Description: %s
-
-From:
-      %s
-
-----
-%s
-
-""" % (alarm.name, alarm.trigger_date, alarm.description, \ - alarm.user_id.name, alarm.user_id.signature) - mail_to = alarm.user_id.email - for att in alarm.attendee_ids: - mail_to = mail_to + " " + att.user_id.email - if mail_to: - vals = { - 'state': 'outgoing', - 'subject': sub, - 'body_html': body, - 'email_to': mail_to, - 'email_from': tools.config.get('email_from', mail_to), - } - self.pool.get('mail.mail').create(cr, uid, vals, context=context) - if next_trigger_date: - update_vals.update({'trigger_date': next_trigger_date}) - else: - update_vals.update({'state': 'done'}) - self.write(cr, uid, [alarm.id], update_vals) - return True - - - -class calendar_event(osv.osv): - _name = "calendar.event" - _description = "Calendar Event" - __attribute__ = {} - - def _tz_get(self, cr, uid, context=None): - return [(x.lower(), x) for x in pytz.all_timezones] - - def onchange_dates(self, cr, uid, ids, start_date, duration=False, end_date=False, allday=False, context=None): - """Returns duration and/or end date based on values 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 ids: List of calendar event's IDs. - @param start_date: Starting date - @param duration: Duration between start date and end date - @param end_date: Ending Datee - @param context: A standard dictionary for contextual values - """ - if context is None: - context = {} - - value = {} - if not start_date: - return value - if not end_date and not duration: - duration = 1.00 - value['duration'] = duration - - start = datetime.strptime(start_date, "%Y-%m-%d %H:%M:%S") - if allday: # For all day event - duration = 24.0 - value['duration'] = duration - # change start_date's time to 00:00:00 in the user's timezone - user = self.pool.get('res.users').browse(cr, uid, uid) - tz = pytz.timezone(user.tz) if user.tz else pytz.utc - start = pytz.utc.localize(start).astimezone(tz) # convert start in user's timezone - start = start.replace(hour=0, minute=0, second=0) # change start's time to 00:00:00 - start = start.astimezone(pytz.utc) # convert start back to utc - start_date = start.strftime("%Y-%m-%d %H:%M:%S") - value['date'] = start_date - - if end_date and not duration: - end = datetime.strptime(end_date, "%Y-%m-%d %H:%M:%S") - diff = end - start - duration = float(diff.days)* 24 + (float(diff.seconds) / 3600) - value['duration'] = round(duration, 2) - elif not end_date: - end = start + timedelta(hours=duration) - value['date_deadline'] = end.strftime("%Y-%m-%d %H:%M:%S") - elif end_date and duration and not allday: - # we have both, keep them synchronized: - # set duration based on end_date (arbitrary decision: this avoid - # getting dates like 06:31:48 instead of 06:32:00) - end = datetime.strptime(end_date, "%Y-%m-%d %H:%M:%S") - diff = end - start - duration = float(diff.days)* 24 + (float(diff.seconds) / 3600) - value['duration'] = round(duration, 2) - - return {'value': value} - - def unlink_events(self, cr, uid, ids, context=None): - """ - This function deletes event which are linked with the event with recurrent_id - (Removes the events which refers to the same UID value) - """ - if context is None: - context = {} - for event_id in ids: - cr.execute("select id from %s where recurrent_id=%%s" % (self._table), (event_id,)) - r_ids = map(lambda x: x[0], cr.fetchall()) - self.unlink(cr, uid, r_ids, context=context) - return True - - def _get_rulestring(self, cr, uid, ids, name, arg, context=None): - """ - Gets Recurrence rule string according to value type RECUR of iCalendar from the values given. - @param self: The object pointer - @param cr: the current row, from the database cursor, - @param id: List of calendar event's ids. - @param context: A standard dictionary for contextual values - @return: dictionary of rrule value. - """ - - result = {} - if not isinstance(ids, list): - ids = [ids] - - for id in ids: - #read these fields as SUPERUSER because if the record is private a normal search could return False and raise an error - data = self.read(cr, SUPERUSER_ID, id, ['interval', 'count'], context=context) - if data.get('interval', 0) < 0: - raise osv.except_osv(_('Warning!'), _('Interval cannot be negative.')) - if data.get('count', 0) <= 0: - raise osv.except_osv(_('Warning!'), _('Count cannot be negative or 0.')) - data = self.read(cr, uid, id, ['id','byday','recurrency', 'month_list','end_date', 'rrule_type', 'select1', 'interval', 'count', 'end_type', 'mo', 'tu', 'we', 'th', 'fr', 'sa', 'su', 'exrule', 'day', 'week_list' ], context=context) - event = data['id'] - if data['recurrency']: - result[event] = self.compute_rule_string(data) - else: - result[event] = "" - return result - - def _rrule_write(self, obj, cr, uid, ids, field_name, field_value, args, context=None): - data = self._get_empty_rrule_data() - if field_value: - data['recurrency'] = True - for event in self.browse(cr, uid, ids, context=context): - rdate = rule_date or event.date - update_data = self._parse_rrule(field_value, dict(data), rdate) - data.update(update_data) - super(calendar_event, obj).write(cr, uid, ids, data, context=context) - return True - - _columns = { - 'id': fields.integer('ID', readonly=True), - 'sequence': fields.integer('Sequence'), - 'name': fields.char('Description', size=64, required=False, states={'done': [('readonly', True)]}), - 'date': fields.datetime('Date', states={'done': [('readonly', True)]}, required=True,), - 'date_deadline': fields.datetime('End Date', states={'done': [('readonly', True)]}, required=True,), - 'create_date': fields.datetime('Created', readonly=True), - 'duration': fields.float('Duration', states={'done': [('readonly', True)]}), - 'description': fields.text('Description', states={'done': [('readonly', True)]}), - 'class': fields.selection([('public', 'Public'), ('private', 'Private'), \ - ('confidential', 'Public for Employees')], 'Privacy', states={'done': [('readonly', True)]}), - 'location': fields.char('Location', size=264, help="Location of Event", states={'done': [('readonly', True)]}), - 'show_as': fields.selection([('free', 'Free'), ('busy', 'Busy')], \ - 'Show Time as', states={'done': [('readonly', True)]}), - 'base_calendar_url': fields.char('Caldav URL', size=264), - 'state': fields.selection([ - ('tentative', 'Uncertain'), - ('cancelled', 'Cancelled'), - ('confirmed', 'Confirmed'), - ], 'Status', readonly=True), - 'exdate': fields.text('Exception Date/Times', help="This property \ -defines the list of date/time exceptions for a recurring calendar component."), - 'exrule': fields.char('Exception Rule', size=352, help="Defines a \ -rule or repeating pattern of time to exclude from the recurring rule."), - 'rrule': fields.function(_get_rulestring, type='char', size=124, \ - fnct_inv=_rrule_write, store=True, string='Recurrent Rule'), - 'rrule_type': fields.selection([ - ('daily', 'Day(s)'), - ('weekly', 'Week(s)'), - ('monthly', 'Month(s)'), - ('yearly', 'Year(s)') - ], 'Recurrency', states={'done': [('readonly', True)]}, - help="Let the event automatically repeat at that interval"), - 'alarm_id': fields.many2one('res.alarm', 'Reminder', states={'done': [('readonly', True)]}, - help="Set an alarm at this time, before the event occurs" ), - 'base_calendar_alarm_id': fields.many2one('calendar.alarm', 'Alarm'), - 'recurrent_id': fields.integer('Recurrent ID'), - 'recurrent_id_date': fields.datetime('Recurrent ID date'), - 'vtimezone': fields.selection(_tz_get, size=64, string='Timezone'), - 'user_id': fields.many2one('res.users', 'Responsible', states={'done': [('readonly', True)]}), - 'organizer': fields.char("Organizer (deprecated)", size=256, states={'done': [('readonly', True)]}, - deprecated='Will be removed with OpenERP v8; use organizer_id field instead'), # Map with organizer attribute of VEvent. - 'organizer_id': fields.many2one('res.users', 'Organizer', states={'done': [('readonly', True)]}), - 'end_type' : fields.selection([('count', 'Number of repetitions'), ('end_date','End date')], 'Recurrence Termination'), - 'interval': fields.integer('Repeat Every', help="Repeat every (Days/Week/Month/Year)"), - 'count': fields.integer('Repeat', help="Repeat x times"), - 'mo': fields.boolean('Mon'), - 'tu': fields.boolean('Tue'), - 'we': fields.boolean('Wed'), - 'th': fields.boolean('Thu'), - 'fr': fields.boolean('Fri'), - 'sa': fields.boolean('Sat'), - 'su': fields.boolean('Sun'), - 'select1': fields.selection([('date', 'Date of month'), - ('day', 'Day of month')], 'Option'), - 'day': fields.integer('Date of month'), - 'week_list': fields.selection([ - ('MO', 'Monday'), - ('TU', 'Tuesday'), - ('WE', 'Wednesday'), - ('TH', 'Thursday'), - ('FR', 'Friday'), - ('SA', 'Saturday'), - ('SU', 'Sunday')], 'Weekday'), - 'byday': fields.selection([ - ('1', 'First'), - ('2', 'Second'), - ('3', 'Third'), - ('4', 'Fourth'), - ('5', 'Fifth'), - ('-1', 'Last')], 'By day'), - 'month_list': fields.selection(months.items(), 'Month'), - 'end_date': fields.date('Repeat Until'), - 'attendee_ids': fields.many2many('calendar.attendee', 'event_attendee_rel', \ - 'event_id', 'attendee_id', 'Attendees'), - 'allday': fields.boolean('All Day', states={'done': [('readonly', True)]}), - '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 - local_context = context.copy() - local_context.pop('default_state', None) - 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=local_context) - if partner.email: - mail_to = mail_to + " " + 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, context=context) - return True - - def default_organizer(self, cr, uid, context=None): - """ - .. deprecated:: 8.0 - Use organizer_id field and its default value instead. - """ - user_pool = self.pool.get('res.users') - user = user_pool.browse(cr, uid, uid, context=context) - res = user.name - if user.email: - res += " <%s>" %(user.email) - return res - - _defaults = { - 'end_type': 'count', - 'count': 1, - 'rrule_type': False, - 'state': 'tentative', - 'class': 'public', - 'show_as': 'busy', - 'select1': 'date', - 'interval': 1, - 'active': 1, - 'user_id': lambda self, cr, uid, ctx: uid, - } - - 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 - This method gives ids of dates that comes between start date and end date of calendar views - @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 limit: The Number of Results to Return """ - if not context: - context = {} - - result = [] - for data in super(calendar_event, self).read(cr, uid, select, ['rrule', 'recurrency', 'exdate', 'exrule', 'date'], context=context): - if not data['recurrency'] or not data['rrule']: - result.append(data['id']) - continue - event_date = datetime.strptime(data['date'], "%Y-%m-%d %H:%M:%S") - - # TOCHECK: the start date should be replaced by event date; the event date will be changed by that of calendar code - - if not data['rrule']: - continue - - exdate = data['exdate'] and data['exdate'].split(',') or [] - rrule_str = data['rrule'] - new_rrule_str = [] - rrule_until_date = False - is_until = False - for rule in rrule_str.split(';'): - name, value = rule.split('=') - if name == "UNTIL": - is_until = True - value = parser.parse(value) - rrule_until_date = parser.parse(value.strftime("%Y-%m-%d %H:%M:%S")) - value = value.strftime("%Y%m%d%H%M%S") - new_rule = '%s=%s' % (name, value) - new_rrule_str.append(new_rule) - new_rrule_str = ';'.join(new_rrule_str) - rdates = get_recurrent_dates(str(new_rrule_str), exdate, event_date, data['exrule']) - for r_date in rdates: - # fix domain evaluation - # step 1: check date and replace expression by True or False, replace other expressions by True - # step 2: evaluation of & and | - # check if there are one False - pile = [] - for arg in domain: - if str(arg[0]) in (str('date'), str('date_deadline')): - if (arg[1] == '='): - ok = r_date.strftime('%Y-%m-%d')==arg[2] - if (arg[1] == '>'): - ok = r_date.strftime('%Y-%m-%d')>arg[2] - if (arg[1] == '<'): - ok = r_date.strftime('%Y-%m-%d')='): - ok = r_date.strftime('%Y-%m-%d')>=arg[2] - if (arg[1] == '<='): - ok = r_date.strftime('%Y-%m-%d')<=arg[2] - pile.append(ok) - elif str(arg) == str('&') or str(arg) == str('|'): - pile.append(arg) - else: - pile.append(True) - pile.reverse() - new_pile = [] - for item in pile: - if not isinstance(item, basestring): - res = item - elif str(item) == str('&'): - first = new_pile.pop() - second = new_pile.pop() - res = first and second - elif str(item) == str('|'): - first = new_pile.pop() - second = new_pile.pop() - res = first or second - new_pile.append(res) - - if [True for item in new_pile if not item]: - continue - idval = real_id2base_calendar_id(data['id'], r_date.strftime("%Y-%m-%d %H:%M:%S")) - result.append(idval) - - if isinstance(select, (str, int, long)): - return ids and ids[0] or False - else: - ids = list(set(result)) - return ids - - def compute_rule_string(self, data): - """ - Compute rule string according to value type RECUR of iCalendar from the values given. - @param self: the object pointer - @param data: dictionary of freq and interval value - @return: string containing recurring rule (empty if no rule) - """ - def get_week_string(freq, data): - weekdays = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su'] - if freq == 'weekly': - byday = map(lambda x: x.upper(), filter(lambda x: data.get(x) and x in weekdays, data)) - if byday: - return ';BYDAY=' + ','.join(byday) - return '' - - def get_month_string(freq, data): - if freq == 'monthly': - if data.get('select1')=='date' and (data.get('day') < 1 or data.get('day') > 31): - raise osv.except_osv(_('Error!'), ("Please select a proper day of the month.")) - - if data.get('select1')=='day': - return ';BYDAY=' + data.get('byday') + data.get('week_list') - elif data.get('select1')=='date': - return ';BYMONTHDAY=' + str(data.get('day')) - return '' - - def get_end_date(data): - if data.get('end_date'): - data['end_date_new'] = ''.join((re.compile('\d')).findall(data.get('end_date'))) + 'T235959Z' - - return (data.get('end_type') == 'count' and (';COUNT=' + str(data.get('count'))) or '') +\ - ((data.get('end_date_new') and data.get('end_type') == 'end_date' and (';UNTIL=' + data.get('end_date_new'))) or '') - - freq = data.get('rrule_type', False) - res = '' - if freq: - interval_srting = data.get('interval') and (';INTERVAL=' + str(data.get('interval'))) or '' - res = 'FREQ=' + freq.upper() + get_week_string(freq, data) + interval_srting + get_end_date(data) + get_month_string(freq, data) - - return res - - def _get_empty_rrule_data(self): - return { - 'byday' : False, - 'recurrency' : False, - 'end_date' : False, - 'rrule_type' : False, - 'select1' : False, - 'interval' : 0, - 'count' : False, - 'end_type' : False, - 'mo' : False, - 'tu' : False, - 'we' : False, - 'th' : False, - 'fr' : False, - 'sa' : False, - 'su' : False, - 'exrule' : False, - 'day' : False, - 'week_list' : False - } - - def _parse_rrule(self, rule, data, date_start): - day_list = ['mo', 'tu', 'we', 'th', 'fr', 'sa', 'su'] - rrule_type = ['yearly', 'monthly', 'weekly', 'daily'] - r = rrule.rrulestr(rule, dtstart=datetime.strptime(date_start, "%Y-%m-%d %H:%M:%S")) - - if r._freq > 0 and r._freq < 4: - data['rrule_type'] = rrule_type[r._freq] - - data['count'] = r._count - data['interval'] = r._interval - data['end_date'] = r._until and r._until.strftime("%Y-%m-%d %H:%M:%S") - #repeat weekly - if r._byweekday: - for i in xrange(0,7): - if i in r._byweekday: - data[day_list[i]] = True - data['rrule_type'] = 'weekly' - #repeat monthly by nweekday ((weekday, weeknumber), ) - if r._bynweekday: - data['week_list'] = day_list[r._bynweekday[0][0]].upper() - data['byday'] = r._bynweekday[0][1] - data['select1'] = 'day' - data['rrule_type'] = 'monthly' - - if r._bymonthday: - data['day'] = r._bymonthday[0] - data['select1'] = 'date' - data['rrule_type'] = 'monthly' - - #repeat yearly but for openerp it's monthly, take same information as monthly but interval is 12 times - if r._bymonth: - data['interval'] = data['interval'] * 12 - - #FIXEME handle forever case - #end of recurrence - #in case of repeat for ever that we do not support right now - if not (data.get('count') or data.get('end_date')): - data['count'] = 100 - if data.get('count'): - data['end_type'] = 'count' - else: - data['end_type'] = 'end_date' - return data - - def search(self, cr, uid, args, offset=0, limit=0, order=None, context=None, count=False): - if context is None: - context = {} - new_args = [] - - for arg in args: - new_arg = arg - if arg[0] in ('date_deadline', unicode('date_deadline')): - if context.get('virtual_id', True): - new_args += ['|','&',('recurrency','=',1),('end_date', arg[1], arg[2])] - elif arg[0] == "id": - new_id = get_real_ids(arg[2]) - new_arg = (arg[0], arg[1], new_id) - new_args.append(new_arg) - #offset, limit and count must be treated separately as we may need to deal with virtual ids - res = super(calendar_event, self).search(cr, uid, new_args, offset=0, limit=0, order=order, context=context, count=False) - if context.get('virtual_id', True): - res = self.get_recurrent_ids(cr, uid, res, args, limit, context=context) - if count: - return len(res) - elif limit: - return res[offset:offset+limit] - return res - - def _get_data(self, cr, uid, id, context=None): - return self.read(cr, uid, id,['date', 'date_deadline']) - - def need_to_update(self, event_id, vals): - split_id = str(event_id).split("-") - if len(split_id) < 2: - return False - else: - date_start = vals.get('date', '') - try: - date_start = datetime.strptime(date_start, '%Y-%m-%d %H:%M:%S').strftime("%Y%m%d%H%M%S") - return date_start == split_id[1] - except Exception: - return True - - def write(self, cr, uid, ids, vals, context=None, check=True, update_check=True): - def _only_changes_to_apply_on_real_ids(field_names): - ''' return True if changes are only to be made on the real ids''' - for field in field_names: - if field not in ['message_follower_ids']: - return False - return True - - context = context or {} - if isinstance(ids, (str, int, long)): - ids = [ids] - res = False - - # Special write of complex IDS - for event_id in ids[:]: - if len(str(event_id).split('-')) == 1: - continue - ids.remove(event_id) - real_event_id = base_calendar_id2real_id(event_id) - - # if we are setting the recurrency flag to False or if we are only changing fields that - # should be only updated on the real ID and not on the virtual (like message_follower_ids): - # then set real ids to be updated. - if not vals.get('recurrency', True) or _only_changes_to_apply_on_real_ids(vals.keys()): - ids.append(real_event_id) - continue - - #if edit one instance of a reccurrent id - data = self.read(cr, uid, event_id, ['date', 'date_deadline', \ - 'rrule', 'duration', 'exdate']) - if data.get('rrule'): - data.update( - vals, - recurrent_id=real_event_id, - recurrent_id_date=data.get('date'), - rrule_type=False, - rrule='', - recurrency=False, - ) - #do not copy the id - if data.get('id'): - del(data['id']) - new_id = self.copy(cr, uid, real_event_id, default=data, context=context) - - date_new = event_id.split('-')[1] - date_new = time.strftime("%Y%m%dT%H%M%S", \ - time.strptime(date_new, "%Y%m%d%H%M%S")) - exdate = (data['exdate'] and (data['exdate'] + ',') or '') + date_new - res = self.write(cr, uid, [real_event_id], {'exdate': exdate}) - - context.update({'active_id': new_id, 'active_ids': [new_id]}) - continue - - if vals.get('vtimezone', '') and vals.get('vtimezone', '').startswith('/freeassociation.sourceforge.net/tzfile/'): - vals['vtimezone'] = vals['vtimezone'][40:] - - res = super(calendar_event, self).write(cr, uid, ids, vals, context=context) - - # set end_date for calendar searching - if vals.get('recurrency', True) and vals.get('end_type', 'count') in ('count', unicode('count')) and \ - (vals.get('rrule_type') or vals.get('count') or vals.get('date') or vals.get('date_deadline')): - for data in self.read(cr, uid, ids, ['date', 'date_deadline', 'recurrency', 'rrule_type', 'count', 'end_type'], context=context): - end_date = self._set_recurrency_end_date(data, context=context) - super(calendar_event, self).write(cr, uid, [data['id']], {'end_date': end_date}, 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): - alarm_obj = self.pool.get('res.alarm') - alarm_obj.do_alarm_create(cr, uid, ids, self._name, 'date', context=context) - return res or True and False - - def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False): - if not context: - context = {} - - if 'date' in groupby: - raise osv.except_osv(_('Warning!'), _('Group by date is not supported, use the calendar view instead.')) - virtual_id = context.get('virtual_id', True) - context.update({'virtual_id': False}) - res = super(calendar_event, self).read_group(cr, uid, domain, fields, groupby, offset=offset, limit=limit, context=context, orderby=orderby) - for re in res: - #remove the count, since the value is not consistent with the result of the search when expand the group - for groupname in groupby: - if re.get(groupname + "_count"): - del re[groupname + "_count"] - re.get('__context', {}).update({'virtual_id' : virtual_id}) - return res - - def read(self, cr, uid, ids, fields=None, context=None, load='_classic_read'): - if context is None: - context = {} - fields2 = fields and fields[:] or None - - EXTRAFIELDS = ('class','user_id','duration') - for f in EXTRAFIELDS: - if fields and (f not in fields): - fields2.append(f) - - # FIXME This whole id mangling has to go! - if isinstance(ids, (str, int, long)): - select = [ids] - else: - select = ids - - select = map(lambda x: (x, base_calendar_id2real_id(x)), select) - result = [] - - real_data = super(calendar_event, self).read(cr, uid, - [real_id for base_calendar_id, real_id in select], - fields=fields2, context=context, load=load) - real_data = dict(zip([x['id'] for x in real_data], real_data)) - - for base_calendar_id, real_id in select: - res = real_data[real_id].copy() - ls = base_calendar_id2real_id(base_calendar_id, with_date=res and res.get('duration', 0) or 0) - if not isinstance(ls, (str, int, long)) and len(ls) >= 2: - res['date'] = ls[1] - res['date_deadline'] = ls[2] - res['id'] = base_calendar_id - - result.append(res) - - for r in result: - if r['user_id']: - user_id = type(r['user_id']) in (tuple,list) and r['user_id'][0] or r['user_id'] - if user_id==uid: - continue - if r['class']=='private': - for f in r.keys(): - if f not in ('id','date','date_deadline','duration','user_id','state','interval','count'): - if isinstance(r[f], list): - r[f] = [] - else: - r[f] = False - if f=='name': - r[f] = _('Busy') - - for r in result: - for k in EXTRAFIELDS: - if (k in r) and (fields and (k not in fields)): - del r[k] - if isinstance(ids, (str, int, long)): - return result and result[0] or False - return result - - def copy(self, cr, uid, id, default=None, context=None): - if context is None: - context = {} - - res = super(calendar_event, self).copy(cr, uid, base_calendar_id2real_id(id), default, context) - alarm_obj = self.pool.get('res.alarm') - alarm_obj.do_alarm_create(cr, uid, [res], self._name, 'date', context=context) - return res - - def unlink(self, cr, uid, ids, context=None): - if not isinstance(ids, list): - ids = [ids] - res = False - attendee_obj=self.pool.get('calendar.attendee') - for event_id in ids[:]: - if len(str(event_id).split('-')) == 1: - continue - - real_event_id = base_calendar_id2real_id(event_id) - data = self.read(cr, uid, real_event_id, ['exdate'], context=context) - date_new = event_id.split('-')[1] - date_new = time.strftime("%Y%m%dT%H%M%S", \ - time.strptime(date_new, "%Y%m%d%H%M%S")) - exdate = (data['exdate'] and (data['exdate'] + ',') or '') + date_new - self.write(cr, uid, [real_event_id], {'exdate': exdate}) - ids.remove(event_id) - for event in self.browse(cr, uid, ids, context=context): - if event.attendee_ids: - attendee_obj.unlink(cr, uid, [x.id for x in event.attendee_ids], context=context) - - res = super(calendar_event, self).unlink(cr, uid, ids, context=context) - self.pool.get('res.alarm').do_alarm_unlink(cr, uid, ids, self._name) - self.unlink_events(cr, uid, ids, context=context) - return res - - def _set_recurrency_end_date(self, data, context=None): - end_date = data.get('end_date') - if data.get('recurrency') and data.get('end_type') in ('count', unicode('count')): - data_date_deadline = datetime.strptime(data.get('date_deadline'), '%Y-%m-%d %H:%M:%S') - if data.get('rrule_type') in ('daily', unicode('count')): - rel_date = relativedelta(days=data.get('count')+1) - elif data.get('rrule_type') in ('weekly', unicode('weekly')): - rel_date = relativedelta(days=(data.get('count')+1)*7) - elif data.get('rrule_type') in ('monthly', unicode('monthly')): - rel_date = relativedelta(months=data.get('count')+1) - elif data.get('rrule_type') in ('yearly', unicode('yearly')): - rel_date = relativedelta(years=data.get('count')+1) - end_date = data_date_deadline + rel_date - return end_date - - def create(self, cr, uid, vals, context=None): - if context is None: - context = {} - - if vals.get('vtimezone', '') and vals.get('vtimezone', '').startswith('/freeassociation.sourceforge.net/tzfile/'): - vals['vtimezone'] = vals['vtimezone'][40:] - - vals['end_date'] = self._set_recurrency_end_date(vals, context=context) - 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): - """ Makes event invitation as Tentative - @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 Event IDs - @param *args: Get Tupple value - @param context: A standard dictionary for contextual values - """ - return self.write(cr, uid, ids, {'state': 'tentative'}, context) - - def do_cancel(self, cr, uid, ids, context=None, *args): - """ Makes event invitation as Tentative - @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 Event IDs - @param *args: Get Tupple value - @param context: A standard dictionary for contextual values - """ - return self.write(cr, uid, ids, {'state': 'cancelled'}, context) - - def do_confirm(self, cr, uid, ids, context=None, *args): - """ Makes event invitation as Tentative - @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 Event IDs - @param *args: Get Tupple value - @param context: A standard dictionary for contextual values - """ - return self.write(cr, uid, ids, {'state': 'confirmed'}, context) - - -class calendar_todo(osv.osv): - """ Calendar Task """ - - _name = "calendar.todo" - _inherit = "calendar.event" - _description = "Calendar Task" - - def _get_date(self, cr, uid, ids, name, arg, context=None): - """ - Get Date - @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 calendar todo's IDs. - @param args: list of tuples of form [(‘name_of_the_field', ‘operator', value), ...]. - @param context: A standard dictionary for contextual values - """ - - res = {} - for event in self.browse(cr, uid, ids, context=context): - res[event.id] = event.date_start - return res - - def _set_date(self, cr, uid, id, name, value, arg, context=None): - """ - Set Date - @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 id: calendar's ID. - @param value: Get Value - @param args: list of tuples of form [('name_of_the_field', 'operator', value), ...]. - @param context: A standard dictionary for contextual values - """ - - assert name == 'date' - return self.write(cr, uid, id, { 'date_start': value }, context=context) - - _columns = { - 'date': fields.function(_get_date, fnct_inv=_set_date, \ - string='Duration', store=True, type='datetime'), - 'duration': fields.integer('Duration'), - } - - __attribute__ = {} - - - - -class ir_values(osv.osv): - _inherit = 'ir.values' - - def set(self, cr, uid, key, key2, name, models, value, replace=True, \ - isobject=False, meta=False, preserve_user=False, company=False): - """ - Set IR Values - @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: Get The Model - """ - - new_model = [] - for data in models: - if type(data) in (list, tuple): - new_model.append((data[0], base_calendar_id2real_id(data[1]))) - else: - new_model.append(data) - return super(ir_values, self).set(cr, uid, key, key2, name, new_model, \ - value, replace, isobject, meta, preserve_user, company) - - def get(self, cr, uid, key, key2, models, meta=False, context=None, \ - res_id_req=False, without_user=True, key2_req=True): - """ - Get IR Values - @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: Get The Model - """ - if context is None: - context = {} - new_model = [] - for data in models: - if type(data) in (list, tuple): - new_model.append((data[0], base_calendar_id2real_id(data[1]))) - else: - new_model.append(data) - return super(ir_values, self).get(cr, uid, key, key2, new_model, \ - meta, context, res_id_req, without_user, key2_req) - - -class ir_model(osv.osv): - - _inherit = 'ir.model' - - def read(self, cr, uid, ids, fields=None, context=None, - load='_classic_read'): - """ - Overrides orm read method. - @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 IR Model's IDs. - @param context: A standard dictionary for contextual values - """ - new_ids = isinstance(ids, (str, int, long)) and [ids] or ids - if context is None: - context = {} - data = super(ir_model, self).read(cr, uid, new_ids, fields=fields, \ - context=context, load=load) - if data: - for val in data: - val['id'] = base_calendar_id2real_id(val['id']) - return isinstance(ids, (str, int, long)) and data[0] or data - - -original_exp_report = openerp.service.report.exp_report - -def exp_report(db, uid, object, ids, data=None, context=None): - """ - Export Report - @param db: get the current database, - @param uid: the current user's ID for security checks, - @param context: A standard dictionary for contextual values - """ - - if object == 'printscreen.list': - original_exp_report(db, uid, object, ids, data, context) - new_ids = [] - for id in ids: - new_ids.append(base_calendar_id2real_id(id)) - if data.get('id', False): - data['id'] = base_calendar_id2real_id(data['id']) - return original_exp_report(db, uid, object, new_ids, data, context) - -openerp.service.report.exp_report = exp_report - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/base_calendar/base_calendar_data.xml b/addons/base_calendar/base_calendar_data.xml deleted file mode 100644 index 64aa7ba59b6..00000000000 --- a/addons/base_calendar/base_calendar_data.xml +++ /dev/null @@ -1,138 +0,0 @@ - - - - - - Event - calendar.event - - - - 1 minute before - - - minutes - before - start - - - - 5 minutes before - - - minutes - before - start - - - - 10 minutes before - - - minutes - before - start - - - - 15 minutes before - - - minutes - before - start - - - - 30 minutes before - - - minutes - before - start - - - - 45 minutes before - - - minutes - before - start - - - - 1 hour before - - - hours - before - start - - - - 2 hours before - - - hours - before - start - - - - 3 hours before - - - - hours - before - start - - - - 4 hours before - - - - hours - before - start - - - - 5 hours before - - - - hours - before - start - - - - 18 hours before - - - - hours - before - start - - - - - - Run Event Reminder - - - 5 - minutes - -1 - - - - - - - diff --git a/addons/base_calendar/crm_meeting_demo.xml b/addons/base_calendar/crm_meeting_demo.xml deleted file mode 100644 index 6c098e2f949..00000000000 --- a/addons/base_calendar/crm_meeting_demo.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - Follow-up for Project proposal - Meeting to discuss project plan and hash out the details of implementation. - - - - - open - - - - - - Initial discussion - Discussion with partner for product. - - - - - open - - - - - - Pricing Discussion - Internal meeting for discussion for new pricing for product and services. - - - - - open - - - - - - Requirements review - - - - - open - - - - - - Changes in Designing - - - - - open - - - - - - Presentation for new Services - - - - - open - - - diff --git a/addons/base_calendar/crm_meeting_view.xml b/addons/base_calendar/crm_meeting_view.xml deleted file mode 100644 index 9ef8bee6e3b..00000000000 --- a/addons/base_calendar/crm_meeting_view.xml +++ /dev/null @@ -1,295 +0,0 @@ - - - - - - - - - Meeting Types Tree - crm.meeting.type - - - - - - - - - Meeting Types - crm.meeting.type - form - - - - - - - - - CRM - Meetings Form - crm.meeting - -
- - -
-
-
-

- -

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    +
    +
    + + +
    -
    -
    -
    -
    -
    -
    -
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + +
    -
    + +
    +
    +
    +
    +
    +
    +
    +
    + + +
    + +
    +
    +
    +

    Loading

    +
    +
    +
    + +
    + <!--[if IE]>
    @@ -73,12 +125,12 @@ -
    +
    -
    +
    @@ -105,67 +157,66 @@ -
  1. +
    - +
    -
  2. +
    -
  3. + -
  4. +
    -
    - +
    -
    -
    -
      -
    -
    +
    +
    +
    +
    -
    -
      -
    +
    +
    +
    -
    -
    +
    @@ -188,7 +239,6 @@
    -

    Product Weighting

    @@ -205,7 +255,7 @@ - +

    @@ -213,47 +263,36 @@
    -
    -

    Payment

    -
    -
    -
    -
    - - Total: +
    +
    +
    +
    +
    +
    + + Paid: - +
    -
    -
    -
    -
    + -
    -

    Receipt

    +
    @@ -263,7 +302,7 @@
    -

    Welcome

    +

    Welcome

    Please scan an item or your member card

    @@ -276,15 +315,15 @@ -
    -

    Please scan an item

    +
    +

    Please scan an item

    -

    Payment

    +

    Payment

    Please insert your card in the reader and follow the instructions to complete @@ -295,18 +334,11 @@

    -

    Please put your product on the scale

    +

    Please put your product on the scale

    - -
    - - -
    -
    -