diff --git a/ext/custom-addons/cam_custom/cam_custom.py b/ext/custom-addons/cam_custom/cam_custom.py deleted file mode 100644 index 6a3ab475..00000000 --- a/ext/custom-addons/cam_custom/cam_custom.py +++ /dev/null @@ -1,148 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 20014-2016 Camadeus GmbH (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -from openerp import fields, models -from openerp import api -from openerp.tools.translate import _ -from openerp import SUPERUSER_ID -from openerp import tools -from lxml import etree - -DISABLED_MENUS = [ -] - -class ir_ui_menu(models.Model): - _inherit = 'ir.ui.menu' - - @tools.ormcache(skiparg=2) - def get_disabled_menu_ids(self, cr, uid, context=None): - data_obj = self.pool.get('ir.model.data') - - menu_ids = [] - for menu in DISABLED_MENUS: - module,xml_id = menu.split('.') - menu = data_obj.get_object(cr, uid, module, xml_id) - if menu: - menu_ids.append(menu.id) - return menu_ids - - def _filter_visible_menus(self, cr, uid, ids, context=None): - if uid != 1: - disabled_ids = self.get_disabled_menu_ids(cr, uid) - - ids = [id for id in ids if id not in disabled_ids] - - ids = super(ir_ui_menu, self)._filter_visible_menus(cr, uid, ids, context) - return ids - -class res_partner(models.Model): - _inherit = 'res.partner' - - @api.model - def fields_view_get_address(self, arch): - """ verhindert das Überschreiben von address_format """ - return arch - - -class mail_notification(models.Model): - _inherit = 'mail.notification' - - # override original function - def get_signature_footer(self, cr, uid, user_id, res_model=None, res_id=None, context=None, user_signature=True): - """ Format a standard footer for notification emails (such as pushed messages - notification or invite emails). - Format: -

--
- Administrator -

-
- Sent from Your Company using OpenERP. -
- """ - footer = "" - if not user_id: - return footer - - # add user signature - user = self.pool.get("res.users").browse(cr, SUPERUSER_ID, [user_id], context=context)[0] - if user_signature: - if user.signature: - signature = user.signature - else: - signature = "--
%s" % user.name - footer = tools.append_content_to_html(footer, signature, plaintext=False) - - # add company signature -# if user.company_id.website: -# website_url = ('http://%s' % user.company_id.website) if not user.company_id.website.lower().startswith(('http:', 'https:')) \ -# else user.company_id.website -# company = "%s" % (website_url, user.company_id.name) -# else: -# company = user.company_id.name -# sent_by = _('Sent by %(company)s using %(odoo)s') -# -# signature_company = '
%s' % (sent_by % { -# 'company': company, -# 'odoo': "Odoo" -# }) -# footer = tools.append_content_to_html(footer, signature_company, plaintext=False, container_tag='div') - - return footer - -# class product_product(osv.osv): -# _inherit = 'product.product' -# -# def name_get(self, cr, user, ids, context=None): -# if context is None: -# context = {} -# c = context.copy() -# c.update({'display_default_code': False}) -# return super(product_product, self).name_get(cr, user, ids, context=c) - -class sale_order_line(models.Model): - _inherit = 'sale.order.line' - - @api.onchange('name') - def onchange_name(self): - if self.name != False and self.product_id.id == False: - ir_values = self.pool.get('ir.values') - company = self.env['res.company'].search([], limit=1) - taxes_id = ir_values.get_default(self._cr, self._uid, 'product.template', 'taxes_id', company_id=company.id) - at = self.env['account.tax'].search([('id','=',isinstance(taxes_id, list) and taxes_id[0] or taxes_id)]) - self.tax_id = at - -class product_product(models.Model): - _inherit = 'product.product' - - def name_get(self, cr, user, ids, context=None): - """ beim Angebot die Nummer nicht in das Feld Bezeichnung übernehmen""" - if context is None: - context = {} - c = context.copy() - if c.get('partner_id', False): - if not c.get('quantity', False): - c.update({'display_default_code': False}) - return super(product_product, self).name_get(cr, user, ids, context=c) - -class res_country(models.Model): - _inherit = 'res.country' - - active = fields.Boolean('Aktiv', default=True) \ No newline at end of file diff --git a/ext/custom-addons/cam_custom/cam_custom_data.xml b/ext/custom-addons/cam_custom/cam_custom_data.xml deleted file mode 100644 index 3018e5f9..00000000 --- a/ext/custom-addons/cam_custom/cam_custom_data.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/ext/custom-addons/cam_custom/cam_custom_view.xml b/ext/custom-addons/cam_custom/cam_custom_view.xml deleted file mode 100644 index 8852021a..00000000 --- a/ext/custom-addons/cam_custom/cam_custom_view.xml +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - tree,kanban,form - - - - - - - - partner_section_form - res.partner - - - -
- - - -
-
- - -
- - - -
-
-
-
- - - - product_template_variant_kanban - product.template - - - - - - - - - product_template_custom_tree - product.template - - - - - - - - - - - - - - tree,form,kanban - - - - - product.supplierinfo.form.view - product.supplierinfo - - - - - - - - - - - - - Dokumente - ir.actions.act_window - ir.attachment - form - tree,form - -

- Click to create a new document. -

- The Documents repository gives you access to all attachments, such - as mails, project documents, invoices etc. -

-
-
- - -
-
diff --git a/ext/custom-addons/cam_custom/static/description/icon.png b/ext/custom-addons/cam_custom/static/description/icon.png deleted file mode 100644 index fd7ee3b9..00000000 Binary files a/ext/custom-addons/cam_custom/static/description/icon.png and /dev/null differ diff --git a/ext/custom-addons/cam_custom/static/src/img/favicon.ico b/ext/custom-addons/cam_custom/static/src/img/favicon.ico deleted file mode 100644 index 98f62754..00000000 Binary files a/ext/custom-addons/cam_custom/static/src/img/favicon.ico and /dev/null differ diff --git a/ext/custom-addons/cam_custom/static/src/img/logo.png b/ext/custom-addons/cam_custom/static/src/img/logo.png deleted file mode 100644 index eab51af1..00000000 Binary files a/ext/custom-addons/cam_custom/static/src/img/logo.png and /dev/null differ diff --git a/ext/custom-addons/cam_custom/views/custom_theme.xml b/ext/custom-addons/cam_custom/views/custom_theme.xml deleted file mode 100644 index 3e1a53aa..00000000 --- a/ext/custom-addons/cam_custom/views/custom_theme.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/ext/custom-addons/cam_customer_pricelist/__init__.py b/ext/custom-addons/cam_customer_pricelist/__init__.py deleted file mode 100644 index 9bf10d74..00000000 --- a/ext/custom-addons/cam_customer_pricelist/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 20014-2016 Camadeus GmbH (). -# -# 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 . -# -############################################################################## - -import cam_customer_pricelist - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/ext/custom-addons/cam_customer_pricelist/__openerp__.py b/ext/custom-addons/cam_customer_pricelist/__openerp__.py deleted file mode 100644 index 9455a401..00000000 --- a/ext/custom-addons/cam_customer_pricelist/__openerp__.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 20014-2016 Camadeus GmbH (). -# -# 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 . -# -############################################################################## - -{ - 'name': 'Camadeus Customer Pricelist', - 'category': 'Custom', - 'version': '1.0', - 'description': """Prices per user basis""", - 'author': 'Camadeus GmbH', - 'website': 'http://www.camadeus.at', - 'depends': ['product'], - 'data': [ - 'cam_customer_pricelist_view.xml', - 'cam_customer_pricelist_data.xml', - 'security/ir.model.access.csv', - ], - 'installable': True, - 'auto_install': False, -} - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/ext/custom-addons/cam_customer_pricelist/cam_customer_pricelist.py b/ext/custom-addons/cam_customer_pricelist/cam_customer_pricelist.py deleted file mode 100644 index baa6ff00..00000000 --- a/ext/custom-addons/cam_customer_pricelist/cam_customer_pricelist.py +++ /dev/null @@ -1,256 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 20014-2016 Camadeus GmbH (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -from openerp.osv import fields, osv -from openerp.tools.translate import _ -import openerp.addons.decimal_precision as dp -import datetime -import time - -class product_pricelist_item(osv.osv): - - _inherit = "product.pricelist.item" - - def _price_field_get(self, cr, uid, context=None): - pt = self.pool.get('product.price.type') - ids = pt.search(cr, uid, [], context=context) - result = [] - for line in pt.browse(cr, uid, ids, context=context): - result.append((line.id, line.name)) - - result.append((-1, _('Other Pricelist'))) - result.append((-2, _('Supplier Prices on the product form'))) - result.append((-3, _('Kundenbezogener Preis'))) - return result - - _columns = { - 'base': fields.selection(_price_field_get, 'Based on', required=True, size=-1, help="Base price for computation."), - } - -class product_pricelist_customer(osv.osv): - - _name = "product.pricelist.customer" - _inherit = ['mail.thread'] - - _columns = { - 'partner_id': fields.many2one('res.partner', 'Kunde', domain="[('customer','=',True)]", required=True), - 'product_id': fields.many2one('product.product', 'Produkt', required=True), - 'unit_price': fields.float('Preis pro Einheit', digits_compute=dp.get_precision('Product Price'), track_visibility='onchange'), - 'min_quantity': fields.integer('Mindestbestellmenge', track_visibility='onchange'), - 'date_start': fields.date('Begindatum', track_visibility='onchange'), - 'date_end': fields.date('Enddatum', track_visibility='onchange'), - } - -class product_pricelist(osv.osv): - - _inherit = "product.pricelist" - - def _price_rule_get_multi(self, cr, uid, pricelist, products_by_qty_by_partner, context=None): - context = context or {} - date = context.get('date') or time.strftime('%Y-%m-%d') - - products = map(lambda x: x[0], products_by_qty_by_partner) - currency_obj = self.pool.get('res.currency') - product_obj = self.pool.get('product.template') - product_uom_obj = self.pool.get('product.uom') - price_type_obj = self.pool.get('product.price.type') - - if not products: - return {} - - version = False - for v in pricelist.version_id: - if ((v.date_start is False) or (v.date_start <= date)) and ((v.date_end is False) or (v.date_end >= date)): - version = v - break - if not version: - raise osv.except_osv(_('Warning!'), _("At least one pricelist has no active version !\nPlease create or activate one.")) - categ_ids = {} - for p in products: - categ = p.categ_id - while categ: - categ_ids[categ.id] = True - categ = categ.parent_id - categ_ids = categ_ids.keys() - - is_product_template = products[0]._name == "product.template" - if is_product_template: - prod_tmpl_ids = [tmpl.id for tmpl in products] - prod_ids = [product.id for product in tmpl.product_variant_ids for tmpl in products] - else: - prod_ids = [product.id for product in products] - prod_tmpl_ids = [product.product_tmpl_id.id for product in products] - - # Load all rules - cr.execute( - 'SELECT i.id ' - 'FROM product_pricelist_item AS i ' - 'WHERE (product_tmpl_id IS NULL OR product_tmpl_id = any(%s)) ' - 'AND (product_id IS NULL OR (product_id = any(%s))) ' - 'AND ((categ_id IS NULL) OR (categ_id = any(%s))) ' - 'AND (price_version_id = %s) ' - 'ORDER BY sequence, min_quantity desc', - (prod_tmpl_ids, prod_ids, categ_ids, version.id)) - - item_ids = [x[0] for x in cr.fetchall()] - items = self.pool.get('product.pricelist.item').browse(cr, uid, item_ids, context=context) - - price_types = {} - - results = {} - for product, qty, partner in products_by_qty_by_partner: - results[product.id] = 0.0 - rule_id = False - price = False - - # Final unit price is computed according to `qty` in the `qty_uom_id` UoM. - # An intermediary unit price may be computed according to a different UoM, in - # which case the price_uom_id contains that UoM. - # The final price will be converted to match `qty_uom_id`. - qty_uom_id = context.get('uom') or product.uom_id.id - price_uom_id = product.uom_id.id - qty_in_product_uom = qty - if qty_uom_id != product.uom_id.id: - try: - qty_in_product_uom = product_uom_obj._compute_qty( - cr, uid, context['uom'], qty, product.uom_id.id or product.uos_id.id) - except except_orm: - # Ignored - incompatible UoM in context, use default product UoM - pass - - for rule in items: - if rule.min_quantity and qty_in_product_uom < rule.min_quantity: - continue - if is_product_template: - if rule.product_tmpl_id and product.id != rule.product_tmpl_id.id: - continue - if rule.product_id: - continue - else: - if rule.product_tmpl_id and product.product_tmpl_id.id != rule.product_tmpl_id.id: - continue - if rule.product_id and product.id != rule.product_id.id: - continue - - if rule.categ_id: - cat = product.categ_id - while cat: - if cat.id == rule.categ_id.id: - break - cat = cat.parent_id - if not cat: - continue - - if rule.base == -1: - if rule.base_pricelist_id: - price_tmp = self._price_get_multi(cr, uid, - rule.base_pricelist_id, [(product, - qty, False)], context=context)[product.id] - ptype_src = rule.base_pricelist_id.currency_id.id - price_uom_id = qty_uom_id - price = currency_obj.compute(cr, uid, - ptype_src, pricelist.currency_id.id, - price_tmp, round=False, - context=context) - elif rule.base == -2: - seller = False - for seller_id in product.seller_ids: - if (not partner) or (seller_id.name.id != partner): - continue - seller = seller_id - if not seller and product.seller_ids: - seller = product.seller_ids[0] - if seller: - qty_in_seller_uom = qty - seller_uom = seller.product_uom.id - if qty_uom_id != seller_uom: - qty_in_seller_uom = product_uom_obj._compute_qty(cr, uid, qty_uom_id, qty, to_uom_id=seller_uom) - price_uom_id = seller_uom - for line in seller.pricelist_ids: - if line.min_quantity <= qty_in_seller_uom: - price = line.price - elif rule.base == -3: - ppc_obj = self.pool.get('product.pricelist.customer') - ppc_ids = ppc_obj.search(cr, uid, [('partner_id','=',partner), ('product_id','=',product.id)], context=context) - - ppc_best = False - today = datetime.date.today() - for ppc in ppc_obj.browse(cr, uid, ppc_ids, context=context): - ppc_start = ppc.date_start or '0001-01-01' - ppc_start = datetime.datetime.strptime(ppc_start, '%Y-%m-%d').date() - ppc_end = ppc.date_end or '9999-01-01' - ppc_end = datetime.datetime.strptime(ppc_end, '%Y-%m-%d').date() - - # 1) Entweder es gibt noch kein best oder die best min_qty muss kleiner sein als die canditate min_qty - # 2) Die qty aus der Zeile muss größer sein als die canditate min_qty - # 3) Heute muss zwischen start und end datum der candite regel sein - if (not ppc_best or ppc_best.min_quantity < ppc.min_quantity) and qty_in_product_uom >= ppc.min_quantity and ppc_start <= today <= ppc_end: - ppc_best = ppc - - if ppc_best: - price = ppc_best.unit_price - else: - continue - - else: - if rule.base not in price_types: - price_types[rule.base] = price_type_obj.browse(cr, uid, int(rule.base)) - price_type = price_types[rule.base] - - # price_get returns the price in the context UoM, i.e. qty_uom_id - price_uom_id = qty_uom_id - price = currency_obj.compute( - cr, uid, - price_type.currency_id.id, pricelist.currency_id.id, - product_obj._price_get(cr, uid, [product], price_type.field, context=context)[product.id], - round=False, context=context) - - if price is not False: - price_limit = price - price = price * (1.0+(rule.price_discount or 0.0)) - if rule.price_round: - price = tools.float_round(price, precision_rounding=rule.price_round) - - convert_to_price_uom = (lambda price: product_uom_obj._compute_price( - cr, uid, product.uom_id.id, - price, price_uom_id)) - if rule.price_surcharge: - price_surcharge = convert_to_price_uom(rule.price_surcharge) - price += price_surcharge - - if rule.price_min_margin: - price_min_margin = convert_to_price_uom(rule.price_min_margin) - price = max(price, price_limit + price_min_margin) - - if rule.price_max_margin: - price_max_margin = convert_to_price_uom(rule.price_max_margin) - price = min(price, price_limit + price_max_margin) - - rule_id = rule.id - break - - # Final price conversion to target UoM - price = product_uom_obj._compute_price(cr, uid, price_uom_id, price, qty_uom_id) - - results[product.id] = (price, rule_id) - return results - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/ext/custom-addons/cam_customer_pricelist/cam_customer_pricelist_view.xml b/ext/custom-addons/cam_customer_pricelist/cam_customer_pricelist_view.xml deleted file mode 100644 index 711f5a09..00000000 --- a/ext/custom-addons/cam_customer_pricelist/cam_customer_pricelist_view.xml +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - product_pricelist_customer_form - product.pricelist.customer - -
- - - - - - - - - - -
- - -
-
-
-
- - - product_pricelist_customer_tree - product.pricelist.customer - - - - - - - - - - - - - - product_pricelist_customer_search - product.pricelist.customer - - - - - - - - - - - - - - - Kundenbez. Preise - ir.actions.act_window - product.pricelist.customer - form - tree,form - - - - Kundenbez. Preise - ir.actions.act_window - product.pricelist.customer - form - tree,form - [('product_id.product_tmpl_id', '=', active_id)] - {'default_product_id': active_id} - - - - Kundenbez. Preise - ir.actions.act_window - product.pricelist.customer - form - tree,form - [('partner_id', '=', active_id)] - {'default_partner_id': active_id} - - - - - - - product.template.product.form - product.template - - - -
- - 17 - - - - diff --git a/ext/custom-addons/cam_work_order/security/ir.model.access.csv b/ext/custom-addons/cam_work_order/security/ir.model.access.csv deleted file mode 100644 index e20db9d7..00000000 --- a/ext/custom-addons/cam_work_order/security/ir.model.access.csv +++ /dev/null @@ -1,5 +0,0 @@ -id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -modify_work_order,modify_order_sale_user,model_work_order,base.group_sale_salesman,1,1,1,1 -modify_work_order_line,modify_order_line_sale_user,model_work_order_line,base.group_sale_salesman,1,1,1,1 -access_work_category,work_category_user,model_work_category,base.group_sale_salesman,1,0,0,0 -modify_work_category,work_category_manager,model_work_category,base.group_sale_manager,1,1,1,1 diff --git a/ext/custom-addons/cam_work_order/static/description/icon.png b/ext/custom-addons/cam_work_order/static/description/icon.png deleted file mode 100644 index fd7ee3b9..00000000 Binary files a/ext/custom-addons/cam_work_order/static/description/icon.png and /dev/null differ diff --git a/ext/custom-addons/cam_max_width/__init__.py b/ext/custom-addons/dp_custom/__init__.py old mode 100755 new mode 100644 similarity index 98% rename from ext/custom-addons/cam_max_width/__init__.py rename to ext/custom-addons/dp_custom/__init__.py index 880f6149..34585445 --- a/ext/custom-addons/cam_max_width/__init__.py +++ b/ext/custom-addons/dp_custom/__init__.py @@ -19,5 +19,7 @@ # ############################################################################## +import models + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/ext/custom-addons/cam_custom/__openerp__.py b/ext/custom-addons/dp_custom/__openerp__.py similarity index 73% rename from ext/custom-addons/cam_custom/__openerp__.py rename to ext/custom-addons/dp_custom/__openerp__.py index c1759a24..ba9d8568 100644 --- a/ext/custom-addons/cam_custom/__openerp__.py +++ b/ext/custom-addons/dp_custom/__openerp__.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- ############################################################################## # -# OpenERP, Open Source Management Solution -# Copyright (C) 20014-2016 Camadeus GmbH (). +# datenpol gmbh +# Copyright (C) 2013-TODAY datenpol gmbh() # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -21,17 +21,16 @@ { - 'name': 'Camadeus Anpassungen', + 'name': 'datenpol Anpassungen', 'category': 'Custom', 'version': '1.0', 'description': """Individuelle Anpassungen""", - 'author': 'camadeus GmbH', - 'website': 'http://www.camadeus.at', - 'depends': ['sale','mail','product','account','knowledge'], - 'data': [ - 'cam_custom_view.xml', - 'cam_custom_data.xml', - 'views/custom_theme.xml', + 'author': 'datenpol gmbh', + 'website': 'http://www.datenpol.at', + 'depends': ['base'], + 'data': [ + 'data/dp_custom_data.xml', + 'views/dp_custom_view.xml', 'security/ir.model.access.csv', ], 'installable': True, diff --git a/ext/custom-addons/dp_custom/data/dp_custom_data.xml b/ext/custom-addons/dp_custom/data/dp_custom_data.xml new file mode 100644 index 00000000..458fac35 --- /dev/null +++ b/ext/custom-addons/dp_custom/data/dp_custom_data.xml @@ -0,0 +1,127 @@ + + + + + + + + + + Stück + + + + + 100 Stk. + + bigger + + + + + 1000 Stk. + + bigger + + + + + + Rolle(n) + + + + + + Satz + + + + + + Arbeitstag + + + + + + + mm + + smaller + + + + + Quadratm. + + + + + + + + + + + + Kubikm. + + + + Kubikm. + + + + + + + + Paket(e) + + + + + + + + Paar(e) + + + + + + + + + min + + + + + + Größe + radio + + + + + + + + + + + + + + diff --git a/ext/custom-addons/cam_custom/i18n/de.po b/ext/custom-addons/dp_custom/i18n/de.po similarity index 71% rename from ext/custom-addons/cam_custom/i18n/de.po rename to ext/custom-addons/dp_custom/i18n/de.po index fbbd795a..d975f048 100644 --- a/ext/custom-addons/cam_custom/i18n/de.po +++ b/ext/custom-addons/dp_custom/i18n/de.po @@ -6,8 +6,8 @@ msgid "" msgstr "" -"Project-Id-Version: camadeus\n" -"Report-Msgid-Bugs-To: Andreas Brueckl \n" +"Project-Id-Version: datenpol\n" +"Report-Msgid-Bugs-To: Andreas Brueckl \n" "POT-Creation-Date: 2014-09-23 16:26+0000\n" "PO-Revision-Date: 2014-08-14 16:14+0000\n" "Last-Translator: FULL NAME \n" @@ -18,8 +18,3 @@ msgstr "" "X-Launchpad-Export-Date: 2014-09-24 09:44+0000\n" "X-Generator: Launchpad (build 17196)\n" -#. module: cam_custom -#: field:product.product,default_code:0 -#: field:product.template,default_code:0 -msgid "Internal Reference" -msgstr "Artikelnummer" diff --git a/ext/custom-addons/cam_custom/__init__.py b/ext/custom-addons/dp_custom/models/__init__.py similarity index 91% rename from ext/custom-addons/cam_custom/__init__.py rename to ext/custom-addons/dp_custom/models/__init__.py index 8dbb873f..b32476c6 100644 --- a/ext/custom-addons/cam_custom/__init__.py +++ b/ext/custom-addons/dp_custom/models/__init__.py @@ -2,7 +2,7 @@ ############################################################################## # # OpenERP, Open Source Management Solution -# Copyright (C) 20014-2016 Camadeus GmbH (). +# Copyright (C) 2004-2010 Tiny SPRL (). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -19,7 +19,8 @@ # ############################################################################## -import cam_custom +import ir_ui_menu + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/ext/custom-addons/dp_custom/models/ir_ui_menu.py b/ext/custom-addons/dp_custom/models/ir_ui_menu.py new file mode 100644 index 00000000..d2652712 --- /dev/null +++ b/ext/custom-addons/dp_custom/models/ir_ui_menu.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# datenpol gmbh +# Copyright (C) 2013-TODAY datenpol gmbh() +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp import fields, models +from openerp import api +from openerp.tools.translate import _ +from openerp import SUPERUSER_ID +from openerp import tools +from lxml import etree + +DISABLED_MENUS = [ +] + +class ir_ui_menu(models.Model): + _inherit = 'ir.ui.menu' + + @tools.ormcache(skiparg=2) + def get_disabled_menu_ids(self, cr, uid, context=None): + data_obj = self.pool.get('ir.model.data') + + menu_ids = [] + for menu in DISABLED_MENUS: + module,xml_id = menu.split('.') + menu = data_obj.get_object(cr, uid, module, xml_id) + if menu: + menu_ids.append(menu.id) + return menu_ids + + def _filter_visible_menus(self, cr, uid, ids, context=None): + if uid != 1: + disabled_ids = self.get_disabled_menu_ids(cr, uid) + + ids = [id for id in ids if id not in disabled_ids] + + ids = super(ir_ui_menu, self)._filter_visible_menus(cr, uid, ids, context) + return ids diff --git a/ext/custom-addons/dp_custom/security/ir.model.access.csv b/ext/custom-addons/dp_custom/security/ir.model.access.csv new file mode 100644 index 00000000..08145a00 --- /dev/null +++ b/ext/custom-addons/dp_custom/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink + diff --git a/ext/custom-addons/dp_custom/static/description/icon.png b/ext/custom-addons/dp_custom/static/description/icon.png new file mode 100644 index 00000000..8387d765 Binary files /dev/null and b/ext/custom-addons/dp_custom/static/description/icon.png differ diff --git a/ext/custom-addons/dp_custom/static/src/img/favicon.ico b/ext/custom-addons/dp_custom/static/src/img/favicon.ico new file mode 100644 index 00000000..3c33e99b Binary files /dev/null and b/ext/custom-addons/dp_custom/static/src/img/favicon.ico differ diff --git a/ext/custom-addons/dp_custom/static/src/img/logo.png b/ext/custom-addons/dp_custom/static/src/img/logo.png new file mode 100644 index 00000000..8387d765 Binary files /dev/null and b/ext/custom-addons/dp_custom/static/src/img/logo.png differ diff --git a/ext/custom-addons/cam_customer_pricelist/cam_customer_pricelist_data.xml b/ext/custom-addons/dp_custom/views/dp_custom_view.xml similarity index 93% rename from ext/custom-addons/cam_customer_pricelist/cam_customer_pricelist_data.xml rename to ext/custom-addons/dp_custom/views/dp_custom_view.xml index aab2e2f0..b24d2621 100644 --- a/ext/custom-addons/cam_customer_pricelist/cam_customer_pricelist_data.xml +++ b/ext/custom-addons/dp_custom/views/dp_custom_view.xml @@ -1,5 +1,10 @@ + + + + + diff --git a/ext/custom-addons/dp_report/__init__.py b/ext/custom-addons/dp_report/__init__.py new file mode 100644 index 00000000..5305644d --- /dev/null +++ b/ext/custom-addons/dp_report/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import models \ No newline at end of file diff --git a/ext/custom-addons/dp_report/__openerp__.py b/ext/custom-addons/dp_report/__openerp__.py new file mode 100644 index 00000000..8b51bdec --- /dev/null +++ b/ext/custom-addons/dp_report/__openerp__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- + +{ + 'name': 'datepol Report Anpassungen', + 'category': 'Custom', + 'version': '1.0', + 'summary': """Individuelle Report Anpassungen""", + 'description': """Individuelle Report Anpassungen""", + 'author': 'datenpol gmbh', + 'website': 'http://www.datenpol.at', + 'depends': ['base'], + 'data': [ + # 'security/ir.model.access.csv', + 'views/layouts.xml', + 'views/saleorder.xml', + 'views/invoice.xml', + 'views/delivery.xml', + ], + # only loaded in demonstration mode + 'demo': [], + 'installable': True, + 'auto_install': False, +} diff --git a/ext/custom-addons/dp_report/i18n/de.po b/ext/custom-addons/dp_report/i18n/de.po new file mode 100644 index 00000000..6762beec --- /dev/null +++ b/ext/custom-addons/dp_report/i18n/de.po @@ -0,0 +1,19 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * dp_report +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo 10.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-10-12 09:17+0000\n" +"PO-Revision-Date: 2016-10-13 11:58+0000\n" +"Last-Translator: datenpol\n" +"Language-Team: German (http://www.transifex.com/odoo/odoo-9/language/de/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + + diff --git a/ext/custom-addons/dp_report/models/__init__.py b/ext/custom-addons/dp_report/models/__init__.py new file mode 100644 index 00000000..7c68785e --- /dev/null +++ b/ext/custom-addons/dp_report/models/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- \ No newline at end of file diff --git a/ext/custom-addons/cam_custom/security/ir.model.access.csv b/ext/custom-addons/dp_report/security/ir.model.access.csv similarity index 100% rename from ext/custom-addons/cam_custom/security/ir.model.access.csv rename to ext/custom-addons/dp_report/security/ir.model.access.csv diff --git a/ext/custom-addons/dp_report/views/delivery.xml b/ext/custom-addons/dp_report/views/delivery.xml new file mode 100644 index 00000000..8063c308 --- /dev/null +++ b/ext/custom-addons/dp_report/views/delivery.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/ext/custom-addons/dp_report/views/invoice.xml b/ext/custom-addons/dp_report/views/invoice.xml new file mode 100644 index 00000000..436df4e1 --- /dev/null +++ b/ext/custom-addons/dp_report/views/invoice.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/ext/custom-addons/dp_report/views/layouts.xml b/ext/custom-addons/dp_report/views/layouts.xml new file mode 100644 index 00000000..ecd180e0 --- /dev/null +++ b/ext/custom-addons/dp_report/views/layouts.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/ext/custom-addons/dp_report/views/saleorder.xml b/ext/custom-addons/dp_report/views/saleorder.xml new file mode 100644 index 00000000..4526105b --- /dev/null +++ b/ext/custom-addons/dp_report/views/saleorder.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/ext/custom-addons/mail_follower_control/README.md b/ext/custom-addons/mail_follower_control/README.md deleted file mode 100644 index 604def8e..00000000 --- a/ext/custom-addons/mail_follower_control/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# mail_follower_control - -This addon allows better control over follower handling for the chatter view. - -## Goals: - -- Checkbox "Do not automatically add as follower" for res.partner -- Set this new Checkbox to True by default -- Show the followers and additional recipients that will receive an email (notify always + email) -- Show a warning when adding additional recipients if the new recipient will not receive an email -- Show followers that will not receive Messages in Red -- Write the followers that received an email to mail.message in a new field to view them in message thread views - -- ToDo: Always show all the followers when writing a message in full message composer - - ToDo: Allow to remove some followers just for the current mail -- ToDo: BCC Field for all Chatter E-Mails - - ToDo: Do NOT add BCC Recipients as followers regardless of the checkbox "Do not automatically ad as follower" - - - diff --git a/ext/custom-addons/mail_follower_control/__init__.py b/ext/custom-addons/mail_follower_control/__init__.py deleted file mode 100644 index 9a1c6cfe..00000000 --- a/ext/custom-addons/mail_follower_control/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 20014-2016 Camadeus GmbH (). -# -# 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 . -# -############################################################################## -import mail_follower_control - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/ext/custom-addons/mail_follower_control/__openerp__.py b/ext/custom-addons/mail_follower_control/__openerp__.py deleted file mode 100644 index 02ece0ca..00000000 --- a/ext/custom-addons/mail_follower_control/__openerp__.py +++ /dev/null @@ -1,60 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 20014-2016 Camadeus GmbH (). -# -# 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 . -# -############################################################################## - - -{ - 'name': 'Mail Follower Control', - 'version': '1.0', - 'category': 'Custom', - 'author': 'DataDialog, Michael Karrer (original version for v7 by camadeus)', - 'website': 'http://www.datadialog.net', - 'installable': True, - 'description': """ -mail_follower_control -===================== - -This addon allows better control over follower handling for the chatter view. - -Goals: ------- - -- Checkbox "Do not automatically add as follower" for res.partner -- Set this new Checkbox to True by default -- Show the followers and additional recipients that will receive an email (notify always + email) -- Show a warning when adding additional recipients if the new recipient will not receive an email -- Show followers that will not receive Messages in Red -- Write the followers that received an email to mail.message in a new field to view them in message thread views - -- ToDo: Always show all the followers when writing a message in full message composer - - ToDo: Allow to remove some followers just for the current mail -- ToDo: BCC Field for all Chatter E-Mails - - ToDo: Do NOT add BCC Recipients as followers regardless of the checkbox "Do not automatically ad as follower" - - """, - 'depends': ['web', 'mail'], - 'qweb': [ - 'views/templates.xml', - ], - 'data': [ - 'views/views.xml', - ], - -} \ No newline at end of file diff --git a/ext/custom-addons/mail_follower_control/i18n/de.pot b/ext/custom-addons/mail_follower_control/i18n/de.pot deleted file mode 100644 index 8c23befd..00000000 --- a/ext/custom-addons/mail_follower_control/i18n/de.pot +++ /dev/null @@ -1,84 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * mail_follower_control -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 8.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-29 12:25+0000\n" -"PO-Revision-Date: 2015-04-29 12:25+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: mail_follower_control -#: field:res.partner,no_subscribe:0 -msgid "Do not add as Follower automatically" -msgstr "Nicht automatisch als Follower hinzufügen" - -#. module: mail_follower_control -#: model:ir.model,name:mail_follower_control.model_mail_thread -msgid "Email Thread" -msgstr "" - -#. module: mail_follower_control -#: model:ir.model,name:mail_follower_control.model_mail_compose_message -msgid "Email composition wizard" -msgstr "" - -#. module: mail_follower_control -#: model:ir.model,name:mail_follower_control.model_mail_wizard_invite -msgid "Invite wizard" -msgstr "" - -#. module: mail_follower_control -#: model:ir.model,name:mail_follower_control.model_mail_message -msgid "Message" -msgstr "Nachricht" - -#. module: mail_follower_control -#: view:mail.compose.message:mail_follower_control.mail_message_wizard_form_view -#: field:mail.compose.message,follower_ids:0 -msgid "Notified by eMail" -msgstr "Benachrichtigt per E-Mail" - -#. module: mail_follower_control -#: model:ir.model,name:mail_follower_control.model_mail_mail -msgid "Outgoing Mails" -msgstr "Ausgehende E-Mails" - -#. module: mail_follower_control -#: model:ir.model,name:mail_follower_control.model_res_partner -msgid "Partner" -msgstr "Kontakt" - -#. module: mail_follower_control -#: field:mail.message,notified_by_email_ids:0 -msgid "Partners notified by e-mail" -msgstr "Benachrichtigt per E-Mail" - -#. module: mail_follower_control -#: code:addons/mail_follower_control/mail_follower_control.py:261 -#, python-format -msgid "Some partners will not be notified by e-mail!" -msgstr "Einige Kontakte werden nicht per E-Mail benachrichtigt!" - -#. module: mail_follower_control -#: code:addons/mail_follower_control/mail_follower_control.py:262 -#, python-format -msgid "The following partners will not be notified by e-mail but they will still get a message in odoo (if they have a login):\n" -"\n" -"%s" -msgstr "Folgende Kontakte werden keine Benachrichtigung per E-Mail bekommen. Diese Kontakte bekommen jedoch zumindest eine Benachrichtigung in Ihren odoo Posteingang sofern sie sich einloggen können.: \n" -"\n" -"%s" - -#. module: mail_follower_control -#: view:mail.compose.message:mail_follower_control.mail_message_wizard_form_view -msgid "onchange_partner_ids(partner_ids, follower_ids, model, res_id, context)" -msgstr "" - diff --git a/ext/custom-addons/mail_follower_control/i18n/mail_follower_control.pot b/ext/custom-addons/mail_follower_control/i18n/mail_follower_control.pot deleted file mode 100644 index 3ec91c84..00000000 --- a/ext/custom-addons/mail_follower_control/i18n/mail_follower_control.pot +++ /dev/null @@ -1,82 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * mail_follower_control -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 8.0\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-29 12:25+0000\n" -"PO-Revision-Date: 2015-04-29 12:25+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: mail_follower_control -#: field:res.partner,no_subscribe:0 -msgid "Do not add as Follower automatically" -msgstr "" - -#. module: mail_follower_control -#: model:ir.model,name:mail_follower_control.model_mail_thread -msgid "Email Thread" -msgstr "" - -#. module: mail_follower_control -#: model:ir.model,name:mail_follower_control.model_mail_compose_message -msgid "Email composition wizard" -msgstr "" - -#. module: mail_follower_control -#: model:ir.model,name:mail_follower_control.model_mail_wizard_invite -msgid "Invite wizard" -msgstr "" - -#. module: mail_follower_control -#: model:ir.model,name:mail_follower_control.model_mail_message -msgid "Message" -msgstr "" - -#. module: mail_follower_control -#: view:mail.compose.message:mail_follower_control.mail_message_wizard_form_view -#: field:mail.compose.message,follower_ids:0 -msgid "Notified by eMail" -msgstr "" - -#. module: mail_follower_control -#: model:ir.model,name:mail_follower_control.model_mail_mail -msgid "Outgoing Mails" -msgstr "" - -#. module: mail_follower_control -#: model:ir.model,name:mail_follower_control.model_res_partner -msgid "Partner" -msgstr "" - -#. module: mail_follower_control -#: field:mail.message,notified_by_email_ids:0 -msgid "Partners notified by e-mail" -msgstr "" - -#. module: mail_follower_control -#: code:addons/mail_follower_control/mail_follower_control.py:261 -#, python-format -msgid "Some partners will not be notified by e-mail!" -msgstr "" - -#. module: mail_follower_control -#: code:addons/mail_follower_control/mail_follower_control.py:262 -#, python-format -msgid "The following partners will not be notified by e-mail but they will still get a message in odoo (if they have a login):\n" -"\n" -"%s" -msgstr "" - -#. module: mail_follower_control -#: view:mail.compose.message:mail_follower_control.mail_message_wizard_form_view -msgid "onchange_partner_ids(partner_ids, follower_ids, model, res_id, context)" -msgstr "" - diff --git a/ext/custom-addons/mail_follower_control/mail_follower_control.py b/ext/custom-addons/mail_follower_control/mail_follower_control.py deleted file mode 100644 index f0b0f377..00000000 --- a/ext/custom-addons/mail_follower_control/mail_follower_control.py +++ /dev/null @@ -1,296 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 20014-2016 Camadeus GmbH (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -from openerp.osv import fields, osv -from openerp.tools.translate import _ -from openerp import SUPERUSER_ID - - -class res_partner(osv.Model): - _inherit = "res.partner" - - _columns = { - 'no_subscribe': fields.boolean("Do not add as Follower automatically"), - } - _defaults = { - 'no_subscribe': True, - } - - def get_partners_notify_by_email(self, cr, uid, ids, message_type, context): - """ Return the list of partners which will be notified per mail, based on their preferences. - :param message_type: type of message - - """ - notify_pids = [] - user = self.pool.get('res.users').browse(cr,uid,uid) - for partner in self.browse(cr, uid, ids): - # Do not send to partners without email address defined - if not partner.email: - continue - # Partner does not want to receive any emails - if partner.notify_email == 'none': - continue - - # Exclude own partner - if partner.email == user.email: - continue - - notify_pids.append(partner.id) - return notify_pids -res_partner() - - -class mail_thread(osv.AbstractModel): - _inherit = "mail.thread" - - # Add data for JS to mark follower in red that will not receive an email - # - # FULL OVERWRITE of function to add 'notify_email': --> stupid but needed - # (this function will be called by the java script mail_followers.js to get the follower data) - # we need to know notify_email in the qweb template to mark followers in red that will not receive an email - # we alter mail_followers.js in addons-own/mail_follower_control/static/src/js/mail_follower_control.js to add - # notify_email to the display_followers function - def read_followers_data(self, cr, uid, follower_ids, context=None): - result = [] - technical_group = self.pool.get('ir.model.data').get_object(cr, uid, 'base', 'group_no_one', context=context) - for follower in self.pool.get('res.partner').browse(cr, uid, follower_ids, context=context): - is_editable = uid in map(lambda x: x.id, technical_group.users) - is_uid = uid in map(lambda x: x.id, follower.user_ids) - data = (follower.id, - follower.name, - {'is_editable': is_editable, 'is_uid': is_uid, 'notify_email': follower.notify_email, }, - ) - result.append(data) - return result - - # Do not subscript followers with no_subscribe=True (except force_subscription is in the context) - # - # message_post will call message_subscribe to add followers - # we alter this method to take our new field no_subscribe into account - def message_subscribe(self, cr, uid, ids, partner_ids, subtype_ids=None, context=None): - if context is None: - context = {} - - # 1.) Filter all mail_post_autofollow_partner_ids if they exists to respect the no_subscribe setting - if context.get('mail_post_autofollow') and context.get('mail_post_autofollow_partner_ids'): - context['mail_post_autofollow_partner_ids'] = self.pool.get('res.partner').search(cr, uid, [ - ('no_subscribe', '=', False), - ('id', 'in', context.get('mail_post_autofollow_partner_ids'), ) - ]) - - # 2.) Filter partner_ids: to respect the no_subscribe setting (except 'force_subscription' is set) - # HINT: force_subscription is set by java script to allow adding a follower with no_subscribe=True by the - # add followers links in the chatter window - without this the follower could not be added by any method. - if not context.get('force_subscription'): - partner_ids = self.pool.get('res.partner').search(cr, uid, [ - ('no_subscribe', '=', False), - ('id', 'in', partner_ids), - ]) - - # Remove force_subscription from the context after the filtering is done - if context.get('force_subscription'): - context.pop('force_subscription') - - res = super(mail_thread, self).message_subscribe(cr, uid, ids, partner_ids, subtype_ids, context) - return res -mail_thread() - - -# Allow to add followers with no_subscribe=True at least with the invite wizard (Add Followers Link) -class invite_wizard(osv.osv_memory): - _inherit = 'mail.wizard.invite' - - # Add force Subscription to the context so that followers can be added even if no_subscribe=True - def add_followers(self, cr, uid, ids, context=None): - if context is None: - context = {} - context['force_subscription'] = True - - return super(invite_wizard, self).add_followers(cr, uid, ids, context) -invite_wizard() - - -class mail_message(osv.Model): - _inherit = "mail.message" - # Add field notified_by_email_ids to store this data from mail.mail if a mail was sent - # WARNING: do not use relation= for old style many2many fields - will be ignored!!!! - # WARNING: always use a custom name for the relation table e.g.: mail_message_res_partner_notified_by_email_rel - # if you use none the system may generate one that is already in use and both fields will have - # the related fields - which is very hard to debug. - _columns = { - 'notified_by_email_ids': fields.many2many('res.partner', - 'mail_message_res_partner_notified_by_email_rel', - 'mail_message_id', 'res_partner_id', - string='Partners notified by e-mail'), - } - - # Update Dict for JS rendering of messages with field notified_by_email_ids - # HINT: _message_read_dict returns a dict representation of the message. This representation is - # used in the JS client code, to display the messages. Partners and - # attachments related stuff will be done in post-processing in batch. - def _message_read_dict(self, cr, uid, message, parent_id=False, context=None): - res = super(mail_message, self)._message_read_dict(cr, uid, message, parent_id, context) - - # ToDo: Create a dict wich holds name and id for each id in ids (partner) - needed in template! - vals = {'notified_by_email_ids': [[p.id, p.name] for p in message.notified_by_email_ids]} - # print 'vals: %s' % vals - res.update(vals) - return res - -mail_message() - - -# Check Receipients while composing a mail (Full composing dialog not quick dialogue) and give a warning -# if the added recipients will not receive an e-mail by setting -class mail_compose_message(osv.TransientModel): - _inherit = "mail.compose.message" - - _columns = { - 'follower_ids': fields.many2many('res.partner', - 'mail_compose_message_followers_rel', - 'wizard_id', - 'partner_id', - string='Notified by eMail', readonly=True), - } - - # This will recalculate/set the field follower_ids for the current mail_compose_message (which is a transient model - # so its not a problem to recalculate it here on the fly) - def get_record_data(self, cr, uid, values, context=None): - - res = super(mail_compose_message, self).get_record_data(cr, uid, values, context) - - # if this message belongs to a resource add follower ids that will receieve an email to the result dict - if values.get('model') and values.get('res_id'): - p_obj = self.pool.get('res.partner') - fol_obj = self.pool.get("mail.followers") - - # get all followers for the current resource (= model and res_id) - fol_ids = fol_obj.search(cr, SUPERUSER_ID, [ - ('res_model', '=', values.get('model')), - ('res_id', '=', values.get('res_id')), - ('subtype_ids', 'in', 1) # ID 1 is always the subtyp "Discussion" - ], context=context) - - # get the res.partner objects of the followers (mail.followers) of this resource - followers = set(fo.partner_id for fo in fol_obj.browse(cr, SUPERUSER_ID, fol_ids, context=context)) - - # get the res.partner ids for the objects in followers - follower_ids = [f.id for f in followers] - - # filter out all followers without an email or with notify_email set to none - notify_pids = p_obj.get_partners_notify_by_email(cr, uid, follower_ids, 'comment', context) - - # add follower_ids tp the result dict - # This result dict is used by the ??? - I DONT KNOW TILL NOW! - res.update({'follower_ids': notify_pids}) - - return res - - def onchange_partner_ids(self, cr, uid, ids, partner_ids, follower_ids, model, res_id, context=None): - - # We unwrap the variable partner_ids which most likely has a form of e.g. [(6, 0, [7]), ] - # see https://doc.odoo.com/v6.0/developer/2_5_Objects_Fields_Methods/methods.html/#osv.osv.osv.write - p_ids = [] - # Unwrap: Only take the first list or tuble - if isinstance(partner_ids, (list, tuple)): - partner_ids = partner_ids[0] - # 4 means "link to existing record with id = ID" so we add new links which in fact is nonsense since - # p_ids is empty at this time anyway. - if isinstance(partner_ids, (list, tuple)) and partner_ids[0] == 4 and len(partner_ids) == 2: - p_ids.add(partner_ids[1]) - # 6 means "replace the list of linked IDs" so we replace the partner ids - if isinstance(partner_ids, (list, tuple)) and partner_ids[0] == 6 and len(partner_ids) == 3 and partner_ids[2]: - p_ids = partner_ids[2] - elif isinstance(partner_ids, (int, long)): - p_ids.add(partner_ids) - else: - pass # we do not manage anything else - - p_obj = self.pool.get('res.partner') - - # get all partners that have an email and also notify_email is not none - parterns_to_notify = p_obj.get_partners_notify_by_email(cr, uid, p_ids, "comment", context) - - # find any partners in p_ids that are not in parterns_to_notify - partners_not_to_notify = [p for p in p_ids if p not in parterns_to_notify] - - # get the names of the partners that will not get an email - partners = p_obj.name_get(cr, uid, partners_not_to_notify, context=context) - partner_names = [p[1] for p in partners] - - # Update follower_ids - # Update the values for the wizzard (found in addons/email_template/wizard/mail_compose_message.py) - # HINT: There was no docu in how to update the wizard but at least i found an example - i have no idea - # If this is the same for all wizards - p_obj = self.pool.get('res.partner') - fol_obj = self.pool.get("mail.followers") - - # get all followers for the current resource (= model and res_id) - fol_ids = fol_obj.search(cr, SUPERUSER_ID, [ - ('res_model', '=', model), - ('res_id', '=', res_id), - ('subtype_ids', 'in', 1) # ID 1 is always the subtyp "Discussion" - ], context=context) - - # get the res.partner objects of the followers (mail.followers) of this resource - followers = set(fo.partner_id for fo in fol_obj.browse(cr, SUPERUSER_ID, fol_ids, context=context)) - - # get the res.partner ids for the objects in followers - follower_ids = [f.id for f in followers] - - # filter out all followers without an email or with notify_email set to none - follower_partner_ids = p_obj.get_partners_notify_by_email(cr, uid, follower_ids, 'comment', context) - - # update the follower_ids to reflect the newly added partners to notify by mail if any - values = {'follower_ids': list(set(follower_partner_ids + parterns_to_notify)), } - - - # Warn if any partners found that will not get an email - if partner_names: - warning = { - 'title': _('Some partners will not be notified by e-mail!'), - 'message': _('The following partners will not be notified by e-mail but they will still get a message in odoo (if they have a login):\n\n%s') % ('\n'.join(partner_names)) - } - res = {'warning': warning, 'value': values} - else: - res = {'value': values} - return res -mail_compose_message() - - - - -# This will update the new custom field mail_sent for the model mail.notification - seems useless ... because -# it will be true if the smtp server takes over the mail which des not guarantee sending was successful -class mail_mail(osv.Model): - _inherit = 'mail.mail' - - def _postprocess_sent_message(self, cr, uid, mail, context=None, mail_sent=True): - - # Copy the notified_by_email_ids to the mail.message - # Hint: It seems that notified_by_email_ids of mail.message is already there but in the state of the initial - # setting so we have to update it here after we send the message to inculde the right notified_by_email_ids - if mail_sent and mail.recipient_ids and mail.mail_message_id: - mail.mail_message_id.notified_by_email_ids = mail.recipient_ids - - - return super(mail_mail, self)._postprocess_sent_message(cr=cr, uid=uid, mail=mail, - context=context, mail_sent=mail_sent) diff --git a/ext/custom-addons/mail_follower_control/static/src/css/mail_follower_control.css b/ext/custom-addons/mail_follower_control/static/src/css/mail_follower_control.css deleted file mode 100644 index 31c40dcf..00000000 --- a/ext/custom-addons/mail_follower_control/static/src/css/mail_follower_control.css +++ /dev/null @@ -1,15 +0,0 @@ - -.oe_follower_red { - color: red !important; -} - -.oe_follower_orange { - color: orange !important; -} - -.oe_msg_notify_mail { - margin-left: 4px; - overflow: hidden; - margin-top: -4px; - font-size: 11px; -} \ No newline at end of file diff --git a/ext/custom-addons/mail_follower_control/static/src/js/mail_follower_control.js b/ext/custom-addons/mail_follower_control/static/src/js/mail_follower_control.js deleted file mode 100644 index 48789eb0..00000000 --- a/ext/custom-addons/mail_follower_control/static/src/js/mail_follower_control.js +++ /dev/null @@ -1,82 +0,0 @@ -openerp.mail_follower_control = function (session) { - - session.mail_followers.Followers = session.mail_followers.Followers.extend({ - - /** FULL OVERWRITE: because we need to add more data to the records: 'notify_email' - * Do not forget to update the python function "read_followers_data" in "mail_follower_control.py" - * ("read_followers_data" is called by JS function "fetch_followers" which then calls "display_followers") - * - * */ - display_followers: function (records) { - var self = this; - this.message_is_follower = false; - console.log('RECORDS:'); - console.log(records); - this.followers = records || this.followers; - // clean and display title - var node_user_list = this.$('.oe_follower_list').empty(); - this.$('.oe_follower_title').html(this._format_followers(this.followers.length)); - self.message_is_follower = _.indexOf(this.followers.map(function (rec) { return rec[2]['is_uid']}), true) != -1; - // truncate number of displayed followers - var truncated = this.followers.slice(0, this.displayed_nb); - _(truncated).each(function (record) { - partner = { - 'id': record[0], - 'name': record[1], - 'is_uid': record[2]['is_uid'], - 'is_editable': record[2]['is_editable'], - 'notify_email': record[2]['notify_email'], - 'avatar_url': session.mail.ChatterUtils.get_image(self.session, 'res.partner', 'image_small', record[0]) - }; - console.log('partner'); - console.log(partner); - $(session.web.qweb.render('mail.followers.partner', {'record': partner, 'widget': self})).appendTo(node_user_list); - // On mouse-enter it will show the edit_subtype pencil. - if (partner.is_editable) { - self.$('.oe_follower_list').on('mouseenter mouseleave', function(e) { - self.$('.oe_edit_subtype').toggleClass('oe_hidden', e.type == 'mouseleave'); - self.$('.oe_follower_list').find('.oe_partner').toggleClass('oe_partner_name', e.type == 'mouseenter'); - }); - } - }); - // FVA note: be sure it is correctly translated - if (truncated.length < this.followers.length) { - $(session.web.qweb.render('mail.followers.show_more', {'number': (this.followers.length - truncated.length)} )).appendTo(node_user_list); - } - }, - - do_follow: function () { - /** - * Add this context value to force subscription - */ - var context = new session.web.CompoundContext(this.build_context(), {'force_subscription': 1}); - console.log('do_follow'); - - this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], [this.session.uid], undefined, context]) - .then(this.proxy('read_value')); - - _.each(this.$('.oe_subtype_list input'), function (record) { - $(record).attr('checked', 'checked'); - }); - - } - - }); - - // HINT: Add recipient_ids to MessageCommon - message common is extended by: - // mail.ThreadMessage AND - // mail.ThreadComposeMessage so both should have recipients_ids now for ThreadComposeMessage it will be - // useless for now because this is updated after we post the message. - // session.mail.MessageCommon = session.mail.MessageCommon.extend({ - // HINT2: mail.MessageCommon did not work ?!? - openerp.mail.ThreadMessage = openerp.mail.ThreadMessage.extend({ - template: 'mail.thread.message', - - init: function (parent, datasets, options) { - this._super(parent, datasets, options); - - this.notified_by_email_ids = datasets.notified_by_email_ids || []; - } - }); - -}; diff --git a/ext/custom-addons/mail_follower_control/views/templates.xml b/ext/custom-addons/mail_follower_control/views/templates.xml deleted file mode 100644 index 99443360..00000000 --- a/ext/custom-addons/mail_follower_control/views/templates.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - -
- By e-mail to: - - - - - - - - - - , - - - -
-
-
- - - - - - - - -
diff --git a/ext/custom-addons/mail_follower_control/views/views.xml b/ext/custom-addons/mail_follower_control/views/views.xml deleted file mode 100644 index 3c6455b7..00000000 --- a/ext/custom-addons/mail_follower_control/views/views.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - chatterimprovments.res_partner.form - res.partner - - - - - - - - - - - chatterimprovments.mail_message_wizard.form - mail.compose.message - - - - - - - - - - onchange_partner_ids(partner_ids, follower_ids, model, res_id, context) - - - - - - - mail_view_message_form_extended - mail.message - - - - - - - - - - - - diff --git a/ext/custom-addons/oerp_no_phoning_home/README.md b/ext/custom-addons/oerp_no_phoning_home/README.md deleted file mode 100644 index 54a855dd..00000000 --- a/ext/custom-addons/oerp_no_phoning_home/README.md +++ /dev/null @@ -1,15 +0,0 @@ -Stop Phoning Home Feature from OpenERP -====================================== - -Note: ------ - -* For V8 checkout master branch -* for V7 checkout 7.0 branch - -Remove Few Phoning home feature effect from Core OpenERP. ---------------------------------------------------------- - -* Stop Scheduler for Sending Company/Database information to Odoo/OpenERP company. -* Remove ``Your OpenERP is not supported.``. -* Change sequence of the ``Apps`` and ``Update`` menu and arrange ``Installed Modules`` at first position. \ No newline at end of file diff --git a/ext/custom-addons/oerp_no_phoning_home/__init__.py b/ext/custom-addons/oerp_no_phoning_home/__init__.py deleted file mode 100644 index fc631b41..00000000 --- a/ext/custom-addons/oerp_no_phoning_home/__init__.py +++ /dev/null @@ -1 +0,0 @@ -import mail diff --git a/ext/custom-addons/oerp_no_phoning_home/__openerp__.py b/ext/custom-addons/oerp_no_phoning_home/__openerp__.py deleted file mode 100644 index eb8dab59..00000000 --- a/ext/custom-addons/oerp_no_phoning_home/__openerp__.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8 -*- -{ - 'name': 'Stop Phoning Home', - 'version': '1.0', - 'category': '', - "sequence": 14, - 'complexity': "easy", - 'category': 'Hidden', - 'description': """ - Remove Few Phoning home feature effect from Core OpenERP. - """, - 'author': 'Ruchir Shukla', - 'website': 'www.bizzappdev.com', - 'depends': ["mail",'web'], - 'init_xml': [], - 'data': [ - "base_view.xml", - "mail_data.xml", - ], - 'demo_xml': [], - 'test': [ - ], - 'qweb' : [ - "static/src/xml/base.xml", - ], - 'installable': True, - 'auto_install': True, -} -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/ext/custom-addons/oerp_no_phoning_home/base_view.xml b/ext/custom-addons/oerp_no_phoning_home/base_view.xml deleted file mode 100644 index a9449c48..00000000 --- a/ext/custom-addons/oerp_no_phoning_home/base_view.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/ext/custom-addons/oerp_no_phoning_home/mail.py b/ext/custom-addons/oerp_no_phoning_home/mail.py deleted file mode 100644 index bb0980a1..00000000 --- a/ext/custom-addons/oerp_no_phoning_home/mail.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- - -from openerp.osv import osv -import logging - -_logger = logging.getLogger(__name__) - -from openerp.tools import config - -config['publisher_warranty_url'] = '' - - -class publisher_warranty_contract(osv.osv): - _inherit = 'publisher_warranty.contract' - - def update_notification(self, cr, uid, ids, cron_mode=True, - context=None): - - _logger.info("NO More Spying Stuff") - - return True - - -publisher_warranty_contract() - diff --git a/ext/custom-addons/oerp_no_phoning_home/mail_data.xml b/ext/custom-addons/oerp_no_phoning_home/mail_data.xml deleted file mode 100644 index 5315dc4b..00000000 --- a/ext/custom-addons/oerp_no_phoning_home/mail_data.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - Update Notification - - - 1 - weeks - -1 - - - - - 1000 - - - - - diff --git a/ext/custom-addons/oerp_no_phoning_home/static/src/img/icon.png b/ext/custom-addons/oerp_no_phoning_home/static/src/img/icon.png deleted file mode 100644 index 9ad73d74..00000000 Binary files a/ext/custom-addons/oerp_no_phoning_home/static/src/img/icon.png and /dev/null differ diff --git a/ext/custom-addons/oerp_no_phoning_home/static/src/js/announcement.js b/ext/custom-addons/oerp_no_phoning_home/static/src/js/announcement.js deleted file mode 100644 index 0d7e1fde..00000000 --- a/ext/custom-addons/oerp_no_phoning_home/static/src/js/announcement.js +++ /dev/null @@ -1,13 +0,0 @@ -openerp.oerp_no_phoning_home = function(instance) { - instance.web.WebClient.include({ - show_application: function() { - return $.when(this._super.apply(this, arguments)); - }, - _ab_location: function(dbuuid) { - // return _.str.sprintf('https://services.openerp.com/openerp-enterprise/ab/css/%s.css', dbuuid); - }, - show_annoucement_bar: function() { - return; - } - }); -}; diff --git a/ext/custom-addons/oerp_no_phoning_home/static/src/xml/base.xml b/ext/custom-addons/oerp_no_phoning_home/static/src/xml/base.xml deleted file mode 100644 index 97da789c..00000000 --- a/ext/custom-addons/oerp_no_phoning_home/static/src/xml/base.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - diff --git a/ext/custom-addons/sale_order_optional/__init__.py b/ext/custom-addons/sale_order_optional/__init__.py deleted file mode 100755 index 24bf354f..00000000 --- a/ext/custom-addons/sale_order_optional/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 20014-2016 Camadeus GmbH (). -# -# 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 . -# -############################################################################## - -import sale_order_optional diff --git a/ext/custom-addons/sale_order_optional/__openerp__.py b/ext/custom-addons/sale_order_optional/__openerp__.py deleted file mode 100755 index c7c2ba19..00000000 --- a/ext/custom-addons/sale_order_optional/__openerp__.py +++ /dev/null @@ -1,42 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 20014-2016 Camadeus GmbH (). -# -# 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 . -# -############################################################################## - -{ - 'name': "Optional Lines for Sale Orders", - 'version': "1.0", - 'category': "Sales", - 'description': """ - This addon adds optional sale order lines. - """, - 'author': "Camadeus GmbH", - 'website': "http://www.camadeus.at", - 'css': [], - 'images': [], - 'depends': ['sale'], - 'data': ['sale_order_optional_view.xml', - 'sale_order_optional_data.xml', - ], - 'installable': True, - 'auto_install': False, - 'application': False, -} - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/ext/custom-addons/sale_order_optional/sale_order_optional.py b/ext/custom-addons/sale_order_optional/sale_order_optional.py deleted file mode 100644 index dd997a96..00000000 --- a/ext/custom-addons/sale_order_optional/sale_order_optional.py +++ /dev/null @@ -1,134 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 20014-2016 Camadeus GmbH (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -from openerp.osv import fields, osv -import openerp.addons.decimal_precision as dp - -class sale_order(osv.osv): - _inherit = "sale.order" - - def _amount_line_tax(self, cr, uid, line, context=None): - val = 0.0 - if not line.optional: - for c in self.pool.get('account.tax').compute_all(cr, uid, line.tax_id, line.price_unit * (1-(line.discount or 0.0)/100.0), line.product_uom_qty, line.product_id, line.order_id.partner_id)['taxes']: - val += c.get('amount', 0.0) - return val - - def _amount_all(self, cr, uid, ids, field_name, arg, context=None): - cur_obj = self.pool.get('res.currency') - res = {} - for order in self.browse(cr, uid, ids, context=context): - res[order.id] = { - 'amount_untaxed': 0.0, - 'amount_tax': 0.0, - 'amount_total': 0.0, - } - val = val1 = 0.0 - cur = order.pricelist_id.currency_id - for line in order.order_line: - val1 += line.price_subtotal - val += self._amount_line_tax(cr, uid, line, context=context) - res[order.id]['amount_tax'] = cur_obj.round(cr, uid, cur, val) - res[order.id]['amount_untaxed'] = cur_obj.round(cr, uid, cur, val1) - res[order.id]['amount_total'] = res[order.id]['amount_untaxed'] + res[order.id]['amount_tax'] - return res - - def _amount_all_wrapper(self, cr, uid, ids, field_name, arg, context=None): - """ Wrapper because of direct method passing as parameter for function fields """ - return self._amount_all(cr, uid, ids, field_name, arg, context=context) - - def _get_order(self, cr, uid, ids, context=None): - result = {} - for line in self.pool.get('sale.order.line').browse(cr, uid, ids, context=context): - result[line.order_id.id] = True - return result.keys() - - _columns = { - 'amount_untaxed': fields.function(_amount_all_wrapper, digits_compute=dp.get_precision('Account'), string='Untaxed Amount', - store={ - 'sale.order': (lambda self, cr, uid, ids, c={}: ids, ['order_line'], 10), - 'sale.order.line': (_get_order, ['price_unit', 'tax_id', 'discount', 'product_uom_qty'], 10), - }, - multi='sums', help="The amount without tax.", track_visibility='always'), - 'amount_tax': fields.function(_amount_all_wrapper, digits_compute=dp.get_precision('Account'), string='Taxes', - store={ - 'sale.order': (lambda self, cr, uid, ids, c={}: ids, ['order_line'], 10), - 'sale.order.line': (_get_order, ['price_unit', 'tax_id', 'discount', 'product_uom_qty'], 10), - }, - multi='sums', help="The tax amount."), - 'amount_total': fields.function(_amount_all_wrapper, digits_compute=dp.get_precision('Account'), string='Total', - store={ - 'sale.order': (lambda self, cr, uid, ids, c={}: ids, ['order_line'], 10), - 'sale.order.line': (_get_order, ['price_unit', 'tax_id', 'discount', 'product_uom_qty'], 10), - }, - multi='sums', help="The total amount."), - } - -class sale_order_line(osv.osv): - _inherit = 'sale.order.line' - - def _fnct_line_invoiced(self, cr, uid, ids, field_name, args, context=None): - res = dict.fromkeys(ids, False) - for this in self.browse(cr, uid, ids, context=context): - res[this.id] = this.invoice_lines and \ - all(iline.invoice_id.state != 'cancel' for iline in this.invoice_lines) or \ - this.optional - return res - - def _order_lines_from_invoice(self, cr, uid, ids, context=None): - # direct access to the m2m table is the less convoluted way to achieve this (and is ok ACL-wise) - cr.execute("""SELECT DISTINCT sol.id FROM sale_order_invoice_rel rel JOIN - sale_order_line sol ON (sol.order_id = rel.order_id) - WHERE rel.invoice_id = ANY(%s)""", (list(ids),)) - return [i[0] for i in cr.fetchall()] - - def _amount_line(self, cr, uid, ids, field_name, arg, context=None): - tax_obj = self.pool.get('account.tax') - cur_obj = self.pool.get('res.currency') - res = {} - if context is None: - context = {} - for line in self.browse(cr, uid, ids, context=context): - if not line.optional: - price = line.price_unit * (1 - (line.discount or 0.0) / 100.0) - taxes = tax_obj.compute_all(cr, uid, line.tax_id, price, line.product_uom_qty, line.product_id, line.order_id.partner_id) - cur = line.order_id.pricelist_id.currency_id - res[line.id] = cur_obj.round(cr, uid, cur, taxes['total']) - else: - res[line.id] = 0 - return res - - _columns = { - 'invoiced': fields.function(_fnct_line_invoiced, string='Invoiced', type='boolean', - store={ - 'account.invoice': (_order_lines_from_invoice, ['state'], 10), - 'sale.order.line': (lambda self,cr,uid,ids,ctx=None: ids, ['invoice_lines'], 10) - }), - 'price_subtotal': fields.function(_amount_line, string='Subtotal', digits_compute= dp.get_precision('Account')), - 'optional': fields.boolean('Optional'), - } - - def _prepare_order_line_invoice_line(self, cr, uid, line, account_id=False, context=None): - if not line.optional: - return super(sale_order_line, self)._prepare_order_line_invoice_line(cr, uid, line, account_id, context=context) - else: - return False - \ No newline at end of file diff --git a/ext/custom-addons/sale_order_optional/sale_order_optional_data.xml b/ext/custom-addons/sale_order_optional/sale_order_optional_data.xml deleted file mode 100644 index d13a406f..00000000 --- a/ext/custom-addons/sale_order_optional/sale_order_optional_data.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/ext/custom-addons/sale_order_optional/sale_order_optional_view.xml b/ext/custom-addons/sale_order_optional/sale_order_optional_view.xml deleted file mode 100644 index 66056673..00000000 --- a/ext/custom-addons/sale_order_optional/sale_order_optional_view.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - sale.order.form.optional - sale.order - - - - - - - - - - diff --git a/ext/custom-addons/sale_order_optional/static/description/icon.png b/ext/custom-addons/sale_order_optional/static/description/icon.png deleted file mode 100644 index fd7ee3b9..00000000 Binary files a/ext/custom-addons/sale_order_optional/static/description/icon.png and /dev/null differ diff --git a/ext/custom-addons/sale_order_reminder/__init__.py b/ext/custom-addons/sale_order_reminder/__init__.py deleted file mode 100755 index 46232dae..00000000 --- a/ext/custom-addons/sale_order_reminder/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 20014-2016 Camadeus GmbH (). -# -# 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 . -# -############################################################################## - -import sale_order_reminder diff --git a/ext/custom-addons/sale_order_reminder/__openerp__.py b/ext/custom-addons/sale_order_reminder/__openerp__.py deleted file mode 100755 index b5fb2f90..00000000 --- a/ext/custom-addons/sale_order_reminder/__openerp__.py +++ /dev/null @@ -1,44 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 20014-2016 Camadeus GmbH (). -# -# 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 . -# -############################################################################## - -{ - 'name': "Reminder for Sale Orders", - 'version': "1.0", - 'category': "Sales", - 'description': """ - This addon adds the field 'offer_valid_until' in the sale order. If this date is passed and the order is still in state 'draft' or 'sent', then - a reminder email is sent to the sales person every day. - """, - 'author': "Camadeus GmbH", - 'website': "http://www.camadeus.at", - 'css': [], - 'images': [], - 'depends': ['sale'], - 'data': ['sale_order_reminder_view.xml', - 'sale_order_reminder_data.xml', - 'email_template.xml', - ], - 'installable': True, - 'auto_install': False, - 'application': False, -} - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/ext/custom-addons/sale_order_reminder/email_template.xml b/ext/custom-addons/sale_order_reminder/email_template.xml deleted file mode 100644 index 512bc06f..00000000 --- a/ext/custom-addons/sale_order_reminder/email_template.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - Erinnerung: Angebot - ${(object.user_id and object.user_id.email or '')|safe} - Erinnerung: Angebot ${object.name} - ${object.user_id and object.user_id.partner_id.id} - - - -

Erinnerung für folgendes offenes Angebot:

- -

- - - - - - - - - - - - - - - - - -
Name:${object.name}
Datum: ${object.date_order}
Kunde: ${object.partner_id.display_name}
Auftragsvolumen (netto): ${object.amount_untaxed}
- -

-
- -]]>
-
-
-
diff --git a/ext/custom-addons/sale_order_reminder/sale_order_reminder.py b/ext/custom-addons/sale_order_reminder/sale_order_reminder.py deleted file mode 100644 index 3c42ac54..00000000 --- a/ext/custom-addons/sale_order_reminder/sale_order_reminder.py +++ /dev/null @@ -1,67 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 20014-2016 Camadeus GmbH (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -from openerp import models, fields, api, _ -from datetime import datetime, timedelta -from openerp.tools import DEFAULT_SERVER_DATE_FORMAT as DATE_FORMAT - -class res_company(models.Model): - _inherit = 'res.company' - - sale_offer_days = fields.Integer(string='Tage Gültigkeit Angebot', default=14) - -class sale_order(models.Model): - _inherit = 'sale.order' - - @api.model - def _offer_valid_until(self): - user = self.env['res.users'].browse(self._uid) - - now = datetime.now() - res = now + timedelta(days=user.company_id.sale_offer_days) - return res.strftime(DATE_FORMAT) - - - offer_valid_until = fields.Date(string='Angebot gültig bis', index=True, - readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, - default=_offer_valid_until) - - @api.model - def order_reminder_job(self): - today = fields.Date.today() - orders = self.search([('offer_valid_until','<',today),('state','in',('draft','sent')),('user_id','!=',False)]) - template_id = self.env['ir.model.data'].xmlid_to_res_id('sale_order_reminder.email_template_sale_reminder') - context = {'append_link': True} - for order in orders: - res = self.pool.get('email.template').send_mail(self._cr, self._uid, template_id, order.id, True, context=context) - return True - -class mail_mail(models.Model): - _inherit = 'mail.mail' - - def create(self, cr, uid, vals, context=None): - # notification field: set if it comes from order reminder job - if context is None: - context = {} - - if context.get('append_link'): - vals['notification'] = True - return super(mail_mail, self).create(cr, uid, vals, context=context) \ No newline at end of file diff --git a/ext/custom-addons/sale_order_reminder/sale_order_reminder_data.xml b/ext/custom-addons/sale_order_reminder/sale_order_reminder_data.xml deleted file mode 100644 index 044a3708..00000000 --- a/ext/custom-addons/sale_order_reminder/sale_order_reminder_data.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - Reminder for Sale Orders - 1 - days - -1 - - - - - - - diff --git a/ext/custom-addons/sale_order_reminder/sale_order_reminder_view.xml b/ext/custom-addons/sale_order_reminder/sale_order_reminder_view.xml deleted file mode 100644 index 589e3c62..00000000 --- a/ext/custom-addons/sale_order_reminder/sale_order_reminder_view.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - sale_order_valid_until_form - sale.order - - - - - - - 20 - # - - - "res_company_order_days_form" - res.company - - - - - - - - - - - - diff --git a/ext/custom-addons/sale_order_reminder/static/description/icon.png b/ext/custom-addons/sale_order_reminder/static/description/icon.png deleted file mode 100644 index fd7ee3b9..00000000 Binary files a/ext/custom-addons/sale_order_reminder/static/description/icon.png and /dev/null differ diff --git a/ext/custom-addons/web_printscreen_zb/__init__.py b/ext/custom-addons/web_printscreen_zb/__init__.py deleted file mode 100644 index 63149b13..00000000 --- a/ext/custom-addons/web_printscreen_zb/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# Copyright (c) 2013 ZestyBeanz Technologies Pvt. Ltd. -# (http://wwww.zbeanztech.com) -# contact@zbeanztech.com -# prajul@zbeanztech.com -# -# 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 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -############################################################################## - -import trml2pdf -import controllers - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/ext/custom-addons/web_printscreen_zb/__openerp__.py b/ext/custom-addons/web_printscreen_zb/__openerp__.py deleted file mode 100644 index b074cd8e..00000000 --- a/ext/custom-addons/web_printscreen_zb/__openerp__.py +++ /dev/null @@ -1,41 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# Copyright (c) 2013 ZestyBeanz Technologies Pvt. Ltd. -# (http://wwww.zbeanztech.com) -# contact@zbeanztech.com -# prajul@zbeanztech.com -# -# 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 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -############################################################################## - -{ - 'name': 'Web Printscreen ZB', - 'version': '1.0', - 'category': 'Web', - 'description': """ - Module to export current active tree view in to excel report - """, - 'author': 'Zesty Beanz Technologies', - 'website': 'http://www.zbeanztech.com', - 'depends': ['web'], - 'data': ['views/web_printscreen_zb.xml'], - 'qweb': ['static/src/xml/web_printscreen_export.xml'], - 'installable': True, - 'auto_install': False, - 'web_preload': False, -} - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/ext/custom-addons/web_printscreen_zb/controllers.py b/ext/custom-addons/web_printscreen_zb/controllers.py deleted file mode 100644 index 8c383af8..00000000 --- a/ext/custom-addons/web_printscreen_zb/controllers.py +++ /dev/null @@ -1,185 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# Copyright (c) 2013 ZestyBeanz Technologies Pvt. Ltd. -# (http://wwww.zbeanztech.com) -# contact@zbeanztech.com -# prajul@zbeanztech.com -# -# 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 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -############################################################################## - -try: - import json -except ImportError: - import simplejson as json -import openerp.addons.web.http as openerpweb -from openerp.addons.web.controllers.main import ExcelExport -from openerp.addons.web.controllers.main import Export -import re -from cStringIO import StringIO -from lxml import etree -import trml2pdf -import time, os -import locale -import openerp.tools as tools -try: - import xlwt -except ImportError: - xlwt = None - -class ZbExcelExport(ExcelExport): - _cp_path = '/web/export/zb_excel_export' - - def from_data(self, fields, rows): - workbook = xlwt.Workbook() - worksheet = workbook.add_sheet('Sheet 1') - style = xlwt.easyxf('align: wrap yes') - font = xlwt.Font() - font.bold = True - style.font = font - ignore_index = [] - count = 0 - for i, fieldname in enumerate(fields): - if fieldname.get('header_data_id', False): - field_name = fieldname.get('header_name', '') - worksheet.write(0, i-count, field_name, style) - worksheet.col(i).width = 8000 - else: - count += 1 - ignore_index.append(i) - style = xlwt.easyxf('align: wrap yes') - bold_style = xlwt.easyxf('align: wrap yes') - font = xlwt.Font() - font.bold = True - bold_style.font = font - for row_index, row in enumerate(rows): - count = 0 - for cell_index, cell_value in enumerate(row): - if cell_index not in ignore_index: - cell_style = style - if cell_value.get('bold', False): - cell_style = bold_style - cellvalue = cell_value.get('data', '') - if isinstance(cellvalue, basestring): - cellvalue = re.sub("\r", " ", cellvalue) - if cell_value.get('number', False) and cellvalue: - cellvalue = float(cellvalue) - if cellvalue is False: cellvalue = None - worksheet.write(row_index + 1, cell_index - count, cellvalue, cell_style) - else: - count += 1 - fp = StringIO() - workbook.save(fp) - fp.seek(0) - data = fp.read() - fp.close() - return data - - @openerpweb.httprequest - def index(self, req, data, token): - data = json.loads(data) - return req.make_response( - self.from_data(data.get('headers', []), data.get('rows', [])), - headers=[ - ('Content-Disposition', 'attachment; filename="%s"' - % data.get('model', 'Export.xls')), - ('Content-Type', self.content_type) - ], - cookies={'fileToken': token} - ) - -class ExportPdf(Export): - _cp_path = '/web/export/zb_pdf' - fmt = { - 'tag': 'pdf', - 'label': 'PDF', - 'error': None - } - - @property - def content_type(self): - return 'application/pdf' - - def filename(self, base): - return base + '.pdf' - - def from_data(self, uid, fields, rows, company_name): - pageSize=[210.0,297.0] - new_doc = etree.Element("report") - config = etree.SubElement(new_doc, 'config') - def _append_node(name, text): - n = etree.SubElement(config, name) - n.text = text - _append_node('date', time.strftime(str(locale.nl_langinfo(locale.D_FMT).replace('%y', '%Y')))) - _append_node('PageSize', '%.2fmm,%.2fmm' % tuple(pageSize)) - _append_node('PageWidth', '%.2f' % (pageSize[0] * 2.8346,)) - _append_node('PageHeight', '%.2f' %(pageSize[1] * 2.8346,)) - _append_node('PageFormat', 'a4') - _append_node('header-date', time.strftime(str(locale.nl_langinfo(locale.D_FMT).replace('%y', '%Y')))) - _append_node('company', company_name) - l = [] - t = 0 - temp = [] - tsum = [] - skip_index = [] - header = etree.SubElement(new_doc, 'header') - i = 0 - for f in fields: - if f.get('header_data_id', False): - value = f.get('header_name', "") - field = etree.SubElement(header, 'field') - field.text = tools.ustr(value) - else: - skip_index.append(i) - i += 1 - lines = etree.SubElement(new_doc, 'lines') - for row_lines in rows: - node_line = etree.SubElement(lines, 'row') - j = 0 - for row in row_lines: - if not j in skip_index: - para = "yes" - tree = "no" - value = row.get('data', '') - if row.get('bold', False): - para = "group" - if row.get('number', False): - tree = "float" - col = etree.SubElement(node_line, 'col', para=para, tree=tree) - col.text = tools.ustr(value) - j += 1 - transform = etree.XSLT( - etree.parse(os.path.join(tools.config['root_path'], - 'addons/base/report/custom_new.xsl'))) - rml = etree.tostring(transform(new_doc)) - self.obj = trml2pdf.parseNode(rml, title='Printscreen') - return self.obj - -class ZbPdfExport(ExportPdf): - _cp_path = '/web/export/zb_pdf_export' - - @openerpweb.httprequest - def index(self, req, data, token): - data = json.loads(data) - uid = data.get('uid', False) - return req.make_response(self.from_data(uid, data.get('headers', []), data.get('rows', []), - data.get('company_name','')), - headers=[('Content-Disposition', - 'attachment; filename=PDF Export'), - ('Content-Type', self.content_type)]) -# cookies={'fileToken': long(token)}) - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/ext/custom-addons/web_printscreen_zb/static/src/js/web_printscreen_export.js b/ext/custom-addons/web_printscreen_zb/static/src/js/web_printscreen_export.js deleted file mode 100644 index dfcbe0a2..00000000 --- a/ext/custom-addons/web_printscreen_zb/static/src/js/web_printscreen_export.js +++ /dev/null @@ -1,122 +0,0 @@ -openerp.web_printscreen_zb = function(instance, m) { - - var _t = instance.web._t; - var QWeb = instance.web.qweb; - - instance.web.ListView.include({ - load_list: function () { - var self = this; - this._super.apply(this, arguments); - self.$pager.find(".oe_list_button_import_excel").unbind('click').click(function(event){self.export_to_excel("excel")}) - self.$pager.find(".oe_list_button_import_pdf").unbind('click').click(function(event){self.export_to_excel("pdf")}) - }, - export_to_excel: function(export_type) { - var self = this - var export_type = export_type - view = this.getParent() - // Find Header Element - header_eles = self.$el.find('.oe_list_header_columns') - header_name_list = [] - $.each(header_eles,function(){ - $header_ele = $(this) - header_td_elements = $header_ele.find('th') - $.each(header_td_elements,function(){ - $header_td = $(this) - text = $header_td.text().trim() || "" - data_id = $header_td.attr('data-id') - if (text && !data_id){ - data_id = 'group_name' - } - header_name_list.push({'header_name': text.trim(), 'header_data_id': data_id}) - // } - }); - }); - - //Find Data Element - data_eles = self.$el.find('.oe_list_content > tbody > tr') - export_data = [] - $.each(data_eles,function(){ - data = [] - $data_ele = $(this) - is_analysis = false - if ($data_ele.text().trim()){ - //Find group name - group_th_eles = $data_ele.find('th') - $.each(group_th_eles,function(){ - $group_th_ele = $(this) - text = $group_th_ele.text().trim() || "" - is_analysis = true - data.push({'data': text, 'bold': true}) - }); - data_td_eles = $data_ele.find('td') - $.each(data_td_eles,function(){ - $data_td_ele = $(this) - text = $data_td_ele.text().trim() || "" - if ($data_td_ele && $data_td_ele[0].classList.contains('oe_number') && !$data_td_ele[0].classList.contains('oe_list_field_float_time')){ - text = text.replace('%', '') - text = instance.web.parse_value(text, { type:"float" }) - data.push({'data': text || "", 'number': true}) - } - else{ - data.push({'data': text}) - } - }); - export_data.push(data) - } - }); - - //Find Footer Element - - footer_eles = self.$el.find('.oe_list_content > tfoot> tr') - $.each(footer_eles,function(){ - data = [] - $footer_ele = $(this) - footer_td_eles = $footer_ele.find('td') - $.each(footer_td_eles,function(){ - $footer_td_ele = $(this) - text = $footer_td_ele.text().trim() || "" - if ($footer_td_ele && $footer_td_ele[0].classList.contains('oe_number')){ - text = instance.web.parse_value(text, { type:"float" }) - data.push({'data': text || "", 'bold': true, 'number': true}) - } - else{ - data.push({'data': text, 'bold': true}) - } - }); - export_data.push(data) - }); - - //Export to excel - $.blockUI(); - if (export_type === 'excel'){ - view.session.get_file({ - url: '/web/export/zb_excel_export', - data: {data: JSON.stringify({ - model : view.model, - headers : header_name_list, - rows : export_data, - })}, - complete: $.unblockUI - }); - } - else{ - console.log(view) - new instance.web.Model("res.users").get_func("read")(this.session.uid, ["company_id"]).then(function(res) { - new instance.web.Model("res.company").get_func("read")(res['company_id'][0], ["name"]).then(function(result) { - view.session.get_file({ - url: '/web/export/zb_pdf_export', - data: {data: JSON.stringify({ - uid: view.session.uid, - model : view.model, - headers : header_name_list, - rows : export_data, - company_name: result['name'] - })}, - complete: $.unblockUI - }); - }); - }); - } - }, - }); -}; diff --git a/ext/custom-addons/web_printscreen_zb/static/src/xml/web_printscreen_export.xml b/ext/custom-addons/web_printscreen_zb/static/src/xml/web_printscreen_export.xml deleted file mode 100644 index 7af23f9e..00000000 --- a/ext/custom-addons/web_printscreen_zb/static/src/xml/web_printscreen_export.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - PDF - - Excel - - - diff --git a/ext/custom-addons/web_printscreen_zb/trml2pdf.py b/ext/custom-addons/web_printscreen_zb/trml2pdf.py deleted file mode 100644 index 5a29c331..00000000 --- a/ext/custom-addons/web_printscreen_zb/trml2pdf.py +++ /dev/null @@ -1,1044 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# -# Copyright (c) 2013 ZestyBeanz Technologies Pvt. Ltd. -# (http://wwww.zbeanztech.com) -# contact@zbeanztech.com -# prajul@zbeanztech.com -# -# 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 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -############################################################################## - - -import sys -import copy -import reportlab -import re -from reportlab.pdfgen import canvas -from reportlab import platypus -from openerp.report.render.rml2pdf import utils -from openerp.report.render.rml2pdf import color -import os -import logging -from lxml import etree -import base64 -from reportlab.platypus.doctemplate import ActionFlowable -from openerp.tools.safe_eval import safe_eval as eval -from reportlab.lib.units import inch,cm,mm -from openerp.tools.misc import file_open -from reportlab.pdfbase import pdfmetrics -from reportlab.lib.pagesizes import A4, letter - -try: - from cStringIO import StringIO - _hush_pyflakes = [ StringIO ] -except ImportError: - from StringIO import StringIO - -_logger = logging.getLogger(__name__) - -encoding = 'utf-8' - -def _open_image(filename, path=None): - """Attempt to open a binary file and return the descriptor - """ - if os.path.isfile(filename): - return open(filename, 'rb') - for p in (path or []): - if p and os.path.isabs(p): - fullpath = os.path.join(p, filename) - if os.path.isfile(fullpath): - return open(fullpath, 'rb') - try: - if p: - fullpath = os.path.join(p, filename) - else: - fullpath = filename - return file_open(fullpath) - except IOError: - pass - raise IOError("File %s cannot be found in image path" % filename) - -class NumberedCanvas(canvas.Canvas): - def __init__(self, *args, **kwargs): - canvas.Canvas.__init__(self, *args, **kwargs) - self._codes = [] - self._flag=False - self._pageCount=0 - self._currentPage =0 - self._pageCounter=0 - self.pages={} - - def showPage(self): - self._currentPage +=1 - if not self._flag: - self._pageCount += 1 - else: - self.pages.update({self._currentPage:self._pageCount}) - self._codes.append({'code': self._code, 'stack': self._codeStack}) - self._startPage() - self._flag=False - - def pageCount(self): - if self.pages.get(self._pageCounter,False): - self._pageNumber=0 - self._pageCounter +=1 - key=self._pageCounter - if not self.pages.get(key,False): - while not self.pages.get(key,False): - key += 1 - self.setFont("Helvetica", 8) - self.drawRightString((self._pagesize[0]-30), (self._pagesize[1]-40), - " %(this)i / %(total)i" % { - 'this': self._pageNumber+1, - 'total': self.pages.get(key,False), - } - ) - - def save(self): - """add page info to each page (page x of y)""" - # reset page counter - self._pageNumber = 0 - for code in self._codes: - self._code = code['code'] - self._codeStack = code['stack'] - self.pageCount() - canvas.Canvas.showPage(self) -# self.restoreState() - self._doc.SaveToFile(self._filename, self) - -class PageCount(platypus.Flowable): - def __init__(self, story_count=0): - platypus.Flowable.__init__(self) - self.story_count = story_count - - def draw(self): - self.canv.beginForm("pageCount%d" % self.story_count) - self.canv.setFont("Helvetica", utils.unit_get(str(8))) - self.canv.drawString(0, 0, str(self.canv.getPageNumber())) - self.canv.endForm() - -class PageReset(platypus.Flowable): - def draw(self): - self.canv._doPageReset = True -class PageReset(platypus.Flowable): - def draw(self): - self.canv._doPageReset = True - -class _rml_styles(object,): - def __init__(self, nodes, localcontext): - self.localcontext = localcontext - self.styles = {} - self.styles_obj = {} - self.names = {} - self.table_styles = {} - self.default_style = reportlab.lib.styles.getSampleStyleSheet() - - for node in nodes: - for style in node.findall('blockTableStyle'): - self.table_styles[style.get('id')] = self._table_style_get(style) - for style in node.findall('paraStyle'): - sname = style.get('name') - self.styles[sname] = self._para_style_update(style) - - self.styles_obj[sname] = reportlab.lib.styles.ParagraphStyle(sname, self.default_style["Normal"], **self.styles[sname]) - - for variable in node.findall('initialize'): - for name in variable.findall('name'): - self.names[ name.get('id')] = name.get('value') - - def _para_style_update(self, node): - data = {} - for attr in ['textColor', 'backColor', 'bulletColor', 'borderColor']: - if node.get(attr): - data[attr] = color.get(node.get(attr)) - for attr in ['fontName', 'bulletFontName', 'bulletText']: - if node.get(attr): - data[attr] = node.get(attr) - for attr in ['fontSize', 'leftIndent', 'rightIndent', 'spaceBefore', 'spaceAfter', - 'firstLineIndent', 'bulletIndent', 'bulletFontSize', 'leading', - 'borderWidth','borderPadding','borderRadius']: - if node.get(attr): - data[attr] = utils.unit_get(node.get(attr)) - if node.get('alignment'): - align = { - 'right':reportlab.lib.enums.TA_RIGHT, - 'center':reportlab.lib.enums.TA_CENTER, - 'justify':reportlab.lib.enums.TA_JUSTIFY - } - data['alignment'] = align.get(node.get('alignment').lower(), reportlab.lib.enums.TA_LEFT) - return data - - def _table_style_get(self, style_node): - styles = [] - for node in style_node: - start = utils.tuple_int_get(node, 'start', (0,0) ) - stop = utils.tuple_int_get(node, 'stop', (-1,-1) ) - if node.tag=='blockValign': - styles.append(('VALIGN', start, stop, str(node.get('value')))) - elif node.tag=='blockFont': - styles.append(('FONT', start, stop, str(node.get('name')))) - elif node.tag=='blockTextColor': - styles.append(('TEXTCOLOR', start, stop, color.get(str(node.get('colorName'))))) - elif node.tag=='blockLeading': - styles.append(('LEADING', start, stop, utils.unit_get(node.get('length')))) - elif node.tag=='blockAlignment': - styles.append(('ALIGNMENT', start, stop, str(node.get('value')))) - elif node.tag=='blockSpan': - styles.append(('SPAN', start, stop)) - elif node.tag=='blockLeftPadding': - styles.append(('LEFTPADDING', start, stop, utils.unit_get(node.get('length')))) - elif node.tag=='blockRightPadding': - styles.append(('RIGHTPADDING', start, stop, utils.unit_get(node.get('length')))) - elif node.tag=='blockTopPadding': - styles.append(('TOPPADDING', start, stop, utils.unit_get(node.get('length')))) - elif node.tag=='blockBottomPadding': - styles.append(('BOTTOMPADDING', start, stop, utils.unit_get(node.get('length')))) - elif node.tag=='blockBackground': - styles.append(('BACKGROUND', start, stop, color.get(node.get('colorName')))) - if node.get('size'): - styles.append(('FONTSIZE', start, stop, utils.unit_get(node.get('size')))) - elif node.tag=='lineStyle': - kind = node.get('kind') - kind_list = [ 'GRID', 'BOX', 'OUTLINE', 'INNERGRID', 'LINEBELOW', 'LINEABOVE','LINEBEFORE', 'LINEAFTER' ] - assert kind in kind_list - thick = 1 - if node.get('thickness'): - thick = float(node.get('thickness')) - styles.append((kind, start, stop, thick, color.get(node.get('colorName')))) - return platypus.tables.TableStyle(styles) - - def para_style_get(self, node): - style = False - sname = node.get('style') - if sname: - if sname in self.styles_obj: - style = self.styles_obj[sname] - else: - _logger.warning('Warning: style not found, %s - setting default!\n' % (node.get('style'),) ) - if not style: - style = self.default_style['Normal'] - para_update = self._para_style_update(node) - if para_update: - # update style only is necessary - style = copy.deepcopy(style) - style.__dict__.update(para_update) - return style - -class _rml_doc(object): - def __init__(self, node, localcontext=None, images=None, path='.', title=None): - if images is None: - images = {} - if localcontext is None: - localcontext = {} - self.localcontext = localcontext - self.etree = node - self.filename = self.etree.get('filename') - self.images = images - self.path = path - self.title = title - - def docinit(self, els): - from reportlab.lib.fonts import addMapping - from reportlab.pdfbase import pdfmetrics - from reportlab.pdfbase.ttfonts import TTFont - - for node in els: - for font in node.findall('registerFont'): - name = font.get('fontName').encode('ascii') - fname = font.get('fontFile').encode('ascii') - if name not in pdfmetrics._fonts: - pdfmetrics.registerFont(TTFont(name, fname)) - addMapping(name, 0, 0, name) #normal - addMapping(name, 0, 1, name) #italic - addMapping(name, 1, 0, name) #bold - addMapping(name, 1, 1, name) #italic and bold - - def setTTFontMapping(self,face, fontname, filename, mode='all'): - from reportlab.lib.fonts import addMapping - from reportlab.pdfbase import pdfmetrics - from reportlab.pdfbase.ttfonts import TTFont - - if fontname not in pdfmetrics._fonts: - pdfmetrics.registerFont(TTFont(fontname, filename)) - if mode == 'all': - addMapping(face, 0, 0, fontname) #normal - addMapping(face, 0, 1, fontname) #italic - addMapping(face, 1, 0, fontname) #bold - addMapping(face, 1, 1, fontname) #italic and bold - elif (mode== 'normal') or (mode == 'regular'): - addMapping(face, 0, 0, fontname) #normal - elif mode == 'italic': - addMapping(face, 0, 1, fontname) #italic - elif mode == 'bold': - addMapping(face, 1, 0, fontname) #bold - elif mode == 'bolditalic': - addMapping(face, 1, 1, fontname) #italic and bold - - def _textual_image(self, node): - rc = '' - for n in node: - rc +=( etree.tostring(n) or '') + n.tail - return base64.decodestring(node.tostring()) - - def _images(self, el): - result = {} - for node in el.findall('.//image'): - rc =( node.text or '') - result[node.get('name')] = base64.decodestring(rc) - return result - - def render(self, out): - el = self.etree.findall('.//docinit') - if el: - self.docinit(el) - - el = self.etree.findall('.//stylesheet') - self.styles = _rml_styles(el,self.localcontext) - - el = self.etree.findall('.//images') - if el: - self.images.update( self._images(el[0]) ) - - el = self.etree.findall('.//template') - if len(el): - pt_obj = _rml_template(self.localcontext, out, el[0], self, images=self.images, path=self.path, title=self.title) - el = utils._child_get(self.etree, self, 'story') - pt_obj.render(el) - else: - self.canvas = canvas.Canvas(out) - pd = self.etree.find('pageDrawing')[0] - pd_obj = _rml_canvas(self.canvas, self.localcontext, None, self, self.images, path=self.path, title=self.title) - pd_obj.render(pd) - - self.canvas.showPage() - self.canvas.save() - -class _rml_canvas(object): - def __init__(self, canvas, localcontext, doc_tmpl=None, doc=None, images=None, path='.', title=None): - if images is None: - images = {} - self.localcontext = localcontext - self.canvas = canvas - self.styles = doc.styles - self.doc_tmpl = doc_tmpl - self.doc = doc - self.images = images - self.path = path - self.title = title - if self.title: - self.canvas.setTitle(self.title) - - def _textual(self, node, x=0, y=0): - text = node.text and node.text.encode('utf-8') or '' - rc = utils._process_text(self, text) - for n in node: - if n.tag == 'seq': - from reportlab.lib.sequencer import getSequencer - seq = getSequencer() - rc += str(seq.next(n.get('id'))) - if n.tag == 'pageCount': - if x or y: - self.canvas.translate(x,y) - self.canvas.doForm('pageCount%s' % (self.canvas._storyCount,)) - if x or y: - self.canvas.translate(-x,-y) - if n.tag == 'pageNumber': - rc += str(self.canvas.getPageNumber()) - rc += utils._process_text(self, n.tail) - return rc.replace('\n','') - - def _drawString(self, node): - v = utils.attr_get(node, ['x','y']) - text=self._textual(node, **v) - text = utils.xml2str(text) - self.canvas.drawString(text=text, **v) - - def _drawCenteredString(self, node): - v = utils.attr_get(node, ['x','y']) - text=self._textual(node, **v) - text = utils.xml2str(text) - self.canvas.drawCentredString(text=text, **v) - - def _drawRightString(self, node): - v = utils.attr_get(node, ['x','y']) - text=self._textual(node, **v) - text = utils.xml2str(text) - self.canvas.drawRightString(text=text, **v) - - def _rect(self, node): - if node.get('round'): - self.canvas.roundRect(radius=utils.unit_get(node.get('round')), **utils.attr_get(node, ['x','y','width','height'], {'fill':'bool','stroke':'bool'})) - else: - self.canvas.rect(**utils.attr_get(node, ['x','y','width','height'], {'fill':'bool','stroke':'bool'})) - - def _ellipse(self, node): - x1 = utils.unit_get(node.get('x')) - x2 = utils.unit_get(node.get('width')) - y1 = utils.unit_get(node.get('y')) - y2 = utils.unit_get(node.get('height')) - - self.canvas.ellipse(x1,y1,x2,y2, **utils.attr_get(node, [], {'fill':'bool','stroke':'bool'})) - - def _curves(self, node): - line_str = node.text.split() - lines = [] - while len(line_str)>7: - self.canvas.bezier(*[utils.unit_get(l) for l in line_str[0:8]]) - line_str = line_str[8:] - - def _lines(self, node): - line_str = node.text.split() - lines = [] - while len(line_str)>3: - lines.append([utils.unit_get(l) for l in line_str[0:4]]) - line_str = line_str[4:] - self.canvas.lines(lines) - - def _grid(self, node): - xlist = [utils.unit_get(s) for s in node.get('xs').split(',')] - ylist = [utils.unit_get(s) for s in node.get('ys').split(',')] - - self.canvas.grid(xlist, ylist) - - def _translate(self, node): - dx = utils.unit_get(node.get('dx')) or 0 - dy = utils.unit_get(node.get('dy')) or 0 - self.canvas.translate(dx,dy) - - def _circle(self, node): - self.canvas.circle(x_cen=utils.unit_get(node.get('x')), y_cen=utils.unit_get(node.get('y')), r=utils.unit_get(node.get('radius')), **utils.attr_get(node, [], {'fill':'bool','stroke':'bool'})) - - def _place(self, node): - flows = _rml_flowable(self.doc, self.localcontext, images=self.images, path=self.path, title=self.title).render(node) - infos = utils.attr_get(node, ['x','y','width','height']) - - infos['y']+=infos['height'] - for flow in flows: - w,h = flow.wrap(infos['width'], infos['height']) - if w<=infos['width'] and h<=infos['height']: - infos['y']-=h - flow.drawOn(self.canvas,infos['x'],infos['y']) - infos['height']-=h - else: - raise ValueError("Not enough space") - - def _line_mode(self, node): - ljoin = {'round':1, 'mitered':0, 'bevelled':2} - lcap = {'default':0, 'round':1, 'square':2} - - if node.get('width'): - self.canvas.setLineWidth(utils.unit_get(node.get('width'))) - if node.get('join'): - self.canvas.setLineJoin(ljoin[node.get('join')]) - if node.get('cap'): - self.canvas.setLineCap(lcap[node.get('cap')]) - if node.get('miterLimit'): - self.canvas.setDash(utils.unit_get(node.get('miterLimit'))) - if node.get('dash'): - dashes = node.get('dash').split(',') - for x in range(len(dashes)): - dashes[x]=utils.unit_get(dashes[x]) - self.canvas.setDash(node.get('dash').split(',')) - - def _image(self, node): - import urllib - import urlparse - from reportlab.lib.utils import ImageReader - nfile = node.get('file') - if not nfile: - if node.get('name'): - image_data = self.images[node.get('name')] - _logger.debug("Image %s used", node.get('name')) - s = StringIO(image_data) - else: - newtext = node.text - if self.localcontext: - res = utils._regex.findall(newtext) - for key in res: - newtext = eval(key, {}, self.localcontext) or '' - image_data = None - if newtext: - image_data = base64.decodestring(newtext) - if image_data: - s = StringIO(image_data) - else: - _logger.debug("No image data!") - return False - else: - if nfile in self.images: - s = StringIO(self.images[nfile]) - else: - try: - up = urlparse.urlparse(str(nfile)) - except ValueError: - up = False - if up and up.scheme: - # RFC: do we really want to open external URLs? - # Are we safe from cross-site scripting or attacks? - _logger.debug("Retrieve image from %s", nfile) - u = urllib.urlopen(str(nfile)) - s = StringIO(u.read()) - else: - _logger.debug("Open image file %s ", nfile) - s = _open_image(nfile, path=self.path) - try: - img = ImageReader(s) - (sx,sy) = img.getSize() - _logger.debug("Image is %dx%d", sx, sy) - args = { 'x': 0.0, 'y': 0.0, 'mask': 'auto'} - for tag in ('width','height','x','y'): - if node.get(tag): - args[tag] = utils.unit_get(node.get(tag)) - if ('width' in args) and (not 'height' in args): - args['height'] = sy * args['width'] / sx - elif ('height' in args) and (not 'width' in args): - args['width'] = sx * args['height'] / sy - elif ('width' in args) and ('height' in args): - if (float(args['width'])/args['height'])>(float(sx)>sy): - args['width'] = sx * args['height'] / sy - else: - args['height'] = sy * args['width'] / sx - self.canvas.drawImage(img, **args) - finally: - s.close() -# self.canvas._doc.SaveToFile(self.canvas._filename, self.canvas) - - def _path(self, node): - self.path = self.canvas.beginPath() - self.path.moveTo(**utils.attr_get(node, ['x','y'])) - for n in utils._child_get(node, self): - if not n.text : - if n.tag=='moveto': - vals = utils.text_get(n).split() - self.path.moveTo(utils.unit_get(vals[0]), utils.unit_get(vals[1])) - elif n.tag=='curvesto': - vals = utils.text_get(n).split() - while len(vals)>5: - pos=[] - while len(pos)<6: - pos.append(utils.unit_get(vals.pop(0))) - self.path.curveTo(*pos) - elif n.text: - data = n.text.split() # Not sure if I must merge all TEXT_NODE ? - while len(data)>1: - x = utils.unit_get(data.pop(0)) - y = utils.unit_get(data.pop(0)) - self.path.lineTo(x,y) - if (not node.get('close')) or utils.bool_get(node.get('close')): - self.path.close() - self.canvas.drawPath(self.path, **utils.attr_get(node, [], {'fill':'bool','stroke':'bool'})) - - def setFont(self, node): - fontname = node.get('name') - if fontname not in pdfmetrics.getRegisteredFontNames()\ - or fontname not in pdfmetrics.standardFonts: - # let reportlab attempt to find it - try: - pdfmetrics.getFont(fontname) - except Exception: - _logger.debug('Could not locate font %s, substituting default: %s', - fontname, - self.canvas._fontname) - fontname = self.canvas._fontname - return self.canvas.setFont(fontname, utils.unit_get(node.get('size'))) - - def render(self, node): - tags = { - 'drawCentredString': self._drawCenteredString, - 'drawRightString': self._drawRightString, - 'drawString': self._drawString, - 'rect': self._rect, - 'ellipse': self._ellipse, - 'lines': self._lines, - 'grid': self._grid, - 'curves': self._curves, - 'fill': lambda node: self.canvas.setFillColor(color.get(node.get('color'))), - 'stroke': lambda node: self.canvas.setStrokeColor(color.get(node.get('color'))), - 'setFont': self.setFont , - 'place': self._place, - 'circle': self._circle, - 'lineMode': self._line_mode, - 'path': self._path, - 'rotate': lambda node: self.canvas.rotate(float(node.get('degrees'))), - 'translate': self._translate, - 'image': self._image - } - for n in utils._child_get(node, self): - if n.tag in tags: - tags[n.tag](n) - -class _rml_draw(object): - def __init__(self, localcontext, node, styles, images=None, path='.', title=None): - if images is None: - images = {} - self.localcontext = localcontext - self.node = node - self.styles = styles - self.canvas = None - self.images = images - self.path = path - self.canvas_title = title - - def render(self, canvas, doc): - canvas.saveState() - cnv = _rml_canvas(canvas, self.localcontext, doc, self.styles, images=self.images, path=self.path, title=self.canvas_title) - cnv.render(self.node) - canvas.restoreState() - -class _rml_Illustration(platypus.flowables.Flowable): - def __init__(self, node, localcontext, styles, self2): - self.localcontext = (localcontext or {}).copy() - self.node = node - self.styles = styles - self.width = utils.unit_get(node.get('width')) - self.height = utils.unit_get(node.get('height')) - self.self2 = self2 - def wrap(self, *args): - return self.width, self.height - def draw(self): - drw = _rml_draw(self.localcontext ,self.node,self.styles, images=self.self2.images, path=self.self2.path, title=self.self2.title) - drw.render(self.canv, None) - -class _rml_flowable(object): - def __init__(self, doc, localcontext, images=None, path='.', title=None): - if images is None: - images = {} - self.localcontext = localcontext - self.doc = doc - self.styles = doc.styles - self.images = images - self.path = path - self.title = title - - def _textual(self, node): - rc1 = utils._process_text(self, node.text or '') - for n in utils._child_get(node,self): - txt_n = copy.deepcopy(n) - for key in txt_n.attrib.keys(): - if key in ('rml_except', 'rml_loop', 'rml_tag'): - del txt_n.attrib[key] - if not n.tag == 'bullet': - txt_n.text = utils.xml2str(self._textual(n)) - txt_n.tail = n.tail and utils.xml2str(utils._process_text(self, n.tail.replace('\n',''))) or '' - rc1 += etree.tostring(txt_n) - return rc1 - - def _table(self, node): - children = utils._child_get(node,self,'tr') - if not children: - return None - length = 0 - colwidths = None - rowheights = None - data = [] - styles = [] - posy = 0 - for tr in children: - paraStyle = None - if tr.get('style'): - st = copy.deepcopy(self.styles.table_styles[tr.get('style')]) - for si in range(len(st._cmds)): - s = list(st._cmds[si]) - s[1] = (s[1][0],posy) - s[2] = (s[2][0],posy) - st._cmds[si] = tuple(s) - styles.append(st) - if tr.get('paraStyle'): - paraStyle = self.styles.styles[tr.get('paraStyle')] - data2 = [] - posx = 0 - for td in utils._child_get(tr, self,'td'): - if td.get('style'): - st = copy.deepcopy(self.styles.table_styles[td.get('style')]) - for s in st._cmds: - s[1][1] = posy - s[2][1] = posy - s[1][0] = posx - s[2][0] = posx - styles.append(st) - if td.get('paraStyle'): - # TODO: merge styles - paraStyle = self.styles.styles[td.get('paraStyle')] - posx += 1 - - flow = [] - for n in utils._child_get(td, self): - if n.tag == etree.Comment: - n.text = '' - continue - fl = self._flowable(n, extra_style=paraStyle) - if isinstance(fl,list): - flow += fl - else: - flow.append( fl ) - - if not len(flow): - flow = self._textual(td) - data2.append( flow ) - if len(data2)>length: - length=len(data2) - for ab in data: - while len(ab) tag: - # - we reset page number to 0 - # - we add an new PageCount flowable (relative to the current - # story number), but not for NumeredCanvas at is handle page - # count itself) - # NOTE: _rml_template render() method add a PageReset flowable at end - # of each story, so we're sure to pass here at least once per story. - if not isinstance(self.canv, NumberedCanvas): - self.handle_flowable([ PageCount(story_count=self.canv._storyCount) ]) - self.canv._pageCount = self.page - self.page = 0 - self.canv._flag = True - self.canv._pageNumber = 0 - self.canv._doPageReset = False - self.canv._storyCount += 1 - -class _rml_template(object): - def __init__(self, localcontext, out, node, doc, images=None, path='.', title=None): - if images is None: - images = {} - if not localcontext: - localcontext={'internal_header':True} - self.localcontext = localcontext - self.images= images - self.path = path - self.title = title - - pagesize_map = {'a4': A4, - 'us_letter': letter - } - pageSize = (841.8897637795275, 595.275590551181) - self.doc_tmpl = TinyDocTemplate(out, pagesize=pageSize, **utils.attr_get(node, ['leftMargin','rightMargin','topMargin','bottomMargin'], {'allowSplitting':'int','showBoundary':'bool','rotation':'int','title':'str','author':'str'})) - self.page_templates = [] - self.styles = doc.styles - self.doc = doc - self.image=[] - pts = node.findall('pageTemplate') - for pt in pts: - frames = [] - for frame_el in pt.findall('frame'): - frame = platypus.Frame( **(utils.attr_get(frame_el, ['x1','y1', 'width','height', 'leftPadding', 'rightPadding', 'bottomPadding', 'topPadding'], {'id':'str', 'showBoundary':'bool'})) ) - if utils.attr_get(frame_el, ['last']): - frame.lastFrame = True - frames.append( frame ) - try : - gr = pt.findall('pageGraphics')\ - or pt[1].findall('pageGraphics') - except Exception: # FIXME: be even more specific, perhaps? - gr='' - if len(gr): -# self.image=[ n for n in utils._child_get(gr[0], self) if n.tag=='image' or not self.localcontext] - drw = _rml_draw(self.localcontext,gr[0], self.doc, images=images, path=self.path, title=self.title) - self.page_templates.append( platypus.PageTemplate(frames=frames, onPage=drw.render, **utils.attr_get(pt, [], {'id':'str'}) )) - else: - drw = _rml_draw(self.localcontext,node,self.doc,title=self.title) - self.page_templates.append( platypus.PageTemplate(frames=frames,onPage=drw.render, **utils.attr_get(pt, [], {'id':'str'}) )) - self.doc_tmpl.addPageTemplates(self.page_templates) - - def render(self, node_stories): - if self.localcontext and not self.localcontext.get('internal_header',False): - del self.localcontext['internal_header'] - fis = [] - r = _rml_flowable(self.doc,self.localcontext, images=self.images, path=self.path, title=self.title) - story_cnt = 0 - for node_story in node_stories: - if story_cnt > 0: - fis.append(platypus.PageBreak()) - fis += r.render(node_story) - # Reset Page Number with new story tag - fis.append(PageReset()) - story_cnt += 1 - if self.localcontext and self.localcontext.get('internal_header',False): - self.doc_tmpl.afterFlowable(fis) - self.doc_tmpl.build(fis,canvasmaker=NumberedCanvas) - else: - self.doc_tmpl.build(fis) - -def parseNode(rml, localcontext=None, fout=None, images=None, path='.', title=None): - node = etree.XML(rml) - r = _rml_doc(node, localcontext, images, path, title=title) - #try to override some font mappings - try: - from customfonts import SetCustomFonts - SetCustomFonts(r) - except ImportError: - # means there is no custom fonts mapping in this system. - pass - except Exception: - _logger.warning('Cannot set font mapping', exc_info=True) - pass - fp = StringIO() - r.render(fp) - return fp.getvalue() - -def parseString(rml, localcontext=None, fout=None, images=None, path='.', title=None): - node = etree.XML(rml) - r = _rml_doc(node, localcontext, images, path, title=title) - - #try to override some font mappings - try: - from customfonts import SetCustomFonts - SetCustomFonts(r) - except Exception: - pass - - if fout: - fp = file(fout,'wb') - r.render(fp) - fp.close() - return fout - else: - fp = StringIO() - r.render(fp) - return fp.getvalue() - -def trml2pdf_help(): - print 'Usage: trml2pdf input.rml >output.pdf' - print 'Render the standard input (RML) and output a PDF file' - sys.exit(0) - -if __name__=="__main__": - if len(sys.argv)>1: - if sys.argv[1]=='--help': - trml2pdf_help() - print parseString(file(sys.argv[1], 'r').read()), - else: - print 'Usage: trml2pdf input.rml >output.pdf' - print 'Try \'trml2pdf --help\' for more information.' - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/ext/custom-addons/web_printscreen_zb/views/web_printscreen_zb.xml b/ext/custom-addons/web_printscreen_zb/views/web_printscreen_zb.xml deleted file mode 100644 index 0386b7d2..00000000 --- a/ext/custom-addons/web_printscreen_zb/views/web_printscreen_zb.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - -