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:
-
- 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
-
-
-
-
-
-
-
-
-
- res.partner.form
- res.partner
-
-
-
-
-
-
-
-
-
-
diff --git a/ext/custom-addons/cam_customer_pricelist/security/ir.model.access.csv b/ext/custom-addons/cam_customer_pricelist/security/ir.model.access.csv
deleted file mode 100644
index 6b4ff6cf..00000000
--- a/ext/custom-addons/cam_customer_pricelist/security/ir.model.access.csv
+++ /dev/null
@@ -1,3 +0,0 @@
-id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
-product_pricelist_customer_user,product.pricelist.customer.user,model_product_pricelist_customer,base.group_sale_salesman,1,0,0,0
-product_pricelist_customer_manager,product.pricelist.customer.manager,model_product_pricelist_customer,base.group_sale_manager,1,1,1,1
diff --git a/ext/custom-addons/cam_customer_pricelist/static/description/icon.png b/ext/custom-addons/cam_customer_pricelist/static/description/icon.png
deleted file mode 100644
index fd7ee3b9..00000000
Binary files a/ext/custom-addons/cam_customer_pricelist/static/description/icon.png and /dev/null differ
diff --git a/ext/custom-addons/cam_customer_pricelist/static/src/img/favicon.ico b/ext/custom-addons/cam_customer_pricelist/static/src/img/favicon.ico
deleted file mode 100644
index fd1ccbc4..00000000
Binary files a/ext/custom-addons/cam_customer_pricelist/static/src/img/favicon.ico and /dev/null differ
diff --git a/ext/custom-addons/cam_invoice_skonto/__init__.py b/ext/custom-addons/cam_invoice_skonto/__init__.py
deleted file mode 100644
index b84c57b5..00000000
--- a/ext/custom-addons/cam_invoice_skonto/__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_invoice_skonto
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/ext/custom-addons/cam_invoice_skonto/__openerp__.py b/ext/custom-addons/cam_invoice_skonto/__openerp__.py
deleted file mode 100644
index 4bc2c926..00000000
--- a/ext/custom-addons/cam_invoice_skonto/__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': 'Camadeus Invoice Skonto',
- 'version': '1.0',
- 'category': 'Custom',
- 'description':
- """
- - Fügt die Felder Netto Tage, Skonto Tage, Skonto Prozent zu Zahlungsbedingungen (account.payment.term) hinzu.
- - Fügt die Felder Skonto Fälligkeit und Betrag inkl. Skonto zur Rechnung (account.invoice) hinzu.
- """,
- 'author': 'camadeus GmbH',
- 'website': 'http://www.camadeus.at',
- 'depends': ['account', 'sale'],
- 'data': [
- 'cam_invoice_skonto_view.xml',
- 'cam_invoice_skonto_data.xml',
- ],
- 'installable': True,
- 'auto_install': False,
-}
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/ext/custom-addons/cam_invoice_skonto/cam_invoice_skonto.py b/ext/custom-addons/cam_invoice_skonto/cam_invoice_skonto.py
deleted file mode 100644
index b663eaa5..00000000
--- a/ext/custom-addons/cam_invoice_skonto/cam_invoice_skonto.py
+++ /dev/null
@@ -1,403 +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 import models, fields as f, api
-import openerp.addons.decimal_precision as dp
-from datetime import date, timedelta, datetime
-from openerp.tools.translate import _
-
-class account_payment_term(osv.osv):
- _inherit = 'account.payment.term'
-
- _columns = {
- 'netto_tage': fields.integer('Netto Tage'),
- 'skonto_tage': fields.integer('Skonto Tage'),
- 'skonto_prozent': fields.float('Skonto Prozent'),
- }
-
- def write(self, cr, uid, ids, values, context=None):
- if context is None:
- context = {}
-
- tl_obj = self.pool.get('account.payment.term.line')
- for pay_term in self.browse(cr, uid, ids, context=context):
- # Delete old account.payment.term.line
- for tl_id in pay_term.line_ids:
- tl_obj.unlink(cr, uid, tl_id.id, context=context)
- # Create new account.payment.term.line based on netto_tage
- days = 0
- if('netto_tage' in values):
- days = values['netto_tage']
- else:
- days = pay_term.netto_tage
- values['line_ids'] = [(0,0, {'payment_id':pay_term.id, 'value': 'balance', 'days': days, 'days2':0})]
-
- return super(account_payment_term, self).write(cr, uid, ids, values, context=context)
-
- def create(self, cr, uid, vals, context=None):
- if context is None:
- context = {}
-
- new_id = super(account_payment_term, self).create(cr, uid, vals, context=context)
- self.write(cr, uid, new_id, {'netto_tage': vals['netto_tage']}, context=context)
-
- return new_id
-
-class account_invoice(models.Model):
- _inherit = 'account.invoice'
-
- @api.one
- def _skonto_betrag_inkl(self):
- if self.payment_term and self.payment_term.skonto_prozent:
- self.skonto_betrag_inkl = self.amount_total * (1 - self.payment_term.skonto_prozent/100.0)
-
- skonto_faelligkeit = f.Date(string=u'Skonto Fälligkeit', readonly=True)
- skonto_betrag_inkl = f.Float(string='Betrag inkl. Skonto', digits=dp.get_precision('Account'), readonly=True, compute='_skonto_betrag_inkl')
-
- @api.multi
- def action_skonto_faelligkeit_assign(self):
- for inv in self:
- if inv.payment_term and inv.payment_term.skonto_tage:
- inv.write({'skonto_faelligkeit': datetime.strptime(inv.date_invoice, '%Y-%m-%d') + timedelta(days=inv.payment_term.skonto_tage)})
- return True
-
- # Add context 'click_register_payment'
- def invoice_pay_customer(self, cr, uid, ids, context=None):
- if not ids: return []
- dummy, view_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account_voucher', 'view_vendor_receipt_dialog_form')
-
- inv = self.browse(cr, uid, ids[0], context=context)
- return {
- 'name':_("Pay Invoice"),
- 'view_mode': 'form',
- 'view_id': view_id,
- 'view_type': 'form',
- 'res_model': 'account.voucher',
- 'type': 'ir.actions.act_window',
- 'nodestroy': True,
- 'target': 'new',
- 'domain': '[]',
- 'context': {
- 'payment_expected_currency': inv.currency_id.id,
- 'default_partner_id': self.pool.get('res.partner')._find_accounting_partner(inv.partner_id).id,
- 'default_amount': inv.type in ('out_refund', 'in_refund') and -inv.residual or inv.residual,
- 'default_reference': inv.name,
- 'close_after_process': True,
- 'invoice_type': inv.type,
- 'invoice_id': inv.id,
- 'default_type': inv.type in ('out_invoice','out_refund') and 'receipt' or 'payment',
- 'type': inv.type in ('out_invoice','out_refund') and 'receipt' or 'payment',
- 'click_register_payment':True,
- }
- }
-
-class account_voucher(osv.osv):
- _inherit = 'account.voucher'
-
- #Workaround to send context in _compute_writeoff_amount()
- def onchange_line_ids(self, cr, uid, ids, line_dr_ids, line_cr_ids, amount, voucher_currency, type, context=None):
- context = context or {}
- if not line_dr_ids and not line_cr_ids:
- return {'value':{'writeoff_amount': 0.0}}
- line_osv = self.pool.get("account.voucher.line")
- line_dr_ids = resolve_o2m_operations(cr, uid, line_osv, line_dr_ids, ['amount'], context)
- line_cr_ids = resolve_o2m_operations(cr, uid, line_osv, line_cr_ids, ['amount'], context)
- #compute the field is_multi_currency that is used to hide/display options linked to secondary currency on the voucher
- is_multi_currency = False
- #loop on the voucher lines to see if one of these has a secondary currency. If yes, we need to see the options
- for voucher_line in line_dr_ids+line_cr_ids:
- line_id = voucher_line.get('id') and self.pool.get('account.voucher.line').browse(cr, uid, voucher_line['id'], context=context).move_line_id.id or voucher_line.get('move_line_id')
- if line_id and self.pool.get('account.move.line').browse(cr, uid, line_id, context=context).currency_id:
- is_multi_currency = True
- break
- return {'value': {'writeoff_amount': self._compute_writeoff_amount(cr, uid, line_dr_ids, line_cr_ids, amount, type, context=context), 'is_multi_currency': is_multi_currency}}
-
-
- def get_default_acc_id(self, cr, uid, args):
- konto = self.pool.get('account.account').search(cr,uid,[('code','=','99999999')],limit=1)
- if konto:
- return konto[0]
- else:
- raise osv.except_osv(_('Konfigurationsfehler!'),_("Es ist kein Konto für den Ausgleich der Rechnungen definiert (Skonto). Bitte wenden Sie sich an den Support."))
-
- return False
-
- _defaults = {
- 'comment': 'Skonto',
- 'writeoff_acc_id': get_default_acc_id,
- }
-
- def _get_writeoff_amount(self, cr, uid, ids, name, args, context={}):
- if not ids: return {}
- currency_obj = self.pool.get('res.currency')
- res = {}; diff_amount = 0.0
- debit = credit = total_inv_residual = 0.0
- for voucher in self.browse(cr, uid, ids, context=context):
- sign = voucher.type == 'payment' and -1 or 1
- for l in voucher.line_dr_ids:
- debit += l.amount
- if context.has_key('click_register_payment'):
- if voucher.payment_option == 'with_writeoff':
- # There can be several open lines => we only want to reconcile the line related to the invoice
- if l.move_line_id and l.move_line_id.invoice and l.move_line_id.invoice.id == context.get('invoice_id',-1):
- l.write({'reconcile': True, 'amount': l.amount_unreconciled})
- total_inv_residual += (l.amount > 0 and l.amount_unreconciled - l.amount)
- for l in voucher.line_cr_ids:
- credit += l.amount
- if context.has_key('click_register_payment'):
- if voucher.payment_option == 'with_writeoff':
- # There can be several open lines => we only want to reconcile the line related to the invoice
- if l.move_line_id and l.move_line_id.invoice and l.move_line_id.invoice.id == context.get('invoice_id',-1):
- l.write({'reconcile': True, 'amount': l.amount_unreconciled})
- total_inv_residual += (l.amount > 0 and l.amount_unreconciled - l.amount)
- currency = voucher.currency_id or voucher.company_id.currency_id
- write_off_amount = voucher.amount - sign * (credit - debit)
- if context.has_key('click_register_payment'):
- write_off_amount = total_inv_residual * sign
-
- res[voucher.id] = currency_obj.round(cr, uid, currency, write_off_amount)
- return res
-
- _columns = {
- 'writeoff_amount': fields.function(_get_writeoff_amount, string='Difference Amount', type='float', readonly=True, help="Computed as the difference between the amount stated in the voucher and the sum of allocation on the voucher lines."),
- }
-
- #working on context to differentiate the button clicks without affecting the present code
- #Workaround to send context in _compute_writeoff_amount()
- def _compute_writeoff_amount(self, cr, uid, line_dr_ids, line_cr_ids, amount, type, context={}):
- debit = credit = total_inv_residual = 0.0
- sign = type == 'payment' and -1 or 1
- for l in line_dr_ids:
- debit += l['amount']
- #total_inv_residual += (l['amount'] > 0 and l['amount_unreconciled'] - l['amount'])
- total_inv_residual += l['amount_unreconciled']
- for l in line_cr_ids:
- credit += l['amount']
- #total_inv_residual += (l['amount'] > 0 and l['amount_unreconciled'] - l['amount'])
- total_inv_residual += l['amount_unreconciled']
- writeoff_amount = amount - sign * (credit - debit)
- if context.has_key('click_register_payment'):
- writeoff_amount = amount - (total_inv_residual)
- return writeoff_amount
-
- #Workaround to send context in _compute_writeoff_amount()
- def recompute_voucher_lines(self, cr, uid, ids, partner_id, journal_id, price, currency_id, ttype, date, context=None):
- """
- Returns a dict that contains new values and context
-
- @param partner_id: latest value from user input for field partner_id
- @param args: other arguments
- @param context: context arguments, like lang, time zone
-
- @return: Returns a dict which contains new values, and context
- """
- def _remove_noise_in_o2m():
- """if the line is partially reconciled, then we must pay attention to display it only once and
- in the good o2m.
- This function returns True if the line is considered as noise and should not be displayed
- """
- if line.reconcile_partial_id:
- if currency_id == line.currency_id.id:
- if line.amount_residual_currency <= 0:
- return True
- else:
- if line.amount_residual <= 0:
- return True
- return False
-
- if context is None:
- context = {}
- context_multi_currency = context.copy()
-
- currency_pool = self.pool.get('res.currency')
- move_line_pool = self.pool.get('account.move.line')
- partner_pool = self.pool.get('res.partner')
- journal_pool = self.pool.get('account.journal')
- line_pool = self.pool.get('account.voucher.line')
-
- #set default values
- default = {
- 'value': {'line_dr_ids': [], 'line_cr_ids': [], 'pre_line': False},
- }
-
- # drop existing lines
- line_ids = ids and line_pool.search(cr, uid, [('voucher_id', '=', ids[0])])
- for line in line_pool.browse(cr, uid, line_ids, context=context):
- if line.type == 'cr':
- default['value']['line_cr_ids'].append((2, line.id))
- else:
- default['value']['line_dr_ids'].append((2, line.id))
-
- if not partner_id or not journal_id:
- return default
-
- journal = journal_pool.browse(cr, uid, journal_id, context=context)
- partner = partner_pool.browse(cr, uid, partner_id, context=context)
- currency_id = currency_id or journal.company_id.currency_id.id
-
- total_credit = 0.0
- total_debit = 0.0
- account_type = None
- if context.get('account_id'):
- account_type = self.pool['account.account'].browse(cr, uid, context['account_id'], context=context).type
- if ttype == 'payment':
- if not account_type:
- account_type = 'payable'
- total_debit = price or 0.0
- else:
- total_credit = price or 0.0
- if not account_type:
- account_type = 'receivable'
-
- if not context.get('move_line_ids', False):
- if context.get('click_register_payment', False) and context.get('invoice_id', False):
- ids = move_line_pool.search(cr, uid, [('state','=','valid'), ('account_id.type', '=', account_type), ('reconcile_id', '=', False), ('partner_id', '=', partner_id),('invoice','=',context.get('invoice_id'))], context=context)
- else:
- ids = move_line_pool.search(cr, uid, [('state','=','valid'), ('account_id.type', '=', account_type), ('reconcile_id', '=', False), ('partner_id', '=', partner_id)], context=context)
- else:
- ids = context['move_line_ids']
- invoice_id = context.get('invoice_id', False)
- company_currency = journal.company_id.currency_id.id
- move_lines_found = []
-
- #order the lines by most old first
- ids.reverse()
- account_move_lines = move_line_pool.browse(cr, uid, ids, context=context)
-
- #compute the total debit/credit and look for a matching open amount or invoice
- for line in account_move_lines:
- if _remove_noise_in_o2m():
- continue
-
- if invoice_id:
- if line.invoice.id == invoice_id:
- #if the invoice linked to the voucher line is equal to the invoice_id in context
- #then we assign the amount on that line, whatever the other voucher lines
- move_lines_found.append(line.id)
- elif currency_id == company_currency:
- #otherwise treatments is the same but with other field names
- if line.amount_residual == price:
- #if the amount residual is equal the amount voucher, we assign it to that voucher
- #line, whatever the other voucher lines
- move_lines_found.append(line.id)
- break
- #otherwise we will split the voucher amount on each line (by most old first)
- total_credit += line.credit or 0.0
- total_debit += line.debit or 0.0
- elif currency_id == line.currency_id.id:
- if line.amount_residual_currency == price:
- move_lines_found.append(line.id)
- break
- total_credit += line.credit and line.amount_currency or 0.0
- total_debit += line.debit and line.amount_currency or 0.0
-
- remaining_amount = price
- #voucher line creation
- for line in account_move_lines:
-
- if _remove_noise_in_o2m():
- continue
-
- if line.currency_id and currency_id == line.currency_id.id:
- amount_original = abs(line.amount_currency)
- amount_unreconciled = abs(line.amount_residual_currency)
- else:
- #always use the amount booked in the company currency as the basis of the conversion into the voucher currency
- amount_original = currency_pool.compute(cr, uid, company_currency, currency_id, line.credit or line.debit or 0.0, context=context_multi_currency)
- amount_unreconciled = currency_pool.compute(cr, uid, company_currency, currency_id, abs(line.amount_residual), context=context_multi_currency)
- line_currency_id = line.currency_id and line.currency_id.id or company_currency
- rs = {
- 'name':line.move_id.name,
- 'type': line.credit and 'dr' or 'cr',
- 'move_line_id':line.id,
- 'account_id':line.account_id.id,
- 'amount_original': amount_original,
- 'amount': (line.id in move_lines_found) and min(abs(remaining_amount), amount_unreconciled) or 0.0,
- 'date_original':line.date,
- 'date_due':line.date_maturity,
- 'amount_unreconciled': amount_unreconciled,
- 'currency_id': line_currency_id,
- }
- remaining_amount -= rs['amount']
- #in case a corresponding move_line hasn't been found, we now try to assign the voucher amount
- #on existing invoices: we split voucher amount by most old first, but only for lines in the same currency
- if not move_lines_found:
- if currency_id == line_currency_id:
- if line.credit:
- amount = min(amount_unreconciled, abs(total_debit))
- rs['amount'] = amount
- total_debit -= amount
- else:
- amount = min(amount_unreconciled, abs(total_credit))
- rs['amount'] = amount
- total_credit -= amount
-
- if rs['amount_unreconciled'] == rs['amount']:
- rs['reconcile'] = True
-
- if rs['type'] == 'cr':
- default['value']['line_cr_ids'].append(rs)
- else:
- default['value']['line_dr_ids'].append(rs)
-
- if len(default['value']['line_cr_ids']) > 0:
- default['value']['pre_line'] = 1
- elif len(default['value']['line_dr_ids']) > 0:
- default['value']['pre_line'] = 1
- default['value']['writeoff_amount'] = self._compute_writeoff_amount(cr, uid, default['value']['line_dr_ids'], default['value']['line_cr_ids'], price, ttype, context=context)
- return default
-
-def resolve_o2m_operations(cr, uid, target_osv, operations, fields, context):
- results = []
- for operation in operations:
- result = None
- if not isinstance(operation, (list, tuple)):
- result = target_osv.read(cr, uid, operation, fields, context=context)
- elif operation[0] == 0:
- # may be necessary to check if all the fields are here and get the default values?
- result = operation[2]
- elif operation[0] == 1:
- result = target_osv.read(cr, uid, operation[1], fields, context=context)
- if not result: result = {}
- result.update(operation[2])
- elif operation[0] == 4:
- result = target_osv.read(cr, uid, operation[1], fields, context=context)
- if result != None:
- results.append(result)
- return results
-
-class sale_order(osv.osv):
- _inherit = 'sale.order'
-
- def _skonto_betrag_inkl(self, cr, uid, ids, field_name, arg, context=None):
- res = {}
- sos = self.browse(cr, uid, ids, context=context)
- for so in sos:
- if so.payment_term and so.payment_term.skonto_prozent:
- res[so.id] = so.amount_total * (1 - so.payment_term.skonto_prozent/100.0)
- return res
-
- _columns = {
- 'skonto_betrag_inkl': fields.function(_skonto_betrag_inkl, string='Betrag inkl. Skonto', type='float'),
- }
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/ext/custom-addons/cam_invoice_skonto/cam_invoice_skonto_data.xml b/ext/custom-addons/cam_invoice_skonto/cam_invoice_skonto_data.xml
deleted file mode 100644
index 31f1fc5a..00000000
--- a/ext/custom-addons/cam_invoice_skonto/cam_invoice_skonto_data.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-
-
-
-
-
-
-
- action_date_assign()
-action_move_create()
-action_number()
-invoice_validate()
-action_skonto_faelligkeit_assign()
-
-
-
-
-
-
- Skonto
- 99999999
- other
-
-
-
-
-
-
diff --git a/ext/custom-addons/cam_invoice_skonto/cam_invoice_skonto_view.xml b/ext/custom-addons/cam_invoice_skonto/cam_invoice_skonto_view.xml
deleted file mode 100644
index 60e6a1bd..00000000
--- a/ext/custom-addons/cam_invoice_skonto/cam_invoice_skonto_view.xml
+++ /dev/null
@@ -1,87 +0,0 @@
-
-
-
-
-
-
-
-
- cam_invoice_skonto.payment.term.form
- account.payment.term
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- cam_invoice_skonto.invoice.form
- account.invoice
-
-
-
-
-
-
-
-
-
-
-
-
-
- cam_invoice_skonto.account_voucher.form
- account.voucher
-
-
-
- 1
-
-
-
-
-
-
- sale.order.form
- sale.order
-
-
-
-
-
-
-
-
-
-
diff --git a/ext/custom-addons/cam_invoice_skonto/static/src/img/icon.png b/ext/custom-addons/cam_invoice_skonto/static/src/img/icon.png
deleted file mode 100644
index 9ad73d74..00000000
Binary files a/ext/custom-addons/cam_invoice_skonto/static/src/img/icon.png and /dev/null differ
diff --git a/ext/custom-addons/cam_max_width/__openerp__.py b/ext/custom-addons/cam_max_width/__openerp__.py
deleted file mode 100755
index 8923c1d0..00000000
--- a/ext/custom-addons/cam_max_width/__openerp__.py
+++ /dev/null
@@ -1,40 +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': 'Max. Width for Form View',
- 'category': 'Custom',
- 'version': '1.0',
- 'description': """
- """,
- 'author': 'camadeus GmbH',
- 'website': 'http://www.camadeus.at',
- 'depends': [],
- 'data': [
- 'views/max_width.xml',
- ],
- 'installable': True,
- 'sequence': 150,
- 'auto_install': False,
-}
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/ext/custom-addons/cam_max_width/static/description/icon.png b/ext/custom-addons/cam_max_width/static/description/icon.png
deleted file mode 100644
index fd7ee3b9..00000000
Binary files a/ext/custom-addons/cam_max_width/static/description/icon.png and /dev/null differ
diff --git a/ext/custom-addons/cam_max_width/static/src/css/max_width.css b/ext/custom-addons/cam_max_width/static/src/css/max_width.css
deleted file mode 100644
index 8150784b..00000000
--- a/ext/custom-addons/cam_max_width/static/src/css/max_width.css
+++ /dev/null
@@ -1,10 +0,0 @@
-.openerp .oe_followers .oe_invite {
- float: none !important;
- display: block;
- padding-left: 0px;
-}
-
-.openerp .oe_form_sheet_width {
- max-width: 95% !important;
-}
-
diff --git a/ext/custom-addons/cam_max_width/views/max_width.xml b/ext/custom-addons/cam_max_width/views/max_width.xml
deleted file mode 100644
index 84864796..00000000
--- a/ext/custom-addons/cam_max_width/views/max_width.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/ext/custom-addons/cam_reports/__init__.py b/ext/custom-addons/cam_reports/__init__.py
deleted file mode 100644
index 4739d040..00000000
--- a/ext/custom-addons/cam_reports/__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_reports
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-
diff --git a/ext/custom-addons/cam_reports/__openerp__.py b/ext/custom-addons/cam_reports/__openerp__.py
deleted file mode 100644
index 57cda6ef..00000000
--- a/ext/custom-addons/cam_reports/__openerp__.py
+++ /dev/null
@@ -1,37 +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 Reports',
- 'category': 'Custom',
- 'version': '1.0',
- 'description': """Individuelle Dokumentenvorlagen""",
- 'author': 'camadeus GmbH',
- 'website': 'http://www.camadeus.at',
- 'depends': ['purchase','sale','account','stock'],
- 'data': ['reports_data.xml',
- ],
- 'installable': True,
- 'auto_install': False,
-}
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/ext/custom-addons/cam_reports/cam_reports.py b/ext/custom-addons/cam_reports/cam_reports.py
deleted file mode 100644
index 1406531f..00000000
--- a/ext/custom-addons/cam_reports/cam_reports.py
+++ /dev/null
@@ -1,93 +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.modules as addons
-import os
-import base64
-
-class res_company(osv.osv):
- _inherit = 'res.company'
-
- def get_image(self, img):
-
- def _get_dir():
- styles_dir = 'cam_reports/static/src/img'
- adps = addons.module.ad_paths
- for adp in adps:
- dir = os.path.join(adp, styles_dir)
- if os.path.isdir(dir):
- return dir
- return False
-
- def _get_file_data(filename):
- try:
- f = open(filename , 'rb')
- data = base64.b64encode(f.read())
- f.close()
- return data
- except:
- print "Error openening file '%s'." % (filename)
- return False
-
- path = _get_dir()
- fname = os.path.join(path, img)
- img_data = _get_file_data(fname)
- return img_data
-
- def _get_rml_header(self, cr, uid, ids, _field_name, _args, context=None):
- result = dict.fromkeys(ids, False)
- # Get filename
- dirname = 'cam_reports/report'
- adps = addons.module.ad_paths
- for adp in adps:
- dir = os.path.join(adp, dirname)
- if os.path.isdir(dir):
- break
-
- if os.path.isdir(dir):
- filename = os.path.join(dir, 'briefkopf.rml')
- f = open(filename , 'rb')
- data = f.read()
- result = dict.fromkeys(ids, data)
- return result
-
- def _get_rml_header2(self, cr, uid, ids, _field_name, _args, context=None):
- result = dict.fromkeys(ids, False)
- # Get filename
- dirname = 'cam_reports/report'
- adps = addons.module.ad_paths
- for adp in adps:
- dir = os.path.join(adp, dirname)
- if os.path.isdir(dir):
- break
-
- if os.path.isdir(dir):
- filename = os.path.join(dir, 'page.rml')
- f = open(filename , 'rb')
- data = f.read()
- result = dict.fromkeys(ids, data)
- return result
-
- _columns = {
- 'rml_header': fields.function(_get_rml_header, type='text', string='Briefkopf',readonly=True),
- 'rml_header2': fields.function(_get_rml_header2, type='text', string='RML Header',readonly=True),
- }
\ No newline at end of file
diff --git a/ext/custom-addons/cam_reports/report/account.invoice.rml b/ext/custom-addons/cam_reports/report/account.invoice.rml
deleted file mode 100644
index a4a8ec3d..00000000
--- a/ext/custom-addons/cam_reports/report/account.invoice.rml
+++ /dev/null
@@ -1,236 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
- [[repeatIn(objects,'o')]] [[ setLang(o.partner_id.commercial_partner_id.lang)]]
-
-
-
-
-
- [[ o.partner_id.commercial_partner_id.name ]]
- [[ (o.partner_id.commercial_partner_id.id != o.partner_id.id and o.partner_id.name) or '' ]]
- [[ (o.partner_id.street ) or '']]
- [[ (o.partner_id.street2) or removeParentNode('para') ]]
- [[ (o.partner_id.zip) or '' ]] [[ (o.partner_id and o.partner_id.city) or '' ]]
- [[ (o.partner_id.state_id and o.partner_id.state_id.name) or removeParentNode('para')]]
- [[ (o.partner_id.country_id and o.partner_id.country_id.name) or '' ]]
-
- [[ not (o.partner_id.commercial_partner_id and o.partner_id.commercial_partner_id.ref) or removeParentNode('section') ]]
-
-
-
-
-
-
- [[ o.partner_id.commercial_partner_id.name ]]
- [[ (o.partner_id.commercial_partner_id.id != o.partner_id.id and o.partner_id.name) or '' ]]
- [[ (o.partner_id.street ) or '']]
- [[ (o.partner_id.street2) or removeParentNode('para') ]]
- [[ (o.partner_id.zip) or '' ]] [[ (o.partner_id and o.partner_id.city) or '' ]]
- [[ (o.partner_id.state_id and o.partner_id.state_id.name) or removeParentNode('para')]]
- [[ (o.partner_id.country_id and o.partner_id.country_id.name) or '' ]]
-
-
- [[ not (o.partner_id.commercial_partner_id and o.partner_id.commercial_partner_id.ref) or removeParentNode('section') ]]
-
-
-
- [[ (o.partner_shipping_id and o.partner_shipping_id.id != o.partner_id.id) or removeParentNode('section')]]
-
- Lieferadresse:
- [[ o.partner_shipping_id.commercial_partner_id.name ]]
- [[ (o.partner_shipping_id.commercial_partner_id.id != o.partner_shipping_id.id and o.partner_shipping_id.name) or '' ]]
- [[ (o.partner_shipping_id.street ) or '']]
- [[ (o.partner_shipping_id.street2) or removeParentNode('para') ]]
- [[ (o.partner_shipping_id.zip) or '' ]] [[ (o.partner_shipping_id and o.partner_shipping_id.city) or '' ]]
- [[ (o.partner_shipping_id.state_id and o.partner_shipping_id.state_id.name) or removeParentNode('para')]]
- [[ (o.partner_shipping_id.country_id and o.partner_shipping_id.country_id.name) or '' ]]
-
-
-
-
-
-
-
-
- Angebotsdatum:[[ o.state not in ['draft','sent'] and removeParentNode('para') ]]
- Bestelldatum:[[ o.state in ['draft','sent'] and removeParentNode('para') ]]
-
-
- [[ formatLang(o.date_order,date = True) ]]
-
-
-
-
- Quelldokument:[[ o.state not in ['draft','sent'] and removeParentNode('tr') ]]
-
-
- [[ o.origin ]]
-
-
-
-
- Kundennummer:
-
-
- [[ o.client_order_ref ]]
-
-
-
-
- Kunde UID Nr.:
-
-
- [[ o.partner_id.commercial_partner_id and o.partner_id.commercial_partner_id.vat or '' ]]
-
-
-
-
- Ansprechpartner:
-
-
- [[ (o.user_id and o.user_id.name) or '' ]]
-
-
-
-
-
-
-
-
-
-
-
- [[ o.state not in ['draft','sent'] and removeParentNode('para') ]] Angebot [[ o.name ]]
- [[ o.state in ['draft','sent'] and removeParentNode('para') ]] Bestellbestätigung [[ o.name ]]
-
-
-
-
-
-
-
- Pos
-
-
- Art.nr.
-
-
- Bezeichnung
-
-
- Menge
-
-
- Einzelpreis
-
-
-
-
-
- Gesamtpreis
-
-
-
-
[[repeatIn(o.order_line,'line')]]
-
-
-
-
-
-
- [[ line.product_id and line.product_id.default_code or '']]
-
-
- [[ (line.name or '').split('\n\n')[0] ]]
- [[ repeatIn((line.name or '').split('\n\n')[1:],'paragraphs') ]]
-
- [[ paragraphs ]]
-
-
-
- [[ formatLang(line.product_uos and line.product_uos_qty or line.product_uom_qty, digits=0) ]] [[ line.product_uom.name ]]
-
-
- [[ formatLang(line.price_unit,digits=2) ]]
-
-
- [[ line.discount <> 0 and (formatLang(line.discount) + '%') or '' ]]
-
-
- [[ picking.partner_id.commercial_partner_id.name ]]
- [[ (picking.partner_id.commercial_partner_id.id != picking.partner_id.id and picking.partner_id.name) or '' ]]
- [[ (picking.partner_id.street ) or '']]
- [[ (picking.partner_id.street2) or removeParentNode('para') ]]
- [[ (picking.partner_id.zip) or '' ]] [[ (picking.partner_id and picking.partner_id.city) or '' ]]
- [[ (picking.partner_id.state_id and picking.partner_id.state_id.name) or removeParentNode('para')]]
- [[ (picking.partner_id.country_id and picking.partner_id.country_id.name) or '' ]]
-
- [[ not (picking.partner_id.commercial_partner_id and picking.partner_id.commercial_partner_id.ref) or removeParentNode('section') ]]
-
-
-
-
-
- [[ formatLang(picking.date_done, date=True) or formatLang(time.strftime('%Y-%m-%d'),date=True) ]]
- [[ picking.origin ]]
- [[ picking.sale_id and picking.sale_id.client_order_ref or '' ]]
- [[ picking.partner_id and picking.partner_id.commercial_partner_id and picking.partner_id.commercial_partner_id.ref or '' ]]
-
-
-
-
-
- [[ (picking.note or '').split('\n\n')[0] ]]
- [[ repeatIn((picking.note or '').split('\n\n')[1:],'paragraphs') ]]
-
- [[ paragraphs ]]
-
-
-
-
diff --git a/ext/custom-addons/cam_reports/reports_data.xml b/ext/custom-addons/cam_reports/reports_data.xml
deleted file mode 100644
index 3df717e2..00000000
--- a/ext/custom-addons/cam_reports/reports_data.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
- cam_reports/report/sale.order.rml
- pdf
-
-
-
- cam_reports/report/stock.picking.rml
- pdf
-
-
-
- cam_reports/report/account.invoice.rml
- pdf
-
-
-
- cam_reports/report/purchase.quotation.rml
- pdf
-
-
-
- cam_reports/report/purchase.order.rml
- pdf
-
-
-
- cam_reports/report/mrp.production.rml
- pdf
-
-
-
\ No newline at end of file
diff --git a/ext/custom-addons/cam_reports/static/description/icon.png b/ext/custom-addons/cam_reports/static/description/icon.png
deleted file mode 100644
index fd7ee3b9..00000000
Binary files a/ext/custom-addons/cam_reports/static/description/icon.png and /dev/null differ
diff --git a/ext/custom-addons/cam_reports/static/src/img/warning.png b/ext/custom-addons/cam_reports/static/src/img/warning.png
deleted file mode 100644
index 54ef62b3..00000000
Binary files a/ext/custom-addons/cam_reports/static/src/img/warning.png and /dev/null differ
diff --git a/ext/custom-addons/cam_testenv/__init__.py b/ext/custom-addons/cam_testenv/__init__.py
deleted file mode 100644
index 601f4302..00000000
--- a/ext/custom-addons/cam_testenv/__init__.py
+++ /dev/null
@@ -1,26 +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 controllers
-import report
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-
diff --git a/ext/custom-addons/cam_testenv/__openerp__.py b/ext/custom-addons/cam_testenv/__openerp__.py
deleted file mode 100644
index 610e0b9a..00000000
--- a/ext/custom-addons/cam_testenv/__openerp__.py
+++ /dev/null
@@ -1,46 +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': 'Test Environment',
- 'version': '1.0',
- 'category': 'Custom',
- 'description': """
-Test Environment
-===========================
-* Shows the message "Test" in the background if the database matches the regular expression of the config paramter "dbfilter_test"
-* Default filter: test*
-* Example: dbfilter_test = ['.*',] # for all Databases
-* Example: dbfilter_test = ['db1','db2'] # only for databases 'db1' and 'db2'
-
- """,
- 'author': 'camadeus Consulting GmbH',
- 'website': 'http://www.camadeus.at',
- 'depends': ['report', 'web', 'base'],
- 'data': [
- 'views/cam_testenv.xml',
- ],
- 'update_xml': [],
- 'demo_xml': [],
- 'installable': True,
- 'active': False,
-}
\ No newline at end of file
diff --git a/ext/custom-addons/cam_testenv/background.xcf b/ext/custom-addons/cam_testenv/background.xcf
deleted file mode 100644
index 1af5fe07..00000000
Binary files a/ext/custom-addons/cam_testenv/background.xcf and /dev/null differ
diff --git a/ext/custom-addons/cam_testenv/controllers/__init__.py b/ext/custom-addons/cam_testenv/controllers/__init__.py
deleted file mode 100644
index 23f15e7e..00000000
--- a/ext/custom-addons/cam_testenv/controllers/__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 testenv_controller
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-
diff --git a/ext/custom-addons/cam_testenv/controllers/testenv_controller.py b/ext/custom-addons/cam_testenv/controllers/testenv_controller.py
deleted file mode 100644
index 3be243a6..00000000
--- a/ext/custom-addons/cam_testenv/controllers/testenv_controller.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 .
-#
-##############################################################################
-
-import re
-import openerp
-from openerp.tools.translate import _
-from openerp.tools import config
-
-from openerp.addons.web import http
-from openerp.addons.web.controllers.main import Home
-from openerp.http import request
-
-
-class Home_Debug(Home):
- @http.route('/', type='http', auth="none")
- def index(self, s_action=None, db=None, **kw):
-
- # Check arguments
- if openerp.tools.config.get('show_debug', False):
- return http.local_redirect('/web?debug=1', query=request.params, keep_hash=True)
- else:
- return http.local_redirect('/web', query=request.params, keep_hash=True)
-
-
-class WebClient(http.Controller):
- _cp_path = "/web/testenv"
-
- @http.jsonrequest
- def testmode(self, req, db=False):
- if not db and req and req.session:
- db = req.session._db
-
- if db:
- h = req.httprequest.environ['HTTP_HOST'].split(':')[0]
- d = h.split('.')[0]
- r = openerp.tools.config.get('dbfilter_test', 'test.*').replace('%h', h).replace('%d', d)
- try:
- pattern_list = eval(r)
- if not hasattr(pattern_list, '__iter__'):
- pattern_list = [pattern_list]
- except:
- pattern_list = [r]
-
- for pattern in pattern_list:
- if isinstance(pattern, str) and re.match(pattern, db):
- return True
- return False
-
-# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:
diff --git a/ext/custom-addons/cam_testenv/print_background.xcf b/ext/custom-addons/cam_testenv/print_background.xcf
deleted file mode 100644
index 909ca4b5..00000000
Binary files a/ext/custom-addons/cam_testenv/print_background.xcf and /dev/null differ
diff --git a/ext/custom-addons/cam_testenv/report.py b/ext/custom-addons/cam_testenv/report.py
deleted file mode 100644
index c422d85c..00000000
--- a/ext/custom-addons/cam_testenv/report.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# Odoo Extension Module
-# Copyright (C) 2014-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 re
-import openerp
-from openerp import models
-import logging
-
-_logger = logging.getLogger(__name__)
-
-
-class Report(models.Model):
- _inherit = "report"
-
- def render(self, cr, uid, ids, template, values=None, context=None):
- testmode = {'testmode': False}
-
- r = openerp.tools.config.get('dbfilter_test', 'test.*')
- try:
- pattern_list = eval(r)
- if not hasattr(pattern_list, '__iter__'):
- pattern_list = [pattern_list]
- except:
- pattern_list = [r]
-
- for pattern in pattern_list:
- if isinstance(pattern, str) and re.match(pattern, cr.dbname):
- testmode = {'testmode': True}
- _logger.info('testmode enabled for reports')
-
- if not values:
- values = {}
- values.update(testmode)
- return super(Report, self).render(cr, uid, ids, template, values, context)
diff --git a/ext/custom-addons/cam_testenv/static/description/icon.png b/ext/custom-addons/cam_testenv/static/description/icon.png
deleted file mode 100644
index fd7ee3b9..00000000
Binary files a/ext/custom-addons/cam_testenv/static/description/icon.png and /dev/null differ
diff --git a/ext/custom-addons/cam_testenv/static/src/css/testenv.css b/ext/custom-addons/cam_testenv/static/src/css/testenv.css
deleted file mode 100644
index a36790a4..00000000
--- a/ext/custom-addons/cam_testenv/static/src/css/testenv.css
+++ /dev/null
@@ -1,20 +0,0 @@
-.test-mode-activated .oe_view_manager_wrapper {
-background-image: url("/cam_testenv/static/src/img/back-testenv.jpg");
-background-size: cover;
-background-attachment: fixed;
-}
-.test-mode-activated .oe_view_manager_body,
-.test-mode-activated .oe_view_manager_wrapper > * {
-opacity: 0.9;
-background: rgba(255,255,255,.8) !important;
-}
-
-.test-mode-activated .oe_list_field {
-opacity: 1;
-}
-
-.test-mode-activated .oe_leftbar > * ,
-.test-mode-activated .oe_view_manager_header > *{
-background: lightblue;
-}
-
diff --git a/ext/custom-addons/cam_testenv/static/src/img/back-testenv.jpg b/ext/custom-addons/cam_testenv/static/src/img/back-testenv.jpg
deleted file mode 100644
index f52bed96..00000000
Binary files a/ext/custom-addons/cam_testenv/static/src/img/back-testenv.jpg and /dev/null differ
diff --git a/ext/custom-addons/cam_testenv/static/src/img/print_background.png b/ext/custom-addons/cam_testenv/static/src/img/print_background.png
deleted file mode 100644
index 6c9324dc..00000000
Binary files a/ext/custom-addons/cam_testenv/static/src/img/print_background.png and /dev/null differ
diff --git a/ext/custom-addons/cam_testenv/static/src/img/print_test_inkscape.svg b/ext/custom-addons/cam_testenv/static/src/img/print_test_inkscape.svg
deleted file mode 100644
index fd571e9c..00000000
--- a/ext/custom-addons/cam_testenv/static/src/img/print_test_inkscape.svg
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
-
-
diff --git a/ext/custom-addons/cam_testenv/static/src/img/print_test_n.svg b/ext/custom-addons/cam_testenv/static/src/img/print_test_n.svg
deleted file mode 100644
index b0784b5d..00000000
--- a/ext/custom-addons/cam_testenv/static/src/img/print_test_n.svg
+++ /dev/null
@@ -1,70 +0,0 @@
-
-
-
-
diff --git a/ext/custom-addons/cam_testenv/static/src/js/testenv.js b/ext/custom-addons/cam_testenv/static/src/js/testenv.js
deleted file mode 100644
index 5e631572..00000000
--- a/ext/custom-addons/cam_testenv/static/src/js/testenv.js
+++ /dev/null
@@ -1,32 +0,0 @@
-openerp.cam_testenv = function (openerp) {
-
- openerp.web.WebClient = openerp.web.WebClient.extend({
- /**
- * Test env
- */
- start: function() {
- var self = this;
-
- return $.when(this._super()).then(function() {
- //this._super();
-
- db = null
- if (jQuery.param !== undefined && jQuery.deparam(jQuery.param.querystring()).db !== undefined) {
- db = jQuery.deparam(jQuery.param.querystring()).db
- }
-
- self.rpc("/web/testenv/testmode", {'db': db}).done(function(result) {
- // If immediately follows a login (triggered by trying to restore
- // an invalid session or no session at all), refresh session data
- // (should not change, but just in case...)
- if (result) {
- $("body").addClass("test-mode-activated");
- // $("body").css("background-image", "url(" + openerp.session.origin + "/cam_testenv/static/src/img/back-testenv.jpg" + ")");
- }
- });
- });
- }
-
- });
-
-}
diff --git a/ext/custom-addons/cam_testenv/views/cam_testenv.xml b/ext/custom-addons/cam_testenv/views/cam_testenv.xml
deleted file mode 100644
index fef19f79..00000000
--- a/ext/custom-addons/cam_testenv/views/cam_testenv.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
- body {
- color: #000 !important;
- word-wrap: break-word;
- }
- .border-black td {
- border-top: 1px solid black !important;
- }
- .table-condensed > thead > tr > th {
- border-bottom: 1px solid black !important;
- }
- .table-condensed > tbody > tr {
- page-break-inside: avoid !important;
- }
- .zero_min_height {
- min-height: 0px !important;
- }
-
-
- div.page {
- background-image: url("/cam_testenv/static/src/img/print_test_n.svg") !important;
- background-repeat: repeat-y;
- background-size: contain;
- background-position: center center;
- min-height: 234mm;
- }
-
-
-
-
diff --git a/ext/custom-addons/cam_work_order/__init__.py b/ext/custom-addons/cam_work_order/__init__.py
deleted file mode 100644
index 73afd9e8..00000000
--- a/ext/custom-addons/cam_work_order/__init__.py
+++ /dev/null
@@ -1,25 +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_work_order
-
-# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
-
diff --git a/ext/custom-addons/cam_work_order/__openerp__.py b/ext/custom-addons/cam_work_order/__openerp__.py
deleted file mode 100644
index 7a1add48..00000000
--- a/ext/custom-addons/cam_work_order/__openerp__.py
+++ /dev/null
@@ -1,40 +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 Produktionsschein',
- 'category': 'Custom',
- 'version': '1.0',
- 'description': """Produktionsschein für die Arbeitsausführung""",
- 'author': 'camadeus GmbH',
- 'website': 'http://www.camadeus.at',
- 'depends': ['sale'],
- 'data': [
- 'cam_work_order_view.xml',
- 'cam_work_order_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_work_order/cam_work_order.py b/ext/custom-addons/cam_work_order/cam_work_order.py
deleted file mode 100644
index 8a019e7d..00000000
--- a/ext/custom-addons/cam_work_order/cam_work_order.py
+++ /dev/null
@@ -1,162 +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 import api
-from openerp.tools.translate import _
-from openerp import SUPERUSER_ID
-from openerp import tools
-from lxml import etree
-
-class sale_order(osv.osv):
- _inherit = 'sale.order'
-
- _columns = {
- 'work_order_ids': fields.one2many('work.order','sale_id','Produktionsscheine'),
- }
-
- def action_view_work_order(self, cr, uid, ids, context=None):
-
- mod_obj = self.pool.get('ir.model.data')
- act_obj = self.pool.get('ir.actions.act_window')
-
- result = mod_obj.get_object_reference(cr, uid, 'cam_work_order', 'work_order_action')
- id = result and result[1] or False
- result = act_obj.read(cr, uid, [id], context=context)[0]
-
- #compute the number of work orders to display
- work_ids = []
- for so in self.browse(cr, uid, ids, context=context):
- work_ids += [order.id for order in so.work_order_ids]
-
- #choose the view_mode accordingly
- if len(work_ids) > 1:
- result['domain'] = "[('id','in',[" + ','.join(map(str, work_ids)) + "])]"
- else:
- res = mod_obj.get_object_reference(cr, uid, 'cam_custom', 'work_order_form')
- result['views'] = [(res and res[1] or False, 'form')]
- result['res_id'] = work_ids and work_ids[0] or False
- return result
-
- def button_work_order(self, cr, uid, ids, context=None):
- assert len(ids) == 1 #'This option should only be used for a single id at a time.'
- order = self.browse(cr, uid, ids[0], context=context)
-
- existing_ids = self.pool.get('work.order').search(cr, uid, [('sale_id','=',order.id)])
- if existing_ids:
- work_id = existing_ids[0]
- else:
- lines = []
- for l in order.order_line:
- line = {
- 'name': l.name,
- 'qty': l.product_uom_qty,
- }
- lines.append((0,0,line))
-
- vals = {
- 'partner_id': order.partner_id.id,
- 'sale_id': order.id,
- 'line_ids': lines,
- }
- work_id = self.pool.get('work.order').create(cr, uid, vals, context=context)
- return {
- 'type': 'ir.actions.act_window',
- 'name': _('Produktionsschein'),
- 'res_model': 'work.order',
- 'res_id': work_id,
- 'view_type': 'form',
- 'view_mode': 'form',
- 'target': 'current',
- 'nodestroy': True,
- }
-
-class work_order_line(osv.Model):
- _name = 'work.order.line'
- _description = 'Arbeitsposition'
- _order = 'seq, id'
- _columns = {
- 'seq': fields.integer('Sequenz'),
- 'name': fields.text('Bezeichnung', size=30, required=True),
- 'qty': fields.float('Stück'),
- 'order_id': fields.many2one('work.order', required=True, ondelete='cascade'),
- }
-
-class work_order_stage(osv.osv):
- _name = "work.order.stage"
- _description = "Stage of work order"
- _order = "sequence, id"
-
- _columns = {
- 'name': fields.char('Stage Name', required=True, translate=True),
- 'sequence': fields.integer('Sequence', help="Used to order stages. Lower is better."),
- 'fold': fields.boolean('Folded in Kanban View', help='This stage is folded in the kanban view when there are no records in that stage to display.'),
- }
-
- _defaults = {
- 'sequence': 1,
- 'fold': False,
- }
-
-class work_order(osv.Model):
- _name = 'work.order'
- _description = 'Produktionsschein'
- _inherit = ['mail.thread']
-
- _columns = {
- 'name': fields.char('Bezeichnung', size=30, required=True),
- 'sale_id': fields.many2one('sale.order', 'Verkaufsauftrag', required=True),
- 'partner_id': fields.many2one('res.partner', 'Kunde', required=True),
- 'parter_id_street': fields.related('partner_id', 'street', type="char", relation="res.partner", string="Strasse", store=False),
- 'parter_id_zip': fields.related('partner_id', 'zip', type="char", relation="res.partner", string="Postleitzahl", store=False),
- 'parter_id_city': fields.related('partner_id', 'city', type="char", relation="res.partner", string="Stadt", store=False),
- 'user_id': fields.many2one('res.users', 'Bearbeiter'),
- 'stage_id': fields.many2one('work.order.stage', 'Status', track_visibility='onchange', select=True),
- 'date_of_creation': fields.date('Erstellungsdatum'),
- 'line_ids': fields.one2many('work.order.line', 'order_id', 'Positionen', copy=True),
- 'work_date': fields.char('Produktionsstermin',size=120),
- 'work_address': fields.text('Produktionsadresse'),
- 'graphic_text': fields.text('Anmerkungen'),
- }
-
- def _get_default_stage_id(self, cr, uid, context=None):
- """ Gives default stage_id """
- return self.pool.get('work.order.stage').search(cr, uid, [], context=context)[0]
-
- _defaults = {
- 'name': '/',
- 'date_of_creation': fields.date.context_today,
- 'stage_id': lambda s, cr, uid, c: s._get_default_stage_id(cr, uid, c),
- }
-
- def create(self, cr, uid, vals, context=None):
- if context is None:
- context = {}
- if vals.get('name', '/') == '/':
- vals['name'] = self.pool.get('ir.sequence').get(cr, uid, 'work.order') or '/'
- new_id = super(work_order, self).create(cr, uid, vals, context=context)
- return new_id
-
- def print_quotation(self, cr, uid, ids, context=None):
- '''
- This function prints the work order
- '''
- return self.pool['report'].get_action(cr, uid, ids, 'cam_reports.report_workorder', context=context)
diff --git a/ext/custom-addons/cam_work_order/cam_work_order_data.xml b/ext/custom-addons/cam_work_order/cam_work_order_data.xml
deleted file mode 100644
index f65a7689..00000000
--- a/ext/custom-addons/cam_work_order/cam_work_order_data.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
-
- Work Order
- work.order
-
-
-
- Work Order
- work.order
- PS-
- 5
-
-
-
-
-
- Neu
- 1
- False
-
-
-
- In Bearbeitung
- 2
- False
-
-
-
- Bereit für Produktion
- 3
- False
-
-
-
- Terminisiert
- 4
- False
-
-
-
- Erledigt
- 5
- False
-
-
-
diff --git a/ext/custom-addons/cam_work_order/cam_work_order_view.xml b/ext/custom-addons/cam_work_order/cam_work_order_view.xml
deleted file mode 100644
index aced5091..00000000
--- a/ext/custom-addons/cam_work_order/cam_work_order_view.xml
+++ /dev/null
@@ -1,211 +0,0 @@
-
-
-
-
-
-
- work_order_form
- work.order
-
-
-
-
-
-
-
- work_order_kanban
- work.order
- kanban
-
-
-
-
-
+
+
+
\ 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 @@
+
+
+
+
+
+
Disc.(%)
+
+
+
+
+
+
+
+
+
+ Order #
+ Quotation #
+
+
+
+
+
+
+ display:none
+
+
+
+
+
+
+
Total Without Taxes
+
+
+
+
+
+
Taxes
+
+
+
+
+
+
Total
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ 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 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
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 @@
-
-
-
-
-
-
-
-
-
-
-