[FIX]: merging from same branch

bzr revid: mga@tinyerp.com-20100203062555-40kpj0gsbk1ra0nr
This commit is contained in:
Mantavya Gajjar
2010-02-03 11:55:55 +05:30
110 changed files with 5838 additions and 854 deletions
+5 -5
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0_rc3\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-12-11 12:37+0000\n"
"Last-Translator: Pieter J. Kersten (EduSense BV) <Unknown>\n"
"PO-Revision-Date: 2010-02-01 15:46+0000\n"
"Last-Translator: Jan Verlaan (Veritos) <Unknown>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2009-12-16 05:16+0000\n"
"X-Launchpad-Export-Date: 2010-02-02 04:48+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: account_analytic_analysis
@@ -191,7 +191,7 @@ msgstr "Berekend met de formule: gefactureerd bedrag - totale kosten."
#: model:ir.actions.act_window,name:account_analytic_analysis.action_account_analytic_managed
#: model:ir.ui.menu,name:account_analytic_analysis.menu_analytic_account_managed
msgid "My Accounts"
msgstr "Mijn rekeningen"
msgstr "Mijn kostenplaatsen"
#. module: account_analytic_analysis
#: model:ir.module.module,description:account_analytic_analysis.module_meta_information
@@ -335,7 +335,7 @@ msgstr "Kostenplaats"
#: model:ir.actions.act_window,name:account_analytic_analysis.action_account_analytic_managed_overpassed
#: model:ir.ui.menu,name:account_analytic_analysis.menu_action_account_analytic_managed_overpassed
msgid "Overpassed Accounts"
msgstr "Overbrugde Kostenplaatsen"
msgstr "Overgehevelde kostenplaatsen"
#. module: account_analytic_analysis
#: model:ir.actions.act_window,name:account_analytic_analysis.action_hr_tree_invoiced_all
+25
View File
@@ -0,0 +1,25 @@
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import product
import stock
import purchase
import invoice
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+39
View File
@@ -0,0 +1,39 @@
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
"name" : "Stock Account",
"version" : "1.1",
"author" : "Tiny",
"website" : "http://tinyerp.com",
"description" : """This module will support the Anglo-Saxons accounting methodology by
changing the accounting logic with stock transactions. The difference between the Anglo-Saxon accounting countries
and the Rhine or also called Continental accounting countries is the moment of taking the Cost of Goods Sold versus Cost of Sales.
Anglo-Saxons accounting does take the cost when sales invoice is created, Continental accounting will take the cost at he moment the goods are shipped.
This module will add this functionality by using a interim account, to store the value of shipped goods and will contra book this interim account
when the invoice is created to transfer this amount to the debtor or creditor account.""",
"depends" : ["product", "account", "sale", "purchase"],
"category" : "Generic Modules/Inventory Control",
"init_xml" : [],
"demo_xml" : [],
"update_xml" : ["product_view.xml",],
"active": False,
"installable": True
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,54 @@
# Translation of OpenERP Server.
# This file contains the translation of the following modules:
# * account_anglo_saxon
#
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 5.0.6\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-11-24 12:50:50+0000\n"
"PO-Revision-Date: 2009-11-24 12:50:50+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: account_anglo_saxon
#: view:product.category:0
msgid " Accounting Property"
msgstr ""
#. module: account_anglo_saxon
#: model:ir.module.module,description:account_anglo_saxon.module_meta_information
msgid "This module will support the Anglo-Saxons accounting methodology by \n"
" changing the accounting logic with stock transactions. The difference between the Anglo-Saxon accounting countries \n"
" and the Rhine or also called Continental accounting countries is the moment of taking the Cost of Goods Sold versus Cost of Sales. \n"
" Anglo-Saxons accounting does take the cost when sales invoice is created, Continental accounting will take the cost at he moment the goods are shipped.\n"
" This module will add this functionality by using a interim account, to store the value of shipped goods and will contra book this interim account \n"
" when the invoice is created to transfer this amount to the debtor or creditor account."
msgstr ""
#. module: account_anglo_saxon
#: model:ir.module.module,shortdesc:account_anglo_saxon.module_meta_information
msgid "Stock Account"
msgstr ""
#. module: account_anglo_saxon
#: constraint:ir.ui.view:0
msgid "Invalid XML for View Architecture!"
msgstr ""
#. module: account_anglo_saxon
#: field:product.category,property_account_creditor_price_difference_categ:0
#: field:product.template,property_account_creditor_price_difference:0
msgid "Price Difference Account"
msgstr ""
#. module: account_anglo_saxon
#: help:product.category,property_account_creditor_price_difference_categ:0
#: help:product.template,property_account_creditor_price_difference:0
msgid "This account will be used to value price difference between purchase price and cost price."
msgstr ""
+54
View File
@@ -0,0 +1,54 @@
# Translation of OpenERP Server.
# This file contains the translation of the following modules:
# * account_anglo_saxon
#
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 5.0.6\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-11-24 12:50:50+0000\n"
"PO-Revision-Date: 2009-11-24 12:50:50+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: account_anglo_saxon
#: view:product.category:0
msgid " Accounting Property"
msgstr ""
#. module: account_anglo_saxon
#: model:ir.module.module,description:account_anglo_saxon.module_meta_information
msgid "This module will support the Anglo-Saxons accounting methodology by \n"
" changing the accounting logic with stock transactions. The difference between the Anglo-Saxon accounting countries \n"
" and the Rhine or also called Continental accounting countries is the moment of taking the Cost of Goods Sold versus Cost of Sales. \n"
" Anglo-Saxons accounting does take the cost when sales invoice is created, Continental accounting will take the cost at he moment the goods are shipped.\n"
" This module will add this functionality by using a interim account, to store the value of shipped goods and will contra book this interim account \n"
" when the invoice is created to transfer this amount to the debtor or creditor account."
msgstr ""
#. module: account_anglo_saxon
#: model:ir.module.module,shortdesc:account_anglo_saxon.module_meta_information
msgid "Stock Account"
msgstr ""
#. module: account_anglo_saxon
#: constraint:ir.ui.view:0
msgid "Invalid XML for View Architecture!"
msgstr ""
#. module: account_anglo_saxon
#: field:product.category,property_account_creditor_price_difference_categ:0
#: field:product.template,property_account_creditor_price_difference:0
msgid "Price Difference Account"
msgstr ""
#. module: account_anglo_saxon
#: help:product.category,property_account_creditor_price_difference_categ:0
#: help:product.template,property_account_creditor_price_difference:0
msgid "This account will be used to value price difference between purchase price and cost price."
msgstr ""
+66
View File
@@ -0,0 +1,66 @@
# Polish translation for openobject-addons
# Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2009-11-24 12:50+0000\n"
"PO-Revision-Date: 2010-02-02 06:30+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Polish <pl@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-02-03 04:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: account_anglo_saxon
#: view:product.category:0
msgid " Accounting Property"
msgstr ""
#. module: account_anglo_saxon
#: model:ir.module.module,description:account_anglo_saxon.module_meta_information
msgid ""
"This module will support the Anglo-Saxons accounting methodology by \n"
" changing the accounting logic with stock transactions. The difference "
"between the Anglo-Saxon accounting countries \n"
" and the Rhine or also called Continental accounting countries is the "
"moment of taking the Cost of Goods Sold versus Cost of Sales. \n"
" Anglo-Saxons accounting does take the cost when sales invoice is "
"created, Continental accounting will take the cost at he moment the goods "
"are shipped.\n"
" This module will add this functionality by using a interim account, to "
"store the value of shipped goods and will contra book this interim account \n"
" when the invoice is created to transfer this amount to the debtor or "
"creditor account."
msgstr ""
#. module: account_anglo_saxon
#: model:ir.module.module,shortdesc:account_anglo_saxon.module_meta_information
msgid "Stock Account"
msgstr ""
#. module: account_anglo_saxon
#: constraint:ir.ui.view:0
msgid "Invalid XML for View Architecture!"
msgstr "XML niewłaściwy dla tej architektury wyświetlania!"
#. module: account_anglo_saxon
#: field:product.category,property_account_creditor_price_difference_categ:0
#: field:product.template,property_account_creditor_price_difference:0
msgid "Price Difference Account"
msgstr "Konto różnic cenowych"
#. module: account_anglo_saxon
#: help:product.category,property_account_creditor_price_difference_categ:0
#: help:product.template,property_account_creditor_price_difference:0
msgid ""
"This account will be used to value price difference between purchase price "
"and cost price."
msgstr ""
"To konto będzie stosowane do rejestrowania różnic cenowych między ceną "
"zakupu a kosztem."
+158
View File
@@ -0,0 +1,158 @@
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import fields, osv
class account_invoice_line(osv.osv):
_inherit = "account.invoice.line"
def move_line_get(self, cr, uid, invoice_id, context=None):
res = super(account_invoice_line,self).move_line_get(cr, uid, invoice_id, context)
inv = self.pool.get('account.invoice').browse(cr, uid, invoice_id)
if inv.type in ('out_invoice','out_refund'):
for i_line in inv.invoice_line:
if i_line.product_id:
if inv.type == 'out_invoice':
dacc = i_line.product_id.product_tmpl_id.property_stock_account_output and i_line.product_id.product_tmpl_id.property_stock_account_output.id
if not dacc:
dacc = i_line.product_id.categ_id.property_stock_account_output_categ and i_line.product_id.categ_id.property_stock_account_output_categ.id
else:
dacc = i_line.product_id.product_tmpl_id.property_stock_account_input and i_line.product_id.product_tmpl_id.property_stock_account_input.id
if not dacc:
dacc = i_line.product_id.categ_id.property_stock_account_input_categ and i_line.product_id.categ_id.property_stock_account_input_categ.id
cacc = i_line.product_id.product_tmpl_id.property_account_expense and i_line.product_id.product_tmpl_id.property_account_expense.id
if not cacc:
cacc = i_line.product_id.categ_id.property_account_expense_categ and i_line.product_id.categ_id.property_account_expense_categ.id
if dacc and cacc:
res.append({
'type':'src',
'name': i_line.name[:64],
'price_unit':i_line.product_id.product_tmpl_id.standard_price,
'quantity':i_line.quantity,
'price':i_line.product_id.product_tmpl_id.standard_price * i_line.quantity,
'account_id':dacc,
'product_id':i_line.product_id.id,
'uos_id':i_line.uos_id.id,
'account_analytic_id':i_line.account_analytic_id.id,
'taxes':i_line.invoice_line_tax_id,
})
res.append({
'type':'src',
'name': i_line.name[:64],
'price_unit':i_line.product_id.product_tmpl_id.standard_price,
'quantity':i_line.quantity,
'price': -1 * i_line.product_id.product_tmpl_id.standard_price * i_line.quantity,
'account_id':cacc,
'product_id':i_line.product_id.id,
'uos_id':i_line.uos_id.id,
'account_analytic_id':i_line.account_analytic_id.id,
'taxes':i_line.invoice_line_tax_id,
})
elif inv.type in ('in_invoice','in_refund'):
for i_line in inv.invoice_line:
if i_line.product_id:
if i_line.product_id.product_tmpl_id.type != 'service':
acc = i_line.product_id.product_tmpl_id.property_account_creditor_price_difference and i_line.product_id.product_tmpl_id.property_account_creditor_price_difference.id
if not acc:
acc = i_line.product_id.categ_id.property_account_creditor_price_difference_categ and i_line.product_id.categ_id.property_account_creditor_price_difference_categ.id
a = None
if inv.type == 'in_invoice':
oa = i_line.product_id.product_tmpl_id.property_stock_account_input and i_line.product_id.product_tmpl_id.property_stock_account_input.id
if not oa:
oa = i_line.product_id.categ_id.property_stock_account_input_categ and i_line.product_id.categ_id.property_stock_account_input_categ.id
else:
oa = i_line.product_id.product_tmpl_id.property_stock_account_output and i_line.product_id.product_tmpl_id.property_stock_account_output.id
if not oa:
oa = i_line.product_id.categ_id.property_stock_account_output_categ and i_line.product_id.categ_id.property_stock_account_output_categ.id
if oa:
fpos = i_line.invoice_id.fiscal_position or False
a = self.pool.get('account.fiscal.position').map_account(cr, uid, fpos, oa)
diff_res = []
for line in res:
if a == line['account_id'] and i_line.product_id.id == line['product_id']:
uom = i_line.product_id.uos_id or i_line.product_id.uom_id
standard_price = self.pool.get('product.uom')._compute_price(cr, uid, uom.id, i_line.product_id.product_tmpl_id.standard_price, i_line.uos_id.id)
if standard_price != i_line.price_unit and line['price'] == i_line.price_unit and acc:
price_diff = i_line.price_unit - standard_price
line.update({'price':standard_price * line['quantity']})
diff_res.append({
'type':'src',
'name': i_line.name[:64],
'price_unit':price_diff,
'quantity':line['quantity'],
'price': price_diff * line['quantity'],
'account_id':acc,
'product_id':line['product_id'],
'uos_id':line['uos_id'],
'account_analytic_id':line['account_analytic_id'],
'taxes':line.get('taxes',[]),
})
res += diff_res
return res
def product_id_change(self, cr, uid, ids, product, uom, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, address_invoice_id=False, context=None):
if not product:
return super(account_invoice_line, self).product_id_change(cr, uid, ids, product, uom, qty, name, type, partner_id, fposition_id, price_unit, address_invoice_id, context)
else:
res = super(account_invoice_line, self).product_id_change(cr, uid, ids, product, uom, qty, name, type, partner_id, fposition_id, price_unit, address_invoice_id, context)
if type in ('in_invoice','in_refund'):
product_obj = self.pool.get('product.product').browse(cr, uid, product, context=context)
if type == 'in_invoice':
oa = product_obj.product_tmpl_id.property_stock_account_input and product_obj.product_tmpl_id.property_stock_account_input.id
if not oa:
oa = product_obj.categ_id.property_stock_account_input_categ and product_obj.categ_id.property_stock_account_input_categ.id
else:
oa = product_obj.product_tmpl_id.property_stock_account_output and product_obj.product_tmpl_id.property_stock_account_output.id
if not oa:
oa = product_obj.categ_id.property_stock_account_output_categ and product_obj.categ_id.property_stock_account_output_categ.id
if oa:
fpos = fposition_id and self.pool.get('account.fiscal.position').browse(cr, uid, fposition_id) or False
a = self.pool.get('account.fiscal.position').map_account(cr, uid, fpos, oa)
res['value'].update({'account_id':a})
return res
account_invoice_line()
class account_invoice(osv.osv):
_inherit = "account.invoice"
def _refund_cleanup_lines(self, cr, uid, lines):
for line in lines:
inv_id = line['invoice_id']
inv_obj = self.browse(cr,uid,inv_id[0])
if inv_obj.type == 'in_invoice':
if line.get('product_id',False):
product_obj = self.pool.get('product.product').browse(cr,uid,line['product_id'][0])
oa = product_obj.product_tmpl_id.property_stock_account_output and product_obj.product_tmpl_id.property_stock_account_output.id
if not oa:
oa = product_obj.categ_id.property_stock_account_output_categ and product_obj.categ_id.property_stock_account_output_categ.id
if oa:
fpos = inv_obj.fiscal_position or False
a = self.pool.get('account.fiscal.position').map_account(cr, uid, fpos, oa)
account_data = self.pool.get('account.account').read(cr,uid,[a],['name'])[0]
line.update({'account_id': (account_data['id'],account_data['name'])})
res = super(account_invoice,self)._refund_cleanup_lines(cr, uid, lines)
return res
account_invoice()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+55
View File
@@ -0,0 +1,55 @@
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import fields, osv
class product_category(osv.osv):
_inherit = "product.category"
_columns = {
'property_account_creditor_price_difference_categ': fields.property(
'account.account',
type='many2one',
relation='account.account',
string="Price Difference Account",
method=True,
view_load=True,
help="This account will be used to value price difference between purchase price and cost price."),
}
product_category()
class product_template(osv.osv):
_inherit = "product.template"
_columns = {
'property_account_creditor_price_difference': fields.property(
'account.account',
type='many2one',
relation='account.account',
string="Price Difference Account",
method=True,
view_load=True,
help="This account will be used to value price difference between purchase price and cost price."),
}
product_template()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,53 @@
<?xml version="1.0"?>
<openerp>
<data>
<record id="product_normal_form_view" model="ir.ui.view">
<field name="name">product.normal.form.inherit.stock</field>
<field name="model">product.product</field>
<field name="type">form</field>
<field name="inherit_id" ref="product.product_normal_form_view"/>
<field name="arch" type="xml">
<xpath expr="/form/notebook/page/field[@name='property_account_expense']" position="after">
<field name="property_account_creditor_price_difference" domain="[('type','&lt;&gt;','view'),('type','&lt;&gt;','consolidation')]" attrs="{'readonly':[('purchase_ok','=',0)]}" />
<newline/>
<!-- <field name="property_account_sending_goods" domain="[('type','&lt;&gt;','view'),('type','&lt;&gt;','consolidation')]" attrs="{'readonly':[('sale_ok','=',0)]}" />-->
<!-- <field name="property_account_received_goods" domain="[('type','&lt;&gt;','view'),('type','&lt;&gt;','consolidation')]" attrs="{'readonly':[('purchase_ok','=',0)]}" />-->
</xpath>
</field>
</record>
<record id="product_template_form_view" model="ir.ui.view">
<field name="name">product.template.product.form.inherit</field>
<field name="model">product.template</field>
<field name="type">form</field>
<field name="inherit_id" ref="product.product_template_form_view"/>
<field name="arch" type="xml">
<xpath expr="/form/notebook/page/field[@name='property_account_expense']" position="after">
<field name="property_account_creditor_price_difference" domain="[('type','&lt;&gt;','view'),('type','&lt;&gt;','consolidation')]" attrs="{'readonly':[('purchase_ok','=',0)]}" />
<newline/>
<!-- <field name="property_account_sending_goods" domain="[('type','&lt;&gt;','view'),('type','&lt;&gt;','consolidation')]" attrs="{'readonly':[('sale_ok','=',0)]}" />-->
<!-- <field name="property_account_received_goods" domain="[('type','&lt;&gt;','view'),('type','&lt;&gt;','consolidation')]" attrs="{'readonly':[('purchase_ok','=',0)]}" />-->
</xpath>
</field>
</record>
<record id="view_category_property_form" model="ir.ui.view">
<field name="name">product.category.property.form.inherit.stock</field>
<field name="model">product.category</field>
<field name="type">form</field>
<field name="inherit_id" ref="product.product_category_form_view"/>
<field name="arch" type="xml">
<form position="inside">
<group col="2" colspan="2">
<separator string=" Accounting Property" colspan="2"/>
<field name="property_account_creditor_price_difference_categ" domain="[('type','&lt;&gt;','view'),('type','&lt;&gt;','consolidation')]" attrs="{'readonly':[('purchase_ok','=',0)]}" />
<!-- <field name="property_account_sending_goods_categ" domain="[('type','&lt;&gt;','view'),('type','&lt;&gt;','consolidation')]" attrs="{'readonly':[('sale_ok','=',0)]}" />-->
<!-- <field name="property_account_received_goods_categ" domain="[('type','&lt;&gt;','view'),('type','&lt;&gt;','consolidation')]" attrs="{'readonly':[('purchase_ok','=',0)]}" />-->
</group>
</form>
</field>
</record>
</data>
</openerp>
+41
View File
@@ -0,0 +1,41 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import fields, osv
class purchase_order(osv.osv):
_name = "purchase.order"
_inherit = "purchase.order"
_description = "Purchase order"
def inv_line_create(self, cr, uid, a, ol):
line = super(purchase_order, self).inv_line_create(cr, uid, a, ol)
if ol.product_id:
oa = ol.product_id.product_tmpl_id.property_stock_account_input and ol.product_id.product_tmpl_id.property_stock_account_input.id
if not oa:
oa = ol.product_id.categ_id.property_stock_account_input_categ and ol.product_id.categ_id.property_stock_account_input_categ.id
if oa:
fpos = ol.order_id.fiscal_position or False
a = self.pool.get('account.fiscal.position').map_account(cr, uid, fpos, oa)
line[2].update({'account_id': a})
return line
purchase_order()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+43
View File
@@ -0,0 +1,43 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import fields, osv
#class sale_order_line(osv.osv):
# _name = 'sale.order.line'
# _description = 'Sale Order line'
# _inherit = 'sale.order.line'
#
# def invoice_line_create(self, cr, uid, ids, context={}):
# line_ids = super('sale_order_line',self).invoice_line_create(cr, uid, ids, context)
# invoice_line_obj = self.pool.get('account.invoice.line')
# for line in invoice_line_obj.browse(cr, uid, line_ids):
# if line.product_id:
# a = line.product_id.product_tmpl_id.property_stock_account_output and line.product_id.product_tmpl_id.property_stock_account_output.id
# if not a:
# a = line.product_id.categ_id.property_stock_account_output_categ and line.product_id.categ_id.property_stock_account_output_categ.id
# if a:
# a = self.pool.get('account.fiscal.position').map_account(cr, uid, fpos, a)
# invoice_line_obj.write(cr, uid, line.id, {'account_id':a})
#
#sale_order_line()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+51
View File
@@ -0,0 +1,51 @@
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import fields,osv
#----------------------------------------------------------
# Stock Picking
#----------------------------------------------------------
class stock_picking(osv.osv):
_inherit = "stock.picking"
_description = "Packing List"
def action_invoice_create(self, cr, uid, ids, journal_id=False,
group=False, type='out_invoice', context=None):
'''Return ids of created invoices for the pickings'''
res = super(stock_picking,self).action_invoice_create(cr, uid, ids, journal_id, group, type, context)
if type == 'in_refund':
for inv in self.pool.get('account.invoice').browse(cr, uid, res.values(), context=context):
for ol in inv.invoice_line:
if ol.product_id:
oa = ol.product_id.product_tmpl_id.property_stock_account_output and ol.product_id.product_tmpl_id.property_stock_account_output.id
if not oa:
oa = ol.product_id.categ_id.property_stock_account_output_categ and ol.product_id.categ_id.property_stock_account_output_categ.id
if oa:
fpos = ol.invoice_id.fiscal_position or False
a = self.pool.get('account.fiscal.position').map_account(cr, uid, fpos, oa)
self.pool.get('account.invoice.line').write(cr, uid, [ol.id], {'account_id': a})
return res
stock_picking()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+6 -6
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-12-11 13:00+0000\n"
"Last-Translator: Pieter J. Kersten (EduSense BV) <Unknown>\n"
"PO-Revision-Date: 2010-02-01 15:48+0000\n"
"Last-Translator: Jan Verlaan (Veritos) <Unknown>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2009-12-16 05:10+0000\n"
"X-Launchpad-Export-Date: 2010-02-02 04:48+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: account_followup
@@ -55,7 +55,7 @@ msgstr "Bedrag in valuta"
#. module: account_followup
#: rml:account_followup.followup.print:0
msgid "Due"
msgstr "Tot"
msgstr "Bedrag"
#. module: account_followup
#: view:account.move.line:0
@@ -97,7 +97,7 @@ msgstr "Soort rekening"
#. module: account_followup
#: rml:account_followup.followup.print:0
msgid "Ref"
msgstr "Ref"
msgstr "Factuur"
#. module: account_followup
#: wizard_view:account_followup.followup.print.all,next:0
@@ -253,7 +253,7 @@ msgstr ""
msgid ""
"The Object name must start with x_ and not contain any special character !"
msgstr ""
"De objectnaam moet beginnen met x_ en mag geen speciale karakters bevatten !"
"De objectnaam moet beginnen met x_ en mag geen speciale tekens bevatten !"
#. module: account_followup
#: wizard_button:account_followup.followup.print.all,summary,end:0
+9 -9
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-11-09 16:28+0000\n"
"Last-Translator: Fabien (Open ERP) <fp@tinyerp.com>\n"
"PO-Revision-Date: 2010-02-02 17:25+0000\n"
"Last-Translator: Nikolay Chesnokov <chesnokov_n@msn.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2009-12-16 05:20+0000\n"
"X-Launchpad-Export-Date: 2010-02-03 04:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: account_reporting
@@ -58,7 +58,7 @@ msgstr "Балансовый отчет"
#. module: account_reporting
#: constraint:ir.actions.act_window:0
msgid "Invalid model name in the action definition."
msgstr ""
msgstr "Недопустимое имя модели в определении действия."
#. module: account_reporting
#: selection:account.report.bs,font_style:0
@@ -78,7 +78,7 @@ msgstr "Распечатать балансовый отчет"
#. module: account_reporting
#: help:account.account.balancesheet.report,init,periods:0
msgid "All periods if empty"
msgstr ""
msgstr "Если не заполнены все периоды"
#. module: account_reporting
#: field:account.report.bs,color_font:0
@@ -95,7 +95,7 @@ msgstr "Отчет с объектами, счетами и потомками
msgid ""
"Financial and accounting reporting\n"
" Balance Sheet Report"
msgstr ""
msgstr "Финансовые и аналитические отчеты"
#. module: account_reporting
#: selection:account.report.bs,report_type:0
@@ -126,7 +126,7 @@ msgstr "Отчетность по счету"
#. module: account_reporting
#: model:ir.ui.menu,name:account_reporting.bs_report_action_form
msgid "Balance Sheet Report Form"
msgstr ""
msgstr "Отчет главной книги (Форма)"
#. module: account_reporting
#: view:account.report.bs:0
@@ -166,7 +166,7 @@ msgstr "Цвета RML"
#. module: account_reporting
#: model:ir.module.module,shortdesc:account_reporting.module_meta_information
msgid "Reporting of Balancesheet for accounting"
msgstr ""
msgstr "Отчет главной книги по счетам"
#. module: account_reporting
#: field:account.report.bs,code:0
@@ -207,7 +207,7 @@ msgstr "Учётные записи"
#. module: account_reporting
#: wizard_field:account.account.balancesheet.report,init,periods:0
msgid "Periods"
msgstr ""
msgstr "Периоды"
#. module: account_reporting
#: field:account.report.bs,color_back:0
+118 -113
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2010-01-23 02:16+0000\n"
"PO-Revision-Date: 2010-02-01 18:21+0000\n"
"Last-Translator: Holverat Bortolossi <holverat@gmail.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-01-24 04:50+0000\n"
"X-Launchpad-Export-Date: 2010-02-02 04:48+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: auction
@@ -150,74 +150,74 @@ msgstr "Antigo/pequeno produto de cobre ou estanho"
#. module: auction
#: field:auction.lots,paid_ach:0
msgid "Buyer invoice reconciled"
msgstr ""
msgstr "Fatura do comprador foi reconciliada"
#. module: auction
#: model:ir.actions.wizard,name:auction.auction_wizard_able_taken
msgid "Mark as taken away"
msgstr ""
msgstr "Marcar como retirado"
#. module: auction
#: xsl:report.auction.seller.list:0
msgid "Inv."
msgstr ""
msgstr "Inv."
#. module: auction
#: field:auction.deposit.cost,amount:0
msgid "Amount"
msgstr ""
msgstr "Valor"
#. module: auction
#: model:ir.actions.act_window,name:auction.action_deposit_border
#: model:ir.ui.menu,name:auction.menu_auction_deposit_border
msgid "Deposit border"
msgstr ""
msgstr "Limite de Depósito"
#. module: auction
#: xsl:report.auction.deposit:0
msgid "VAT"
msgstr ""
msgstr "Imposto sobre Valor Agregado"
#. module: auction
#: view:auction.lots:0
msgid "Statements"
msgstr ""
msgstr "Demonstrações"
#. module: auction
#: xsl:flagey.huissier:0
msgid "Adjudication"
msgstr ""
msgstr "Conceder"
#. module: auction
#: field:auction.dates,account_analytic_id:0
msgid "Analytic Account"
msgstr ""
msgstr "Conta analítica"
#. module: auction
#: selection:auction.lot.category,aie_categ:0
msgid "Unclassifieds"
msgstr ""
msgstr "Não classificados"
#. module: auction
#: model:ir.ui.menu,name:auction.menu_auction_dates_next_by_auction
msgid "Objects by Auction"
msgstr ""
msgstr "Objetos em leilão"
#. module: auction
#: field:auction.lots,lot_num:0
#: field:report.unclassified.objects,lot_num:0
msgid "List Number"
msgstr ""
msgstr "Número de lista"
#. module: auction
#: field:auction.deposit.cost,name:0
msgid "Cost Name"
msgstr ""
msgstr "Nome do custo"
#. module: auction
#: selection:auction.lot.category,aie_categ:0
msgid "Antiques"
msgstr ""
msgstr "Antiguidades"
#. module: auction
#: view:auction.dates:0
@@ -227,17 +227,17 @@ msgstr ""
#. module: auction
#: field:report.auction.estimation.adj.category,lot_type:0
msgid "Object Type"
msgstr ""
msgstr "Tipo de objeto"
#. module: auction
#: wizard_field:auction.lots.sms_send,init,text:0
msgid "SMS Message"
msgstr ""
msgstr "Mensagem SMS"
#. module: auction
#: selection:auction.lot.category,aie_categ:0
msgid "Contemporary Art"
msgstr ""
msgstr "Arte contemporânea"
#. module: auction
#: view:auction.lots:0
@@ -248,7 +248,7 @@ msgstr ""
#. module: auction
#: field:report.auction.view,nseller:0
msgid "No of sellers"
msgstr ""
msgstr "Nenhum vendedor"
#. module: auction
#: selection:auction.lots.send.aie,date_ask,lang:0
@@ -269,7 +269,7 @@ msgstr ""
#. module: auction
#: field:report.auction.view2,obj_margin_procent:0
msgid "Net margin (%)"
msgstr ""
msgstr "Margem líquida (%)"
#. module: auction
#: selection:auction.lots,state:0
@@ -277,12 +277,12 @@ msgstr ""
#: selection:report.seller.auction,state:0
#: selection:report.unclassified.objects,state:0
msgid "Unsold"
msgstr ""
msgstr "Não vendidos"
#. module: auction
#: view:auction.dates:0
msgid "Dates"
msgstr ""
msgstr "Datas"
#. module: auction
#: constraint:product.template:0
@@ -294,13 +294,13 @@ msgstr ""
#. module: auction
#: rml:auction.total.rml:0
msgid "Items"
msgstr ""
msgstr "Itens"
#. module: auction
#: model:account.tax,name:auction.auction_tax5
#: field:auction.dates,seller_costs:0
msgid "Seller Costs"
msgstr ""
msgstr "Custos do Vendedor"
#. module: auction
#: view:auction.bid:0
@@ -310,22 +310,22 @@ msgstr ""
#: model:ir.actions.report.xml,name:auction.bid_auction
#: model:ir.ui.menu,name:auction.menu_action_bid_open
msgid "Bids"
msgstr ""
msgstr "Lances"
#. module: auction
#: model:ir.ui.menu,name:auction.auction_all_objects_menu
msgid "All objects"
msgstr ""
msgstr "Todos Objetos"
#. module: auction
#: model:ir.actions.act_window,name:auction.action_auction_buyer_reporting_all2
msgid "Buyer's auction for all months"
msgstr ""
msgstr "Leilão do comprador para todos os meses"
#. module: auction
#: field:auction.bid,contact_tel:0
msgid "Contact"
msgstr ""
msgstr "Contato"
#. module: auction
#: field:report.auction.view,obj_ret:0
@@ -337,7 +337,7 @@ msgstr ""
#. module: auction
#: wizard_button:auction.lots.sms_send,init,send:0
msgid "Send SMS"
msgstr ""
msgstr "Enviar SMS"
#. module: auction
#: selection:auction.lot.category,aie_categ:0
@@ -347,38 +347,38 @@ msgstr ""
#. module: auction
#: field:auction.lots,sel_inv_id:0
msgid "Seller Invoice"
msgstr ""
msgstr "Fatura do Vendedor"
#. module: auction
#: view:auction.dates:0
msgid "Commissions"
msgstr ""
msgstr "Comissões"
#. module: auction
#: wizard_button:auction.lots.numerotate,search,init:0
msgid "Back"
msgstr ""
msgstr "Voltar"
#. module: auction
#: model:ir.actions.act_window,name:auction.action_all_objects_unsold
msgid "Unsold objects"
msgstr ""
msgstr "Objetos não vendidos"
#. module: auction
#: model:ir.ui.menu,name:auction.menu_all_objects_sold1
msgid "Sold Objects"
msgstr ""
msgstr "Objetos vendidos"
#. module: auction
#: view:report.buyer.auction2:0
#: view:report.seller.auction2:0
msgid "Sum net margin"
msgstr ""
msgstr "Somar margem líquida"
#. module: auction
#: view:auction.deposit:0
msgid "Deposit Border Form"
msgstr ""
msgstr "Formuálio de Limite de Depósito"
#. module: auction
#: field:auction.bid,bid_lines:0
@@ -386,12 +386,12 @@ msgstr ""
#: rml:bids.lots:0
#: model:ir.model,name:auction.model_auction_bid_line
msgid "Bid"
msgstr ""
msgstr "Lance"
#. module: auction
#: wizard_field:auction.lots.send.aie,date_ask,lang:0
msgid "Langage"
msgstr ""
msgstr "Idioma"
#. module: auction
#: field:auction.bid_line,lot_id:0
@@ -399,7 +399,7 @@ msgstr ""
#: view:auction.lots:0
#: model:ir.model,name:auction.model_auction_lots
msgid "Object"
msgstr ""
msgstr "Objeto"
#. module: auction
#: model:ir.actions.wizard,name:auction.wizard_map_user
@@ -409,7 +409,7 @@ msgstr ""
#. module: auction
#: wizard_field:auction.lots.numerotate,search,lot_num:0
msgid "Inventory Number"
msgstr ""
msgstr "Número de inventário"
#. module: auction
#: wizard_button:auction.lots.buyer_map,check,end:0
@@ -417,12 +417,12 @@ msgstr ""
#: wizard_button:auction.lots.numerotate,search,end:0
#: wizard_button:auction.lots.numerotate_cont,init,end:0
msgid "Exit"
msgstr ""
msgstr "Sair"
#. module: auction
#: field:report.buyer.auction2,net_revenue:0
msgid "Net Revenue"
msgstr ""
msgstr "Receita Líquida"
#. module: auction
#: view:report.buyer.auction:0
@@ -437,17 +437,17 @@ msgstr ""
#: field:report.seller.auction,state:0
#: field:report.unclassified.objects,state:0
msgid "Status"
msgstr ""
msgstr "Situação"
#. module: auction
#: model:ir.actions.wizard,name:auction.wizard_sms
msgid "SMS Send"
msgstr ""
msgstr "Enviar SMS"
#. module: auction
#: selection:auction.lot.category,aie_categ:0
msgid "Antique/Cartoons"
msgstr ""
msgstr "Antigo/Desenhos"
#. module: auction
#: view:auction.lots:0
@@ -455,42 +455,42 @@ msgstr ""
#: selection:report.seller.auction,state:0
#: selection:report.unclassified.objects,state:0
msgid "Sold"
msgstr ""
msgstr "Vendido"
#. module: auction
#: constraint:hr.employee:0
msgid "Error ! You cannot create recursive Hierarchy of Employees."
msgstr ""
msgstr "Erro! Você não pode criar hierarquia recursiva de funcionários."
#. module: auction
#: field:auction.bid_line,name:0
msgid "Bid date"
msgstr ""
msgstr "Data do lance"
#. module: auction
#: field:auction.dates,acc_expense:0
msgid "Expense Account"
msgstr ""
msgstr "Conta de despesas"
#. module: auction
#: model:ir.ui.menu,name:auction.menu_wizard_emporte
msgid "Deliveries Management"
msgstr ""
msgstr "Gerenciamento de entregas"
#. module: auction
#: field:auction.lots,obj_desc:0
msgid "Object Description"
msgstr ""
msgstr "Descrição do objeto"
#. module: auction
#: selection:auction.deposit,method:0
msgid "Contact the Seller"
msgstr ""
msgstr "Entre em contato com o vendedor"
#. module: auction
#: view:auction.lots:0
msgid "Auction Objects"
msgstr ""
msgstr "Leilão de Objetos"
#. module: auction
#: field:auction.lots,gross_revenue:0
@@ -498,12 +498,12 @@ msgstr ""
#: field:report.object.encoded.manager,gross_revenue:0
#: field:report.seller.auction2,gross_revenue:0
msgid "Gross revenue"
msgstr ""
msgstr "Receita bruta"
#. module: auction
#: view:report.seller.auction2:0
msgid "Auction reporting2 form view"
msgstr ""
msgstr "Relatório2 de formulário de Leilão"
#. module: auction
#: model:ir.actions.wizard,name:auction.wizard_pay
@@ -513,45 +513,45 @@ msgstr ""
#. module: auction
#: view:report.deposit.border:0
msgid "Depositer's statistics"
msgstr ""
msgstr "Estatísticas dos Depositantes"
#. module: auction
#: view:auction.lots:0
msgid "Buyer information"
msgstr ""
msgstr "Informações do Comprador"
#. module: auction
#: model:ir.model,name:auction.model_report_seller_auction
msgid "Auction Reporting on seller view"
msgstr ""
msgstr "Relatório Leilão na visão do Vendedor"
#. module: auction
#: field:auction.lots,name2:0
msgid "Short Description (2)"
msgstr ""
msgstr "Descrição resumida (2)"
#. module: auction
#: model:ir.model,name:auction.model_auction_dates
msgid "auction.dates"
msgstr ""
msgstr "leilão.datas"
#. module: auction
#: rml:auction.total.rml:0
#: model:ir.ui.menu,name:auction.auction_buyers_menu
msgid "Buyers"
msgstr ""
msgstr "Vendedores"
#. module: auction
#: wizard_field:auction.pay.buy,init,amount:0
#: wizard_field:auction.pay.buy,init,amount2:0
#: wizard_field:auction.pay.buy,init,amount3:0
msgid "Amount paid"
msgstr ""
msgstr "Valor pago"
#. module: auction
#: model:ir.ui.menu,name:auction.menu_report_latest_doposit_tree
msgid "My Latest Deposits"
msgstr ""
msgstr "Meus Últimos Depósitos"
#. module: auction
#: field:auction.lots,lot_est1:0
@@ -560,32 +560,32 @@ msgstr ""
#: field:report.auction.view,min_est:0
#: field:report.unclassified.objects,lot_est1:0
msgid "Minimum Estimation"
msgstr ""
msgstr "Estimativa mínima"
#. module: auction
#: view:auction.dates:0
msgid "Accounting"
msgstr ""
msgstr "Contabilidade"
#. module: auction
#: model:ir.ui.menu,name:auction.menu_buyer_allmonth_view2
msgid "Buyer's Revenues"
msgstr ""
msgstr "Receitas do comprador"
#. module: auction
#: model:ir.model,name:auction.model_report_auction_adjudication
msgid "report_auction_adjudication"
msgstr ""
msgstr "relatório_leilão_concedido"
#. module: auction
#: field:auction.bid_line,price:0
msgid "Maximum Price"
msgstr ""
msgstr "Preço máximo"
#. module: auction
#: selection:auction.lots.send.aie,date_ask,lang:0
msgid "eng"
msgstr ""
msgstr "Inglês"
#. module: auction
#: view:report.buyer.auction2:0
@@ -595,17 +595,17 @@ msgstr ""
#. module: auction
#: wizard_view:auction.lots.sms_send,init:0
msgid "Bulk SMS send"
msgstr ""
msgstr "Enviar SMS em massa"
#. module: auction
#: wizard_view:auction.taken,init:0
msgid "Select lots which are Sold"
msgstr ""
msgstr "Selecione lotes que são vendidos"
#. module: auction
#: field:auction.lots,statement_id:0
msgid "Payment"
msgstr ""
msgstr "Pagamento"
#. module: auction
#: selection:auction.lots.send.aie,date_ask,lang:0
@@ -615,50 +615,50 @@ msgstr ""
#. module: auction
#: selection:auction.lot.category,aie_categ:0
msgid "Antique/Old weapons and militaria"
msgstr ""
msgstr "Antiguidade/Armas antigas e militares"
#. module: auction
#: selection:auction.lot.category,aie_categ:0
msgid "Antique/Oriental Arts/Chineese furnitures"
msgstr ""
msgstr "Antiguidade/Arte Orientas/Mobiliário Chinês"
#. module: auction
#: selection:auction.deposit,method:0
msgid "Keep until sold"
msgstr ""
msgstr "Manter até vender"
#. module: auction
#: wizard_button:auction.lots.numerotate,init,choice:0
#: wizard_button:auction.lots.send.aie,init,date_ask:0
#: wizard_button:auction.lots.send.aie.results,init,date_ask:0
msgid "Continue"
msgstr ""
msgstr "Continuar"
#. module: auction
#: field:report.object.encoded,obj_num:0
#: field:report.object.encoded.manager,obj_num:0
msgid "# of Encoded obj."
msgstr ""
msgstr "# do Objeto Codificado"
#. module: auction
#: xsl:report.auction.vnd_bordereau:0
msgid "List N."
msgstr ""
msgstr "Lista N."
#. module: auction
#: field:report.deposit.border,moy_est:0
msgid "Avg. Est"
msgstr ""
msgstr "Média Estimada"
#. module: auction
#: rml:auction.total.rml:0
msgid "# of sellers:"
msgstr ""
msgstr "# dos vendedores:"
#. module: auction
#: constraint:product.product:0
msgid "Error: Invalid ean code"
msgstr "Error: código EAN invalido"
msgstr "Erro: Código EAN inválido"
#. module: auction
#: model:ir.module.module,description:auction.module_meta_information
@@ -669,26 +669,31 @@ msgid ""
" Delivery Management. \n"
" "
msgstr ""
"Este módulo fornece funcionalidade para \n"
" gerenciar artistas, artigos, vendedores, compradores e leilão.\n"
" Gerenciar ofertas, registro de objetos vendidos, pagos e não pagos.\n"
" A administração das entregas. \n"
" "
#. module: auction
#: rml:auction.total.rml:0
msgid "# of items taken away:"
msgstr ""
msgstr "# de itens retirados:"
#. module: auction
#: model:ir.ui.menu,name:auction.menu_auction_allmonth_view1
msgid "Auction's Summary"
msgstr ""
msgstr "Resumo do Leilão"
#. module: auction
#: rml:buyer.list:0
msgid "%)"
msgstr ""
msgstr "%)"
#. module: auction
#: wizard_view:auction.lots.able,init:0
msgid "Confirmation set taken away"
msgstr ""
msgstr "Confirmação marcada como retirada"
#. module: auction
#: wizard_field:auction.lots.make_invoice,init,objects:0
@@ -697,7 +702,7 @@ msgstr ""
#: wizard_field:auction.lots.send.aie.results,date_ask,objects:0
#: field:report.deposit.border,nb_obj:0
msgid "# of objects"
msgstr ""
msgstr "# dos Objetos"
#. module: auction
#: field:auction.lots,lot_est2:0
@@ -706,12 +711,12 @@ msgstr ""
#: field:report.auction.view,max_est:0
#: field:report.unclassified.objects,lot_est2:0
msgid "Maximum Estimation"
msgstr ""
msgstr "Estimativa Máxima"
#. module: auction
#: field:auction.lots,buyer_price:0
msgid "Buyer price"
msgstr ""
msgstr "Preço Comprador"
#. module: auction
#: model:ir.actions.wizard,name:auction.auction_wizard_payer_sel
@@ -721,17 +726,17 @@ msgstr ""
#. module: auction
#: model:ir.actions.report.xml,name:auction.seller_form_id
msgid "Seller List"
msgstr ""
msgstr "Lista de Vendedor"
#. module: auction
#: field:auction.lots,is_ok:0
msgid "Buyer's payment"
msgstr ""
msgstr "Pagamento do Comprador"
#. module: auction
#: view:auction.dates:0
msgid "Close + Create all invoices"
msgstr ""
msgstr "Fechar + Criar todas as Faturas"
#. module: auction
#: model:ir.actions.wizard,name:auction.auction_catalog_flagy
@@ -741,48 +746,48 @@ msgstr ""
#. module: auction
#: field:auction.lot.history,price:0
msgid "Withdrawn price"
msgstr ""
msgstr "Preço de retirada"
#. module: auction
#: model:account.tax,name:auction.auction_tax4
msgid "Seller Costs1"
msgstr ""
msgstr "Custo1 do Venderor"
#. module: auction
#: selection:auction.lot.category,aie_categ:0
msgid "Antique/Verreries"
msgstr ""
msgstr "Antiguidade/Cristais"
#. module: auction
#: selection:auction.lot.category,aie_categ:0
msgid "Antique/Toys"
msgstr ""
msgstr "Antiguidade/Briquedos"
#. module: auction
#: field:auction.deposit,create_uid:0
#: field:auction.lots,create_uid:0
msgid "Created by"
msgstr ""
msgstr "Criado por"
#. module: auction
#: xsl:report.auction.ach_bordereau:0
msgid "Buyer form"
msgstr ""
msgstr "Formulário do comprador"
#. module: auction
#: xsl:report.auction.deposit:0
msgid "Estimate"
msgstr ""
msgstr "Estimativa"
#. module: auction
#: rml:auction.total.rml:0
msgid "# of buyers:"
msgstr ""
msgstr "# dos compradores:"
#. module: auction
#: field:auction.lots,costs:0
msgid "Indirect costs"
msgstr ""
msgstr "Custos indiretos"
#. module: auction
#: xsl:report.auction.ach_bordereau:0
@@ -792,12 +797,12 @@ msgstr ""
#. module: auction
#: constraint:account.tax.code:0
msgid "Error ! You can not create recursive accounts."
msgstr ""
msgstr "Erro ! Você não pode criar contas repetidas."
#. module: auction
#: model:ir.ui.menu,name:auction.auction_menu_root
msgid "Auction Management"
msgstr ""
msgstr "Gerenciamento de leilão"
#. module: auction
#: field:auction.dates,journal_seller_id:0
@@ -807,23 +812,23 @@ msgstr ""
#. module: auction
#: view:report.buyer.auction:0
msgid "Auction buyer reporting tree view"
msgstr ""
msgstr "Relatório de compra do leilão exibição em árvore"
#. module: auction
#: model:ir.ui.menu,name:auction.menu_auction_artist
msgid "Define Artists"
msgstr ""
msgstr "Definir artistas"
#. module: auction
#: field:auction.lot.category,name:0
msgid "Category Name"
msgstr ""
msgstr "Nome da Categoria"
#. module: auction
#: model:ir.ui.menu,name:auction.menu_report_auction_estimation_adj_category_manager
#: model:ir.ui.menu,name:auction.menu_report_auction_estimation_adj_category_member
msgid "Comparison of estimations"
msgstr ""
msgstr "Comparação das estimativas"
#. module: auction
#: model:ir.actions.report.xml,name:auction.v_report_barcode_lot
@@ -833,34 +838,34 @@ msgstr ""
#. module: auction
#: wizard_button:auction.lots.numerotate,not_exist,init:0
msgid "Retry"
msgstr ""
msgstr "Repetir"
#. module: auction
#: field:auction.artists,birth_death_dates:0
msgid "Birth / Death dates"
msgstr ""
msgstr "Datas de Nascimento / Morte"
#. module: auction
#: selection:auction.lot.category,aie_categ:0
msgid "Antique/Jewelry"
msgstr ""
msgstr "Antiguidade/Jóias"
#. module: auction
#: model:ir.model,name:auction.model_report_unclassified_objects
msgid "Unclassified objects "
msgstr ""
msgstr "objetos não classificados "
#. module: auction
#: wizard_button:auction.lots.numerotate_cont,init,set_number:0
#: wizard_field:auction.lots.send.aie,date_ask,numerotation:0
#: wizard_field:auction.lots.send.aie,init,numerotation:0
msgid "Numerotation"
msgstr ""
msgstr "Numerotation"
#. module: auction
#: model:ir.actions.act_window,name:auction.act_auction_lot_open_deposit
msgid "Bordereau de dépôt"
msgstr ""
msgstr "Comprovante de depósito"
#. module: auction
#: xsl:report.auction.deposit:0
@@ -0,0 +1,99 @@
#!/usr/bin/env python
"""
Buffering HTTP Server
Copyright (C) 1999 Christian Scholz (ruebe@aachen.heimat.de)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
from utils import VERSION, AUTHOR
__version__ = VERSION
__author__ = AUTHOR
from BaseHTTPServer import BaseHTTPRequestHandler
import os
class BufferedHTTPRequestHandler(BaseHTTPRequestHandler):
"""
Buffering HTTP Request Handler
This class is an extension to the BaseHTTPRequestHandler
class which buffers the whole output and sends it at once
after the processing if the request is finished.
This makes it possible to work together with some clients
which otherwise would break (e.g. cadaver)
"""
def _init_buffer(self):
"""initialize the buffer.
If you override the handle() method remember to call
this (see below)
"""
self.__buffer=""
self.__outfp=os.tmpfile()
def _append(self,s):
""" append a string to the buffer """
self.__buffer=self.__buffer+s
def _flush(self):
""" flush the buffer to wfile """
self.wfile.write(self.__buffer)
self.__outfp.write(self.__buffer)
self.__outfp.flush()
self.wfile.flush()
self.__buffer=""
def handle(self):
""" Handle a HTTP request """
self._init_buffer()
BaseHTTPRequestHandler.handle(self)
self._flush()
def send_header(self, keyword, value):
"""Send a MIME header."""
if self.request_version != 'HTTP/0.9':
self._append("%s: %s\r\n" % (keyword, value))
def end_headers(self):
"""Send the blank line ending the MIME headers."""
if self.request_version != 'HTTP/0.9':
self._append("\r\n")
def send_response(self, code, message=None):
self.log_request(code)
if message is None:
if self.responses.has_key(code):
message = self.responses[code][0]
else:
message = ''
if self.request_version != 'HTTP/0.9':
self._append("%s %s %s\r\n" %
(self.protocol_version, str(code), message))
self.send_header('Server', self.version_string())
self.send_header('Connection', 'close')
self.send_header('Date', self.date_time_string())
protocol_version="HTTP/1.1"
+379
View File
@@ -0,0 +1,379 @@
"""
Python WebDAV Server.
Copyright (C) 1999 Christian Scholz (ruebe@aachen.heimat.de)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
This module builds on AuthServer by implementing the standard DAV
methods.
Subclass this class and specify an IFACE_CLASS. See example.
"""
DEBUG=None
from utils import VERSION, AUTHOR
__version__ = VERSION
__author__ = AUTHOR
import os
import sys
import time
import socket
import string
import posixpath
import base64
import urlparse
import urllib
from propfind import PROPFIND
from delete import DELETE
from davcopy import COPY
from davmove import MOVE
from string import atoi,split
from status import STATUS_CODES
from errors import *
import BaseHTTPServer
class DAVRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
"""Simple DAV request handler with
- GET
- HEAD
- PUT
- OPTIONS
- PROPFIND
- PROPPATCH
- MKCOL
It uses the resource/collection classes for serving and
storing content.
"""
server_version = "DAV/" + __version__
protocol_version = 'HTTP/1.1'
### utility functions
def _log(self, message):
pass
def _append(self,s):
""" write the string to wfile """
self.wfile.write(s)
def send_body(self,DATA,code,msg,desc,ctype='application/octet-stream',headers=None):
""" send a body in one part """
if not headers:
headers = {}
self.send_response(code,message=msg)
self.send_header("Connection", "keep-alive")
self.send_header("Accept-Ranges", "bytes")
for a,v in headers.items():
self.send_header(a,v)
if DATA:
self.send_header("Content-Length", str(len(DATA)))
self.send_header("Content-Type", ctype)
else:
self.send_header("Content-Length", "0")
self.end_headers()
if DATA:
self._append(DATA)
def send_body_chunks(self,DATA,code,msg,desc,ctype='text/xml; encoding="utf-8"'):
""" send a body in chunks """
self.responses[207]=(msg,desc)
self.send_response(code,message=msg)
self.send_header("Content-type", ctype)
self.send_header("Connection", "keep-alive")
self.send_header("Transfer-Encoding", "chunked")
self.end_headers()
self._append(hex(len(DATA))[2:]+"\r\n")
self._append(DATA)
self._append("\r\n")
self._append("0\r\n")
self._append("\r\n")
### HTTP METHODS
def do_OPTIONS(self):
"""return the list of capabilities """
self.send_response(200)
self.send_header("Allow", "GET, HEAD, COPY, MOVE, POST, PUT, PROPFIND, PROPPATCH, OPTIONS, MKCOL, DELETE, TRACE")
self.send_header("Content-Type", "text/plain")
self.send_header("Connection", "keep-alive")
self.send_header("DAV", "1")
self.end_headers()
def do_PROPFIND(self):
dc=self.IFACE_CLASS
# read the body
body=None
if self.headers.has_key("Content-Length"):
l=self.headers['Content-Length']
body=self.rfile.read(atoi(l))
alt_body = """<?xml version="1.0" encoding="utf-8"?>
<propfind xmlns="DAV:"><prop>
<getcontentlength xmlns="DAV:"/>
<getlastmodified xmlns="DAV:"/>
<getcreationdate xmlns="DAV:"/>
<checked-in xmlns="DAV:"/>
<executable xmlns="http://apache.org/dav/props/"/>
<displayname xmlns="DAV:"/>
<resourcetype xmlns="DAV:"/>
<checked-out xmlns="DAV:"/>
</prop></propfind>"""
#self.wfile.write(body)
# which Depth?
if self.headers.has_key('Depth'):
d=self.headers['Depth']
else:
d="infinity"
uri=self.geturi()
pf=PROPFIND(uri,dc,d)
if body:
pf.read_propfind(body)
try:
DATA=pf.createResponse()
DATA=DATA+"\n"
# print "Data:", DATA
except DAV_NotFound,(ec,dd):
return self.send_notFound(dd, uri)
except DAV_Error, (ec,dd):
return self.send_error(ec,dd)
self.send_body_chunks(DATA,207,"Multi-Status","Multiple responses")
def geturi(self):
buri = self.IFACE_CLASS.baseuri
if buri[-1] == '/':
return urllib.unquote(buri[:-1]+self.path)
else:
return urllib.unquote(buri+self.path)
def do_GET(self):
"""Serve a GET request."""
dc=self.IFACE_CLASS
uri=self.geturi()
# get the last modified date
try:
lm=dc.get_prop(uri,"DAV:","getlastmodified")
except:
lm="Sun, 01 Dec 2014 00:00:00 GMT" # dummy!
headers={"Last-Modified":lm , "Connection": "keep-alive"}
# get the content type
try:
ct=dc.get_prop(uri,"DAV:","getcontenttype")
except:
ct="application/octet-stream"
# get the data
try:
data=dc.get_data(uri)
except DAV_Error, (ec,dd):
self.send_status(ec)
return
# send the data
self.send_body(data,200,"OK","OK",ct,headers)
def do_HEAD(self):
""" Send a HEAD response """
dc=self.IFACE_CLASS
uri=self.geturi()
# get the last modified date
try:
lm=dc.get_prop(uri,"DAV:","getlastmodified")
except:
lm="Sun, 01 Dec 2014 00:00:00 GMT" # dummy!
headers={"Last-Modified":lm, "Connection": "keep-alive"}
# get the content type
try:
ct=dc.get_prop(uri,"DAV:","getcontenttype")
except:
ct="application/octet-stream"
try:
data=dc.get_data(uri)
headers["Content-Length"]=str(len(data))
except DAV_NotFound:
self.send_body(None,404,"Not Found","")
return
self.send_body(None,200,"OK","OK",ct,headers)
def do_POST(self):
self.send_error(404,"File not found")
def do_MKCOL(self):
""" create a new collection """
dc=self.IFACE_CLASS
uri=self.geturi()
try:
res = dc.mkcol(uri)
if res:
self.send_body(None,201,"Created",'')
else:
self.send_body(None,415,"Cannot create",'')
#self.send_header("Connection", "keep-alive")
# Todo: some content, too
except DAV_Error, (ec,dd):
self.send_body(None,int(ec),dd,dd)
def do_DELETE(self):
""" delete an resource """
dc=self.IFACE_CLASS
uri=self.geturi()
dl=DELETE(uri,dc)
if dc.is_collection(uri):
res=dl.delcol()
else:
res=dl.delone()
if res:
self.send_status(207,body=res)
else:
self.send_status(204)
def do_PUT(self):
dc=self.IFACE_CLASS
# read the body
body=None
if self.headers.has_key("Content-Length"):
l=self.headers['Content-Length']
body=self.rfile.read(atoi(l))
uri=self.geturi()
ct=None
if self.headers.has_key("Content-Type"):
ct=self.headers['Content-Type']
try:
dc.put(uri,body,ct)
except DAV_Error, (ec,dd):
self.send_status(ec)
return
self.send_status(201)
def do_COPY(self):
""" copy one resource to another """
try:
self.copymove(COPY)
except DAV_Error, (ec,dd):
self.send_status(ec)
def do_MOVE(self):
""" move one resource to another """
try:
self.copymove(MOVE)
except DAV_Error, (ec,dd):
self.send_status(ec)
def copymove(self,CLASS):
""" common method for copying or moving objects """
dc=self.IFACE_CLASS
# get the source URI
source_uri=self.geturi()
# get the destination URI
dest_uri=self.headers['Destination']
dest_uri=urllib.unquote(dest_uri)
# Overwrite?
overwrite=1
result_code=204
if self.headers.has_key("Overwrite"):
if self.headers['Overwrite']=="F":
overwrite=None
result_code=201
# instanciate ACTION class
cp=CLASS(dc,source_uri,dest_uri,overwrite)
# Depth?
d="infinity"
if self.headers.has_key("Depth"):
d=self.headers['Depth']
if d!="0" and d!="infinity":
self.send_status(400)
return
if d=="0":
res=cp.single_action()
self.send_status(res)
return
# now it only can be "infinity" but we nevertheless check for a collection
if dc.is_collection(source_uri):
try:
res=cp.tree_action()
except DAV_Error, (ec,dd):
self.send_status(ec)
return
else:
try:
res=cp.single_action()
except DAV_Error, (ec,dd):
self.send_status(ec)
return
if res:
self.send_body_chunks(res,207,STATUS_CODES[207],STATUS_CODES[207],
ctype='text/xml; charset="utf-8"')
else:
self.send_status(result_code)
def get_userinfo(self,user,pw):
""" Dummy method which lets all users in """
return 1
def send_status(self,code=200,mediatype='text/xml; charset="utf-8"', \
msg=None,body=None):
if not msg: msg=STATUS_CODES[code]
self.send_body(body,code,STATUS_CODES[code],msg,mediatype)
def send_notFound(self,descr,uri):
body = """<?xml version="1.0" encoding="utf-8" ?>
<D:response xmlns:D="DAV:">
<D:href>%s</D:href>
<D:error/>
<D:responsedescription>%s</D:responsedescription>
</D:response>
"""
return self.send_status(404,descr, body=body % (uri,descr))
+20
View File
@@ -0,0 +1,20 @@
"""
python davserver
Copyright (C) 1999 Christian Scholz (ruebe@aachen.heimat.de)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
+18
View File
@@ -0,0 +1,18 @@
"""
constants definition
"""
# definition for resourcetype
COLLECTION=1
OBJECT=None
DAV_PROPS=['creationdate', 'displayname', 'getcontentlanguage', 'getcontentlength', 'getcontenttype', 'getetag', 'getlastmodified', 'lockdiscovery', 'resourcetype', 'source', 'supportedlock']
# Request classes in propfind
RT_ALLPROP=1
RT_PROPNAME=2
RT_PROP=3
+218
View File
@@ -0,0 +1,218 @@
"""
davcmd.py
---------
containts commands like copy, move, delete for normal
resources and collections
"""
from string import split,replace,joinfields
import urlparse
from utils import create_treelist, is_prefix
from errors import *
def deltree(dc,uri,exclude={}):
""" delete a tree of resources
dc -- dataclass to use
uri -- root uri to delete
exclude -- an optional list of uri:error_code pairs which should not
be deleted.
returns dict of uri:error_code tuples from which
another method can create a multistatus xml element.
Also note that we only know Depth=infinity thus we don't have
to test for it.
"""
tlist=create_treelist(dc,uri)
result={}
for i in range(len(tlist),0,-1):
problem_uris=result.keys()
element=tlist[i-1]
# test here, if an element is a prefix of an uri which
# generated an error before.
# note that we walk here from childs to parents, thus
# we cannot delete a parent if a child made a problem.
# (see example in 8.6.2.1)
ok=1
for p in problem_uris:
if is_prefix(element,p):
ok=None
break
if not ok: continue
# here we test for the exclude list which is the other way round!
for p in exclude.keys():
if is_prefix(p,element):
ok=None
break
if not ok: continue
# now delete stuff
try:
delone(dc,element)
except DAV_Error, (ec,dd):
result[element]=ec
return result
def delone(dc,uri):
""" delete a single object """
if dc.is_collection(uri):
dc.rmcol(uri) # should be empty
else:
dc.rm(uri)
###
### COPY
###
# helper function
def copy(dc,src,dst):
""" only copy the element
This is just a helper method factored out from copy and
copytree. It will not handle the overwrite or depth header.
"""
# destination should have been deleted before
if dc.exists(dst): raise DAV_Error, 412
# source should exist also
if not dc.exists(src): raise DAV_NotFound
if dc.is_collection(src):
dc.copycol(src,dst) # an exception will be passed thru
else:
dc.copy(src,dst) # an exception will be passed thru
# the main functions
def copyone(dc,src,dst,overwrite=None):
""" copy one resource to a new destination """
if overwrite and dc.exists(dst):
delres=deltree(dc,dst)
else:
delres={}
# if we cannot delete everything, then do not copy!
if delres: return delres
try:
copy(dc,src,dst) # pass thru exceptions
except DAV_Error, (ec,dd):
return ec
def copytree(dc,src,dst,overwrite=None):
""" copy a tree of resources to another location
dc -- dataclass to use
src -- src uri from where to copy
dst -- dst uri
overwrite -- if 1 then delete dst uri before
returns dict of uri:error_code tuples from which
another method can create a multistatus xml element.
"""
# first delete the destination resource
if overwrite and dc.exists(dst):
delres=deltree(dc,dst)
else:
delres={}
# if we cannot delete everything, then do not copy!
if delres: return delres
# get the tree we have to copy
tlist=create_treelist(dc,src)
result={}
# prepare destination URIs (get the prefix)
dpath=urlparse.urlparse(dst)[2]
for element in tlist:
problem_uris=result.keys()
# now URIs get longer and longer thus we have
# to test if we had a parent URI which we were not
# able to copy in problem_uris which is the prefix
# of the actual element. If it is, then we cannot
# copy this as well but do not generate another error.
ok=1
for p in problem_uris:
if is_prefix(p,element):
ok=None
break
if not ok: continue
# now create the destination URI which corresponds to
# the actual source URI. -> actual_dst
# ("subtract" the base src from the URI and prepend the
# dst prefix to it.)
esrc=replace(element,src,"")
actual_dst=dpath+esrc
# now copy stuff
try:
copy(dc,element,actual_dst)
except DAV_Error, (ec,dd):
result[element]=ec
return result
###
### MOVE
###
def moveone(dc,src,dst,overwrite=None):
""" move a single resource
This is done by first copying it and then deleting
the original.
"""
# first copy it
copyone(dc,src,dst,overwrite)
# then delete it
dc.rm(src)
def movetree(dc,src,dst,overwrite=None):
""" move a collection
This is done by first copying it and then deleting
the original.
PROBLEM: if something did not copy then we have a problem
when deleting as the original might get deleted!
"""
# first copy it
res=copytree(dc,src,dst,overwrite)
# then delete it
res=deltree(dc,src,exclude=res)
return res
+133
View File
@@ -0,0 +1,133 @@
#!/usr/bin/env python
"""
python davserver
Copyright (C) 1999 Christian Scholz (ruebe@aachen.heimat.de)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
from xml.dom import ext
from xml.dom.Document import Document
import sys
import string
import urlparse
import urllib
from StringIO import StringIO
import utils
from constants import COLLECTION, OBJECT, DAV_PROPS, RT_ALLPROP, RT_PROPNAME, RT_PROP
from errors import *
from utils import create_treelist, quote_uri, gen_estring
class COPY:
""" copy resources and eventually create multistatus responses
This module implements the COPY class which is responsible for
copying resources. Usually the normal copy work is done in the
interface class. This class only creates error messages if error
occur.
"""
def __init__(self,dataclass,src_uri,dst_uri,overwrite):
self.__dataclass=dataclass
self.__src=src_uri
self.__dst=dst_uri
self.__overwrite=overwrite
def single_action(self):
""" copy a normal resources.
We try to copy it and return the result code.
This is for Depth==0
"""
dc=self.__dataclass
base=self.__src
### some basic tests
# test if dest exists and overwrite is false
if dc.exists(self.__dst) and not self.__overwrite: raise DAV_Error, 412
# test if src and dst are the same
# (we assume that both uris are on the same server!)
ps=urlparse.urlparse(self.__src)[2]
pd=urlparse.urlparse(self.__dst)[2]
if ps==pd: raise DAV_Error, 403
return dc.copyone(self.__src,self.__dst,self.__overwrite)
#return copyone(dc,self.__src,self.__dst,self.__overwrite)
def tree_action(self):
""" copy a tree of resources (a collection)
Here we return a multistatus xml element.
"""
dc=self.__dataclass
base=self.__src
### some basic tests
# test if dest exists and overwrite is false
if dc.exists(self.__dst) and not self.__overwrite: raise DAV_Error, 412
# test if src and dst are the same
# (we assume that both uris are on the same server!)
ps=urlparse.urlparse(self.__src)[2]
pd=urlparse.urlparse(self.__dst)[2]
if ps==pd: raise DAV_Error, 403
result=dc.copytree(self.__src,self.__dst,self.__overwrite)
#result=copytree(dc,self.__src,self.__dst,self.__overwrite)
if not result: return None
###
### create the multistatus XML element
### (this is also the same as in delete.py.
### we might make a common method out of it)
###
doc = Document(None)
ms=doc.createElement("D:multistatus")
ms.setAttribute("xmlns:D","DAV:")
doc.appendChild(ms)
for el,ec in result.items():
re=doc.createElement("D:response")
hr=doc.createElement("D:href")
st=doc.createElement("D:status")
huri=doc.createTextNode(quote_uri(el))
t=doc.createTextNode(gen_estring(ec))
st.appendChild(t)
hr.appendChild(huri)
re.appendChild(hr)
re.appendChild(st)
ms.appendChild(re)
sfile=StringIO()
ext.PrettyPrint(doc,stream=sfile)
s=sfile.getvalue()
sfile.close()
return s
+102
View File
@@ -0,0 +1,102 @@
#!/usr/bin/env python
"""
python davserver
Copyright (C) 1999 Christian Scholz (ruebe@aachen.heimat.de)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
import sys
import string
import urlparse
import urllib
from StringIO import StringIO
import utils
from constants import COLLECTION, OBJECT, DAV_PROPS
from constants import RT_ALLPROP, RT_PROPNAME, RT_PROP
from errors import *
from utils import create_treelist, quote_uri, gen_estring, make_xmlresponse
from davcmd import moveone, movetree
class MOVE:
""" move resources and eventually create multistatus responses
This module implements the MOVE class which is responsible for
moving resources.
MOVE is implemented by a COPY followed by a DELETE of the old
resource.
"""
def __init__(self,dataclass,src_uri,dst_uri,overwrite):
self.__dataclass=dataclass
self.__src=src_uri
self.__dst=dst_uri
self.__overwrite=overwrite
def single_action(self):
""" move a normal resources.
We try to move it and return the result code.
This is for Depth==0
"""
dc=self.__dataclass
base=self.__src
### some basic tests
# test if dest exists and overwrite is false
if dc.exists(self.__dst) and not self.__overwrite: raise DAV_Error, 412
# test if src and dst are the same
# (we assume that both uris are on the same server!)
ps=urlparse.urlparse(self.__src)[2]
pd=urlparse.urlparse(self.__dst)[2]
if ps==pd: raise DAV_Error, 403
return dc.moveone(self.__src,self.__dst,self.__overwrite)
def tree_action(self):
""" move a tree of resources (a collection)
Here we return a multistatus xml element.
"""
dc=self.__dataclass
base=self.__src
### some basic tests
# test if dest exists and overwrite is false
if dc.exists(self.__dst) and not self.__overwrite: raise DAV_Error, 412
# test if src and dst are the same
# (we assume that both uris are on the same server!)
ps=urlparse.urlparse(self.__src)[2]
pd=urlparse.urlparse(self.__dst)[2]
if ps==pd: raise DAV_Error, 403
result=dc.movetree(self.__src,self.__dst,self.__overwrite)
if not result: return None
# create the multistatus XML element
return make_xmlresponse(result)
+63
View File
@@ -0,0 +1,63 @@
#!/usr/bin/env python
"""
python davserver
Copyright (C) 1999 Christian Scholz (ruebe@aachen.heimat.de)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
import os
import string
import urllib
from StringIO import StringIO
from status import STATUS_CODES
from utils import gen_estring, quote_uri, make_xmlresponse
from davcmd import deltree
class DELETE:
def __init__(self,uri,dataclass):
self.__dataclass=dataclass
self.__uri=uri
def delcol(self):
""" delete a collection """
dc=self.__dataclass
result=dc.deltree(self.__uri)
if not len(result.items()):
return None # everything ok
# create the result element
return make_xmlresponse(result)
def delone(self):
""" delete a resource """
dc=self.__dataclass
result=dc.delone(self.__uri)
if not result: return None
if not len(result.items()):
return None # everything ok
# create the result element
return make_xmlresponse(result)
+56
View File
@@ -0,0 +1,56 @@
#!/usr/bin/env python
"""
Exceptions for the DAVserver implementation
"""
class DAV_Error(Exception):
""" in general we can have the following arguments:
1. the error code
2. the error result element, e.g. a <multistatus> element
"""
def __init__(self,*args):
if len(args)==1:
self.args=(args[0],"")
else:
self.args=args
class DAV_Secret(DAV_Error):
""" the user is not allowed to know anything about it
returning this for a property value means to exclude it
from the response xml element.
"""
def __init__(self):
DAV_Error.__init__(self,0)
pass
class DAV_NotFound(DAV_Error):
""" a requested property was not found for a resource """
def __init__(self,*args):
if len(args):
if isinstance(args[0],list):
stre = "Path %s not found!"%('/'.join(args[0]))
else:
stre = args[0]
DAV_Error.__init__(self,404,stre)
else:
DAV_Error.__init__(self,404)
pass
class DAV_Forbidden(DAV_Error):
""" a method on a resource is not allowed """
def __init__(self,*args):
if len(args):
DAV_Error.__init__(self,403,args[0])
else:
DAV_Error.__init__(self,403)
pass
+263
View File
@@ -0,0 +1,263 @@
"""
basic interface class
use this for subclassing when writing your own interface
class.
"""
from errors import *
import time
from string import lower
class dav_interface:
""" interface class for implementing DAV servers """
### defined properties (modify this but let the DAV stuff there!)
### the format is namespace: [list of properties]
PROPS={"DAV:" : ('creationdate',
'displayname',
'getcontentlanguage',
'getcontentlength',
'getcontenttype',
'getetag',
'getlastmodified',
'lockdiscovery',
'resourcetype',
'source',
'supportedlock'),
"NS2" : ("p1","p2")
}
# here we define which methods handle which namespace
# the first item is the namespace URI and the second one
# the method prefix
# e.g. for DAV:getcontenttype we call dav_getcontenttype()
M_NS={"DAV:" : "_get_dav",
"NS2" : "ns2" }
def get_propnames(self,uri):
""" return the property names allowed for the given URI
In this method we simply return the above defined properties
assuming that they are valid for any resource.
You can override this in order to return a different set
of property names for each resource.
"""
return self.PROPS
def get_prop2(self,uri,ns,pname):
""" return the value of a property
"""
if lower(ns)=="dav:": return self.get_dav(uri,pname)
raise DAV_NotFound
def get_prop(self,uri,ns,propname):
""" return the value of a given property
uri -- uri of the object to get the property of
ns -- namespace of the property
pname -- name of the property
"""
if self.M_NS.has_key(ns):
prefix=self.M_NS[ns]
else:
print "No namespace:",ns, "( for prop:", propname,")"
raise DAV_NotFound
mname=prefix+"_"+propname
if not hasattr(self,mname):
raise DAV_NotFound
try:
m=getattr(self,mname)
r=m(uri)
return r
except AttributeError, e:
print 'Property %s not supported' % propname
print "Exception:", e
raise DAV_NotFound
###
### DATA methods (for GET and PUT)
###
def get_data(self,uri):
""" return the content of an object
return data or raise an exception
"""
raise DAV_NotFound
def put(self,uri,data):
""" write an object to the repository
return a result code or raise an exception
"""
raise DAV_Forbidden
###
### Methods for DAV properties
###
def _get_dav_creationdate(self,uri):
""" return the creationdate of a resource """
d=self.get_creationdate(uri)
# format it
if isinstance(d, int) or isinstance(d, float):
d = time.localtimetime(d)
return time.strftime("%Y-%m-%dT%H:%M:%S%Z",d)
def _get_dav_getlastmodified(self,uri):
""" return the last modified date of a resource """
d=self.get_lastmodified(uri)
if isinstance(d, int) or isinstance(d, float):
d = time.localtime(d)
# format it
return time.asctime(d)
###
### OVERRIDE THESE!
###
def get_creationdate(self,uri):
""" return the creationdate of the resource """
return time.time()
def get_lastmodified(self,uri):
""" return the last modification date of the resource """
return time.time()
###
### COPY MOVE DELETE
###
### methods for deleting a resource
def rmcol(self,uri):
""" delete a collection
This should not delete any children! This is automatically done
before by the DELETE class in DAV/delete.py
return a success code or raise an exception
"""
raise DAV_NotFound
def rm(self,uri):
""" delete a single resource
return a success code or raise an exception
"""
raise DAV_NotFound
"""
COPY/MOVE HANDLER
These handler are called when a COPY or MOVE method is invoked by
a client. In the default implementation it works as follows:
- the davserver receives a COPY/MOVE method
- the davcopy or davmove module will be loaded and the corresponding
class will be initialized
- this class parses the query and decides which method of the interface class
to call:
copyone for a single resource to copy
copytree for a tree to copy (collection)
(the same goes for move of course).
- the interface class has now two options:
1. to handle the action directly (e.g. cp or mv on filesystems)
2. to let it handle via the copy/move methods in davcmd.
ad 1) The first approach can be used when we know that no error can
happen inside a tree or when the action can exactly tell which
element made which error. We have to collect these and return
it in a dict of the form {uri: error_code, ...}
ad 2) The copytree/movetree/... methods of davcmd.py will do the recursion
themselves and call for each resource the copy/move method of the
interface class. Thus method will then only act on a single resource.
(Thus a copycol on a normal unix filesystem actually only needs to do
an mkdir as the content will be copied by the davcmd.py function.
The davcmd.py method will also automatically collect all errors and
return the dictionary described above.
When you use 2) you also have to implement the copy() and copycol()
methods in your interface class. See the example for details.
To decide which approach is the best you have to decide if your application
is able to generate errors inside a tree. E.g. a function which completely
fails on a tree if one of the tree's childs fail is not what we need. Then
2) would be your way of doing it.
Actually usually 2) is the better solution and should only be replaced by
1) if you really need it.
The remaining question is if we should do the same for the DELETE method.
"""
### MOVE handlers
def moveone(self,src,dst,overwrite):
""" move one resource with Depth=0 """
return moveone(self,src,dst,overwrite)
def movetree(self,src,dst,overwrite):
""" move a collection with Depth=infinity """
return movetree(self,src,dst,overwrite)
### COPY handlers
def copyone(self,src,dst,overwrite):
""" copy one resource with Depth=0 """
return copyone(self,src,dst,overwrite)
def copytree(self,src,dst,overwrite):
""" copy a collection with Depth=infinity """
return copytree(self,src,dst,overwrite)
### low level copy methods (you only need these for method 2)
def copy(self,src,dst):
""" copy a resource with depth==0
You don't need to bother about overwrite or not.
This has been done already.
return a success code or raise an exception if something fails
"""
return 201
def copycol(self,src,dst):
""" copy a resource with depth==infinity
You don't need to bother about overwrite or not.
This has been done already.
return a success code or raise an exception if something fails
"""
return 201
### some utility functions you need to implement
def exists(self,uri):
""" return 1 or None depending on if a resource exists """
return None # no
def is_collection(self,uri):
""" return 1 or None depending on if a resource is a collection """
return None # no
+372
View File
@@ -0,0 +1,372 @@
#!/usr/bin/env python
"""
python davserver
Copyright (C) 1999 Christian Scholz (ruebe@aachen.heimat.de)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
from xml.dom import ext
from xml.dom.Document import Document
import sys
import string
import urlparse
import urllib
from StringIO import StringIO
import utils
from constants import COLLECTION, OBJECT, DAV_PROPS, RT_ALLPROP, RT_PROPNAME, RT_PROP
from errors import *
def utf8str(st):
if isinstance(st,unicode):
return st.encode('utf8')
else:
return str(st)
class PROPFIND:
""" parse a propfind xml element and extract props
It will set the following instance vars:
request_class : ALLPROP | PROPNAME | PROP
proplist : list of properties
nsmap : map of namespaces
The list of properties will contain tuples of the form
(element name, ns_prefix, ns_uri)
"""
def __init__(self,uri,dataclass,depth):
self.request_type=None
self.nsmap={}
self.proplist={}
self.default_ns=None
self.__dataclass=dataclass
self.__depth=str(depth)
self.__uri=uri
self.use_full_urls=True
self.__has_body=None # did we parse a body?
def read_propfind(self,xml_doc):
self.request_type,self.proplist,self.namespaces=utils.parse_propfind(xml_doc)
# a violation of the expected logic: client (korganizer) will ask for DAV:resourcetype
# but we also have to return the http://groupdav.org/:resourcetype property!
if self.proplist.has_key('DAV:') and 'resourcetype' in self.proplist['DAV:']:
if not self.proplist.has_key('http://groupdav.org/'):
self.proplist['http://groupdav.org/'] = []
self.proplist['http://groupdav.org/'].append('resourcetype')
if 'DAV:' in self.namespaces: #TMP
self.namespaces.append('http://groupdav.org/')
def createResponse(self):
""" create the multistatus response
This will be delegated to the specific method
depending on which request (allprop, propname, prop)
was found.
If we get a PROPNAME then we simply return the list with empty
values which we get from the interface class
If we get an ALLPROP we first get the list of properties and then
we do the same as with a PROP method.
If the uri doesn't exist, return an xml response with a 404 status
"""
if not self.__dataclass.exists(self.__uri):
raise DAV_NotFound("Path %s doesn't exist" % self.__uri)
if self.request_type==RT_ALLPROP:
return self.create_allprop()
if self.request_type==RT_PROPNAME:
return self.create_propname()
if self.request_type==RT_PROP:
return self.create_prop()
# no body means ALLPROP!
return self.create_allprop()
def create_propname(self):
""" create a multistatus response for the prop names """
dc=self.__dataclass
# create the document generator
doc = Document(None)
ms=doc.createElement("D:multistatus")
ms.setAttribute("xmlns:D","DAV:")
doc.appendChild(ms)
if self.__depth=="0":
pnames=dc.get_propnames(self.__uri)
re=self.mk_propname_response(self.__uri,pnames,doc)
ms.appendChild(re)
elif self.__depth=="1":
pnames=dc.get_propnames(self.__uri)
re=self.mk_propname_response(self.__uri,pnames,doc)
ms.appendChild(re)
for newuri in dc.get_childs(self.__uri):
pnames=dc.get_propnames(newuri)
re=self.mk_propname_response(newuri,pnames,doc)
ms.appendChild(re)
# *** depth=="infinity"
sfile=StringIO()
ext.PrettyPrint(doc,stream=sfile)
s=sfile.getvalue()
sfile.close()
return s
def create_allprop(self):
""" return a list of all properties """
self.proplist={}
self.namespaces=[]
for ns,plist in self.__dataclass.get_propnames(self.__uri).items():
self.proplist[ns]=plist
self.namespaces.append(ns)
return self.create_prop()
def create_prop(self):
""" handle a <prop> request
This will
1. set up the <multistatus>-Framework
2. read the property values for each URI
(which is dependant on the Depth header)
This is done by the get_propvalues() method.
3. For each URI call the append_result() method
to append the actual <result>-Tag to the result
document.
We differ between "good" properties, which have been
assigned a value by the interface class and "bad"
properties, which resulted in an error, either 404
(Not Found) or 403 (Forbidden).
"""
# create the document generator
doc = Document(None)
ms=doc.createElement("D:multistatus")
ms.setAttribute("xmlns:D","DAV:")
doc.appendChild(ms)
if self.__depth=="0":
gp,bp=self.get_propvalues(self.__uri)
res=self.mk_prop_response(self.__uri,gp,bp,doc)
ms.appendChild(res)
elif self.__depth=="1":
gp,bp=self.get_propvalues(self.__uri)
res=self.mk_prop_response(self.__uri,gp,bp,doc)
ms.appendChild(res)
try:
for newuri in self.__dataclass.get_childs(self.__uri):
gp,bp=self.get_propvalues(newuri)
res=self.mk_prop_response(newuri,gp,bp,doc)
ms.appendChild(res)
except DAV_NotFound:
# If no children, never mind.
pass
sfile=StringIO()
ext.PrettyPrint(doc,stream=sfile)
s=sfile.getvalue()
sfile.close()
return s
def mk_propname_response(self,uri,propnames,doc):
""" make a new <prop> result element for a PROPNAME request
This will simply format the propnames list.
propnames should have the format {NS1 : [prop1, prop2, ...], NS2: ...}
"""
re=doc.createElement("D:response")
# write href information
href=doc.createElement("D:href")
if self.use_full_urls:
huri=doc.createTextNode(uri)
else:
uparts=urlparse.urlparse(uri)
fileloc=uparts[2]
huri=doc.createTextNode(urllib.quote(fileloc.encode('utf8')))
href.appendChild(huri)
re.appendChild(href)
ps=doc.createElement("D:propstat")
nsnum=0
for ns,plist in propnames.items():
# write prop element
pr=doc.createElement("D:prop")
nsp="ns"+str(nsnum)
pr.setAttribute("xmlns:"+nsp,ns)
nsnum=nsnum+1
# write propertynames
for p in plist:
pe=doc.createElement(nsp+":"+p)
pr.appendChild(pe)
ps.appendChild(pr)
re.appendChild(ps)
return re
def mk_prop_response(self,uri,good_props,bad_props,doc):
""" make a new <prop> result element
We differ between the good props and the bad ones for
each generating an extra <propstat>-Node (for each error
one, that means).
"""
re=doc.createElement("D:response")
# append namespaces to response
nsnum=0
for nsname in self.namespaces:
re.setAttribute("xmlns:ns"+str(nsnum),nsname)
nsnum=nsnum+1
# write href information
href=doc.createElement("D:href")
if self.use_full_urls:
huri=doc.createTextNode(uri)
else:
uparts=urlparse.urlparse(uri)
fileloc=uparts[2]
huri=doc.createTextNode(urllib.quote(fileloc.encode('utf8')))
href.appendChild(huri)
re.appendChild(href)
# write good properties
if good_props and len(good_props.items()):
ps=doc.createElement("D:propstat")
gp=doc.createElement("D:prop")
for ns in good_props.keys():
ns_prefix="ns"+str(self.namespaces.index(ns))+":"
for p,v in good_props[ns].items():
pe=doc.createElement(ns_prefix+str(p))
if v == None:
pass
elif ns=='DAV:' and p=="resourcetype":
if v == 1:
ve=doc.createElement("D:collection")
pe.appendChild(ve)
elif isinstance(v,tuple) and v[1] == ns:
ve=doc.createElement(ns_prefix+v[0])
pe.appendChild(ve)
else:
ve=doc.createTextNode(utf8str(v))
pe.appendChild(ve)
gp.appendChild(pe)
if gp.hasChildNodes():
re.appendChild(ps)
ps.appendChild(gp)
s=doc.createElement("D:status")
t=doc.createTextNode("HTTP/1.1 200 OK")
s.appendChild(t)
ps.appendChild(s)
re.appendChild(ps)
# now write the errors!
if len(bad_props.items()):
# write a propstat for each error code
for ecode in bad_props.keys():
ps=doc.createElement("D:propstat")
re.appendChild(ps)
bp=doc.createElement("D:prop")
ps.appendChild(bp)
for ns in bad_props[ecode].keys():
ns_prefix="ns"+str(self.namespaces.index(ns))+":"
for p in bad_props[ecode][ns]:
pe=doc.createElement(ns_prefix+str(p))
bp.appendChild(pe)
s=doc.createElement("D:status")
t=doc.createTextNode(utils.gen_estring(ecode))
s.appendChild(t)
ps.appendChild(s)
re.appendChild(ps)
# return the new response element
return re
def get_propvalues(self,uri):
""" create lists of property values for an URI
We create two lists for an URI: the properties for
which we found a value and the ones for which we
only got an error, either because they haven't been
found or the user is not allowed to read them.
"""
good_props={}
bad_props={}
for (ns,plist) in self.proplist.items():
good_props[ns]={}
bad_props={}
ec = 0
for prop in plist:
try:
ec = 0
r=self.__dataclass.get_prop(uri,ns,prop)
good_props[ns][prop]=r
except DAV_Error, error_code:
ec=error_code[0]
# ignore props with error_code if 0 (invisible)
if ec==0: continue
if bad_props.has_key(ec):
if bad_props[ec].has_key(ns):
bad_props[ec][ns].append(prop)
else:
bad_props[ec][ns]=[prop]
else:
bad_props[ec]={ns:[prop]}
return good_props, bad_props
+31
View File
@@ -0,0 +1,31 @@
"""
status codes for DAV services
"""
STATUS_CODES={
102: "Processing",
200: "Ok",
201: "Created",
204: "No Content",
207: "Multi-Status",
201: "Created",
400: "Bad Request",
403: "Forbidden",
404: "Not Found",
405: "Method Not Allowed",
409: "Conflict",
412: "Precondition failed",
423: "Locked",
415: "Unsupported Media Type",
507: "Insufficient Storage",
422: "Unprocessable Entity",
423: "Locked",
424: "Failed Dependency",
502: "Bad Gateway",
507: "Insufficient Storage",
999: "Some error in Create Method please check the data of create method"
}
+160
View File
@@ -0,0 +1,160 @@
#!/usr/bin/env python
"""
UTILITIES
- parse a propfind request body into a list of props
"""
from xml.dom import ext
from xml.dom.Document import Document
from xml.dom.ext.reader import PyExpat
from xml.dom import Node
from xml.dom import NodeIterator, NodeFilter
from string import lower, split, atoi, joinfields
import urlparse
from StringIO import StringIO
from constants import RT_ALLPROP, RT_PROPNAME, RT_PROP
from status import STATUS_CODES
VERSION = '0.6'
AUTHOR = 'Simon Pamies <s.pamies@banality.de>'
def gen_estring(ecode):
""" generate an error string from the given code """
ec=atoi(str(ecode))
if STATUS_CODES.has_key(ec):
return "HTTP/1.1 %s %s" %(ec,STATUS_CODES[ec])
else:
return "HTTP/1.1 %s" %(ec)
def parse_propfind(xml_doc):
""" parse an propfind xml file and return a list of props
returns:
request_type -- ALLPROP, PROPNAME, PROP
proplist -- list of properties found
namespaces -- list of namespaces found
"""
doc = PyExpat.Reader().fromString(xml_doc)
snit = doc.createNodeIterator(doc, NodeFilter.NodeFilter.SHOW_ELEMENT, None, None)
request_type=None
props={}
namespaces=[]
while 1:
curr_elem = snit.nextNode()
if not curr_elem: break
ename=fname=lower(curr_elem.nodeName)
if ":" in fname:
ename=split(fname,":")[1]
if ename=="prop": request_type=RT_PROP; continue
if ename=="propfind": continue
if ename=="allprop": request_type=RT_ALLPROP; continue
if ename=="propname": request_type=RT_PROPNAME; continue
# rest should be names of attributes
ns = curr_elem.namespaceURI
if props.has_key(ns):
props[ns].append(ename)
else:
props[ns]=[ename]
namespaces.append(ns)
return request_type,props,namespaces
def create_treelist(dataclass,uri):
""" create a list of resources out of a tree
This function is used for the COPY, MOVE and DELETE methods
uri - the root of the subtree to flatten
It will return the flattened tree as list
"""
queue=[uri]
list=[uri]
while len(queue):
element=queue[-1]
if dataclass.is_collection(element):
childs=dataclass.get_childs(element)
else:
childs=[]
if len(childs):
list=list+childs
# update queue
del queue[-1]
if len(childs):
queue=queue+childs
return list
def is_prefix(uri1,uri2):
""" returns 1 of uri1 is a prefix of uri2 """
if uri2[:len(uri1)]==uri1:
return 1
else:
return None
def quote_uri(uri):
""" quote an URL but not the protocol part """
import urlparse
import urllib
up=urlparse.urlparse(uri)
np=urllib.quote(up[2])
return urlparse.urlunparse((up[0],up[1],np,up[3],up[4],up[5]))
def get_uriparentpath(uri):
""" extract the uri path and remove the last element """
up=urlparse.urlparse(uri)
return joinfields(split(up[2],"/")[:-1],"/")
def get_urifilename(uri):
""" extract the uri path and return the last element """
up=urlparse.urlparse(uri)
return split(up[2],"/")[-1]
def get_parenturi(uri):
""" return the parent of the given resource"""
up=urlparse.urlparse(uri)
np=joinfields(split(up[2],"/")[:-1],"/")
return urlparse.urlunparse((up[0],up[1],np,up[3],up[4],up[5]))
### XML utilities
def make_xmlresponse(result):
""" construct a response from a dict of uri:error_code elements """
doc = Document(None)
ms=doc.createElement("D:multistatus")
ms.setAttribute("xmlns:D","DAV:")
doc.appendChild(ms)
for el,ec in result.items():
re=doc.createElement("D:response")
hr=doc.createElement("D:href")
st=doc.createElement("D:status")
huri=doc.createTextNode(quote_uri(el))
t=doc.createTextNode(gen_estring(ec))
st.appendChild(t)
hr.appendChild(huri)
re.appendChild(hr)
re.appendChild(st)
ms.appendChild(re)
sfile=StringIO()
ext.PrettyPrint(doc,stream=sfile)
s=sfile.getvalue()
sfile.close()
return s
+2 -1
View File
@@ -21,5 +21,6 @@
import base_calendar
import wizard
import base_calendar_node
import webdav_server
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+19 -12
View File
@@ -71,7 +71,10 @@ def get_attribute_mapping(cr, uid, calname, context={}):
pool = pooler.get_pool(cr.dbname)
field_obj = pool.get('basic.calendar.fields')
type_obj = pool.get('basic.calendar.lines')
type_id = type_obj.search(cr, uid, [('object_id.model', '=', context.get('model'))])
domain = [('object_id.model', '=', context.get('model'))]
if context.get('calendar_id'):
domain.append(('calendar_id', '=', context.get('calendar_id')))
type_id = type_obj.search(cr, uid, domain)
fids = field_obj.search(cr, uid, [('type_id', '=', type_id[0])])
res = {}
for field in field_obj.browse(cr, uid, fids):
@@ -194,6 +197,8 @@ class CalDAV(object):
self.ical_set(cal_data.name.lower(), vals, 'value')
continue
if cal_data.name.lower() in self.__attribute__:
if cal_data.params.get('X-VOBJ-ORIGINAL-TZID'):
self.ical_set('vtimezone', cal_data.params.get('X-VOBJ-ORIGINAL-TZID'), 'value')
self.ical_set(cal_data.name.lower(), cal_data.value, 'value')
vals = map_data(cr, uid, self)
return vals
@@ -255,7 +260,7 @@ class CalDAV(object):
dtfield = vevent.add(field)
dtfield.value = parser.parse(data[map_field])
if tzval:
dtfield.params['TZID'] = [tzval]
dtfield.params['TZID'] = [tzval.title()]
elif map_type == "timedelta":
vevent.add(field).value = timedelta(hours=data[map_field])
elif map_type == "many2one":
@@ -312,9 +317,6 @@ class CalDAV(object):
for child in parsedCal.getChildren():
if child.name.lower() in ('vevent', 'vtodo'):
vals = self.parse_ics(cr, uid, child, context=context)
elif child.name.lower() == 'vtimezone':
tz_obj = self.pool.get('basic.calendar.timezone')
tz_obj.import_cal(cr, uid, child, context=context)
else:
vals = {}
continue
@@ -361,7 +363,9 @@ class Calendar(CalDAV, osv.osv):
mod_obj = self.pool.get(line.object_id.model)
data_ids = mod_obj.search(cr, uid, eval(line.domain), context=context)
datas = mod_obj.read(cr, uid, data_ids, context=context)
context.update({'model': line.object_id.model})
context.update({'model': line.object_id.model,
'calendar_id': cal.id
})
self.__attribute__ = get_attribute_mapping(cr, uid, line.name, context)
self.create_ics(cr, uid, datas, line.name, ical, context=context)
return ical.serialize()
@@ -380,7 +384,9 @@ class Calendar(CalDAV, osv.osv):
cal_children[line.name] = line.object_id.model
for child in parsedCal.getChildren():
if child.name.lower() in cal_children:
context.update({'model': cal_children[child.name.lower()]})
context.update({'model': cal_children[child.name.lower()],
'calendar_id': cal.id
})
self.__attribute__ = get_attribute_mapping(cr, uid, child.name.lower(), context=context)
val = self.parse_ics(cr, uid, child, cal_children=cal_children, context=context)
obj = self.pool.get(cal_children[child.name.lower()])
@@ -616,7 +622,7 @@ class Timezone(CalDAV, osv.osv_memory):
}
def get_name_offset(self, cr, uid, tzid, context={}):
mytz = pytz.timezone(tzid)
mytz = pytz.timezone(tzid.title())
mydt = datetime.now(tz=mytz)
offset = mydt.utcoffset()
val = offset.days * 24 + float(offset.seconds) / 3600
@@ -629,7 +635,7 @@ class Timezone(CalDAV, osv.osv_memory):
ctx = context.copy()
ctx.update({'model': model})
cal_tz = ical.add('vtimezone')
cal_tz.add('TZID').value = tzid
cal_tz.add('TZID').value = tzid.title()
tz_std = cal_tz.add('STANDARD')
tzname, offset = self.get_name_offset(cr, uid, tzid)
tz_std.add("TZOFFSETFROM").value = offset
@@ -769,14 +775,15 @@ class Attendee(CalDAV, osv.osv_memory):
cn_val = ''
for a_key, a_val in self.__attribute__.items():
if attendee[a_val['field']] and a_val['field'] != 'cn':
if a_val['type'] == 'text':
if a_val['type'] in ('text', 'char', 'selection'):
attendee_add.params[a_key] = [str(attendee[a_val['field']])]
elif a_val['type'] == 'boolean':
attendee_add.params[a_key] = [str(attendee[a_val['field']])]
if a_val['field'] == 'cn' and attendee[a_val['field']]:
cn_val = [str(attendee[a_val['field']])]
if cn_val:
attendee_add.params['CN'] = cn_val
if cn_val:
attendee_add.params['CN'] = cn_val
attendee_add.value = 'MAILTO:' + attendee['email']
return vevent
Attendee()
@@ -0,0 +1,83 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from osv import osv, fields
from tools.translate import _
import pooler
import tools
import time
import base64
class node_calendar(object):
def __init__(self, path, context, calendar):
self.path = path
self.context = context
self.calendar_id = calendar.id
self.mimetype = 'ics'
self.create_date = calendar.create_date
self.write_date = calendar.write_date or calendar.create_date
self.content_length = 0
self.displayname = calendar.name
def get_data(self, cr, uid):
calendar_obj = pooler.get_pool(cr.dbname).get('basic.calendar')
return calendar_obj.export_cal(cr, uid, [self.calendar_id])
def get_data_len(self, cr):
return self.content_length
def set_data(self, cr, uid, data):
calendar_obj = pooler.get_pool(cr.dbname).get('basic.calendar')
return calendar_obj.import_cal(cr, uid, base64.encodestring(data), self.calendar_id)
def get_etag(self,cr):
""" Get a tag, unique per object + modification.
see. http://tools.ietf.org/html/rfc2616#section-13.3.3 """
return self._get_ttag(cr) + ':' + self._get_wtag(cr)
def _get_wtag(self,cr):
""" Return the modification time as a unique, compact string """
if self.write_date:
wtime = time.mktime(time.strptime(self.write_date,'%Y-%m-%d %H:%M:%S'))
else: wtime = time.time()
return str(wtime)
def _get_ttag(self,cr):
return 'calendar-%d' % self.calendar_id
class Calendar(osv.osv):
_inherit = 'basic.calendar'
def get_calendar_object(self, cr, uid, uri, context=None):
if not uri:
return None
if len(uri) > 1:
return None
name, file_type = tuple(uri[0].split('.'))
res = self.name_search(cr, uid, name)
if not res:
return None
calendar_id, calendar_name = res[0]
calendar = self.browse(cr, uid, calendar_id)
return node_calendar(uri, context, calendar)
Calendar()
+39
View File
@@ -0,0 +1,39 @@
import time
import heapq
def memoize(maxsize):
"""decorator to 'memoize' a function - caching its results"""
def decorating_function(f):
cache = {} # map from key to value
heap = [] # list of keys, in LRU heap
cursize = 0 # because len() is slow
def wrapper(*args):
key = repr(args)
# performance crap
_cache=cache
_heap=heap
_heappop = heapq.heappop
_heappush = heapq.heappush
_time = time.time
_cursize = cursize
_maxsize = maxsize
if not _cache.has_key(key):
if _cursize == _maxsize:
# pop oldest element
(_,oldkey) = _heappop(_heap)
_cache.pop(oldkey)
else:
_cursize += 1
# insert this element
_cache[key] = f(*args)
_heappush(_heap,(_time(),key))
wrapper.misses += 1
else:
wrapper.hits += 1
return cache[key]
wrapper.__doc__ = f.__doc__
wrapper.__name__ = f.__name__
wrapper.hits = wrapper.misses = 0
return wrapper
return decorating_function
+335
View File
@@ -0,0 +1,335 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import pooler
import base64
import sys
import os
import time
from string import joinfields, split, lower
from service import security
import netsvc
import urlparse
from DAV.constants import COLLECTION, OBJECT
from DAV.errors import *
from DAV.iface import *
import urllib
from DAV.davcmd import copyone, copytree, moveone, movetree, delone, deltree
from document.nodes import node_res_dir, node_res_obj
from cache import memoize
from tools import misc
CACHE_SIZE=20000
class tinydav_handler(dav_interface):
"""
This class models a Tiny ERP interface for the DAV server
"""
PROPS={'DAV:': dav_interface.PROPS['DAV:'], }
M_NS={ "DAV:" : dav_interface.M_NS['DAV:'], }
def __init__(self, parent, verbose=False):
self.db_name = False
self.parent = parent
self.baseuri = parent.baseuri
def get_propnames(self, uri):
props = self.PROPS
self.parent.log_message('get propnames: %s' % uri)
if uri[-1]=='/':uri=uri[:-1]
cr, uid, pool, dbname, uri2 = self.get_cr(uri)
if not dbname:
cr.close()
return props
node = self.uri2object(cr,uid,pool, uri2)
if node:
props.update(node.get_dav_props(cr))
cr.close()
return props
def get_prop(self,uri,ns,propname):
""" return the value of a given property
uri -- uri of the object to get the property of
ns -- namespace of the property
pname -- name of the property
"""
if self.M_NS.has_key(ns):
return dav_interface.get_prop(self,uri,ns,propname)
if uri[-1]=='/':uri=uri[:-1]
cr, uid, pool, dbname, uri2 = self.get_cr(uri)
if not dbname:
cr.close()
raise DAV_NotFound
node = self.uri2object(cr,uid,pool, uri2)
if not node:
cr.close()
raise DAV_NotFound
res = node.get_dav_eprop(cr,ns,propname)
cr.close()
return res
def urijoin(self,*ajoin):
""" Return the base URI of this request, or even join it with the
ajoin path elements
"""
return self.baseuri+ '/'.join(ajoin)
def uri2local(self, uri):
uparts=urlparse.urlparse(uri)
reluri=uparts[2]
if reluri and reluri[-1]=="/":
reluri=reluri[:-1]
return reluri
#
# pos: -1 to get the parent of the uri
#
def get_cr(self, uri):
pdb = self.parent.auth_proxy.last_auth
reluri = self.uri2local(uri)
try:
dbname = reluri.split('/')[2]
except:
dbname = False
if not dbname:
return None, None, None, False, None
if not pdb and dbname:
# if dbname was in our uri, we should have authenticated
# against that.
raise Exception("Programming error")
assert pdb == dbname, " %s != %s" %(pdb, dbname)
user, passwd, dbn2, uid = self.parent.auth_proxy.auth_creds[pdb]
db,pool = pooler.get_db_and_pool(dbname)
cr = db.cursor()
uri2 = reluri.split('/')[3:]
return cr, uid, pool, dbname, uri2
def uri2object(self, cr, uid, pool, uri):
if not uid:
return None
return pool.get('basic.calendar').get_calendar_object(cr, uid, uri)
def get_data(self,uri):
self.parent.log_message('GET: %s' % uri)
if uri[-1]=='/':uri=uri[:-1]
cr, uid, pool, dbname, uri2 = self.get_cr(uri)
try:
if not dbname:
raise DAV_Error, 409
node = self.uri2object(cr,uid,pool, uri2)
if not node:
raise DAV_NotFound(uri2)
try:
datas = node.get_data(cr, uid)
except TypeError,e:
import traceback
self.parent.log_error("GET typeError: %s", str(e))
self.parent.log_message("Exc: %s",traceback.format_exc())
raise DAV_Forbidden
except IndexError,e :
self.parent.log_error("GET IndexError: %s", str(e))
raise DAV_NotFound(uri2)
except Exception,e:
import traceback
self.parent.log_error("GET exception: %s",str(e))
self.parent.log_message("Exc: %s", traceback.format_exc())
raise DAV_Error, 409
return datas
finally:
cr.close()
@memoize(CACHE_SIZE)
def _get_dav_resourcetype(self,uri):
""" return type of object """
self.parent.log_message('get RT: %s' % uri)
if uri[-1]=='/':uri=uri[:-1]
cr, uid, pool, dbname, uri2 = self.get_cr(uri)
try:
if not dbname:
return COLLECTION
node = self.uri2object(cr,uid,pool, uri2)
if not node:
raise DAV_NotFound(uri2)
return OBJECT
finally:
cr.close()
def _get_dav_displayname(self,uri):
self.parent.log_message('get DN: %s' % uri)
if uri[-1]=='/':uri=uri[:-1]
cr, uid, pool, dbname, uri2 = self.get_cr(uri)
if not dbname:
cr.close()
return COLLECTION
node = self.uri2object(cr,uid,pool, uri2)
if not node:
cr.close()
raise DAV_NotFound(uri2)
cr.close()
return node.displayname
@memoize(CACHE_SIZE)
def _get_dav_getcontentlength(self,uri):
""" return the content length of an object """
self.parent.log_message('get length: %s' % uri)
if uri[-1]=='/':uri=uri[:-1]
result = 0
cr, uid, pool, dbname, uri2 = self.get_cr(uri)
if not dbname:
cr.close()
return '0'
node = self.uri2object(cr, uid, pool, uri2)
if not node:
cr.close()
raise DAV_NotFound(uri2)
result = node.content_length or 0
cr.close()
return str(result)
@memoize(CACHE_SIZE)
def _get_dav_getetag(self,uri):
""" return the ETag of an object """
self.parent.log_message('get etag: %s' % uri)
if uri[-1]=='/':uri=uri[:-1]
result = 0
cr, uid, pool, dbname, uri2 = self.get_cr(uri)
if not dbname:
cr.close()
return '0'
node = self.uri2object(cr, uid, pool, uri2)
if not node:
cr.close()
raise DAV_NotFound(uri2)
result = node.get_etag(cr)
cr.close()
return str(result)
@memoize(CACHE_SIZE)
def get_lastmodified(self,uri):
""" return the last modified date of the object """
if uri[-1]=='/':uri=uri[:-1]
today = time.time()
cr, uid, pool, dbname, uri2 = self.get_cr(uri)
try:
if not dbname:
return today
node = self.uri2object(cr,uid,pool, uri2)
if not node:
raise DAV_NotFound(uri2)
if node.write_date:
return time.mktime(time.strptime(node.write_date,'%Y-%m-%d %H:%M:%S'))
else:
return today
finally:
cr.close()
@memoize(CACHE_SIZE)
def get_creationdate(self,uri):
""" return the last modified date of the object """
if uri[-1]=='/':uri=uri[:-1]
cr, uid, pool, dbname, uri2 = self.get_cr(uri)
try:
if not dbname:
raise DAV_Error, 409
node = self.uri2object(cr,uid,pool, uri2)
if not node:
raise DAV_NotFound(uri2)
if node.create_date:
result = time.strptime(node.create_date,'%Y-%m-%d %H:%M:%S')
else:
result = time.gmtime()
return result
finally:
cr.close()
@memoize(CACHE_SIZE)
def _get_dav_getcontenttype(self,uri):
self.parent.log_message('get contenttype: %s' % uri)
if uri[-1]=='/':uri=uri[:-1]
cr, uid, pool, dbname, uri2 = self.get_cr(uri)
try:
if not dbname:
return 'httpd/unix-directory'
node = self.uri2object(cr,uid,pool, uri2)
if not node:
raise DAV_NotFound(uri2)
result = node.mimetype
return result
#raise DAV_NotFound, 'Could not find %s' % path
finally:
cr.close()
def put(self, uri, data, content_type=None):
""" put the object into the filesystem """
self.parent.log_message('Putting %s (%d), %s'%( misc.ustr(uri), len(data), content_type))
parent='/'.join(uri.split('/')[:-1])
cr, uid, pool,dbname, uri2 = self.get_cr(uri)
if not dbname:
raise DAV_Forbidden
try:
node = self.uri2object(cr,uid,pool, uri2[:])
except:
node = False
if not node:
raise DAV_Forbidden
else:
try:
node.set_data(cr, uid, data)
except Exception,e:
import traceback
self.parent.log_error("Cannot save :%s", str(e))
self.parent.log_message("Exc: %s",traceback.format_exc())
raise DAV_Forbidden
cr.commit()
cr.close()
return 201
def exists(self,uri):
""" test if a resource exists """
result = False
cr, uid, pool,dbname, uri2 = self.get_cr(uri)
if not dbname:
cr.close()
return True
try:
node = self.uri2object(cr,uid,pool, uri2)
if node:
result = True
except:
pass
cr.close()
return result
+79
View File
@@ -0,0 +1,79 @@
# -*- encoding: utf-8 -*-
#
# Copyright P. Christeas <p_christ@hol.gr> 2008,2009
#
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
###############################################################################
import netsvc
from dav_fs import tinydav_handler
from tools.config import config
from DAV.WebDAVServer import DAVRequestHandler
from service.websrv_lib import HTTPDir,FixSendError
class DAVHandler(FixSendError,DAVRequestHandler):
verbose = False
def get_userinfo(self,user,pw):
return False
def _log(self, message):
netsvc.Logger().notifyChannel("webdav",netsvc.LOG_DEBUG,message)
def handle(self):
pass
def finish(self):
pass
def setup(self):
davpath = '/calendar/'
self.baseuri = "http://%s:%d%s"% (self.server.server_name,self.server.server_port,davpath)
self.IFACE_CLASS = tinydav_handler(self)
pass
def log_message(self, format, *args):
netsvc.Logger().notifyChannel('webdav',netsvc.LOG_DEBUG_RPC,format % args)
def log_error(self, format, *args):
netsvc.Logger().notifyChannel('webdav',netsvc.LOG_WARNING,format % args)
try:
from service.http_server import reg_http_service,OpenERPAuthProvider
davpath = '/calendar/'
handler = DAVHandler
handler.verbose = config.get_misc('webdav','verbose',True)
handler.debug = config.get_misc('webdav','debug',True)
reg_http_service(HTTPDir(davpath,DAVHandler,OpenERPAuthProvider()))
netsvc.Logger().notifyChannel('webdav',netsvc.LOG_INFO,"WebDAV service registered at path: %s/ "% davpath)
except Exception, e:
logger = netsvc.Logger()
logger.notifyChannel('webdav', netsvc.LOG_ERROR, 'Cannot launch webdav: %s' % e)
#eof
+4 -4
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-12-11 22:28+0000\n"
"Last-Translator: Pieter J. Kersten (EduSense BV) <Unknown>\n"
"PO-Revision-Date: 2010-02-01 15:47+0000\n"
"Last-Translator: Jan Verlaan (Veritos) <Unknown>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2009-12-16 05:08+0000\n"
"X-Launchpad-Export-Date: 2010-02-02 04:48+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base_contact
@@ -36,7 +36,7 @@ msgstr "res.partner.contact"
msgid ""
"The Object name must start with x_ and not contain any special character !"
msgstr ""
"De objectnaam moet beginnen met x_ en mag geen speciale karakters bevatten !"
"De objectnaam moet beginnen met x_ en mag geen speciale tekens bevatten !"
#. module: base_contact
#: field:res.partner.job,function_id:0
+25 -24
View File
@@ -7,19 +7,19 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0_rc3\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-11-17 08:55+0000\n"
"Last-Translator: Fabien (Open ERP) <fp@tinyerp.com>\n"
"PO-Revision-Date: 2010-02-02 17:45+0000\n"
"Last-Translator: Nikolay Chesnokov <chesnokov_n@msn.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2009-12-16 05:26+0000\n"
"X-Launchpad-Export-Date: 2010-02-03 04:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base_module_quality
#: field:module.quality.check,final_score:0
msgid "Final Score (%)"
msgstr ""
msgstr "% выполнения"
#. module: base_module_quality
#: constraint:ir.model:0
@@ -32,12 +32,12 @@ msgstr ""
#. module: base_module_quality
#: model:ir.module.module,shortdesc:base_module_quality.module_meta_information
msgid "Base module quality"
msgstr ""
msgstr "Базисный модуль контроля качества"
#. module: base_module_quality
#: field:module.quality.check,name:0
msgid "Rated Module"
msgstr ""
msgstr "Оценка модуля"
#. module: base_module_quality
#: view:module.quality.detail:0
@@ -47,17 +47,17 @@ msgstr "Подробности"
#. module: base_module_quality
#: field:module.quality.detail,note:0
msgid "Note"
msgstr ""
msgstr "Заметка"
#. module: base_module_quality
#: field:module.quality.detail,state:0
msgid "State"
msgstr ""
msgstr "Область/штат"
#. module: base_module_quality
#: field:module.quality.detail,detail:0
msgid "Details"
msgstr ""
msgstr "Подробно"
#. module: base_module_quality
#: field:module.quality.detail,ponderation:0
@@ -75,12 +75,12 @@ msgstr ""
#: view:module.quality.check:0
#: field:module.quality.check,check_detail_ids:0
msgid "Tests"
msgstr ""
msgstr "Тесты"
#. module: base_module_quality
#: selection:module.quality.detail,state:0
msgid "Skipped"
msgstr ""
msgstr "Пропущено"
#. module: base_module_quality
#: help:module.quality.detail,state:0
@@ -88,6 +88,7 @@ msgid ""
"The test will be completed only if the module is installed or if the test "
"may be processed on uninstalled module."
msgstr ""
"Тест проводится только для установленных или помеченных для деинсталяции."
#. module: base_module_quality
#: constraint:ir.ui.view:0
@@ -102,27 +103,27 @@ msgstr ""
#. module: base_module_quality
#: field:module.quality.detail,name:0
msgid "Name"
msgstr ""
msgstr "Имя"
#. module: base_module_quality
#: wizard_field:quality_detail_save,init,module_file:0
msgid "Save report"
msgstr ""
msgstr "Сохранить отчет"
#. module: base_module_quality
#: wizard_field:quality_detail_save,init,name:0
msgid "File name"
msgstr ""
msgstr "Имя файла"
#. module: base_module_quality
#: field:module.quality.detail,score:0
msgid "Score (%)"
msgstr ""
msgstr "% выполнения"
#. module: base_module_quality
#: help:quality_detail_save,init,name:0
msgid "Save report as .html format"
msgstr ""
msgstr "Сохранить отчет в формате HTML"
#. module: base_module_quality
#: view:module.quality.detail:0
@@ -133,22 +134,22 @@ msgstr "Аннотация"
#. module: base_module_quality
#: model:ir.actions.wizard,name:base_module_quality.quality_detail_save
msgid "Report Save"
msgstr ""
msgstr "Сохранить отчет"
#. module: base_module_quality
#: wizard_view:quality_detail_save,init:0
msgid "Standard entries"
msgstr ""
msgstr "Стандартные точки входа"
#. module: base_module_quality
#: view:module.quality.detail:0
msgid "Save Report"
msgstr ""
msgstr "Сохранить отчет"
#. module: base_module_quality
#: model:ir.actions.wizard,name:base_module_quality.create_quality_check_id
msgid "Quality Check"
msgstr ""
msgstr "Проверка качества"
#. module: base_module_quality
#: model:ir.model,name:base_module_quality.model_module_quality_detail
@@ -158,23 +159,23 @@ msgstr ""
#. module: base_module_quality
#: selection:module.quality.detail,state:0
msgid "Done"
msgstr ""
msgstr "Завершено"
#. module: base_module_quality
#: view:module.quality.check:0
#: view:module.quality.detail:0
msgid "Result"
msgstr ""
msgstr "Результат"
#. module: base_module_quality
#: wizard_button:quality_detail_save,init,end:0
msgid "Cancel"
msgstr ""
msgstr "Отмена"
#. module: base_module_quality
#: field:module.quality.detail,message:0
msgid "Message"
msgstr ""
msgstr "Сообщение"
#. module: base_module_quality
#: field:module.quality.detail,quality_check_id:0
+6 -4
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-12-01 15:37+0000\n"
"Last-Translator: Wei \"oldrev\" Li <oldrev@gmail.com>\n"
"PO-Revision-Date: 2010-02-01 23:39+0000\n"
"Last-Translator: mrshelly <Unknown>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2009-12-16 05:21+0000\n"
"X-Launchpad-Export-Date: 2010-02-03 04:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base_report_creator
@@ -22,7 +22,7 @@ msgid ""
"Provide an expression for the field based on which you want to filter the "
"records.\n"
" e.g. res_partner.id=3"
msgstr ""
msgstr "可以使用基于字段的Python条件表达式做为过滤条件.(如 res_partner.id=3)"
#. module: base_report_creator
#: field:base_report_creator.report,view_graph_type:0
@@ -406,6 +406,8 @@ msgid ""
"After installing the module, it adds a menu to define custom report in\n"
"the \"Dashboard\" menu.\n"
msgstr ""
"本模块可以让您使用SQL查询器新建很灵活的对象统计报表.\n"
"安装此模块后, \"Dashboard(系统面板)\" 上会添加对应的菜单入口.\n"
#. module: base_report_creator
#: selection:base_report_creator.report.fields,calendar_mode:0
+10 -4
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-11-17 08:51+0000\n"
"Last-Translator: Fabien (Open ERP) <fp@tinyerp.com>\n"
"PO-Revision-Date: 2010-02-02 17:28+0000\n"
"Last-Translator: Nikolay Chesnokov <chesnokov_n@msn.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2009-12-16 05:10+0000\n"
"X-Launchpad-Export-Date: 2010-02-03 04:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base_setup
@@ -134,7 +134,7 @@ msgstr "Улица (2-я строка)"
#. module: base_setup
#: wizard_view:base_setup.base_setup,company:0
msgid "Report Information"
msgstr ""
msgstr "Информация об отчетах"
#. module: base_setup
#: wizard_field:base_setup.base_setup,company,phone:0
@@ -194,6 +194,9 @@ msgid ""
"We suggest you to write legal sentences here:\n"
"Web: http://openerp.com - Fax: +32.81.73.35.01 - Fortis Bank: 126-2013269-07"
msgstr ""
"Это предложение появится внизу ваших отчетов.\n"
"Рекомендуем поместить здесь юридическую информацию:\n"
"Web: http://openerp.com - Fax: +32.81.73.35.01 - Fortis Bank: 126-2013269-07"
#. module: base_setup
#: wizard_view:base_setup.base_setup,update:0
@@ -219,6 +222,9 @@ msgid ""
"We suggest you to put a slogan here:\n"
"\"Open Source Business Solutions\"."
msgstr ""
"Это предложение появится в правом верхнем углу ваших отчетов.\n"
"Рекомендуем поместить здесь слоган:\n"
"\"Решения для бизнеса с открытым исходным кодом\"."
#. module: base_setup
#: wizard_field:base_setup.base_setup,company,rml_header1:0
+8 -6
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-11-17 08:49+0000\n"
"Last-Translator: Sergei Kostigoff <sergei.kostigoff@gmail.com>\n"
"PO-Revision-Date: 2010-02-02 17:36+0000\n"
"Last-Translator: Nikolay Chesnokov <chesnokov_n@msn.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2009-12-16 05:09+0000\n"
"X-Launchpad-Export-Date: 2010-02-03 04:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base_vat
@@ -21,18 +21,20 @@ msgstr ""
msgid ""
"Enable the VAT Number for the partner. Check the validity of that VAT Number."
msgstr ""
"Разрешить использование кода налога для партнера. Проверьте правильность "
"кода налога."
#. module: base_vat
#: constraint:ir.ui.view:0
msgid "Invalid XML for View Architecture!"
msgstr "Неправильный XML для просмотра архитектуры!"
msgstr "Некорректный формат XML структуры для просмотра."
#. module: base_vat
#: field:res.partner,vat_subjected:0
msgid "VAT Legal Statement"
msgstr "Официальное положение по НДС"
msgstr "Действующий код налога"
#. module: base_vat
#: model:ir.module.module,shortdesc:base_vat.module_meta_information
msgid "VAT"
msgstr "НДС"
msgstr "Код налога"
+4 -4
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-11-17 07:58+0000\n"
"Last-Translator: Fabien (Open ERP) <fp@tinyerp.com>\n"
"PO-Revision-Date: 2010-02-02 09:39+0000\n"
"Last-Translator: Carlo Vettore <Unknown>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2009-12-16 05:10+0000\n"
"X-Launchpad-Export-Date: 2010-02-03 04:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: board_crm_configuration
@@ -86,7 +86,7 @@ msgstr "Richieste di Lavoro del Mese per Personale Assunto"
#. module: board_crm_configuration
#: constraint:ir.actions.act_window:0
msgid "Invalid model name in the action definition."
msgstr ""
msgstr "Nome del modulo non valido nella definizione dell'azione."
#. module: board_crm_configuration
#: view:board.board:0
@@ -19,5 +19,6 @@
#
##############################################################################
import document_caldav
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -21,17 +21,22 @@
{
'name': 'Support for caldav based on Document Management System',
'name': 'Board for Human Reasources Management',
'version': '1.0',
'category': 'Generic Modules/Others',
'description': """Allows to synchronise calendars with others applications.""",
'category': '',
'description': """
This module implements a dashboard for human resource management that includes:
* My Current Timesheet
* My Leaves
* My Expenses
""",
'author': 'Tiny',
'website': 'http://www.openerp.com',
'depends': ['caldav','document_webdav', 'crm'],
'init_xml': ['document_data.xml'],
'update_xml': ['document_view.xml'],
'demo_xml': ['document_demo.xml'],
'depends': [ 'crm_project','board','hr_expense','hr_timesheet_sheet','hr_holidays'
],
'update_xml': ['board_hr_view.xml'],
'demo_xml': [],
'installable': True,
'active': False,
'certificate': '',
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+72
View File
@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<menuitem icon="terp-graph" id="base.dashboard" name="Dashboards" sequence="2" parent="base.reporting_menu"/>
<menuitem
id="menu_hr_deshboard"
name="Human Resources"
parent="base.dashboard"/>
<record id="action_my_expense" model="ir.actions.act_window">
<field name="name">My Expenses</field>
<field name="res_model">hr.expense.expense</field>
<field name="view_type">form</field>
<field name="domain">[('state','=','draft'),('user_id','=',uid)]</field>
<field name="view_id" ref="hr_expense.view_editable_expenses_tree"/>
</record>
<record id="act_hr_current_timesheet_sheet_form" model="ir.actions.act_window">
<field name="name">Timesheets</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">hr_timesheet_sheet.sheet</field>
<field name="view_type">form</field>
<field name="view_id" eval="False"/>
<field name="domain">[('date_to','&gt;=',time.strftime('%Y-%m-01')),('date_from','&lt;=',time.strftime('%Y-%m-01'))]</field>
<field name="search_view_id" ref="hr_timesheet_sheet.hr_timesheet_sheet_tree"/>
</record>
<record id="action_view_holiday_status_board" model="ir.actions.act_window">
<field name="name">My Leaves</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">hr.holidays.per.user</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="hr_holidays.view_my_leave_board_tree"/>
</record>
<record id="board_hr_form" model="ir.ui.view">
<field name="name">board.hr.form</field>
<field name="model">board.board</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="My Board">
<hpaned>
<child1>
<action colspan="4" height="220" name="%(act_hr_current_timesheet_sheet_form)d" string="My current timesheet" width="510"/>
</child1>
<child2>
<action colspan="4" height="220" name="%(action_view_holiday_status_board)d" string="My Leaves"/>
<action colspan="4" height="220" name="%(action_my_expense)d" string="My Expenses" />
</child2>
</hpaned>
</form>
</field>
</record>
<record id="open_board_hr" model="ir.actions.act_window">
<field name="name">Human Resources Dashboard</field>
<field name="res_model">board.board</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="usage">menu</field>
<field name="view_id" ref="board_hr_form"/>
</record>
<menuitem
action="open_board_hr"
icon="terp-graph"
id="menu_hr_project"
parent="menu_hr_deshboard"
sequence="4"/>
</data>
</openerp>
+8 -7
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
##############################################################################
#
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
@@ -15,7 +15,7 @@
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
@@ -27,10 +27,9 @@
'description': """
This module implements a dashboard for project member that includes:
* List of my open tasks
* List of my next deadlines
* List of public notes
* Graph of my timesheet
* Graph of my work analysis
* List of messages
* Members list of project
* Issues
""",
'author': 'Tiny',
'depends': [
@@ -40,7 +39,9 @@ This module implements a dashboard for project member that includes:
'report_analytic_planning',
'report_analytic_line',
'report_task',
'hr_timesheet_sheet'
'hr_timesheet_sheet',
'crm_project',
'resource'
],
'update_xml': ['board_project_view.xml', 'board_project_manager_view.xml'],
'demo_xml': ['board_project_demo.xml'],
@@ -1,18 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="note_project_type" model="board.note.type">
<field name="name">Project managers</field>
</record>
<!--
Board for project managers
-->
<act_window domain="[('manager', '=', uid)]" id="act_my_project" name="My projects" res_model="project.project" view_mode="tree,form" view_type="form"/>
<act_window domain="[('user_id','=',uid),('state','&lt;&gt;','close')]" id="act_my_account" name="My accounts to invoice" res_model="account.analytic.account" view_id="view_account_analytic_simplified" view_mode="tree,form" view_type="form"/>
<record id="action_project_pipeline_user" model="ir.actions.act_window">
<field name="name">Pipeline of tasks</field>
<field name="res_model">report.task.user.pipeline.open</field>
@@ -20,7 +20,7 @@
<field name="view_mode">graph,tree</field>
<field name="domain">[('user_id','in',department_users_get())]</field>
</record>
<record id="hr_timesheet_sheet_tree" model="ir.ui.view">
<field name="name">hr.timesheet.sheet.tree.simplified.board</field>
<field name="model">hr_timesheet_sheet.sheet</field>
@@ -43,8 +43,8 @@
<field name="view_type">form</field>
<field name="view_id" ref="hr_timesheet_sheet_tree"/>
</record>
<record id="board_project_manager_form" model="ir.ui.view">
<field name="name">board.project.manager.form</field>
<field name="model">board.board</field>
@@ -53,27 +53,27 @@
<form string="Project manager board">
<hpaned>
<child1>
<action colspan="4" height="220" name="%(act_my_project)d" string="My projects" width="510"/>
<!-- <action colspan="4" height="220" name="%(act_my_project)d" string="My projects" width="510"/>-->
<action colspan="4" height="150" name="%(act_my_account)d" string="My accounts to invoice"/>
<action colspan="4" height="150" name="%(act_hr_timesheet_sheet)d" string="User's timesheets"/>
</child1>
<child2>
<button colspan="4" icon="terp-partner" name="%(open_board_project)d" string="My tasks board" type="action"/>
<button colspan="4" icon="terp-partner" name="%(open_board_project)d" string="My tasks board" type="action"/>
<action colspan="4" name="%(report_analytic_planning.action_account_analytic_planning_stat_form)d" string="My Project's planning" domain="[('manager_id','=',uid),('planning_id.state','&lt;&gt;','cancel')]"/>
<action colspan="4" name="%(action_project_pipeline_user)d" string="My user's pipeline"/>
</child2>
</hpaned>
</form>
</field>
</record>
<record id="open_board_project_manager" model="ir.actions.act_window">
<field name="name">Project Manager Dashboard</field>
<field name="res_model">board.board</field>
@@ -82,7 +82,7 @@
<field name="usage">menu</field>
<field name="view_id" ref="board_project_manager_form"/>
</record>
<menuitem action="open_board_project_manager" icon="terp-graph" id="menu_board_project_manager" parent="board_project.next_id_86" sequence="1" groups="project.group_project_user"/>
</data>
+40 -5
View File
@@ -22,6 +22,23 @@
</tree>
</field>
</record>
<!-- Editable My task -->
<record id="view_task_tree" model="ir.ui.view">
<field name="name">project.task.tree</field>
<field name="model">project.task</field>
<field name="type">tree</field>
<field eval="99" name="priority"/>
<field name="arch" type="xml">
<tree editable="top" colors="red:date_deadline&lt;current_date;blue:date_deadline==current_date;black:date_deadline&gt;current_date" string="My Tasks">
<field name="name"/>
<field name="project_id"/>
<field name="date_deadline"/>
<field name="planned_hours"/>
<field name="effective_hours"/>
<field name="priority"/>
</tree>
</field>
</record>
<record id="action_view_task_tree" model="ir.actions.act_window">
<field name="name">My Open Tasks</field>
<field name="res_model">project.task</field>
@@ -47,6 +64,25 @@
<field name="domain">[('type','=','Project')]</field>
</record>
<!--Actions for deshboard -->
<record id="action_view_project_editable_messages_tree" model="ir.actions.act_window">
<field name="name">Messages</field>
<field name="res_model">project.message</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="project.view_project_message_tree"/>
</record>
<record id="action_view_project_member_tree" model="ir.actions.act_window">
<field name="name">Project's Members</field>
<field name="res_model">resource.resource</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('resource_type','=','user')]</field>
<field name="view_id" ref="resource.view_project_member_tree"/>
</record>
<record id="board_project_form" model="ir.ui.view">
<field name="name">board.project.form</field>
<field name="model">board.board</field>
@@ -56,12 +92,11 @@
<hpaned>
<child1>
<action colspan="4" height="220" name="%(action_view_task_tree)d" string="My Open Tasks" width="510"/>
<action colspan="4" height="150" name="%(action_view_task_tree_deadline)d" string="My Deadlines"/>
<action colspan="4" height="150" name="%(action_view_board_note_tree)d" string="Public Notes"/>
</child1>
<action colspan="4" height="150" name="%(action_view_project_member_tree)d" string="Members list of project"/>
</child1>
<child2>
<action colspan="4" name="%(report_analytic_planning.action_account_analytic_planning_stat_form)d" string="My Planning" domain="[('user_id','=',uid),('planning_id.state','&lt;&gt;','cancel')]"/>
<action colspan="4" name="%(report_timesheet.action_timesheet_user_stat_all)d" string="Timesheets"/>
<action colspan="4" name="%(action_view_project_editable_messages_tree)d" string="Messages"/>
<action colspan="4" name="%(crm_project.crm_case_categ_act0)d" string="Issues"/>
</child2>
</hpaned>
</form>
+25 -4
View File
@@ -5,6 +5,24 @@
<field name="name">Sales</field>
</record>
<record model="ir.actions.act_window" id="board_crm_case_categ_phone_incoming0">
<field name="res_model">crm.phonecall</field>
<field name="view_type">form</field>
<field name="view_mode">tree,calendar</field>
<field name="view_id" ref="crm.crm_case_phone_tree_view"/>
<field name="domain">[('user_id','=',uid)]</field>
<field name="context" eval="{'default_state':'open'}"/>
<field name="search_view_id" ref="crm.view_crm_case_phonecalls_filter"/>
</record>
<record model="ir.actions.act_window" id="board_crm_case_categ_meet">
<field name="res_model">crm.meeting</field>
<field name="view_mode">tree,form,gantt</field>
<field name="view_id" ref="crm.crm_case_tree_view_meet"/>
<field name="domain">[('user_id','=',uid)]</field>
<field name="domain">[('date','&gt;=',time.strftime('%Y-%m-%d')),('date','&lt;=',(datetime.datetime.today() + datetime.timedelta(days=2)).strftime('%Y-%m-%d'))]</field>
<field name="context" eval="{'default_state':'open'}"/>
</record>
<record id="board_sales_manager_form" model="ir.ui.view">
<field name="name">board.sales.manager.form</field>
<field name="model">board.board</field>
@@ -14,13 +32,16 @@
<hpaned position="100">
<child1>
<action colspan="4" height="200" name="%(sale.action_order_tree5)d" string="My quotations" width="510" domain="[('state','=','draft'),('user_id','=',uid)]"/>
<action colspan="4" name="%(report_sale.action_order_sale_list)d" string="Top ten sales of the month"/>
<action colspan="4" name="%(report_crm.action_report_crm_case_user_tree)d" string="Cases statistics"/>
<action colspan="4" name="%(board_crm_case_categ_phone_incoming0)d" string="My planned calling calls (IN / OUT)" width="510"/>
<!-- <action colspan="4" name="%(report_sale.action_order_sale_list)d" string="Top ten sales of the month"/>-->
<!-- <action colspan="4" name="%(report_crm.action_report_crm_case_user_tree)d" string="Cases statistics"/>-->
</child1>
<child2>
<action colspan="4" name="%(report_sale.action_order_category_tree_all)d" string="Average Sales by Category of Products(this month)" view_mode="graph,tree"/>
<action colspan="4" name="%(report_crm.action_report_crm_case_user_tree)d" string="Cases of the month" view_mode="graph,tree"/>
<action colspan="4" name="%(crm.crm_case_category_act_oppor11)d" string="My Opportunities" width="510" domain="[('user_id','=',uid)]"/>
<action colspan="4" name="%(board_crm_case_categ_meet)d" String="My Meetings" domain="[('state','=','open')]" width="510"/>
<!-- <action colspan="4" name="%(report_sale.action_order_category_tree_all)d" string="Average Sales by Category of Products(this month)" view_mode="graph,tree"/>-->
<!-- <action colspan="4" name="%(report_crm.action_report_crm_case_user_tree)d" string="Cases of the month" view_mode="graph,tree"/>-->
</child2>
</hpaned>
</form>
+24
View File
@@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+42
View File
@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': 'Dashboard for Warehouse',
'version': '1.0',
'category': 'Board/Warehouse',
'description': """
This module implements a dashboard for warehouse that includes:
* Products to receive in delay (date < = today)
* Procurement in exception
* Graph : Number of Receive products vs planned (bar graph on week par day)
* Graph : Number of Delivery products vs planned (bar graph on week par day)
""",
'author': 'Tiny',
'depends': ['board','mrp','stock' ],
'update_xml': ['board_warehouse_view.xml'],
'demo_xml': [],
'installable': True,
'active': False,
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="note_warehouse_type" model="board.note.type">
<field name="name">Warehouse</field>
</record>
<record id="board_warehouse_form" model="ir.ui.view">
<field name="name">board.warehouse.form</field>
<field name="model">board.board</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Warehouse board">
<hpaned position="100">
<child1>
<action colspan="4" name="%(mrp.mrp_procurement_action5)d" string="Procurement Exceptions" width="510" />
<action colspan="4" name="%(stock.action_reception_picking_move)d" string="Products To Receive" />
</child1>
<child2>
<action colspan="4" name="%(stock.action_move_graph_reception_picking)d" string="Products To Receive" width="510"/>
<action colspan="4" name="%(stock.action_move_delivery_products_planned)d" string="Delivery Products Vs Planned" width="510"/>
</child2>
</hpaned>
</form>
</field>
</record>
<record id="open_board_warehouse" model="ir.actions.act_window">
<field name="name">Warehouse Dashboard</field>
<field name="res_model">board.board</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="view_id" ref="board_warehouse_form"/>
</record>
<menuitem icon="terp-graph" id="base.dashboard" name="Dashboards" sequence="2" parent="base.reporting_menu"/>
<menuitem id="menu_board_warehouse_main" name="Warehouse" parent="base.dashboard"/>
<menuitem action="open_board_warehouse" icon="terp-graph" id="menu_board_warehouse" parent="menu_board_warehouse_main" sequence="1"/>
</data>
</openerp>
+86 -17
View File
@@ -31,6 +31,7 @@ import pooler
import pytz
import re
import time
import tools
months = {
1:"January", 2:"February", 3:"March", 4:"April", \
@@ -65,6 +66,54 @@ def _links_get(self, cr, uid, context={}):
res = obj.read(cr, uid, ids, ['object', 'name'], context)
return [(r['object'], r['name']) for r in res]
html_invitation = """
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>%(name)s</title>
</head>
<div>
<table cellspacing="0" cellpadding="0" border=3D "1" summary=3D"">
<tr align="center">
<td bgcolor="DFDFDF">
<h3>%(name)s</h3>
</td>
</tr>
<tr>
<td>
<table cellpadding="8" cellspacing="0" border=3D "0" summary=3D
"Eventdetails" bgcolor="f6f6f6">
<tr>
<td>
<div><b><i>Start Date</i></b></div>
</td>
<td>%(start_date)s</td>
<td>
<div><b><i>End Date</i></b></div>
</td>
<td>%(end_date)s</td>
</tr>
<tr>
<td><b><i>Description</i></b></td>
<td colspan="3">%(description)s</td>
</tr>
<tr>
<td>
<div><b><i>Location</i></b></div>
</td>
<td colspan="3">%(location)s</td>
</tr>
<tr>
<td>
<div><b><i>Event Attendees</i></b></div>
</td>
<td colspan="3">
<div>
<div>%(attendees)s</div>
</div>
</td>
</tr>
</table>"""
class calendar_attendee(osv.osv):
_name = 'calendar.attendee'
_description = 'Attendee information'
@@ -82,8 +131,11 @@ class calendar_attendee(osv.osv):
result = {}
def get_delegate_data(user):
email = user.address_id and user.address_id.email or ''
return self._get_address(user.name, email)
if not user.address_id.email:
raise osv.except_osv(_('Error!'), \
("User does not have an email Address"))
email = (user.address_id and ('MAILTO:' + user.address_id.email)) or ''
return email
for attdata in self.browse(cr, uid, ids, context=context):
id = attdata.id
@@ -112,12 +164,11 @@ class calendar_attendee(osv.osv):
fromdata = map(get_delegate_data, attdata.del_from_user_ids)
result[id][name] = ', '.join(fromdata)
if name == 'event_date':
# TO fix date for project task
if attdata.ref:
model, res_id = tuple(attdata.ref.split(','))
model_obj = self.pool.get(model)
obj = model_obj.read(cr, uid, res_id, ['date'])[0]
result[id][name] = None#obj['date']
result[id][name] = obj.get('date')
else:
result[id][name] = None
if name == 'event_end_date':
@@ -125,7 +176,7 @@ class calendar_attendee(osv.osv):
model, res_id = tuple(attdata.ref.split(','))
model_obj = self.pool.get(model)
obj = model_obj.read(cr, uid, res_id, ['date_deadline'])[0]
result[id][name] = obj['date_deadline']
result[id][name] = obj.get('date_deadline')
else:
result[id][name] = None
if name == 'sent_by_uid':
@@ -133,9 +184,13 @@ class calendar_attendee(osv.osv):
model, res_id = tuple(attdata.ref.split(','))
model_obj = self.pool.get(model)
obj = model_obj.read(cr, uid, res_id, ['user_id'])[0]
result[id][name] = obj['user_id']
result[id][name] = obj.get('user_id')
else:
result[id][name] = uid
if name == 'language':
user_obj = self.pool.get('res.users')
lang = user_obj.read(cr, uid, uid, ['context_lang']) ['context_lang']
result[id][name] = lang.replace('_', '-')
return result
def _links_get(self, cr, uid, context={}):
@@ -182,15 +237,14 @@ request was delegated to"),
'del_from_user_ids': fields.many2many('res.users', 'att_del_from_user_rel', \
'attendee_id', 'user_id', 'Users'),
'sent_by': fields.function(_compute_data, method=True, 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.many2one('res.users', 'Sent by User'),
'sent_by_uid': fields.function(_compute_data, method=True, string='Sent By User', type="many2one", relation="res.users", multi='sent_by_uid'),
'cn': fields.function(_compute_data, method=True, 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.selection(_lang_get, 'Language',
help="To specify the language for text values in a property or property parameter."),
'language': fields.function(_compute_data, method=True, 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_address_id': fields.many2one('res.partner.address', 'Contact'),
'partner_id':fields.related('partner_address_id', 'partner_id', type='many2one', relation='res.partner', string='Partner'),
'email': fields.char('Email', size=124),
'email': fields.char('Email', size=124, required=True),
'event_date': fields.function(_compute_data, method=True, string='Event Date', type="datetime", multi='event_date'),
'event_end_date': fields.function(_compute_data, method=True, string='Event End Date', type="datetime", multi='event_end_date'),
'ref': fields.reference('Document Ref', selection=_links_get, size=128),
@@ -426,7 +480,7 @@ class calendar_event(osv.osv):
__attribute__ = {}
def _tz_get(self,cr,uid, context={}):
return [(x, x) for x in pytz.all_timezones]
return [(x.lower(), x) for x in pytz.all_timezones]
def onchange_rrule_type(self, cr, uid, ids, rtype, *args, **argv):
if rtype == 'none' or not rtype:
@@ -501,9 +555,7 @@ rule or repeating pattern for anexception to a recurrence set"),
event_data = self.read(cr, uid, ids)
event_obj = self.pool.get('basic.calendar.event')
ical = event_obj.export_cal(cr, uid, event_data, context={'model': self._name})
cal_val = ical.serialize()
cal_val = cal_val.replace('"', '').strip()
return cal_val
return ical.serialize()
def import_cal(self, cr, uid, data, data_id=None, context={}):
event_obj = self.pool.get('basic.calendar.event')
@@ -1001,9 +1053,7 @@ class res_users(osv.osv):
status = 'busy'
res.update({user_id:status})
#TOCHECK: Delegrated Event
#cr.execute("SELECT user_id,'busy' FROM att_del_to_user_rel where user_id = ANY(%s)", (ids,))
#res.update(cr.dictfetchall())
#TOCHECK: Delegrated Event
for user_id in ids:
if user_id not in res:
res[user_id] = 'free'
@@ -1063,6 +1113,25 @@ class invite_attendee_wizard(osv.osv_memory):
vals.update({'email': datas['email']})
att_id = att_obj.create(cr, uid, vals)
obj.write(cr, uid, res_obj.id, {'attendee_ids': [(4, att_id)]})
sub = '[OpenERP Invitation] %s' % (res_obj.name)
body_vals = {'name': res_obj.name,
'start_date': res_obj.date,
'end_date': res_obj.date_deadline or None,
'description': res_obj.description,
'location': res_obj.location or '-',
'attendees': '-' #Todo
}
body = html_invitation % body_vals
mail_to = [datas['email']]
tools.email_send(
res_obj.user_id.name,
mail_to,
sub,
body,
subtype='html'
)
elif type == 'partner':
add_obj = self.pool.get('res.partner.address')
for contact in add_obj.browse(cr, uid, datas['contact_ids']):
+13 -29
View File
@@ -65,6 +65,8 @@
<field name="user_id"
on_change="onchange_user_id(user_id)" readonly="1" />
<field name="email" select="1" readonly="1" />
<field name="partner_id" select="1" readonly="1" />
<field name="partner_address_id" select="1" readonly="1" />
<newline />
<field name="role" select="1" readonly="1" string="Role" />
<field name="cutype" select="1" readonly="1" string="Invitation type" />
@@ -114,7 +116,7 @@
</field>
</record>
<record id="caldav_attendee_tree_view" model="ir.ui.view">
<record id="caldav_attendee_tree_view" model="ir.ui.view">
<field name="name">calendar.attendee.tree</field>
<field name="model">calendar.attendee</field>
<field name="type">tree</field>
@@ -126,32 +128,9 @@
<field name="state" />
</tree>
</field>
</record>
</record>
<record id="action_view_attendee_form" model="ir.actions.act_window">
<field name="name">My Invitations</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">calendar.attendee</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="caldav_attendee_tree_view" />
<field name="domain">[('user_id', '=', uid)]</field>
<field name="context">{'default_sent_by_uid': uid}</field>
</record>
<record id="action_invitation_tree_view1" model="ir.actions.act_window.view">
<field eval="1" name="sequence" />
<field name="view_mode">tree</field>
<field name="view_id" ref="caldav_attendee_tree_view" />
<field name="act_window_id" ref="action_view_attendee_form" />
</record>
<record id="action_invitation_form_view1" model="ir.actions.act_window.view">
<field eval="2" name="sequence" />
<field name="view_mode">form</field>
<field name="view_id" ref="caldav_attendee_form_view" />
<field name="act_window_id" ref="action_view_attendee_form" />
</record>
<record id="res_alarm_form_view" model="ir.ui.view">
<field name="name">res.alarm.form</field>
@@ -251,7 +230,7 @@
</field>
</record>
<record id="action_calendar_custom_rrule_wizard" model="ir.actions.act_window">
<record id="action_calendar_custom_rrule_wizard" model="ir.actions.act_window">
<field name="name">Custom Rule</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">calendar.custom.rrule</field>
@@ -260,9 +239,14 @@
<field name="target">new</field>
</record>
<menuitem id="menu_attendee_invitations"
name="My Invitations" parent="base_calendar.menu_calendar_configuration"
sequence="10" action="action_view_attendee_form" />
<!-- Available alarms-->
<menuitem name="Available alarms" id="menu_crm_meeting_avail_alarm"
action="caldav.action_res_alarm_view"
parent="base_calendar.menu_calendar_configuration" />
</data>
</openerp>
+6
View File
@@ -406,6 +406,12 @@ class crm_case(osv.osv):
return True
def onchange_categ_id(self, cr, uid, ids, categ, context={}):
if not categ:
return {'value':{}}
cat = self.pool.get('crm.case.categ').browse(cr, uid, categ, context).probability
return {'value':{'probability':cat}}
def onchange_case_id(self, cr, uid, ids, case_id, name, partner_id, context={}):
if not case_id:
return {}
+1 -13
View File
@@ -19,16 +19,9 @@
#
##############################################################################
import tools
from osv import fields, osv
import os
import pooler
import netsvc
from tools.translate import _
import crm
class crm_claim(osv.osv):
_name = "crm.claim"
_description = "Claim Cases"
@@ -59,12 +52,7 @@ class crm_claim(osv.osv):
_defaults = {
'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0],
}
def onchange_categ_id(self, cr, uid, ids, categ, context={}):
if not categ:
return {'value':{}}
cat = self.pool.get('crm.case.categ').browse(cr, uid, categ, context).probability
return {'value':{'probability':cat}}
crm_claim()
+9 -9
View File
@@ -8,24 +8,24 @@
<field name="name">Claim Categories</field>
<field name="res_model">crm.case.categ</field>
<field name="view_type">form</field>
<field name="view_id" ref="crm.crm_case_categ_tree-view"/>
<field name="view_id" ref="crm.crm_case_categ_tree-view"/>
<field name="domain">[('object_id.model', '=', 'crm.claim')]</field>
<field name="context">{'object_id':'crm.claim'}</field>
<field name="context">{'object_id':'crm.claim'}</field>
</record>
<menuitem action="crm_claim_categ_action" id="menu_crm_case_claim-act" parent="crm.menu_crm_case_categ"/>
# ------------------------------------------------------
# Stages
# ------------------------------------------------------
# ------------------------------------------------------
<record id="crm_claim_stage_act" model="ir.actions.act_window">
<field name="name">Claim Stages</field>
<field name="res_model">crm.case.stage</field>
<field name="view_type">form</field>
<field name="view_id" ref="crm.crm_case_stage_tree"/>
<field name="domain">[('object_id.model', '=', 'crm.claim')]</field>
<field name="context">{'object_id':'crm.claim'}</field>
<field name="context">{'object_id':'crm.claim'}</field>
</record>
<menuitem action="crm_claim_stage_act" id="menu_crm_claim_stage_act" parent="crm.menu_crm_case_stage"/>
<!-- Claims -->
<record model="ir.ui.view" id="crm_case_claims_tree_view">
<field name="name">CRM - Claims Tree</field>
@@ -169,7 +169,7 @@
</graph>
</field>
</record>
<record id="view_crm_case_claims_filter" model="ir.ui.view">
<field name="name">CRM - Claims Search</field>
<field name="model">crm.claim</field>
@@ -198,12 +198,12 @@
<field name="partner_id" select="1"/>
<field name="user_id" select="1" widget="selection"/>
</group>
<field name="section_id" select="1" widget="selection" string="Section">
<field name="section_id" select="1" widget="selection" string="Section" default="context.get('section_id', False)">
<filter icon="terp-crm"
domain="[('section_id','=',context.get('section_id',False))]"
help="My section"
/>
</field>
/>
</field>
</search>
</field>
</record>
+8 -8
View File
@@ -9,9 +9,9 @@
<field name="name">Fundraising Categories</field>
<field name="res_model">crm.case.categ</field>
<field name="view_type">form</field>
<field name="view_id" ref="crm.crm_case_categ_tree-view"/>
<field name="domain">[('object_id.model', '=', 'crm.fundraising')]</field>
<field name="context">{'object_id':'crm.fundraising'}</field>
<field name="view_id" ref="crm.crm_case_categ_tree-view"/>
<field name="domain">[('object_id.model', '=', 'crm.fundraising')]</field>
<field name="context">{'object_id':'crm.fundraising'}</field>
</record>
<menuitem action="crm_fund_categ_action" id="menu_crm_case_fundraising-act" parent="crm.menu_crm_case_categ"/>
# ------------------------------------------------------
@@ -23,10 +23,10 @@
<field name="view_type">form</field>
<field name="view_id" ref="crm.crm_case_stage_tree"/>
<field name="domain">[('object_id.model', '=', 'crm.fundraising')]</field>
<field name="context">{'object_id':'crm.fundraising'}</field>
<field name="context">{'object_id':'crm.fundraising'}</field>
</record>
<menuitem action="crm_fundraising_stage_act" id="menu_crm_fundraising_stage_act" parent="crm.menu_crm_case_stage"/>
# ------------------------------------------------------
# Fund Raising
# ------------------------------------------------------
@@ -194,12 +194,12 @@
</field>
<field name="name" select='1'/>
<field name="user_id" select="1" widget="selection"/>
<field name="section_id" select="1" widget="selection" string="Section">
<field name="section_id" select="1" widget="selection" string="Section" default="context.get('section_id', False)">
<filter icon="terp-crm"
domain="[('section_id','=',context.get('section_id',False))]"
help="My section"
/>
</field>
/>
</field>
</group>
</search>
</field>
-20
View File
@@ -19,23 +19,9 @@
#
##############################################################################
import time
import re
import os
import mx.DateTime
import base64
from tools.translate import _
import tools
from osv import fields,osv,orm
from osv.orm import except_orm
import crm
class crm_fundraising(osv.osv):
_name = "crm.fundraising"
_description = "Fund Raising Cases"
@@ -67,11 +53,5 @@ class crm_fundraising(osv.osv):
_defaults = {
'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0],
}
def onchange_categ_id(self, cr, uid, ids, categ, context={}):
if not categ:
return {'value':{}}
cat = self.pool.get('crm.case.categ').browse(cr, uid, categ, context).probability
return {'value':{'probability':cat}}
crm_fundraising()
+1 -20
View File
@@ -19,23 +19,9 @@
#
##############################################################################
import time
import re
import os
import mx.DateTime
import base64
from tools.translate import _
import tools
from osv import fields,osv,orm
from osv.orm import except_orm
import crm
class crm_helpdesk(osv.osv):
_name = "crm.helpdesk"
_description = "Helpdesk Cases"
@@ -57,12 +43,7 @@ class crm_helpdesk(osv.osv):
'categ_id': fields.many2one('crm.case.categ', 'Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.helpdesk')]"),
'duration': fields.float('Duration'),
}
def onchange_categ_id(self, cr, uid, ids, categ, context={}):
if not categ:
return {'value':{}}
cat = self.pool.get('crm.case.categ').browse(cr, uid, categ, context).probability
return {'value':{'probability':cat}}
crm_helpdesk()
+1 -1
View File
@@ -10,7 +10,7 @@
<field name="view_mode">tree,calendar,form</field>
<field name="view_id" ref="crm_case_tree_view_helpdesk"/>
<field name="context" eval="{'default_state':'open'}"/>
<field name="search_view_id" ref="crm.view_crm_case_filter"/>
<field name="search_view_id" ref="crm.view_crm_case_helpdesk_filter"/>
</record>
<record model="ir.actions.act_window.view" id="action_crm_sec_tree_view_act111">
<field name="sequence" eval="1"/>
+37
View File
@@ -154,5 +154,42 @@
</calendar>
</field>
</record>
<record id="view_crm_case_helpdesk_filter" model="ir.ui.view">
<field name="name">CRM - Helpdesk Search</field>
<field name="model">crm.helpdesk</field>
<field name="type">search</field>
<field name="arch" type="xml">
<search string="Search Helpdesk">
<group col="6" colspan="1">
<filter icon="gtk-home" string="Today"
separator="1"
domain="[('date','=',time.strftime('%%Y-%%m-%%d'))]"
help="Todays's Helpdesk Requests"
/>
<filter icon="gtk-media-rewind"
string="7 Days" separator="1"
help="Helpdesk requests during last 7 days"
domain="[('date','&lt;', time.strftime('%%Y-%%m-%%d')), ('date','&gt;=',(datetime.date.today()-datetime.timedelta(days=7)).strftime('%%Y-%%m-%%d'))]"
/>
</group>
<separator orientation="vertical"/>
<group col="6" colspan="2">
<field name="name" select='1' string="Subject"/>
<field name="user_id" select="1" widget="selection">
<filter icon="terp-partner" domain="[('user_id','=',uid)]" help="My Helpdesk Requests" default="1"/>
</field>
<field name="state" select="1">
<filter icon="gtk-index" domain="[('state','in',('open','draft' ))]" help="Current "/>
</field>
<field name="section_id" select="1" widget="selection" string="Section">
<filter icon="terp-crm"
domain="[('section_id','=',context.get('section_id',False))]"
help="My section"/>
</field>
</group>
</search>
</field>
</record>
</data>
</openerp>
-19
View File
@@ -19,22 +19,9 @@
#
##############################################################################
import time
import re
import os
import mx.DateTime
import base64
from tools.translate import _
import tools
from osv import fields,osv,orm
from osv.orm import except_orm
import crm
class crm_opportunity(osv.osv):
_name = "crm.opportunity"
_description = "Opportunity Cases"
@@ -65,13 +52,7 @@ class crm_lead(osv.osv):
'som': fields.many2one('res.partner.som', 'State of Mind', help="The minds states allow to define a value scale which represents" \
"the partner mentality in relation to our services.The scale has" \
"to be created with a factor for each level from 0 (Very dissatisfied) to 10 (Extremely satisfied)."),
'opportunity_id': fields.many2one ('crm.opportunity', 'Opportunity'),
}
def onchange_categ_id(self, cr, uid, ids, categ, context={}):
if not categ:
return {'value':{}}
cat = self.pool.get('crm.case.categ').browse(cr, uid, categ, context).probability
return {'value':{'probability':cat}}
crm_lead()
+11 -11
View File
@@ -2,23 +2,23 @@
<openerp>
<data>
# ------------------------------------------------------
# ------------------------------------------------------
# Stage
# ------------------------------------------------------
# ------------------------------------------------------
<record id="crm_lead_stage_act" model="ir.actions.act_window">
<field name="name">Lead Stages</field>
<field name="res_model">crm.case.stage</field>
<field name="view_type">form</field>
<field name="view_id" ref="crm.crm_case_stage_tree"/>
<field name="domain">[('object_id.model', '=', 'crm.lead')]</field>
<field name="context">{'object_id':'crm.lead'}</field>
<field name="context">{'object_id':'crm.lead'}</field>
</record>
<menuitem action="crm_lead_stage_act" id="menu_crm_lead_stage_act" parent="crm.menu_crm_case_stage"/>
# ------------------------------------------------------
# Leads
# ------------------------------------------------------
# ------------------------------------------------------
<record model="ir.ui.view" id="crm_case_form_view_leads">
<field name="name">CRM - Leads Form</field>
@@ -29,9 +29,9 @@
<group colspan="4" col="7">
<field name="name" select="1" string="Lead Subject"/>
<field name="section_id" colspan="1" widget="selection"/>
<field name="opportunity_id" string="Opportunity Case"/>
<field name="opportunity_id" string="Opportunity Case"/>
<button string="Convert to Opportunity" name="%(wizard_crm_lead_opportunity_set)d" icon="gtk-index" type="action" attrs="{'invisible':[('opportunity_id','!=',False)]}"/>
<label string="Stage: " align="1.0"/>
<group colspan="1" col="2">
<field name="stage_id" select="1" nolabel="1"/>
@@ -53,7 +53,7 @@
<field name="partner_mobile"/>
<field name="email_from" string="Lead Email"/>
<newline/>
<label string="Partner:" align="1.0"/>
<label string="Partner:" align="1.0"/>
<group colspan="1" col="2">
<field name="partner_id" nolabel="1" colspan="1"/>
<button string="Convert to Partner"
@@ -177,11 +177,11 @@
<filter icon="gtk-new" domain="[('state','=','draft')]" help="Draft Leads"/>
<filter icon="gtk-yes" domain="[('state','=','open')]" help="Open Leads"/>
</field>
<field name="section_id" select="1" widget="selection" string="Section">
<field name="section_id" select="1" default="context.get('section_id', False)" widget="selection" string="Section">
<filter icon="terp-crm"
domain="[('section_id','=',context.get('section_id',False))]"
help="My section"
/>
/>
</field>
</group>
</search>
+2 -1
View File
@@ -31,7 +31,7 @@
<!-- Event Attribute mapping for Calendar-->
<record model="basic.calendar" id="base_calendar.basic_calendar1">
<field name="name">meeting</field>
<field name="name">Meetings</field>
</record>
<record model="basic.calendar.lines" id="caldav.calendar_lines_event">
@@ -102,6 +102,7 @@
<field name="type_id" ref="caldav.calendar_lines_event" />
<field name="field_id" search="[('name','=','priority'),('model_id.model','=','crm.meeting')]" />
<field name="fn">field</field>
<field name="mapping">{'1': '1', '2': '2', '3': '2','4': '2', '5': '3', '6': '4', '7': '4', '8': '4', '9': '5'}</field>
</record>
+16 -6
View File
@@ -42,12 +42,6 @@
<field name="act_window_id" ref="crm_case_categ_meet_create_partner"/>
</record>
<!-- Available alarms-->
<menuitem name="Available alarms" id="menu_crm_meeting_avail_alarm"
action="caldav.action_res_alarm_view"
parent="menu_crm_configuration" />
<act_window
id="crm_case_categ_meet_case"
name="Schedule a Meeting"
@@ -125,6 +119,22 @@
<menuitem name="Meetings" id="menu_meeting_sale" parent="base.menu_base_partner" sequence="3"/>
<menuitem name="Meetings" id="menu_crm_case_categ_meet" action="crm_case_categ_meet" parent="menu_meeting_sale" sequence="1"/>
<record id="action_view_attendee_form" model="ir.actions.act_window">
<field name="name">Meeting Invitations</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">calendar.attendee</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="caldav.caldav_attendee_tree_view" />
<field name="domain">[('ref','like','crm.meeting,')]</field>
<field name="context">{'default_sent_by_uid': uid}</field>
</record>
<menuitem id="menu_attendee_invitations"
name="Meeting Invitations" parent="menu_meeting_sale"
sequence="10" action="action_view_attendee_form" />
<record model="ir.actions.act_window" id="crm_case_category_act_meetall3">
<field name="name">Next Meetings</field>
<field name="res_model">crm.meeting</field>
+12 -12
View File
@@ -9,11 +9,11 @@
<field name="name">Meeting Categories</field>
<field name="res_model">crm.case.categ</field>
<field name="view_type">form</field>
<field name="view_id" ref="crm.crm_case_categ_tree-view"/>
<field name="view_id" ref="crm.crm_case_categ_tree-view"/>
<field name="domain">[('object_id.model', '=', 'crm.meeting')]</field>
<field name="context">{'object_id':'crm.meeting'}</field>
<field name="context">{'object_id':'crm.meeting'}</field>
</record>
<menuitem action="crm_meeting_categ_action" id="menu_crm_case_meeting-act" parent="crm.menu_crm_case_categ"/>
<menuitem action="crm_meeting_categ_action" id="menu_crm_case_meeting-act" parent="crm.menu_crm_case_categ"/>
# ------------------------------------------------------
# Meetings
@@ -43,11 +43,11 @@
colspan="1" />
<button string="Custom"
name="%(caldav.action_calendar_custom_rrule_wizard)d"
icon="gtk-save-as" type="action" context="{'model' : 'crm.meeting'}"
icon="gtk-save-as" type="action" context="{'model' : 'crm.meeting'}"
attrs="{'readonly': [('rrule_type','!=','custom')]}"
/>
</group>
</group>
<notebook colspan="4">
<page string="Description">
@@ -88,7 +88,7 @@
<page string="Other Information">
<field name="priority"/>
<field name="show_as"/>
<field name="alarm_id" string="Reminder" widget="selection" />
<field name="alarm_id" string="Reminder" widget="selection" />
<field name="class"/>
<field name="user_id"/>
<field name="vtimezone"/>
@@ -133,10 +133,10 @@
<field name="type">calendar</field>
<field name="priority" eval="2"/>
<field name="arch" type="xml">
<calendar string="Meetings" date_start="date" color="section_id" date_delay="duration">
<calendar string="Meetings" date_start="date" color="user_id" date_delay="duration">
<field name="name"/>
<field name="partner_id"/>
<field name="user_id" widget="selection"/>
<field name="section_id" widget="selection"/>
</calendar>
</field>
</record>
@@ -167,16 +167,16 @@
<separator orientation="vertical"/>
<field name="name" select="1" string="Subject"/>
<field name="partner_id" select="1"/>
<field name="section_id" select="1" widget="selection">
<field name="section_id" default="context.get('section_id', False)" select="1" widget="selection">
<filter icon="terp-crm"
domain="[('section_id','=',context.get('section_id',False))]"
help="My section"
/>
</field>
/>
</field>
<field name="user_id" select="1" widget="selection"/>
</group>
</search>
</field>
</record>
</record>
</data>
</openerp>
-18
View File
@@ -19,22 +19,9 @@
#
##############################################################################
import time
import re
import os
import mx.DateTime
import base64
from tools.translate import _
import tools
from osv import fields,osv,orm
from osv.orm import except_orm
import crm
class crm_opportunity(osv.osv):
_name = "crm.opportunity"
_description = "Opportunity Cases"
@@ -58,11 +45,6 @@ class crm_opportunity(osv.osv):
'date_closed': fields.datetime('Closed', readonly=True),
'phonecall_id':fields.many2one ('crm.phonecall', 'Phonecall'),
}
def onchange_categ_id(self, cr, uid, ids, categ, context={}):
if not categ:
return {'value':{}}
cat = self.pool.get('crm.case.categ').browse(cr, uid, categ, context).probability
return {'value':{'probability':cat}}
crm_opportunity()
+11 -11
View File
@@ -10,14 +10,14 @@
<field name="name">Opportunity Categories</field>
<field name="res_model">crm.case.categ</field>
<field name="view_type">form</field>
<field name="view_id" ref="crm.crm_case_categ_tree-view"/>
<field name="view_id" ref="crm.crm_case_categ_tree-view"/>
<field name="domain">[('object_id.model', '=', 'crm.opportunity')]</field>
<field name="context">{'object_id':'crm.opportunity'}</field>
<field name="context">{'object_id':'crm.opportunity'}</field>
</record>
<menuitem action="crm_opportunity_categ_action" id="menu_crm_case_opportunity-act" parent="crm.menu_crm_case_categ"/>
# ------------------------------------------------------
# ------------------------------------------------------
# Stage
# ------------------------------------------------------
# ------------------------------------------------------
<record id="crm_opportunity_stage_act" model="ir.actions.act_window">
<field name="name">Opportunity Stages</field>
<field name="res_model">crm.case.stage</field>
@@ -29,7 +29,7 @@
<menuitem action="crm_opportunity_stage_act" id="menu_crm_opportunity_stage_act" parent="crm.menu_crm_case_stage"/>
# ------------------------------------------------------
# Opportunities
# ------------------------------------------------------
# ------------------------------------------------------
@@ -52,9 +52,9 @@
<button icon="gtk-go-forward" string="" name="stage_next" type="object"/>
</group>
<field name="date" />
<field name="date_deadline"/>
<field name="date_deadline"/>
<button string="Schedule a Phone Call"
name="%(wizard_crm_opportunity_reschedule_phone_call)d" icon="gtk-redo" type="action" />
name="%(wizard_crm_opportunity_reschedule_phone_call)d" icon="gtk-redo" type="action" />
</group>
<notebook colspan="4">
<page string="Description">
@@ -172,7 +172,7 @@
<field name="state" group="True"/>
</graph>
</field>
</record>
</record>
<record id="view_crm_case_opportunities_filter" model="ir.ui.view">
<field name="name">CRM - Opportunities Search</field>
@@ -204,11 +204,11 @@
<field name="state" select="1">
<filter icon="gtk-index" domain="[('state','in',('open','draft'))]" help="Current "/>
</field>
<field name="section_id" select="1" widget="selection" string="Section">
<field name="section_id" default="context.get('section_id', False)" select="1" widget="selection" string="Section">
<filter icon="terp-crm"
domain="[('section_id','=',context.get('section_id',False))]"
help="My section"/>
</field>
help="My section"/>
</field>
</group>
</search>
</field>
+1 -16
View File
@@ -19,19 +19,9 @@
#
##############################################################################
from dateutil.rrule import *
from osv import fields, osv
import datetime
import base64
import re
import time
import tools
from tools.translate import _
import crm
class crm_phonecall(osv.osv):
_name = "crm.phonecall"
_description = "Phonecall Cases"
@@ -53,11 +43,6 @@ class crm_phonecall(osv.osv):
'date_closed': fields.datetime('Closed', readonly=True),
'opportunity_id':fields.many2one ('crm.opportunity', 'Opportunity'),
}
def onchange_categ_id(self, cr, uid, ids, categ, context={}):
if not categ:
return {'value':{}}
cat = self.pool.get('crm.case.categ').browse(cr, uid, categ, context).probability
return {'value':{'probability':cat}}
crm_phonecall()
+20 -31
View File
@@ -1,20 +1,20 @@
<?xml version="1.0"?>
<openerp>
<data>
# ------------------------------------------------------
# Phonecall Categories
# ------------------------------------------------------
<record id="crm_phonecall_categ_action" model="ir.actions.act_window">
<field name="name">Phonecall Categories</field>
<field name="res_model">crm.case.categ</field>
<field name="view_type">form</field>
<field name="view_id" ref="crm.crm_case_categ_tree-view"/>
<field name="domain">[('object_id.model', '=', 'crm.phonecall')]</field>
<field name="domain">[('object_id.model', '=', 'crm.phonecall')]</field>
<field name="context">{'object_id':'crm.phonecall'}</field>
</record>
<menuitem action="crm_phonecall_categ_action" id="menu_crm_case_phonecall-act" parent="crm.menu_crm_case_categ"/>
# ------------------------------------------------------
# Fund Stage
@@ -24,11 +24,11 @@
<field name="res_model">crm.case.stage</field>
<field name="view_type">form</field>
<field name="view_id" ref="crm.crm_case_stage_tree"/>
<field name="domain">[('object_id.model', '=', 'crm.phonecall')]</field>
<field name="domain">[('object_id.model', '=', 'crm.phonecall')]</field>
<field name="context">{'object_id':'crm.phonecall'}</field>
</record>
<menuitem action="crm_phonecall_stage_act" id="menu_crm_phonecall_stage_act" parent="crm.menu_crm_case_stage"/>
# ------------------------------------------------------
# Phone Calls
# ------------------------------------------------------
@@ -45,7 +45,7 @@
<field name="partner_id" string="Partner"/>
<field name="partner_address_id" string="Contact"/>
<field name="opportunity_id"/>
<button string="Opportunity" name="%(wizard_crm_phonecall_opportunity_set)d" type="action" attrs="{'invisible':[('opportunity_id','!=',False)]}" />
<button string="Opportunity" name="%(wizard_crm_phonecall_opportunity_set)d" type="action" attrs="{'invisible':[('opportunity_id','!=',False)]}" />
<button string="Meeting"
name="%(wizard_crm_phonecall_meeting_set)d" type="action" />
</tree>
@@ -62,12 +62,12 @@
<field name="name" string="Call Summary"/>
<field name="partner_id" string="Partner"/>
<field name="partner_address_id" string="Contact"/>
<group col="2">
<group col="2">
<field name="opportunity_id"/>
<button string="Opportunity" name="%(wizard_crm_phonecall_opportunity_set)d" type="action" attrs="{'invisible':[('opportunity_id','!=',False)]}" />
<button string="Opportunity" name="%(wizard_crm_phonecall_opportunity_set)d" type="action" attrs="{'invisible':[('opportunity_id','!=',False)]}" />
<button string="Meeting"
name="%(wizard_crm_phonecall_meeting_set)d" type="action" />
</group>
</group>
</tree>
</field>
</record>
@@ -84,25 +84,25 @@
<field name="user_id" string="Assigned to" select="2"/>
<button string="Schedule a Meeting"
name="%(wizard_crm_phonecall_meeting_set)d" icon="gtk-redo" type="action" />
<newline/>
<field name="date" string="Planned Date"/>
<field name="duration"/>
<field name="duration"/>
<field name="opportunity_id" on_change="onchange_case_id(case_id, name, partner_id)"
context="{'default_name':name,'default_section_id':section_id,'default_user_id':user_id,'default_duration':duration,
'default_partner_id':partner_id,'default_partner_address_id':partner_address_id,'default_partner_phone':partner_phone,
'default_partner_mobile':partner_mobile,'default_categ_id':categ_id}"/>
<button string="Convert to Opportunity" name="%(wizard_crm_phonecall_opportunity_set)d" icon="gtk-index" type="action" attrs="{'invisible':[('opportunity_id','!=',False)]}" />
<button string="Convert to Opportunity" name="%(wizard_crm_phonecall_opportunity_set)d" icon="gtk-index" type="action" attrs="{'invisible':[('opportunity_id','!=',False)]}" />
</group>
<notebook colspan="4">
<page string="General">
<field name="categ_id" string="Direction" select="1" on_change="onchange_categ_id(categ_id)" required="1"/>
<field name="active" string="Reminder"/>
<field name="active" string="Reminder"/>
<group colspan="2" col="3">
<field name="partner_id" string="Partner"/>
<button string="Convert to Partner" icon="terp-crm" name="%(wizard_crm_phonecall_partner_create)d" type="action" attrs="{'invisible':[('partner_id','!=',False)]}" />
<button string="Convert to Partner" icon="terp-crm" name="%(wizard_crm_phonecall_partner_create)d" type="action" attrs="{'invisible':[('partner_id','!=',False)]}" />
</group>
<field name="partner_address_id" string="Contact"/>
<field name="partner_phone"/>
@@ -148,17 +148,6 @@
<field name="arch" type="xml">
<search string="Search Phonecalls">
<group col="6" colspan="1">
<filter icon="gtk-jump-to"
string="Inbound"
domain="[('categ_id.name','=','Inbound')]"
separator="1" help="All Inbound Phonecalls"
/>
<filter icon="gtk-redo"
string="Outbound"
domain="[('categ_id.name','=','Outbound')]"
separator="1" help="All Outbound Phonecalls"
/>
<separator orientation="vertical"/>
<filter icon="gtk-home" string=" Today "
separator="1"
domain="[('date','=',time.strftime('%%Y-%%m-%%d'))]"
@@ -179,11 +168,11 @@
<field name="state" select="1">
<filter icon="gtk-index" domain="[('state','in',('open','draft' ))]" help="Current "/>
</field>
<field name="section_id" select="1" widget="selection" string="Section">
<field name="section_id" default="context.get('section_id', False)" select="1" widget="selection" string="Section">
<filter icon="terp-crm"
domain="[('section_id','=',context.get('section_id',False))]"
help="My section"/>
</field>
help="My section"/>
</field>
</group>
</search>
</field>
+1 -1
View File
@@ -68,7 +68,7 @@
<filter string="This Year" icon="terp-hr" domain="[('name','=',time.localtime()[0])]" help="Cases by Section and Type for this year"/>
<filter string="This Month" icon="terp-hr" domain="[('month','=',time.localtime()[1])]" help="Cases by Section and Type for this month"/>
<separator orientation="vertical"/>
<field name="section_id" select="1" widget="selection"/>
<field name="section_id" default="context.get('section_id', False)" select="1" widget="selection"/>
<field name="category2_id" select="1"/>
<field name="nbr" select="1"/>
<field name="state" select="1"/>
+8 -8
View File
@@ -48,9 +48,9 @@
<field name="view_id" ref="crm_case_section_view_tree"/>
</record>
# ------------------------------------------------------
# ------------------------------------------------------
# Stage
# ------------------------------------------------------
# ------------------------------------------------------
<record model="ir.ui.view" id="crm_case_stage_tree">
<field name="name">crm.case.stage.tree</field>
<field name="model">crm.case.stage</field>
@@ -92,7 +92,7 @@
<form string="Case Category">
<field name="name" select="1"/>
<field name="section_id" select="1" widget="selection"/>
<field name="object_id" invisible="1" />
<field name="object_id" invisible="1" />
<field name="probability"/>
</form>
</field>
@@ -117,7 +117,7 @@
<field name="view_id" ref="crm_case_categ_tree-view"/>
</record>
<menuitem id="menu_crm_case_categ" name="Categories" parent="crm.menu_crm_configuration"/>
<menuitem action="crm_case_section_act" id="menu_crm_case_section_act" parent="crm.menu_crm_configuration"/>
<!-- <menuitem id="next_id_52" name="All Cases" parent="crm.menu_crm" sequence="1"/>-->
@@ -442,11 +442,11 @@
<field name="name" select='1'/>
<field name="user_id" select="1" widget="selection"/>
</group>
<field name="section_id" select="1" widget="selection" string="Section"/>
<field name="section_id" default="context.get('section_id', False)" select="1" widget="selection" string="Section"/>
</search>
</field>
</record>
<record id="crm_case_categ0-act" model="ir.actions.act_window">
<field name="name">Cases</field>
<field name="res_model">crm.case</field>
@@ -507,8 +507,8 @@
<separator orientation="vertical"/>
<group col="6" colspan="2">
<field name="date" select="1"/>
<field name="user_id" select="1" widget="selection"/>
<field name="section_id" select="1" widget="selection" string="Section"/>
<field name="user_id" select="1" widget="selection"/>
<field name="section_id" default="context.get('section_id', False)" select="1" widget="selection" string="Section"/>
</group>
</search>
</field>
+50 -42
View File
@@ -7,19 +7,19 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2010-01-05 05:59+0000\n"
"PO-Revision-Date: 2010-01-17 17:11+0000\n"
"Last-Translator: Jaerhigo <Unknown>\n"
"PO-Revision-Date: 2010-02-02 02:48+0000\n"
"Last-Translator: Carlos Alberto Ospina <Unknown>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-01-18 04:44+0000\n"
"X-Launchpad-Export-Date: 2010-02-03 04:46+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: crm
#: field:crm.email.add.cc,name:0
msgid "Send to"
msgstr ""
msgstr "Enviar a"
#. module: crm
#: help:crm.meeting,exdate:0
@@ -33,16 +33,18 @@ msgstr ""
msgid ""
"Check this if you want the rule to send an email to the responsible person."
msgstr ""
"Revise esto si quiere la regla para enviar un correo a la persona "
"responsable."
#. module: crm
#: view:crm.meeting:0
msgid "Title"
msgstr ""
msgstr "Título"
#. module: crm
#: model:ir.model,name:crm.model_report_crm_case_section_categ2
msgid "Cases by section and category2"
msgstr "Casos segmentados por sección y categoría 2"
msgstr "Casos por sección y categoria2"
#. module: crm
#: wizard_field:crm.lead.partner_create,init,close:0
@@ -55,22 +57,22 @@ msgstr ""
#: view:crm.opportunity:0
#: view:crm.phonecall:0
msgid " 7 Days "
msgstr ""
msgstr " 7 días "
#. module: crm
#: help:crm.menu.config_wizard,helpdesk:0
msgid "Manages an Helpdesk service."
msgstr ""
msgstr "Gestiona un servicio de mesa de ayuda"
#. module: crm
#: view:crm.job:0
msgid "Pending Jobs"
msgstr ""
msgstr "Trabajos pendientes"
#. module: crm
#: field:crm.case.rule,trg_state_to:0
msgid "Button Pressed"
msgstr "Botón presionado"
msgstr "Botón oprimido"
#. module: crm
#: view:crm.case:0
@@ -85,7 +87,7 @@ msgstr "Requerimiento de trabajo a finalizar"
#. module: crm
#: field:crm.case.stage,name:0
msgid "Stage Name"
msgstr ""
msgstr "Nombre de etapa"
#. module: crm
#: view:crm.case:0
@@ -109,12 +111,12 @@ msgstr ""
#. module: crm
#: model:ir.ui.menu,name:crm.menu_hr
msgid "Human Resources"
msgstr ""
msgstr "Recursos humanos"
#. module: crm
#: model:ir.ui.menu,name:crm.menu_action_report_crm_case_oppor_categ_categ2
msgid "Cases by Opportunities, Category and Type"
msgstr ""
msgstr "Casos por oportunidades, categoria y tipo"
#. module: crm
#: help:crm.menu.config_wizard,claims:0
@@ -122,22 +124,24 @@ msgid ""
"Manages the supplier and customers claims, including your corrective or "
"preventive actions."
msgstr ""
"Gestiona los reclamos de proveedores y clientes, incluyendon sus acciones "
"prevenivas ó correctivas."
#. module: crm
#: view:crm.fundraising:0
msgid "Amount"
msgstr ""
msgstr "Cantidad"
#. module: crm
#: model:process.transition,note:crm.process_transition_opportunitymeeting0
msgid "Normal or phone meeting for opportunity"
msgstr ""
msgstr "Oportunidad de reunion normal ó telefonico."
#. module: crm
#: model:crm.case.stage,name:crm.stage_claim2
#: model:crm.case.stage,name:crm.stage_meet1
msgid "Fixed"
msgstr ""
msgstr "Reparado"
#. module: crm
#: code:addons/crm/crm.py:0
@@ -146,35 +150,35 @@ msgstr ""
#: code:addons/crm/wizard/crm_phonecall_wizard.py:0
#, python-format
msgid "Warning !"
msgstr "¡Atención!"
msgstr "Advertencia !"
#. module: crm
#: code:addons/crm/wizard/wizard_crm_new_send_email.py:0
#, python-format
msgid "Please specify user's email address !"
msgstr ""
msgstr "Por favor especiificar el nombre de usuario de correo"
#. module: crm
#: model:crm.case.categ,name:crm.categ_oppor5
msgid "Campaign"
msgstr ""
msgstr "Campaña"
#. module: crm
#: view:crm.opportunity:0
msgid "Search Opportunities"
msgstr ""
msgstr "Busqueda de oportunidades"
#. module: crm
#: model:ir.ui.menu,name:crm.menu_crm_case_section_stage_tree
#: view:report.crm.case.section.stage:0
msgid "Cases by Section and Stage"
msgstr ""
msgstr "Casos por sección y estados"
#. module: crm
#: wizard_field:crm.job.meeting_set,init,duration:0
#: wizard_field:crm.phonecall.meeting_set,init,duration:0
msgid "Duration (Hours)"
msgstr ""
msgstr "Duración (Horas)"
#. module: crm
#: selection:crm.meeting,transparent:0
@@ -194,6 +198,8 @@ msgid ""
"Section to which Case belongs to. Define Responsible user and Email account "
"for mail gateway."
msgstr ""
"Sección a la cual pertenece el caso. Definir usuario responsable y cuenta de "
"correo para correo de salida."
#. module: crm
#: view:crm.case:0
@@ -212,7 +218,7 @@ msgstr ""
#: wizard_field:crm.phonecall.opportunity_set,opportunity,partner_id:0
#: model:process.node,name:crm.process_node_partner0
msgid "Partner"
msgstr "Empresa"
msgstr "Compañero"
#. module: crm
#: field:crm.case.categ,section_id:0
@@ -227,12 +233,13 @@ msgstr "Sección del caso"
#. module: crm
#: view:crm.job:0
msgid "Proposed Salary"
msgstr ""
msgstr "Salario sugerido"
#. module: crm
#: help:crm.case.section,sequence:0
msgid "Gives the sequence order when displaying a list of case sections."
msgstr ""
"Dar orden de la secuencia cuando se muestre la lista de casos de sección."
#. module: crm
#: code:addons/crm/wizard/crm_job_wizard.py:0
@@ -240,17 +247,17 @@ msgstr ""
#: model:crm.case.categ,name:crm.categ_meet3
#, python-format
msgid "Phone Call"
msgstr ""
msgstr "Llamada de telefono"
#. module: crm
#: model:ir.model,name:crm.model_report_crm_case_section_stage
msgid "Cases by section and stage"
msgstr ""
msgstr "Casos por secciòn y estado"
#. module: crm
#: field:crm.case.rule,act_mail_to_email:0
msgid "Mail to these emails"
msgstr "Enviar correo a estos emails"
msgstr "Correo a estos correos electronicos"
#. module: crm
#: selection:crm.case.rule,trg_date_type:0
@@ -260,7 +267,7 @@ msgstr "Ninguno"
#. module: crm
#: view:crm.case.rule:0
msgid "Special Keywords to Be Used in The Body"
msgstr "Palabras clave especiales para ser usadas en el mensaje"
msgstr "Palabras claves especiales para ser usadas en el cuerpo del mensaje."
#. module: crm
#: view:crm.case:0
@@ -270,12 +277,12 @@ msgstr "Palabras clave especiales para ser usadas en el mensaje"
#: view:crm.lead:0
#: view:crm.opportunity:0
msgid "Send New Email"
msgstr ""
msgstr "Enviar nuevo correo eléctronico"
#. module: crm
#: view:crm.case.history:0
msgid "My Histories"
msgstr "Mis historiales"
msgstr "Mis historias"
#. module: crm
#: field:crm.segmentation,segmentation_line:0
@@ -286,12 +293,13 @@ msgstr "Criterios"
#: model:ir.actions.act_window,name:crm.crm_case_section_act
#: model:ir.ui.menu,name:crm.menu_crm_case_section_act
msgid "Sections"
msgstr "Secciones"
msgstr "Secciónes"
#. module: crm
#: help:crm.menu.config_wizard,opportunity:0
msgid "Tracks identified business opportunities for your sales pipeline."
msgstr ""
"Temas de oportunidades de negocio identificadas para su canal de ventas."
#. module: crm
#: view:crm.meeting:0
@@ -301,12 +309,12 @@ msgstr ""
#. module: crm
#: selection:crm.case.rule,trg_date_type:0
msgid "Last Action Date"
msgstr "Fecha última acción"
msgstr "Fechas de ultima acción"
#. module: crm
#: view:crm.job:0
msgid "Appreciation"
msgstr ""
msgstr "Reconocimiento"
#. module: crm
#: model:crm.case.stage,name:crm.stage_job3
@@ -316,7 +324,7 @@ msgstr ""
#. module: crm
#: model:ir.actions.wizard,name:crm.wizard_crm_cal_subscribe
msgid "Subscribe to a Remote calendar"
msgstr ""
msgstr "Suscribirse a un calendario remoto"
#. module: crm
#: model:ir.actions.act_window,name:crm.crm_case_categ-act
@@ -328,7 +336,7 @@ msgstr "Categorías"
#: code:addons/crm/wizard/wizard_crm_new_send_email.py:0
#, python-format
msgid "Warning!"
msgstr ""
msgstr "Advertencia!"
#. module: crm
#: view:crm.case:0
@@ -348,29 +356,29 @@ msgstr "Prueba de segmentación"
#. module: crm
#: model:process.transition,name:crm.process_transition_leadpartner0
msgid "Prospect Partner"
msgstr ""
msgstr "Socio prospecto"
#. module: crm
#: view:crm.fundraising:0
#: view:crm.opportunity:0
msgid "Description Information"
msgstr ""
msgstr "Información de descripción"
#. module: crm
#: view:crm.lead:0
msgid "Contact Name"
msgstr ""
msgstr "Nombre de contacto"
#. module: crm
#: selection:crm.lead.opportunity_set,create_partner,action:0
#: selection:crm.phonecall.opportunity_set,create_partner,action:0
msgid "Link to an existing partner"
msgstr ""
msgstr "Enlace al socio existente"
#. module: crm
#: field:crm.case.rule,trg_date_range_type:0
msgid "Delay type"
msgstr "Tipo de demora"
msgstr "Tipo de retraso"
#. module: crm
#: view:crm.claim:0
@@ -380,12 +388,12 @@ msgstr "Tipo de demora"
#: view:crm.opportunity:0
#: view:crm.phonecall:0
msgid "Contact"
msgstr ""
msgstr "Contacto"
#. module: crm
#: view:crm.job:0
msgid "Next Interview"
msgstr ""
msgstr "Próxima entrevista"
#. module: crm
#: field:crm.case.rule,regex_history:0
+19 -19
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2010-01-05 05:59+0000\n"
"PO-Revision-Date: 2010-01-22 14:44+0000\n"
"Last-Translator: Carlo <Unknown>\n"
"PO-Revision-Date: 2010-02-02 16:15+0000\n"
"Last-Translator: Carlo Vettore <Unknown>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-01-23 04:45+0000\n"
"X-Launchpad-Export-Date: 2010-02-03 04:46+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: crm
@@ -678,7 +678,7 @@ msgstr " Oggi "
#: wizard_view:crm.job.reschedule_phone_call,init:0
#: wizard_view:crm.opportunity.reschedule_phone_call,init:0
msgid "Phone Call Description"
msgstr ""
msgstr "Descrizione Chiamata Telefonica"
#. module: crm
#: view:crm.case.categ:0
@@ -1397,7 +1397,7 @@ msgstr "Casi aperti"
#: field:report.crm.case.section.categ2,stage_id:0
#: field:report.crm.case.section.stage,stage_id:0
msgid "Stage"
msgstr ""
msgstr "Scenario"
#. module: crm
#: constraint:ir.ui.view:0
@@ -1428,7 +1428,7 @@ msgstr ""
#: model:ir.actions.act_window,name:crm.crm_case_stage_act
#: model:ir.ui.menu,name:crm.menu_crm_case_stage_act
msgid "Stages"
msgstr ""
msgstr "Tirocini"
#. module: crm
#: wizard_field:crm.case.opportunity.partner_opportunity,init,planned_revenue:0
@@ -1857,7 +1857,7 @@ msgstr "Permetti di cancellare i casi non in bozza"
#. module: crm
#: model:crm.case.stage,name:crm.stage_oppor7
msgid "Closed Lost"
msgstr ""
msgstr "Perdita chiusa"
#. module: crm
#: field:crm.menu.config_wizard,bugs:0
@@ -1886,7 +1886,7 @@ msgstr "Alta"
#. module: crm
#: model:process.node,note:crm.process_node_partner0
msgid "Convert to prospect to business partner"
msgstr ""
msgstr "Converti candidato in business partner"
#. module: crm
#: view:crm.claim:0
@@ -2065,7 +2065,7 @@ msgstr "Minuti"
#: field:report.crm.case.section.categ2,amount_revenue:0
#: field:report.crm.case.section.stage,amount_revenue:0
msgid "Est.Revenue"
msgstr ""
msgstr "Entrate stimate"
#. module: crm
#: model:crm.case.stage,name:crm.stage_job1
@@ -2278,7 +2278,7 @@ msgstr "Luglio"
#. module: crm
#: model:crm.case.stage,name:crm.stage_oppor1
msgid "Prospecting"
msgstr ""
msgstr "Candidatura"
#. module: crm
#: field:crm.case,partner_name2:0
@@ -2362,7 +2362,7 @@ msgstr "Mese"
#: model:ir.ui.menu,name:crm.menu_crm_case_categ0_act_leads
#: model:process.node,name:crm.process_node_leads0
msgid "Leads"
msgstr ""
msgstr "Iniziative"
#. module: crm
#: wizard_button:crm.new.send.mail,init,send:0
@@ -2432,7 +2432,7 @@ msgstr "Note"
#: field:report.crm.case.section.categ2,delay_close:0
#: field:report.crm.case.section.stage,delay_close:0
msgid "Delay Close"
msgstr ""
msgstr "Ritardo Chiusura"
#. module: crm
#: selection:crm.case,priority:0
@@ -2595,7 +2595,7 @@ msgstr ">"
#. module: crm
#: view:crm.job:0
msgid "Candidate Phone"
msgstr ""
msgstr "Telefono Candidato"
#. module: crm
#: model:ir.actions.wizard,name:crm.wizard_crm_send_mail
@@ -2759,7 +2759,7 @@ msgstr ""
#: code:addons/crm/wizard/crm_phonecall_wizard.py:0
#, python-format
msgid "A partner is already existing with the same name."
msgstr ""
msgstr "Esiste già un Partner con lo stesso nome"
#. module: crm
#: model:ir.model,name:crm.model_crm_phonecall
@@ -2899,7 +2899,7 @@ msgstr ""
#. module: crm
#: view:crm.job:0
msgid "Open Jobs"
msgstr ""
msgstr "Lavori Aperti"
#. module: crm
#: selection:crm.email.add.cc,name:0
@@ -3071,7 +3071,7 @@ msgstr "Modulo Fondi"
#. module: crm
#: view:crm.meeting:0
msgid "Search Meetings"
msgstr ""
msgstr "Ricerca Incontri"
#. module: crm
#: selection:crm.lead.opportunity_set,create_partner,action:0
@@ -3174,7 +3174,7 @@ msgstr "Annullato"
#. module: crm
#: view:crm.job:0
msgid "Applied Job"
msgstr ""
msgstr "Lavoro Svolto"
#. module: crm
#: help:crm.meeting,exrule:0
@@ -4008,7 +4008,7 @@ msgstr "Sequenza"
#: wizard_view:caldav.crm.import,init:0
#: wizard_field:caldav.crm.import,init,file_path:0
msgid "Select ICS file"
msgstr ""
msgstr "Seleziona il file ICS"
#. module: crm
#: wizard_view:caldav.crm.import,display:0
@@ -4029,7 +4029,7 @@ msgstr "Casi per Sezione"
#. module: crm
#: view:crm.job:0
msgid "New Jobs"
msgstr ""
msgstr "Nuovo Lavoro"
#. module: crm
#: field:crm.menu.config_wizard,fund:0
+12 -10
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2010-01-05 05:59+0000\n"
"PO-Revision-Date: 2010-01-26 22:43+0000\n"
"PO-Revision-Date: 2010-02-02 17:06+0000\n"
"Last-Translator: pedrobom <pedrobomlimeira@gmail.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-01-29 04:52+0000\n"
"X-Launchpad-Export-Date: 2010-02-03 04:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: crm
@@ -1557,11 +1557,13 @@ msgid ""
"Helps you to organise the jobs hiring process: evaluation, meetings, email "
"integration..."
msgstr ""
"Ajuda você a organizar as tarefas do processo de contratação: avaliação, "
"reuniões, integração de e-mail ..."
#. module: crm
#: view:crm.fundraising:0
msgid "Funds"
msgstr ""
msgstr "Fundos"
#. module: crm
#: code:addons/crm/crm.py:0
@@ -1573,7 +1575,7 @@ msgstr "esboço"
#: model:crm.case.stage,name:crm.stage_claim5
#: model:crm.case.stage,name:crm.stage_meet4
msgid "Awaiting Response"
msgstr ""
msgstr "Aguardando resposta"
#. module: crm
#: field:crm.case,date:0
@@ -1587,7 +1589,7 @@ msgstr "Data"
#. module: crm
#: view:crm.job:0
msgid "Candidate Name"
msgstr ""
msgstr "Nome do candidato"
#. module: crm
#: model:crm.case.categ,name:crm.categ_lead2
@@ -1598,12 +1600,12 @@ msgstr ""
#. module: crm
#: model:crm.case.stage,name:crm.stage_claim3
msgid "Won't fix"
msgstr ""
msgstr "Não irá corrigir"
#. module: crm
#: model:crm.case.stage,name:crm.stage_lead4
msgid "Converted"
msgstr ""
msgstr "Convertido"
#. module: crm
#: view:crm.case:0
@@ -1613,7 +1615,7 @@ msgstr ""
#: view:crm.lead:0
#: view:crm.opportunity:0
msgid "Reply to Last Email"
msgstr ""
msgstr "Resposta ao último Email"
#. module: crm
#: view:crm.segmentation:0
@@ -1623,7 +1625,7 @@ msgstr "Descrição da segmentação"
#. module: crm
#: help:crm.meeting,location:0
msgid "Gives Location of Meeting"
msgstr ""
msgstr "Dá a localização da reunião"
#. module: crm
#: view:crm.case:0
@@ -1638,7 +1640,7 @@ msgstr "Histórico"
#. module: crm
#: model:ir.model,name:crm.model_crm_job
msgid "Job Cases"
msgstr ""
msgstr "Casos de Emprego"
#. module: crm
#: view:crm.job:0
+14 -3
View File
@@ -62,6 +62,15 @@ class lead2opportunity(wizard.interface):
'probability': {'type':'float', 'digits':(16,2), 'string': 'Success Probability'},
'partner_id' : {'type':'many2one', 'relation':'res.partner', 'string':'Partner'},
}
def _check_state(self, cr, uid, data, context):
pool = pooler.get_pool(cr.dbname)
case_obj = pool.get('crm.lead')
for case in case_obj.browse(cr, uid, data['ids']):
if case.state != 'open':
raise wizard.except_wizard(_('Warning !'),
_('Lead should be in \'Open\' state before converting to Opportunity.'))
return {}
def _selectopportunity(self, cr, uid, data, context):
pool = pooler.get_pool(cr.dbname)
@@ -105,8 +114,10 @@ class lead2opportunity(wizard.interface):
'partner_id': data['form']['partner_id'],
'section_id':lead.section_id.id,
'description':lead.description,
'date_deadline': lead.date_deadline,
'partner_address_id':lead.partner_address_id.id,
'priority':lead.priority,
'priority':lead.priority,
'date': lead.date,
})
new_opportunity = opportunity_case_obj.browse(cr, uid, new_opportunity_id)
@@ -118,7 +129,7 @@ class lead2opportunity(wizard.interface):
vals.update({'opportunity_id' : new_opportunity.id})
lead_case_obj.write(cr, uid, [lead.id], vals)
lead_case_obj.case_cancel(cr, uid, [lead.id])
lead_case_obj.case_close(cr, uid, [lead.id])
opportunity_case_obj.case_open(cr, uid, [new_opportunity_id])
value = {
@@ -170,7 +181,7 @@ class lead2opportunity(wizard.interface):
states = {
'init': {
'actions': [],
'actions': [_check_state],
'result': {'type':'choice','next_state':_selectChoice}
},
'create_partner': {
@@ -56,6 +56,10 @@ class opportunity2phonecall(wizard.interface):
case_obj = pooler.get_pool(cr.dbname).get('crm.opportunity')
categ_id = pooler.get_pool(cr.dbname).get('crm.case.categ').search(cr, uid, [('name','=','Outbound')])
case = case_obj.browse(cr, uid, data['id'])
if case.state != 'open':
raise wizard.except_wizard(_('Warning !'),
_('Opportunity should be in \'Open\' state before converting to Phone Call.'))
return {}
return {
'user_id' : case.user_id and case.user_id.id,
'category_id' : categ_id and categ_id[0] or case.categ_id and case.categ_id.id,
+19 -8
View File
@@ -62,6 +62,15 @@ class phonecall2opportunity(wizard.interface):
'probability': {'type':'float', 'digits':(16,2), 'string': 'Success Probability'},
'partner_id' : {'type':'many2one', 'relation':'res.partner', 'string':'Partner'},
}
def _check_state(self, cr, uid, data, context):
pool = pooler.get_pool(cr.dbname)
case_obj = pool.get('crm.phonecall')
for case in case_obj.browse(cr, uid, data['ids']):
if case.state != 'open':
raise wizard.except_wizard(_('Warning !'),
_('Phone Call state should be \'Open\' before converting to Opportunity.'))
return {}
def _selectopportunity(self, cr, uid, data, context):
pool = pooler.get_pool(cr.dbname)
@@ -103,9 +112,11 @@ class phonecall2opportunity(wizard.interface):
'planned_revenue': data['form']['planned_revenue'],
'probability': data['form']['probability'],
'partner_id': data['form']['partner_id'],
'section_id':phonecall.section_id.id,
'description':phonecall.description,
'phonecall_id': phonecall.id
'section_id': phonecall.section_id.id,
'description': phonecall.description,
'phonecall_id': phonecall.id,
'date': phonecall.date,
'priority': phonecall.priority
})
new_opportunity = opportunity_case_obj.browse(cr, uid, new_opportunity_id)
vals = {
@@ -113,7 +124,7 @@ class phonecall2opportunity(wizard.interface):
'opportunity_id' : new_opportunity_id,
}
phonecall_case_obj.write(cr, uid, [phonecall.id], vals)
phonecall_case_obj.case_cancel(cr, uid, [phonecall.id])
phonecall_case_obj.case_close(cr, uid, [phonecall.id])
opportunity_case_obj.case_open(cr, uid, [new_opportunity_id])
value = {
'name': _('Opportunity'),
@@ -164,7 +175,7 @@ class phonecall2opportunity(wizard.interface):
states = {
'init': {
'actions': [],
'actions': [_check_state],
'result': {'type':'choice','next_state':_selectChoice}
},
'create_partner': {
@@ -276,18 +287,18 @@ class partner_create(wizard.interface):
partner_obj = pool.get('res.partner')
contact_obj = pool.get('res.partner.address')
for case in case_obj.browse(cr, uid, data['ids']):
partner_id = partner_obj.search(cr, uid, [('name', '=', case.partner_name or case.name)])
partner_id = partner_obj.search(cr, uid, [('name', '=', case.name)])
if partner_id:
raise wizard.except_wizard(_('Warning !'),_('A partner is already existing with the same name.'))
else:
partner_id = partner_obj.create(cr, uid, {
'name': case.partner_name or case.name,
'name': case.name,
'user_id': case.user_id.id,
'comment': case.description,
})
contact_id = contact_obj.create(cr, uid, {
'partner_id': partner_id,
'name': case.partner_name2,
'name': case.name,
'phone': case.partner_phone,
'mobile': case.partner_mobile,
'email': case.email_from
+6
View File
@@ -240,6 +240,12 @@
<field name="email_from" select='1' string="Email"/>
<field name="user_id" select="1" widget="selection"/>
</group>
<field name="section_id" select="1" widget="selection" string="Section">
<filter icon="terp-crm"
domain="[('section_id','=',context.get('section_id',False))]"
help="My section"
/>
</field>
</search>
</field>
</record>
+6 -5
View File
@@ -189,11 +189,12 @@
<field name="user_id" select="1" widget="selection">
<filter icon="terp-partner" domain="[('user_id','=',uid)]" help="My Bugs" default="1"/>
</field>
<field name="state" select="1">
<filter icon="gtk-new" domain="[('state','=','draft')]" help="Draft Bugs"/>
<filter icon="gtk-yes" domain="[('state','=','open')]" help="Open Bugs"/>
<filter icon="gtk-media-pause" domain="[('state','=','pending')]" help="Pending Bugs"/>
</field>
<field name="section_id" select="1" widget="selection" string="Section" default="context.get('section_id', False)">
<filter icon="terp-crm"
domain="[('section_id','=',context.get('section_id',False))]"
help="My section"
/>
</field>
</group>
</search>
</field>
+6 -5
View File
@@ -164,11 +164,12 @@
<field name="user_id" select="1" widget="selection">
<filter icon="terp-partner" domain="[('user_id','=',uid)]" help="My Future Requests" default="1"/>
</field>
<field name="state" select="1">
<filter icon="gtk-new" domain="[('state','=','draft')]" help="Draft Future Requests"/>
<filter icon="gtk-yes" domain="[('state','=','open')]" help="Open Future Requests"/>
<filter icon="gtk-media-pause" domain="[('state','=','pending')]" help="Pending Future Requests"/>
</field>
<field name="section_id" select="1" widget="selection" string="Section" default="context.get('section_id', False)">
<filter icon="terp-crm"
domain="[('section_id','=',context.get('section_id',False))]"
help="My section"
/>
</field>
</group>
</search>
</field>
+5 -5
View File
@@ -54,20 +54,20 @@ class crm_project_bug(osv.osv):
'categ_id': fields.many2one('crm.case.categ','Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.project.bug')]"),
'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'),
'type_id': fields.many2one('crm.case.resource.type', 'Bug Type', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.project.bug')]"),
'partner_name': fields.char("Employee's Name", size=64),
'partner_mobile': fields.char('Mobile', size=32),
'partner_phone': fields.char('Phone', size=32),
'stage_id': fields.many2one ('crm.case.stage', 'Stage', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.project.bug')]"),
'project_id':fields.many2one('project.project', 'Project'),
'duration': fields.float('Duration') ,
'probability': fields.float('Probability (%)'),
'probability': fields.float('Probability (%)'),
}
def _get_project(self, cr, uid, context):
user = self.pool.get('res.users').browse(cr,uid,uid, context=context)
if user.context_project_id:
return user.context_project_id.id
return user.context_project_id
return False
_defaults = {
@@ -77,8 +77,8 @@ class crm_project_bug(osv.osv):
if not categ:
return {'value':{}}
cat = self.pool.get('crm.case.categ').browse(cr, uid, categ, context).probability
return {'value':{'probability':cat}}
return {'value':{'probability':cat}}
crm_project_bug()
+5 -5
View File
@@ -38,7 +38,7 @@ class crm_project_future_request(osv.osv):
_name = "crm.project.future"
_description = "Project Future Request"
_order = "id desc"
_inherit = 'crm.case'
_inherit = 'crm.case'
_columns = {
'date_closed': fields.datetime('Closed', readonly=True),
'ref' : fields.reference('Reference', selection=crm._links_get, size=128),
@@ -53,19 +53,19 @@ class crm_project_future_request(osv.osv):
'categ_id': fields.many2one('crm.case.categ','Category', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.project.future')]"),
'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'),
'type_id': fields.many2one('crm.case.resource.type', 'Bug Type', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.project.future')]"),
'partner_name': fields.char("Employee's Name", size=64),
'partner_mobile': fields.char('Mobile', size=32),
'partner_phone': fields.char('Phone', size=32),
'stage_id': fields.many2one ('crm.case.stage', 'Stage', domain="[('section_id','=',section_id),('object_id.model', '=', 'crm.project.future')]"),
'project_id':fields.many2one('project.project', 'Project'),
'duration': fields.float('Duration') ,
'probability': fields.float('Probability (%)'),
'probability': fields.float('Probability (%)'),
}
def _get_project(self, cr, uid, context):
user = self.pool.get('res.users').browse(cr,uid,uid, context=context)
if user.context_project_id:
return user.context_project_id.id
return user.context_project_id
return False
_defaults = {
@@ -76,7 +76,7 @@ class crm_project_future_request(osv.osv):
return {'value':{}}
cat = self.pool.get('crm.case.categ').browse(cr, uid, categ, context).probability
return {'value':{'probability':cat}}
crm_project_future_request()
+5 -5
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-12-11 13:36+0000\n"
"Last-Translator: Pieter J. Kersten (EduSense BV) <Unknown>\n"
"PO-Revision-Date: 2010-02-01 15:45+0000\n"
"Last-Translator: Jan Verlaan (Veritos) <Unknown>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2009-12-16 05:25+0000\n"
"X-Launchpad-Export-Date: 2010-02-02 04:48+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: document
@@ -29,14 +29,14 @@ msgstr "Bron ID"
#. module: document
#: field:document.directory.content,include_name:0
msgid "Include Record Name"
msgstr ""
msgstr "Inclusief naam record"
#. module: document
#: constraint:ir.model:0
msgid ""
"The Object name must start with x_ and not contain any special character !"
msgstr ""
"De objectnaam moet beginnen met x_ en mag geen speciale karakters bevatten !"
"De objectnaam moet beginnen met x_ en mag geen speciale tekens bevatten !"
#. module: document
#: field:ir.actions.report.xml,model_id:0
+6 -6
View File
@@ -7,24 +7,24 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-12-28 08:46+0000\n"
"Last-Translator: Jeroen Vet <Unknown>\n"
"PO-Revision-Date: 2010-02-01 23:45+0000\n"
"Last-Translator: mrshelly <Unknown>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2009-12-29 04:35+0000\n"
"X-Launchpad-Export-Date: 2010-02-03 04:47+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: document
#: field:document.directory,create_date:0
msgid "Date Created"
msgstr "已建立日期"
msgstr "创建时间"
#. module: document
#: field:document.directory,ressource_id:0
msgid "Resource ID"
msgstr "资源编码"
msgstr "资源ID"
#. module: document
#: field:document.directory.content,include_name:0
@@ -40,7 +40,7 @@ msgstr "对象名必须以“x_”开始且不能包含任何特殊字符!"
#. module: document
#: field:ir.actions.report.xml,model_id:0
msgid "Model Id"
msgstr "模式标识符(ID)"
msgstr "模块ID"
#. module: document
#: constraint:document.directory:0
-60
View File
@@ -1,60 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from document.nodes import node_content
from osv import osv, fields
from osv.orm import except_orm
import base64
import os
class document_directory_content(osv.osv):
_inherit = 'document.directory.content'
_columns = {
'object_id': fields.many2one('ir.model', 'Object', required=True),
}
def process_write(self, cr, uid, node, data, context=None):
if node.extension != '.ics':
return super(document_directory_content, self).process_write(cr, uid, node, data, context)
content = self.browse(cr, uid, node.cnt_id, context)
fobj = self.pool.get(content.object_id.model)
if not context:
context = {}
fobj.import_cal(cr, uid, base64.encodestring(data), context=context)
return True
def process_read(self, cr, uid, node, context=None):
ctx = (context or {})
ctx.update(node.context.context.copy())
ctx.update(node.dctx)
content = self.browse(cr, uid, node.cnt_id, ctx)
obj_class = self.pool.get(content.object_id.model)
domain = []
if node.act_id:
domain.append(('id','=',node.act_id))
# print "process read clause:",domain
ids = obj_class.search(cr, uid, domain, context=ctx)
ctx.update({'model': content.object_id.model})
s = obj_class.export_cal(cr, uid, ids, context=ctx)
return s
document_directory_content()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-12
View File
@@ -1,12 +0,0 @@
<?xml version="1.0"?>
<openerp>
<data>
<record model="document.directory.content.type" id="ics">
<field name="code">.ics</field>
<field name="name">ICS Calendar</field>
<field name="mimetype">text/calendar</field>
</record>
</data>
</openerp>
-19
View File
@@ -1,19 +0,0 @@
<?xml version="1.0"?>
<openerp>
<data noupdate="1">
<record model="document.directory" id="dir_calendars">
<field name="name">Meeting Calendars</field>
</record>
<record model="document.directory.content" id="dir_content_calendar">
<field name="name">Meeting Calendars</field>
<field name="suffix">meetings</field>
<field name="directory_id" ref="dir_calendars"/>
<field name="extension">.ics</field>
<field name="include_name" eval="False"/>
<field name="object_id" ref="crm.model_crm_meeting"/>
</record>
</data>
</openerp>
-18
View File
@@ -1,18 +0,0 @@
<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="view_document_directory_form_1">
<field name="name">document.directory</field>
<field name="model">document.directory</field>
<field name="type">form</field>
<field name="inherit_id" ref="document.view_document_directory_form"/>
<field name="arch" type="xml">
<field name="include_name" position="after">
<field name="object_id"/>
</field>
</field>
</record>
</data>
</openerp>
+48
View File
@@ -0,0 +1,48 @@
# Hindi translation for openobject-addons
# Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010
# This file is distributed under the same license as the openobject-addons package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2010.
#
msgid ""
msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2010-02-01 07:18+0000\n"
"Last-Translator: vir (Open ERP) <vir@tinyerp.com>\n"
"Language-Team: Hindi <hi@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-02-02 04:48+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: google_map
#: model:ir.actions.wizard,name:google_map.wizard_google_map
msgid "Launch Google Map"
msgstr "आरम्भ करना Google Map"
#. module: google_map
#: constraint:ir.ui.view:0
msgid "Invalid XML for View Architecture!"
msgstr ""
#. module: google_map
#: view:res.partner:0
#: view:res.partner.address:0
msgid "Street2 : "
msgstr "स्ट्रीट 2 "
#. module: google_map
#: model:ir.module.module,description:google_map.module_meta_information
msgid ""
"The module adds google map field in partner address\n"
"so that we can directly open google map from the\n"
"url widget."
msgstr ""
#. module: google_map
#: view:res.partner:0
#: view:res.partner.address:0
msgid "Map"
msgstr "नक़्शा"
+12 -12
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-12-11 13:55+0000\n"
"Last-Translator: Pieter J. Kersten (EduSense BV) <Unknown>\n"
"PO-Revision-Date: 2010-02-01 16:11+0000\n"
"Last-Translator: Jan Verlaan (Veritos) <Unknown>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2009-12-16 05:21+0000\n"
"X-Launchpad-Export-Date: 2010-02-02 04:48+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: hr
@@ -110,7 +110,7 @@ msgstr "Werkt van"
#. module: hr
#: model:ir.actions.act_window,name:hr.action2
msgid "Employee Hierarchy"
msgstr "Medewerkershiërarchie"
msgstr "Werknemershiërarchie"
#. module: hr
#: model:ir.ui.menu,name:hr.menu_hr_configuration
@@ -130,7 +130,7 @@ msgstr "Vrouw"
#. module: hr
#: view:hr.timesheet.group:0
msgid "Working Time Category"
msgstr "Werktijdcategorie"
msgstr "Werktijd categorie"
#. module: hr
#: model:ir.actions.act_window,name:hr.open_view_employee_tree
@@ -232,7 +232,7 @@ msgstr "Gehuwd"
#. module: hr
#: field:hr.timesheet,tgroup_id:0
msgid "Employee's timesheet group"
msgstr "Medewerkers urenstaatgroep"
msgstr "Werknemers urenstaatgroep"
#. module: hr
#: selection:hr.employee,gender:0
@@ -305,7 +305,7 @@ msgstr "Dag van de week"
#. module: hr
#: field:hr.employee,birthday:0
msgid "Birthday"
msgstr "Verjaardag"
msgstr "Geboortedatum"
#. module: hr
#: field:hr.employee,active:0
@@ -325,12 +325,12 @@ msgstr "Contractproces werknemer"
#. module: hr
#: model:process.node,note:hr.process_node_openerpuser0
msgid "Create OpenERP User"
msgstr "Maak een OpenERP gebruiker"
msgstr "Maak een OpenERP gebruiker aan"
#. module: hr
#: model:process.node,note:hr.process_node_employee0
msgid "Employee Complete Form"
msgstr "Maak formulier compleet"
msgstr "Maak werknemersformulier compleet"
#. module: hr
#: view:hr.department:0
@@ -356,7 +356,7 @@ msgstr "Startdatum"
#. module: hr
#: field:res.users,parent_id:0
msgid "Parent Users"
msgstr "Hoofdgebruikers"
msgstr "Bovenliggende gebruikers"
#. module: hr
#: field:hr.employee,address_id:0
@@ -383,7 +383,7 @@ msgstr "Persoonlijke gegevens"
msgid ""
"The Object name must start with x_ and not contain any special character !"
msgstr ""
"De objectnaam moet beginnen met x_ en mag geen speciale karakters bevatten !"
"De objectnaam moet beginnen met x_ en mag geen speciale tekens bevatten !"
#. module: hr
#: view:hr.timesheet:0
@@ -420,7 +420,7 @@ msgstr "Privé-adres"
#. module: hr
#: view:hr.department:0
msgid "department"
msgstr "Afdeling"
msgstr "afdeling"
#. module: hr
#: field:hr.employee,country_id:0
+15
View File
@@ -37,6 +37,21 @@
</field>
</record>
<record id="view_editable_expenses_tree" model="ir.ui.view">
<field name="name">hr.expense.expense.tree</field>
<field name="model">hr.expense.expense</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Expenses" editable="top">
<field name="date"/>
<field name="employee_id"/>
<field name="name"/>
<field name="ref"/>
<field name="amount"/>
<field name="state"/>
</tree>
</field>
</record>
<record id="view_expenses_form" model="ir.ui.view">
<field name="name">hr.expense.form</field>
+4 -4
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-08-28 16:01+0000\n"
"PO-Revision-Date: 2009-12-11 14:19+0000\n"
"Last-Translator: Pieter J. Kersten (EduSense BV) <Unknown>\n"
"PO-Revision-Date: 2010-02-01 16:15+0000\n"
"Last-Translator: Jan Verlaan (Veritos) <Unknown>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2009-12-16 05:19+0000\n"
"X-Launchpad-Export-Date: 2010-02-02 04:48+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: hr_expense
@@ -326,7 +326,7 @@ msgstr "Declaraties"
#. module: hr_expense
#: field:hr.expense.expense,date_valid:0
msgid "Date Validated"
msgstr "Datum akkoord:"
msgstr "Controledatum"
#. module: hr_expense
#: field:hr.expense.expense,account_move_id:0
+14 -1
View File
@@ -148,7 +148,20 @@
</field>
</record>
<!-- My leave dashboard -->
<record model="ir.ui.view" id="view_my_leave_board_tree">
<field name="name">hr.holidays.per.user.form</field>
<field name="model">hr.holidays.per.user</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="My Leaves" editable="top">
<field name="holiday_status"/>
<field name="max_leaves"/>
<field name="leaves_taken" />
<field name="remaining_leaves"/>
</tree>
</field>
</record>
<!-- <menuitem
name="Holidays Management"
@@ -19,6 +19,25 @@
</field>
</record>
<!-- Editable current timesheet used in dashboard-->
<record id="hr_timesheet_sheet_tree" model="ir.ui.view">
<field name="name">hr.timesheet.sheet.tree</field>
<field name="model">hr_timesheet_sheet.sheet</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Timesheets" editable="top">
<field name="user_id"/>
<field name="date_from"/>
<field name="date_to"/>
<field name="name"/>
<field name="total_attendance" groups="hr_attendance.group_hr_attendance"/>
<field name="total_timesheet"/>
<field name="total_difference" groups="hr_attendance.group_hr_attendance"/>
<field name="state"/>
</tree>
</field>
</record>
<record id="hr_timesheet_account_form" model="ir.ui.view">
<field name="name">hr.timesheet.account.form</field>
<field name="model">hr_timesheet_sheet.sheet.account</field>
@@ -46,7 +65,7 @@
</tree>
</field>
</record>
<!--
<!--
<record id="hr_timesheet_day_form" model="ir.ui.view">
<field name="name">hr.timesheet.day.form</field>
<field name="model">hr_timesheet_sheet.sheet.day</field>
@@ -61,7 +80,7 @@
</form>
</field>
</record>
<record id="hr_timesheet_day_tree" model="ir.ui.view">
<field name="name">hr.timesheet.day.tree</field>
<field name="model">hr_timesheet_sheet.sheet.day</field>
+2 -2
View File
@@ -790,7 +790,7 @@ class mrp_procurement(osv.osv):
'priority': fields.selection([('0','Not urgent'),('1','Normal'),('2','Urgent'),('3','Very Urgent')], 'Priority', required=True),
'date_planned': fields.datetime('Scheduled date', required=True),
'date_close': fields.datetime('Date Closed'),
'product_id': fields.many2one('product.product', 'Product', required=True),
'product_id': fields.many2one('product.product', 'Product', required=True, states={'draft':[('readonly',False)]}, readonly=True),
'product_qty': fields.float('Quantity', required=True, states={'draft':[('readonly',False)]}, readonly=True),
'product_uom': fields.many2one('product.uom', 'Product UoM', required=True, states={'draft':[('readonly',False)]}, readonly=True),
'product_uos_qty': fields.float('UoS Quantity', states={'draft':[('readonly',False)]}, readonly=True),
@@ -800,7 +800,7 @@ class mrp_procurement(osv.osv):
'bom_id': fields.many2one('mrp.bom', 'BoM', ondelete='cascade', select=True),
'close_move': fields.boolean('Close Move at end', required=True),
'location_id': fields.many2one('stock.location', 'Location', required=True),
'location_id': fields.many2one('stock.location', 'Location', required=True, states={'draft':[('readonly',False)]}, readonly=True),
'procure_method': fields.selection([('make_to_stock','from stock'),('make_to_order','on order')], 'Requisition Method', states={'draft':[('readonly',False)], 'confirmed':[('readonly',False)]},
readonly=True, required=True, help="If you encode manually a Requisition, you probably want to use" \
" a make to order method."),
+1 -2
View File
@@ -772,8 +772,7 @@
<field name="type">ir.actions.act_window</field>
<field name="res_model">mrp.procurement</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('state','=','confirmed')]</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem action="mrp_procurement_action3" id="menu_procurement_requisitions" parent="purchase.menu_procurement_management"
File diff suppressed because it is too large Load Diff
+7 -1
View File
@@ -254,7 +254,7 @@ class task(osv.osv):
def _default_project(self, cr, uid, context={}):
if 'project_id' in context and context['project_id']:
return context['project_id']
return int(context['project_id'])
return False
#_sql_constraints = [
@@ -527,6 +527,12 @@ class message(osv.osv):
'date': fields.date('Date'),
'user_id': fields.many2one('res.users', 'User'),
}
def _default_project(self, cr, uid, context={}):
if 'project_id' in context and context['project_id']:
return int(context['project_id'])
return False
_defaults = {
'project_id':_default_project}
message()
def _project_get(self, cr, uid, context={}):
+11 -28
View File
@@ -57,9 +57,9 @@
<button name="set_cancel" string="Cancel" type="object" states="open,pending" icon="gtk-cancel"/>
<button name="set_done" string="Done" type="object" states="open,pending" icon="gtk-jump-to"/>
<button name="reset_project" string="Reset as Project" type="object" states="template" icon="gtk-convert"/>
<button
<button
string="New Project Based on Template"
name="%(wizard_duplicate_template)d" type="action"
name="%(wizard_duplicate_template)d" type="action"
states="template" icon="gtk-new"/>
</group>
</page>
@@ -366,10 +366,10 @@
<field name="remaining_hours" widget="float_time" sum="Remaining Hours"/>
<field name="date_deadline"/>
<field name="type" groups="base.group_extended"/>
<button name="next_type"
states="draft,open,pending"
string="Change Stage"
type="object"
<button name="next_type"
states="draft,open,pending"
string="Change Stage"
type="object"
icon="gtk-go-forward"
groups="base.group_extended"
help="Change Type"/>
@@ -406,26 +406,6 @@
</field>
</record>
<record id="my_pending_task" model="ir.ui.view">
<field name="name">my.pending.task.tree</field>
<field name="model">project.task</field>
<field name="type">tree</field>
<field eval="2" name="priority"/>
<field name="arch" type="xml">
<tree colors="grey:state in ('cancelled','done');blue:remaining_hours&lt;0;red:bool(date_deadline) and (date_deadline&lt;current_date) and (state in ('draft','open'));black:state not in ('cancelled','done')" string="Tasks">
<field name="sequence" string="Seq."/>
<field name="name"/>
<field name="project_id"/>
<field name="delegated_user_id"/>
<field name="date_deadline"/>
<field name="remaining_hours" widget="float_time"/>
<field name="progress" widget="progressbar"/>
<field name="priority"/>
<field name="state"/>
</tree>
</field>
</record>
<record id="view_task_calendar" model="ir.ui.view">
<field name="name">project.task.calendar</field>
<field name="model">project.task</field>
@@ -478,7 +458,7 @@
<filter string="Pending" domain="[('state','=','pending')]" help="Pending Tasks" icon="terp-project"/>
<separator orientation="vertical"/>
<field name="name" select="1"/>
<field name="project_id" select="1" widget="selection">
<field name="project_id" select="1" widget="selection" default="context.get('project_id', False)">
<filter domain="[('manager_id','=',False)]" help="Unassigned Project" icon="terp-project"/>
</field>
<field name="user_id" select="1" widget="selection">
@@ -491,6 +471,9 @@
<filter string="By Project" icon="terp-project" domain="[]" context="{'group_by':'project_id'}"/>
<filter string="By Stage" icon="terp-project" domain="[]" context="{'group_by':'type'}"/>
<filter string="By State" icon="terp-project" domain="[]" context="{'group_by':'state'}"/>
<separator orientation="vertical"/>
<filter string="Start Date" icon="terp-project" domain="[]" context="{'group_by':'date_start'}"/>
<filter string="End Date" icon="terp-project" domain="[]" context="{'group_by':'date_end'}"/>
</group>
</search>
</field>
@@ -656,7 +639,7 @@
</record>
<record id="view_project_message_tree" model="ir.ui.view">
<field name="name">project.message.form</field>
<field name="name">project.message.tree</field>
<field name="model">project.message</field>
<field name="type">tree</field>
<field name="arch" type="xml">
@@ -1,8 +1,9 @@
<?xml version="1.0"?>
<openerp>
<data noupdate="1">
<record model="basic.calendar" id="base_calendar.basic_calendar2">
<field name="name">meeting_todo</field>
<field name="name">Meeting-Todo</field>
</record>
<record model="basic.calendar.lines" id="caldav.calendar_lines_todo">
@@ -81,6 +82,7 @@
<field name="type_id" ref="caldav.calendar_lines_todo" />
<field name="field_id" search="[('name','=','priority'),('model_id.model','=','project.task')]" />
<field name="fn">field</field>
<field name="mapping">{'1': '0', '2': '1', '3': '1','4': '1', '5': '2', '6': '3', '7': '3', '8': '3', '9': '4'}</field>
</record>
<record model="basic.calendar.fields" id="map_todo_13">
@@ -439,10 +441,5 @@
<field name="fn">field</field>
</record>
</data>
</openerp>

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