From 52d653f2418f0f2558759b32827b7a8a8e284b1a Mon Sep 17 00:00:00 2001 From: Stefan Katzensteiner Date: Mon, 24 Nov 2014 15:03:39 +0100 Subject: [PATCH] Created dir structure, imported files from cam-int and whole cam-ext --- .gitignore | 4 + dev/odoo-server.conf | 14 + ext/config/logrotate | 5 + ext/config/odoo-443.nginx | 66 ++++ ext/config/odoo-80.nginx | 50 +++ ext/config/odoo-server.conf | 35 ++ ext/config/odoo-server.init | 85 +++++ ext/custom-addons/cam_custom/__init__.py | 25 ++ ext/custom-addons/cam_custom/__openerp__.py | 40 +++ ext/custom-addons/cam_custom/cam_custom.py | 81 +++++ .../cam_custom/cam_custom_data.xml | 7 + .../cam_custom/cam_custom_view.xml | 68 ++++ .../cam_custom/static/description/icon.png | Bin 0 -> 2870 bytes .../cam_custom/static/src/img/favicon.ico | Bin 0 -> 1150 bytes .../cam_custom/views/custom_theme.xml | 11 + ext/custom-addons/cam_max_width/__init__.py | 23 ++ .../cam_max_width/__openerp__.py | 40 +++ .../cam_max_width/static/description/icon.png | Bin 0 -> 2870 bytes .../static/src/css/max_width.css | 10 + .../cam_max_width/views/max_width.xml | 12 + ext/custom-addons/cam_reports/__init__.py | 24 ++ ext/custom-addons/cam_reports/__openerp__.py | 37 ++ ext/custom-addons/cam_reports/cam_reports.py | 55 +++ .../cam_reports/report/account.invoice.rml | 208 ++++++++++++ ext/custom-addons/cam_reports/report/page.rml | 103 ++++++ .../cam_reports/report/purchase.order.rml | 246 ++++++++++++++ .../cam_reports/report/purchase.quotation.rml | 188 ++++++++++ .../cam_reports/report/sale.order.rml | 199 +++++++++++ .../cam_reports/report/stock.picking.list.rml | 117 +++++++ .../cam_reports/reports_data.xml | 29 ++ .../cam_reports/static/description/icon.png | Bin 0 -> 2870 bytes .../cam_reports/static/src/img/warning.png | Bin 0 -> 6439 bytes ext/custom-addons/cam_testenv/__init__.py | 25 ++ ext/custom-addons/cam_testenv/__openerp__.py | 48 +++ ext/custom-addons/cam_testenv/background.xcf | Bin 0 -> 80910 bytes .../cam_testenv/controllers/__init__.py | 25 ++ .../controllers/testenv_controller.py | 66 ++++ .../cam_testenv/static/description/icon.png | Bin 0 -> 2870 bytes .../cam_testenv/static/src/css/testenv.css | 10 + .../static/src/img/back-testenv.jpg | Bin 0 -> 22037 bytes .../cam_testenv/static/src/js/testenv.js | 32 ++ ext/custom-addons/cam_work_order/__init__.py | 25 ++ .../cam_work_order/__openerp__.py | 40 +++ .../cam_work_order/cam_work_order.py | 163 +++++++++ .../cam_work_order/cam_work_order_data.xml | 49 +++ .../cam_work_order/cam_work_order_view.xml | 211 ++++++++++++ .../security/ir.model.access.csv | 5 + .../static/description/icon.png | Bin 0 -> 2870 bytes .../oerp_no_phoning_home/README.md | 15 + .../oerp_no_phoning_home/__init__.py | 1 + .../oerp_no_phoning_home/__openerp__.py | 29 ++ .../oerp_no_phoning_home/base_view.xml | 7 + .../oerp_no_phoning_home/mail.py | 25 ++ .../oerp_no_phoning_home/mail_data.xml | 26 ++ .../static/src/img/icon.png | Bin 0 -> 11169 bytes .../static/src/js/announcement.js | 13 + .../static/src/xml/base.xml | 17 + ext/scripts/odoo-backup.sh | 33 ++ setup/cam | 5 + setup/install-odoo-7.sh | 150 ++++++++ setup/install_nginx.sh | 34 ++ setup/install_odoo.sh | 149 ++++++++ setup/install_tools.sh | 28 ++ setup/lib/__init__.py | 4 + setup/lib/cli.py | 89 +++++ setup/lib/config_at.py | 111 ++++++ setup/lib/environments.py | 28 ++ setup/lib/functions.py | 321 ++++++++++++++++++ 68 files changed, 3566 insertions(+) create mode 100644 .gitignore create mode 100644 dev/odoo-server.conf create mode 100644 ext/config/logrotate create mode 100644 ext/config/odoo-443.nginx create mode 100644 ext/config/odoo-80.nginx create mode 100644 ext/config/odoo-server.conf create mode 100755 ext/config/odoo-server.init create mode 100644 ext/custom-addons/cam_custom/__init__.py create mode 100644 ext/custom-addons/cam_custom/__openerp__.py create mode 100644 ext/custom-addons/cam_custom/cam_custom.py create mode 100644 ext/custom-addons/cam_custom/cam_custom_data.xml create mode 100644 ext/custom-addons/cam_custom/cam_custom_view.xml create mode 100644 ext/custom-addons/cam_custom/static/description/icon.png create mode 100644 ext/custom-addons/cam_custom/static/src/img/favicon.ico create mode 100644 ext/custom-addons/cam_custom/views/custom_theme.xml create mode 100755 ext/custom-addons/cam_max_width/__init__.py create mode 100755 ext/custom-addons/cam_max_width/__openerp__.py create mode 100644 ext/custom-addons/cam_max_width/static/description/icon.png create mode 100644 ext/custom-addons/cam_max_width/static/src/css/max_width.css create mode 100644 ext/custom-addons/cam_max_width/views/max_width.xml create mode 100644 ext/custom-addons/cam_reports/__init__.py create mode 100644 ext/custom-addons/cam_reports/__openerp__.py create mode 100644 ext/custom-addons/cam_reports/cam_reports.py create mode 100644 ext/custom-addons/cam_reports/report/account.invoice.rml create mode 100644 ext/custom-addons/cam_reports/report/page.rml create mode 100644 ext/custom-addons/cam_reports/report/purchase.order.rml create mode 100644 ext/custom-addons/cam_reports/report/purchase.quotation.rml create mode 100644 ext/custom-addons/cam_reports/report/sale.order.rml create mode 100644 ext/custom-addons/cam_reports/report/stock.picking.list.rml create mode 100644 ext/custom-addons/cam_reports/reports_data.xml create mode 100644 ext/custom-addons/cam_reports/static/description/icon.png create mode 100644 ext/custom-addons/cam_reports/static/src/img/warning.png create mode 100644 ext/custom-addons/cam_testenv/__init__.py create mode 100644 ext/custom-addons/cam_testenv/__openerp__.py create mode 100644 ext/custom-addons/cam_testenv/background.xcf create mode 100644 ext/custom-addons/cam_testenv/controllers/__init__.py create mode 100644 ext/custom-addons/cam_testenv/controllers/testenv_controller.py create mode 100644 ext/custom-addons/cam_testenv/static/description/icon.png create mode 100644 ext/custom-addons/cam_testenv/static/src/css/testenv.css create mode 100644 ext/custom-addons/cam_testenv/static/src/img/back-testenv.jpg create mode 100644 ext/custom-addons/cam_testenv/static/src/js/testenv.js create mode 100644 ext/custom-addons/cam_work_order/__init__.py create mode 100644 ext/custom-addons/cam_work_order/__openerp__.py create mode 100644 ext/custom-addons/cam_work_order/cam_work_order.py create mode 100644 ext/custom-addons/cam_work_order/cam_work_order_data.xml create mode 100644 ext/custom-addons/cam_work_order/cam_work_order_view.xml create mode 100644 ext/custom-addons/cam_work_order/security/ir.model.access.csv create mode 100644 ext/custom-addons/cam_work_order/static/description/icon.png create mode 100644 ext/custom-addons/oerp_no_phoning_home/README.md create mode 100644 ext/custom-addons/oerp_no_phoning_home/__init__.py create mode 100644 ext/custom-addons/oerp_no_phoning_home/__openerp__.py create mode 100644 ext/custom-addons/oerp_no_phoning_home/base_view.xml create mode 100644 ext/custom-addons/oerp_no_phoning_home/mail.py create mode 100644 ext/custom-addons/oerp_no_phoning_home/mail_data.xml create mode 100644 ext/custom-addons/oerp_no_phoning_home/static/src/img/icon.png create mode 100644 ext/custom-addons/oerp_no_phoning_home/static/src/js/announcement.js create mode 100644 ext/custom-addons/oerp_no_phoning_home/static/src/xml/base.xml create mode 100755 ext/scripts/odoo-backup.sh create mode 100755 setup/cam create mode 100755 setup/install-odoo-7.sh create mode 100755 setup/install_nginx.sh create mode 100755 setup/install_odoo.sh create mode 100755 setup/install_tools.sh create mode 100644 setup/lib/__init__.py create mode 100755 setup/lib/cli.py create mode 100644 setup/lib/config_at.py create mode 100644 setup/lib/environments.py create mode 100755 setup/lib/functions.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..2375512a --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.pyc +.project +.pydevproject +.settings diff --git a/dev/odoo-server.conf b/dev/odoo-server.conf new file mode 100644 index 00000000..fbb4c00b --- /dev/null +++ b/dev/odoo-server.conf @@ -0,0 +1,14 @@ +[options] + +xmlrpc_port = 8080 +; This is the password that allows database operations: +; admin_passwd = admin +db_host = False +db_port = 5436 +db_user = False +db_password = False + +addons_path = odoo/addons,ext/addons +timezone = Europe/Brussels + +dbfilter_test = ['.*',] \ No newline at end of file diff --git a/ext/config/logrotate b/ext/config/logrotate new file mode 100644 index 00000000..060ec54d --- /dev/null +++ b/ext/config/logrotate @@ -0,0 +1,5 @@ +/var/log/odoo/*.log { + copytruncate + missingok + notifempty +} diff --git a/ext/config/odoo-443.nginx b/ext/config/odoo-443.nginx new file mode 100644 index 00000000..40750f45 --- /dev/null +++ b/ext/config/odoo-443.nginx @@ -0,0 +1,66 @@ +server { + listen 80 default_server; + server_name "xxxxx"; + + # Strict Transport Security + # add_header Strict-Transport-Security max-age=2592000; + rewrite ^ https://$server_name$request_uri? permanent; +} + + +upstream odoo-server { + server 127.0.0.1:8069 fail_timeout=3000s; +} + +server { + listen 443 ssl default_server; + server_name _; + + + # Specifies the maximum accepted body size of a client request, + # as indicated by the request header Content-Length. + client_max_body_size 200m; + + # log files + access_log /var/log/nginx/odoo-access.log; + error_log /var/log/nginx/odoo-error.log; + + # increase proxy buffer to handle some OpenERP web requests + proxy_buffers 16 64k; + proxy_buffer_size 128k; + + # SSL config + ssl_certificate /etc/nginx/ssl/server.crt; + ssl_certificate_key /etc/nginx/ssl/server.key; + ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2; + ssl_ciphers HIGH:!aNULL:!MD5; + + location / { + proxy_pass http://odoo-server; + # force timeouts if the backend dies + proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; + proxy_read_timeout 300s; + + # set headers + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forward-For $proxy_add_x_forwarded_for; + + # Let the OpenERP web service know that we're using HTTPS, otherwise + # it will generate URL using http:// and not https:// + # proxy_set_header X-Forwarded-Proto https; + + # by default, do not forward anything + proxy_redirect off; + } + + # cache some static data in memory for 60mins. + # under heavy load this should relieve stress on the OpenERP web interface a bit. + location ~* /web/static/ { + proxy_cache_valid 200 60m; + proxy_buffering on; + expires 864000; + proxy_pass http://odoo-server; + } + +} diff --git a/ext/config/odoo-80.nginx b/ext/config/odoo-80.nginx new file mode 100644 index 00000000..6fb7c17c --- /dev/null +++ b/ext/config/odoo-80.nginx @@ -0,0 +1,50 @@ +upstream odoo-server { + server 127.0.0.1:8069 fail_timeout=3000s; +} + +server { + listen 80 default_server; + server_name _; + + + # Specifies the maximum accepted body size of a client request, + # as indicated by the request header Content-Length. + client_max_body_size 200m; + + # log files + access_log /var/log/nginx/odoo-access.log; + error_log /var/log/nginx/odoo-error.log; + + # increase proxy buffer to handle some OpenERP web requests + proxy_buffers 16 64k; + proxy_buffer_size 128k; + + location / { + proxy_pass http://odoo-server; + # force timeouts if the backend dies + proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; + proxy_read_timeout 300s; + + # set headers + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forward-For $proxy_add_x_forwarded_for; + + # Let the OpenERP web service know that we're using HTTPS, otherwise + # it will generate URL using http:// and not https:// + # proxy_set_header X-Forwarded-Proto https; + + # by default, do not forward anything + proxy_redirect off; + } + + # cache some static data in memory for 60mins. + # under heavy load this should relieve stress on the OpenERP web interface a bit. + location ~* /web/static/ { + proxy_cache_valid 200 60m; + proxy_buffering on; + expires 864000; + proxy_pass http://odoo-server; + } + +} diff --git a/ext/config/odoo-server.conf b/ext/config/odoo-server.conf new file mode 100644 index 00000000..32c2d163 --- /dev/null +++ b/ext/config/odoo-server.conf @@ -0,0 +1,35 @@ +[options] +addons_path = /opt/odoo/odoo/addons,/opt/odoo/ext/addons +admin_passwd = c76EVdqj + +db_host = False +db_name = False +db_password = False +db_port = False +db_user = odoo + +debug_mode = False +list_db = True +log_level = error +logfile = /var/log/odoo/odoo-server.log + +max_cron_threads = 1 +workers = 1 + +xmlrpc_interface = 127.0.0.1 +xmlrpc_port = 8069 + +timezone = Europe/Brussels + +# 5 min +#limit_time_cpu = 300 +# 10 min +#limit_time_real = 600 + +# input DMI: +limit_time_cpu = 3000 +limit_time_real = 6000 + +# if DB > 150MB, otherwise "AccessDenied" error occurs +# 10 GB +limit_memory_hard = 10000000000 diff --git a/ext/config/odoo-server.init b/ext/config/odoo-server.init new file mode 100755 index 00000000..2f0aac66 --- /dev/null +++ b/ext/config/odoo-server.init @@ -0,0 +1,85 @@ +#!/bin/sh + +### BEGIN INIT INFO +# Provides: odoo-server +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Should-Start: $network +# Should-Stop: $network +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Enterprise Resource Management software +# Description: Open ERP is a complete ERP and CRM software. +### END INIT INFO + +PATH=/bin:/sbin:/usr/bin:/usr/local/bin +DAEMON=/opt/odoo/odoo/openerp-server +NAME=odoo-server +DESC=odoo-server + +#FILTER="^%d$" +# Specify the user name (Default: openerp). +USER=odoo + +# Specify an alternate config file (Default: /etc/openerp-server.conf). +CONFIGFILE="/opt/odoo/ext/config/odoo-server.conf" + +# pidfile +PIDFILE=/var/run/$NAME.pid + +# Additional options that are passed to the Daemon. +DAEMON_OPTS="-c $CONFIGFILE" + +[ -x $DAEMON ] || exit 0 +[ -f $CONFIGFILE ] || exit 0 + +checkpid() { + [ -f $PIDFILE ] || return 1 + pid=`cat $PIDFILE` + [ -d /proc/$pid ] && return 0 + return 1 +} + +case "${1}" in + start) + echo -n "Starting ${DESC}: " + + start-stop-daemon --start --quiet --pidfile ${PIDFILE} \ + --chuid ${USER} --background --make-pidfile \ + --exec ${DAEMON} -- ${DAEMON_OPTS} + + echo "${NAME}." + ;; + + stop) + echo -n "Stopping ${DESC}: " + + start-stop-daemon --stop --quiet --pidfile ${PIDFILE} \ + --oknodo + + echo "${NAME}." + ;; + + restart|force-reload) + echo -n "Restarting ${DESC}: " + + start-stop-daemon --stop --quiet --pidfile ${PIDFILE} \ + --oknodo + + sleep 1 + + start-stop-daemon --start --quiet --pidfile ${PIDFILE} \ + --chuid ${USER} --background --make-pidfile \ + --exec ${DAEMON} -- ${DAEMON_OPTS} + + echo "${NAME}." + ;; + + *) + N=/etc/init.d/${NAME} + echo "Usage: ${NAME} {start|stop|restart|force-reload}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/ext/custom-addons/cam_custom/__init__.py b/ext/custom-addons/cam_custom/__init__.py new file mode 100644 index 00000000..384274dc --- /dev/null +++ b/ext/custom-addons/cam_custom/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +import cam_custom + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + diff --git a/ext/custom-addons/cam_custom/__openerp__.py b/ext/custom-addons/cam_custom/__openerp__.py new file mode 100644 index 00000000..d1ae3a28 --- /dev/null +++ b/ext/custom-addons/cam_custom/__openerp__.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + + +{ + 'name': 'Camadeus Anpassungen', + 'category': 'Custom', + 'version': '1.0', + 'description': """Individuelle Anpassungen""", + 'author': 'camadeus GmbH', + 'website': 'http://www.camadeus.at', + 'depends': ['crm','sale','mail','account'], + 'data': [ + 'cam_custom_view.xml', + 'cam_custom_data.xml', + 'views/custom_theme.xml', + ], + 'installable': True, + 'auto_install': False, +} + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/ext/custom-addons/cam_custom/cam_custom.py b/ext/custom-addons/cam_custom/cam_custom.py new file mode 100644 index 00000000..aeb2ff42 --- /dev/null +++ b/ext/custom-addons/cam_custom/cam_custom.py @@ -0,0 +1,81 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved +# $Id$ +# +# 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 . +# +############################################################################## + +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 res_partner(osv.osv): + _inherit = 'res.partner' + + @api.model + def fields_view_get_address(self, arch): + """ verhindert das Überschreiben von address_format """ + return arch + +class mail_notification(osv.Model): + _inherit = 'mail.notification' + + # override original function + def get_signature_footer(self, cr, uid, user_id, res_model=None, res_id=None, context=None, user_signature=True): + """ Format a standard footer for notification emails (such as pushed messages + notification or invite emails). + Format: +

--
+ Administrator +

+
+ Sent from Your Company using OpenERP. +
+ """ + footer = "" + if not user_id: + return footer + + # add user signature + user = self.pool.get("res.users").browse(cr, SUPERUSER_ID, [user_id], context=context)[0] + if user_signature: + if user.signature: + signature = user.signature + else: + signature = "--
%s" % user.name + footer = tools.append_content_to_html(footer, signature, plaintext=False) + + # add company signature +# if user.company_id.website: +# website_url = ('http://%s' % user.company_id.website) if not user.company_id.website.lower().startswith(('http:', 'https:')) \ +# else user.company_id.website +# company = "%s" % (website_url, user.company_id.name) +# else: +# company = user.company_id.name +# sent_by = _('Sent by %(company)s using %(odoo)s') +# +# signature_company = '
%s' % (sent_by % { +# 'company': company, +# 'odoo': "Odoo" +# }) +# footer = tools.append_content_to_html(footer, signature_company, plaintext=False, container_tag='div') + + return footer \ No newline at end of file diff --git a/ext/custom-addons/cam_custom/cam_custom_data.xml b/ext/custom-addons/cam_custom/cam_custom_data.xml new file mode 100644 index 00000000..3018e5f9 --- /dev/null +++ b/ext/custom-addons/cam_custom/cam_custom_data.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/ext/custom-addons/cam_custom/cam_custom_view.xml b/ext/custom-addons/cam_custom/cam_custom_view.xml new file mode 100644 index 00000000..e2cf755e --- /dev/null +++ b/ext/custom-addons/cam_custom/cam_custom_view.xml @@ -0,0 +1,68 @@ + + + + + + tree,kanban,form + + + + + + + + partner_section_form + res.partner + + + +
+ + + +
+
+ + +
+ + + +
+
+
+
+ + + + product_template_variant_kanban + product.template + + + + + + + + + product_template_custom_tree + product.template + + + + + + + + + + + + + + tree,form,kanban + + + +
+
diff --git a/ext/custom-addons/cam_custom/static/description/icon.png b/ext/custom-addons/cam_custom/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..fd7ee3b90ede569d07369b51f5036c9c0de4e9b2 GIT binary patch literal 2870 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 + + + + + + \ No newline at end of file diff --git a/ext/custom-addons/cam_max_width/__init__.py b/ext/custom-addons/cam_max_width/__init__.py new file mode 100755 index 00000000..49a09e55 --- /dev/null +++ b/ext/custom-addons/cam_max_width/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: + diff --git a/ext/custom-addons/cam_max_width/__openerp__.py b/ext/custom-addons/cam_max_width/__openerp__.py new file mode 100755 index 00000000..881f882c --- /dev/null +++ b/ext/custom-addons/cam_max_width/__openerp__.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + + +{ + '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 new file mode 100644 index 0000000000000000000000000000000000000000..fd7ee3b90ede569d07369b51f5036c9c0de4e9b2 GIT binary patch literal 2870 zcma);XE+-Q8-}B$h*9cO(W+W8YHu|osHhRtII2;j?V%bgv4WyawMr>zjo4~b6^+KO zy-LNX+F~ST?OlX?&iVKK`>ywTp7(j5>w5p+(Uum*9Kb6;006*Y0yDHe+m`=`<-(cA zac`HLEe4deF%(eRE3kZaTyQltHU!ZBne6&P+*!lw19LzD0Bk(}hyj342c4D7XcKcI zW-<`Sp$PPl67mE9fR!eO`Zhu1Yh%GazvlUywloDOO)Yim{s0j;a?#54`AdvV-hL1F$(fA01)q<;M!IO%tp|u$GvJx2X^o z{e$_6>Uy12iCX}UM;Tn_!q-B9f=&!Di11?=YpE7i0{aIN@a9|6r)mA&i}5GnGjAmA zw?8N;oOBeYJ2jyH^V+O%bLbv+WF!W)E!MJl71JBjo>IMoB*ISnuY#+*p-Y-9k#tlt zN3)hh97P~ReMf1eUC&eQt{3C+%+vHZJHvgC=G-KFm`vkWq48V}shZ26XbA!3QzC{ar}NWJJhF{igFlv7-q zf4m)BjX(%7Dy8PlIj{6HuQk$-#WEd}YdU>FjRe8^-6wO$=g~t>jCi$lVW<#-`9n3f zWvDNEp08hVUip=?LYls4xnx4#oR1drA$6d|r6o{K^xN(P03Gh4<^{jlz^^P78mfw5 zdqm-2kKmfAbp|<)fp~diLoigXT=5c>{aFKppr8J%h~Pb+0EStuja%ZEf->8Do417; z0_8>09&Qa4_d|uT9?$xW>E7$t6NEKE7w&4rUIx0nHPcrMek>OwdQvy5ahXI4g)`3{f$S(I%G@1pfg z)0k2}E1D~io212z-rs+0VnUQm zy*C}pWzHodbU(Ft%(9$CQ+xV1cdS~RhWz5cemoUld+XXXk;pjJmqU-JGYFsqsKVo)?DwZ_)op)|L)g1n@r%~EAz{rOPPApX#SOmoO20b&BvCv4EOE0@;x$ks7mU;&W$TkIR;WOYrwy2btFLyeSOrCKp%-t^oLp(U0m^@$C*{7T}B@oIqV z#;WkO7@RsGMY}am6zL|+qF0}^t(DY&#e4?X3>wK-2w!XY(5g*ma$j>Q#`$_+0`bKKfRHs;;Mj&PL;*W*EtQca3ZS zr^@AKAVv!@(Q@?}FXW$)0FP%C!irRcHuKu{wK0L}JThehQyy67AAE~BFQ7rz6o$h) zpNeV@LWp}D&LM(!t)4X0?VF|3FFhv&!u(`Wr^Kj_$iY;zTz=gGIhqnuk0#hso=^}e z7~Sug|FS!Darg}p9Y9^WB9V!C-Ju%ZsvK7RQ}l#_GHdYUU+ZEl?dQ^}RDKKdIhtYE zKRGeM7Uaywx~wws{S<_YAV68ka2FCZQ;3k2P$Qgbpj-nO)#$2bW}$2K@*{Q*jFby zrX$i8?lZin&Y{|m@K*83En;;!+7g3lLvc688W-fz`H8Tmub-cAn+luppv>O7$?F_9Zu44tSoitvJqrgZGlRnLom-s9DUHdeV`}OR!MeC)a%+;7mpBwLo<9P8=MKZAS%|7|oWyn+c6V31EINKDtsoNn$z)P2zw)cX zK>=-_h%R2<(Ilg%PJ$-`lEJeIb$C2T&qYK(%f!lx`>e{bWNCEi|2bs=_m3!%-(H2>n5T$7cRT_qoL##|;hnL1V}_&-*)wY5!0Shp1HtvHlFU@f+%zc+Zvi6Z-t42)LC zl$Y;(EGfxf{3Yc|0Br@)1~sR-Sr}hEa8z;QT4g#6mQ|> zp%@deeoHy*!=^x|@PDqHhX~CS=H`kVYd~CFgx|k^|JmVdRI2jdN&%~XReDdy^(|gs zUr<$~Opx|{YAwVPV^(U>Xtbq+18Y-P5-vT&i=WyVPk$HRH3rt+ZN;dS=uC(Y1>#Qw zFY+Lf`pV|O8^s{y94th?xe;-$GwvF7bGB9HuP+hqD&4&qTB+*Zf|bZSHa2bRWRh9t zJre_i^I$O8#@3dAoKU-Qqq~dr#%HF9f%a7I@bJ*a#>R*C$Ct7N8X8(0oSf|0T^{ss z4|-2Ip<;Y``Uy|h>7Y$AY`FaC9gPnKty z;Rb~FUuXIVJ + + + + + + diff --git a/ext/custom-addons/cam_reports/__init__.py b/ext/custom-addons/cam_reports/__init__.py new file mode 100644 index 00000000..a45901fe --- /dev/null +++ b/ext/custom-addons/cam_reports/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +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 new file mode 100644 index 00000000..eeac5896 --- /dev/null +++ b/ext/custom-addons/cam_reports/__openerp__.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + + +{ + '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 new file mode 100644 index 00000000..46d5125b --- /dev/null +++ b/ext/custom-addons/cam_reports/cam_reports.py @@ -0,0 +1,55 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved +# $Id$ +# +# 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 . +# +############################################################################## + +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 = 'pittoresk_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 \ 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 new file mode 100644 index 00000000..fe1b2cd0 --- /dev/null +++ b/ext/custom-addons/cam_reports/report/account.invoice.rml @@ -0,0 +1,208 @@ + + + + + + + + + + + [[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 '' ]] + + + + + Kundennr.: + + + [[ o.partner_id.ref or removeParentNode('tr') ]] + + + + + Ihre Referenz: + + + [[ o.name ]] + + + + + Ansprechpartner: + + + [[ (o.user_id and o.user_id.name) or '' ]] + + + + + Ihre UID: + + + [[ o.partner_id.commercial_partner_id and o.partner_id.commercial_partner_id.vat or '' ]] + + + + + Datum: + + + [[ formatLang(o.date_invoice,date = True) ]] + + + + + + + Rechnung [[ ((o.type == 'out_invoice' and (o.state == 'open' or o.state == 'paid')) or removeParentNode('para')) and '' ]] [[ o.number ]] + PRO-FORMA [[ ((o.type == 'out_invoice' and o.state == 'proforma2') or removeParentNode('para')) and '' ]] + Rechnungsentwurf [[ ((o.type == 'out_invoice' and o.state == 'draft') or removeParentNode('para')) and '' ]] + Stornierte Rechnung [[ ((o.type == 'out_invoice' and o.state == 'cancel') or removeParentNode('para')) and '' ]] [[ o.number ]] + Stornorechnung [[ (o.type=='out_refund' or removeParentNode('para')) and '' ]] [[ o.number ]] + Stornorechnung [[ (o.type=='in_refund' or removeParentNode('para')) and '' ]] [[ o.number ]] + Rechnung [[ (o.type=='in_invoice' or removeParentNode('para')) and '' ]] [[ o.number ]] + + + + + + + + Pos + + + Art-nr. + + + Bezeichnung + + + Menge + + + E-Preis + + + + + + Gesamtpreis + + + + [[repeatIn(o.invoice_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.quantity, digits=2)[-2:]=='00' and formatLang(line.quantity, digits=0) or formatLang(line.quantity, digits=2)]] + + + [[ formatLang(line.price_unit,digits=2) ]] + + + [[ line.discount <> 0 and (formatLang(line.discount) + '%') or '' ]] + + + [[ formatLang(line.price_subtotal,digits=2 ) ]] + + +
+ + + + + + + + Zwischensumme in € + + + [[ formatLang(o.amount_untaxed,digits=2 )]] + + + + + + + + MwSt. in € + + + [[ formatLang(o.amount_tax,digits=2 ) ]] + + + + + + + + Rechnungsbetrag in € + + + [[ formatLang(o.amount_total,digits=2 ) ]] + + + + + + + [[ (o.comment or '').split('\n\n')[0] ]] +
[[ repeatIn((o.comment or '').split('\n\n')[1:],'paragraphs') ]] + + [[ paragraphs ]] +
+ + + + + + + Zahlungsbedingungen: + + + [[ (o.payment_term and o.payment_term.note) or removeParentNode('blockTable') ]] + + + + + + Vielen Dank für Ihren Auftrag! + + + Bis zur Bezahlung aller Ansprüche aus den Geschäftsverbindungen behält sich der Verkäufer das Eigentum an seinen Warenlieferungen vor. Es gelten unsere Allgemeinen Geschäftsbedingungen. + + + +
+
diff --git a/ext/custom-addons/cam_reports/report/page.rml b/ext/custom-addons/cam_reports/report/page.rml new file mode 100644 index 00000000..eff25669 --- /dev/null +++ b/ext/custom-addons/cam_reports/report/page.rml @@ -0,0 +1,103 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [[ company.logo]] + + + + [[ company.partner_id.name ]], [[ company.partner_id.street ]], [[ company.partner_id.zip ]] [[ company.partner_id.city ]] + + + + + Seite + + + + + + + + -- + -- + -- + + + + + + + + [[ company.partner_id.street ]] + [[ company.partner_id.zip ]] [[ company.partner_id.city ]] + UID: [[company.vat ]] + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/ext/custom-addons/cam_reports/report/purchase.order.rml b/ext/custom-addons/cam_reports/report/purchase.order.rml new file mode 100644 index 00000000..23619f7a --- /dev/null +++ b/ext/custom-addons/cam_reports/report/purchase.order.rml @@ -0,0 +1,246 @@ + + + + + + + + + + [[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.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 '' ]] + + + + + + + + Ihr Ansprechpartner + + + + Name: + + + [[ (user.name) or '' ]] + + + + + Telefon: + + + [[ user.partner_id.phone or '' ]] + + + + + E-Mail: + + + [[ user.partner_id.email or '' ]] + + + + + + + + + + + + + Datum: + + + [[ formatLang(time.strftime('%Y-%m-%d'),date=True) ]] + + + + + Referenz: + + + [[ o.partner_ref or '' ]] + + + + + + + + + Bestellung [[ o.name ]] + + + + + + + Pos + + + Art.nr. + + + Bezeichnung + + + gepl. + Lieferung + + + Menge + + + E-Preis + + + G-Preis + + + [[repeatIn(o.order_line,'line')]] + + + + + + + [[ line.product_id and line.product_id.default_code ]] + + + [[ (line.name or '').split('\n\n')[0] ]] +
[[ repeatIn((line.name or '').split('\n\n')[1:],'paragraphs') ]] + + [[ paragraphs ]] +
+ + Ihre Artikelnr.: [[ line.supplier_code or removeParentNode('para')]] + + + [[ formatLang(line.date_planned,date=True) ]] + + + + [[ formatLang(line.product_qty, digits=2)[-2:]=='00' and formatLang(line.product_qty, digits=0) or formatLang(line.product_qty, digits=2) ]] + + + [[ formatLang(line.price_unit, digits=2) ]] + + + [[ formatLang(line.price_subtotal, digits=2) ]] + + +
+ + + + + [[ o.amount_tax > 0 or removeParentNode('tr') ]] + + + + + Nettobetrag in €: + + + [[o.pricelist_id.currency_id.name]] + + + [[ formatLang(o.amount_untaxed, digits=2)]] + + + [[ o.amount_tax > 0 or removeParentNode('tr') ]] + + + + + MwSt. in €: + + + [[ o.pricelist_id.currency_id.name ]] + + + [[ formatLang(o.amount_tax, digits=2) ]] + + + + + + + + Gesamt in €: + + + [[ o.pricelist_id.currency_id.name ]] + + + [[ formatLang(o.amount_total,digits=2) ]] + + + + + + + [[ (o.notes or '').split('\n\n')[0] ]] +
[[ repeatIn((o.notes or '').split('\n\n')[1:],'paragraphs') ]] + + [[ paragraphs ]] +
+ + + + [[o.incoterm_id or removeParentNode('blockTable') ]] + + + Lieferbedingung: + + + [[o.incoterm_id and o.incoterm_id.name or '' ]] + + + + [[o.payment_term_id or removeParentNode('blockTable') ]] + + + Zahlungsbedingungen: + + + [[o.payment_term_id and o.payment_term_id.note or '' ]] + + + + + + + + Mit freundlichen Grüßen, + + + + + [[ company.signature]] + + + + B. Neumeier + +
+
diff --git a/ext/custom-addons/cam_reports/report/purchase.quotation.rml b/ext/custom-addons/cam_reports/report/purchase.quotation.rml new file mode 100644 index 00000000..bfab0ae1 --- /dev/null +++ b/ext/custom-addons/cam_reports/report/purchase.quotation.rml @@ -0,0 +1,188 @@ + + + + + + + + + + [[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.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 '' ]] + + + + + + + + Ihr Ansprechpartner + + + + Name: + + + [[ (user.name) or '' ]] + + + + + Telefon: + + + [[ user.partner_id.phone or '' ]] + + + + + E-Mail: + + + [[ user.partner_id.email or '' ]] + + + + + + + + + + + + + + Datum: + + + [[ formatLang(time.strftime('%Y-%m-%d'),date=True) ]] + + + + + Referenz: + + + [[ o.partner_ref or '' ]] + + + + + + + + + Anfrage [[ o.name ]] + + + + + + + Pos + + + Art.nr. + + + Bezeichnung + + + gepl. + Lieferung + + + Menge + + + [[repeatIn(o.order_line,'line')]] + + + + + + + [[ line.product_id and line.product_id.default_code ]] + + + [[ (line.name or '').split('\n\n')[0] ]] +
[[ repeatIn((line.name or '').split('\n\n')[1:],'paragraphs') ]] + + [[ paragraphs ]] +
+ + Ihre Artikelnr.: [[ line.supplier_code or removeParentNode('para')]] + + + [[ formatLang(line.date_planned,date=True) ]] + + + + [[ formatLang(line.product_qty, digits=2)[-2:]=='00' and formatLang(line.product_qty, digits=0) or formatLang(line.product_qty, digits=2) ]] + + +
+ + + + [[ (o.notes or '').split('\n\n')[0] ]] +
[[ repeatIn((o.notes or '').split('\n\n')[1:],'paragraphs') ]] + + [[ paragraphs ]] +
+ + + + [[o.incoterm_id or removeParentNode('blockTable') ]] + + + Lieferbedingung: + + + [[o.incoterm_id and o.incoterm_id.name or '' ]] + + + + [[o.payment_term_id or removeParentNode('blockTable') ]] + + + Zahlungsbedingungen: + + + [[o.payment_term_id and o.payment_term_id.note or '' ]] + + + + + + + + Mit freundlichen Grüßen, + + + + + [[ company.signature]] + + + + B. Neumeier + +
+
diff --git a/ext/custom-addons/cam_reports/report/sale.order.rml b/ext/custom-addons/cam_reports/report/sale.order.rml new file mode 100644 index 00000000..43e7e83e --- /dev/null +++ b/ext/custom-addons/cam_reports/report/sale.order.rml @@ -0,0 +1,199 @@ + + + + + + + + + + + [[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 '' ]] + + + + + + Ihre Referenz: + + + [[ o.client_order_ref ]] + + + + + Ansprechpartner: + + + [[ (o.user_id and o.user_id.name) or '' ]] + + + [[ o.user_id and o.user_id.phone or removeParentNode('tr') ]] + + Tel.: + + + [[ (o.user_id and o.user_id.phone) or '' ]] + + + + + Ihre UID: + + + [[ o.partner_id.commercial_partner_id and o.partner_id.commercial_partner_id.vat 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) ]] + + + + + +
+ [[ 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 + + + E-Preis + + + + + + 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) ]] + + + [[ formatLang(line.price_unit,digits=2) ]] + + + [[ line.discount <> 0 and (formatLang(line.discount) + '%') or '' ]] + + + [[ formatLang(line.price_subtotal,digits=2 ) ]] + + +
+ + + + + + + + Zwischensumme in € + + + [[ formatLang(o.amount_untaxed,digits=2 )]] + + + + + + + + MwSt. in € + + + [[ formatLang(o.amount_tax,digits=2 ) ]] + + + + + + + + Rechnungsbetrag in € + + + [[ formatLang(o.amount_total,digits=2 ) ]] + + + + + + + [[ (o.note or '').split('\n\n')[0] ]] +
[[ repeatIn((o.note or '').split('\n\n')[1:],'paragraphs') ]] + + [[ paragraphs ]] +
+ + + + + + + Zahlungsziele: + + + [[ (o.payment_term and o.payment_term.note) or removeParentNode('blockTable') ]] + + + + + + +
+
diff --git a/ext/custom-addons/cam_reports/report/stock.picking.list.rml b/ext/custom-addons/cam_reports/report/stock.picking.list.rml new file mode 100644 index 00000000..3b99dac0 --- /dev/null +++ b/ext/custom-addons/cam_reports/report/stock.picking.list.rml @@ -0,0 +1,117 @@ + + + + + + + + + + + + [[ repeatIn(objects,'picking') ]] [[ picking.partner_id and setLang(picking.partner_id.lang) ]] + + [[ 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 and picking.partner_id.street ) or '']] + [[ (picking.partner_id and picking.partner_id.street2) or removeParentNode('para') ]] + [[ (picking.partner_id and picking.partner_id.zip) or '' ]] [[ (picking.partner_id and picking.partner_id.city) or '' ]] + [[ (picking.partner_id and picking.partner_id.state_id and picking.partner_id.state_id.name) or removeParentNode('para')]] + [[ (picking.partner_id and picking.partner_id.country_id and picking.partner_id.country_id.name) or '' ]] + + + + + + Bestellung: + + + [[ picking.origin ]] + + + + + Datum: + + + [[ formatLang(picking.date_done, date=True) or formatLang(time.strftime('%Y-%m-%d'),date=True) ]] + + + + + Referenz: + + + [[ picking.sale_id and picking.sale_id.client_order_ref or '' ]] + + + + + Kundennr.: + + + [[ picking.partner_id and picking.partner_id.commercial_partner_id and picking.partner_id.commercial_partner_id.ref or '' ]] + + + + + + Lieferschein [[ picking.name ]] + + + + + + + Pos + + + Art.nr. + + + Bezeichnung + + + Menge + + + [[ repeatIn([line for line in picking.move_lines if line.state <> 'cancel'],'move_lines') ]] + + + + + + + [[ move_lines.product_id.default_code ]] + + + [[ (move_lines.name or '').split('\n\n')[0] ]] +
[[ repeatIn((move_lines.name or '').split('\n\n')[1:],'paragraphs') ]] + + [[ paragraphs ]] +
+ + + [[ formatLang(move_lines.product_qty, digits=0) ]] + + +
+ + + + [[ (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 new file mode 100644 index 00000000..eecd06db --- /dev/null +++ b/ext/custom-addons/cam_reports/reports_data.xml @@ -0,0 +1,29 @@ + + + + + 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 + + + \ 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 new file mode 100644 index 0000000000000000000000000000000000000000..fd7ee3b90ede569d07369b51f5036c9c0de4e9b2 GIT binary patch literal 2870 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 literal 0 HcmV?d00001 diff --git a/ext/custom-addons/cam_testenv/__init__.py b/ext/custom-addons/cam_testenv/__init__.py new file mode 100644 index 00000000..41102c7b --- /dev/null +++ b/ext/custom-addons/cam_testenv/__init__.py @@ -0,0 +1,25 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved +# $Id$ +# +# 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 controllers +# 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 new file mode 100644 index 00000000..1ddf5d6a --- /dev/null +++ b/ext/custom-addons/cam_testenv/__openerp__.py @@ -0,0 +1,48 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved +# $Id$ +# +# 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': '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* + + """, + 'author': 'camadeus Consulting GmbH', + 'website': 'http://www.camadeus.at', + 'depends': ['web','base'], + 'js': [ + 'static/src/js/testenv.js', + ], + 'css': [ + 'static/src/css/testenv.css', + ], + '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 new file mode 100644 index 0000000000000000000000000000000000000000..eb98e7b84edfe7f67b81b6d8ff0e7b16b12cefe1 GIT binary patch literal 80910 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
e~W&f)4f_ELy0IPP@2F({YOv& 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 jv&vH#FiOpS5xEo@vo_@`J@1-i`!Zx). All Rights Reserved +# $Id$ +# +# 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 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 new file mode 100644 index 00000000..02e70dbd --- /dev/null +++ b/ext/custom-addons/cam_testenv/controllers/testenv_controller.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- + +import ast +import base64 +import csv +import glob +import itertools +import logging +import operator +import datetime +import hashlib +import os +import re +import simplejson +import time +import urllib +import urllib2 +import urlparse +import xmlrpclib +import zlib +from xml.etree import ElementTree +from cStringIO import StringIO + +import babel.messages.pofile +import werkzeug.utils +import werkzeug.wrappers +try: + import xlwt +except ImportError: + xlwt = None + +import openerp +import openerp.modules.registry +from openerp.tools.translate import _ +from openerp.tools import config + +from openerp.addons.web import http + + +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/static/description/icon.png b/ext/custom-addons/cam_testenv/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..fd7ee3b90ede569d07369b51f5036c9c0de4e9b2 GIT binary patch literal 2870 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 * { + opacity: 0.9; + background-color: rgba(0,0,0,0); +} \ No newline at end of file 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 new file mode 100644 index 0000000000000000000000000000000000000000..f52bed96835d507e19e549d43079c950f5b2b309 GIT binary patch literal 22037 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 Hv;Y4AQS6RW literal 0 HcmV?d00001 diff --git a/ext/custom-addons/cam_testenv/static/src/js/testenv.js b/ext/custom-addons/cam_testenv/static/src/js/testenv.js new file mode 100644 index 00000000..e47184c5 --- /dev/null +++ b/ext/custom-addons/cam_testenv/static/src/js/testenv.js @@ -0,0 +1,32 @@ +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_work_order/__init__.py b/ext/custom-addons/cam_work_order/__init__.py new file mode 100644 index 00000000..88b64a62 --- /dev/null +++ b/ext/custom-addons/cam_work_order/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +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 new file mode 100644 index 00000000..6e1e2c8c --- /dev/null +++ b/ext/custom-addons/cam_work_order/__openerp__.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + + +{ + '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 new file mode 100644 index 00000000..4c846835 --- /dev/null +++ b/ext/custom-addons/cam_work_order/cam_work_order.py @@ -0,0 +1,163 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2009 Tiny SPRL (). All Rights Reserved +# $Id$ +# +# 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 . +# +############################################################################## + +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 new file mode 100644 index 00000000..f65a7689 --- /dev/null +++ b/ext/custom-addons/cam_work_order/cam_work_order_data.xml @@ -0,0 +1,49 @@ + + + + + + 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 new file mode 100644 index 00000000..aced5091 --- /dev/null +++ b/ext/custom-addons/cam_work_order/cam_work_order_view.xml @@ -0,0 +1,211 @@ + + + + + + + work_order_form + work.order + +
+ +
+
+ +

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+
+
+
+ + + + work_order_kanban + work.order + kanban + + + + +
+ +
+
+ +
+
+
+  
+   +
+
+ +
+
+
+
+ + + + + + + + + work_order_search + work.order + + + + + + + + + + + + + + + + + + work_order_tree + work.order + + + + + + + + + + + + + + Produktionsscheine + ir.actions.act_window + work.order + form + kanban,tree,form + +

+ Hier klicken um einen neuen Produktionsschein zu erstellen. +

+ Verwaltung von Produktionsscheinen. +

+
+
+ + + + work_order_stages_form + work.order.stage + +
+
+ +

+ +

+ + + + + + + + +
+ + + + + + + Status + ir.actions.act_window + work.order.stage + form + tree,form + +

+ Hier klicken um einen neuen Status für Produktionsschein zu erstellen. +

+ Verwaltung von Status von Produktionsscheinen. +

+
+
+ + + + + + + + + + + + view_order_work_form + sale.order + + + + + 17 + + + + diff --git a/ext/custom-addons/cam_work_order/security/ir.model.access.csv b/ext/custom-addons/cam_work_order/security/ir.model.access.csv new file mode 100644 index 00000000..e20db9d7 --- /dev/null +++ b/ext/custom-addons/cam_work_order/security/ir.model.access.csv @@ -0,0 +1,5 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +modify_work_order,modify_order_sale_user,model_work_order,base.group_sale_salesman,1,1,1,1 +modify_work_order_line,modify_order_line_sale_user,model_work_order_line,base.group_sale_salesman,1,1,1,1 +access_work_category,work_category_user,model_work_category,base.group_sale_salesman,1,0,0,0 +modify_work_category,work_category_manager,model_work_category,base.group_sale_manager,1,1,1,1 diff --git a/ext/custom-addons/cam_work_order/static/description/icon.png b/ext/custom-addons/cam_work_order/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..fd7ee3b90ede569d07369b51f5036c9c0de4e9b2 GIT binary patch literal 2870 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 + + + + + + diff --git a/ext/custom-addons/oerp_no_phoning_home/mail.py b/ext/custom-addons/oerp_no_phoning_home/mail.py new file mode 100644 index 00000000..bb0980a1 --- /dev/null +++ b/ext/custom-addons/oerp_no_phoning_home/mail.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- + +from openerp.osv import osv +import logging + +_logger = logging.getLogger(__name__) + +from openerp.tools import config + +config['publisher_warranty_url'] = '' + + +class publisher_warranty_contract(osv.osv): + _inherit = 'publisher_warranty.contract' + + def update_notification(self, cr, uid, ids, cron_mode=True, + context=None): + + _logger.info("NO More Spying Stuff") + + return True + + +publisher_warranty_contract() + diff --git a/ext/custom-addons/oerp_no_phoning_home/mail_data.xml b/ext/custom-addons/oerp_no_phoning_home/mail_data.xml new file mode 100644 index 00000000..5315dc4b --- /dev/null +++ b/ext/custom-addons/oerp_no_phoning_home/mail_data.xml @@ -0,0 +1,26 @@ + + + + + + + Update Notification + + + 1 + weeks + -1 + + + + + 1000 + + + + + diff --git a/ext/custom-addons/oerp_no_phoning_home/static/src/img/icon.png b/ext/custom-addons/oerp_no_phoning_home/static/src/img/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..9ad73d74e66cc4b16f1901d708c576c2bbac87d7 GIT binary patch literal 11169 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 literal 0 HcmV?d00001 diff --git a/ext/custom-addons/oerp_no_phoning_home/static/src/js/announcement.js b/ext/custom-addons/oerp_no_phoning_home/static/src/js/announcement.js new file mode 100644 index 00000000..0d7e1fde --- /dev/null +++ b/ext/custom-addons/oerp_no_phoning_home/static/src/js/announcement.js @@ -0,0 +1,13 @@ +openerp.oerp_no_phoning_home = function(instance) { + instance.web.WebClient.include({ + show_application: function() { + return $.when(this._super.apply(this, arguments)); + }, + _ab_location: function(dbuuid) { + // return _.str.sprintf('https://services.openerp.com/openerp-enterprise/ab/css/%s.css', dbuuid); + }, + show_annoucement_bar: function() { + return; + } + }); +}; diff --git a/ext/custom-addons/oerp_no_phoning_home/static/src/xml/base.xml b/ext/custom-addons/oerp_no_phoning_home/static/src/xml/base.xml new file mode 100644 index 00000000..97da789c --- /dev/null +++ b/ext/custom-addons/oerp_no_phoning_home/static/src/xml/base.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/ext/scripts/odoo-backup.sh b/ext/scripts/odoo-backup.sh new file mode 100755 index 00000000..67c3efc6 --- /dev/null +++ b/ext/scripts/odoo-backup.sh @@ -0,0 +1,33 @@ +#!/bin/sh +#dump the OpenERP DB (postgreSQL) +#author: Camadeus GmbH + +hostname=`/bin/hostname` + + +dbnames=`psql -d postgres -c "SELECT datname FROM pg_database WHERE NOT datistemplate AND datname <> 'postgres'" --tuples-only` + +# Dump DBs +for db in $dbnames +do + echo "creating backup for db: " $db + date=`date +"%Y%m%d_%H%M%N"` + filename="/var/pgdump/${hostname}_${db}_${date}.sql" + pg_dump -E UTF-8 -F p -b -f $filename $db + chmod 600 $filename + gzip $filename +done + + +########################################## +## Housekeeping +########################################## +for file in `find /var/pgdump/ -mtime +30 -type f -name '*.sql.gz'` +do + echo "deleting: " $file + rm $file +done + + +exit 0 + diff --git a/setup/cam b/setup/cam new file mode 100755 index 00000000..697c9f10 --- /dev/null +++ b/setup/cam @@ -0,0 +1,5 @@ +#!/usr/bin/env python +from lib import cli + +if __name__ == "__main__": + cli.main() diff --git a/setup/install-odoo-7.sh b/setup/install-odoo-7.sh new file mode 100755 index 00000000..4934fce2 --- /dev/null +++ b/setup/install-odoo-7.sh @@ -0,0 +1,150 @@ +#!/bin/bash +################################################################################ +# Script for Installation: ODOO Saas4/Trunk server on Ubuntu 14.04 LTS +# Author: André Schenkels, ICTSTUDIO 2014 +#------------------------------------------------------------------------------- +# +# This script will install ODOO Server on +# clean Ubuntu 14.04 Server +#------------------------------------------------------------------------------- +# USAGE: +# +# odoo-install +# +# EXAMPLE: +# ./odoo-install +# +################################################################################ + +##fixed parameters +OE_USER="odoo" +OE_HOME="/opt/$OE_USER" +OE_HOME_EXT="/opt/$OE_USER/$OE_USER-server" + +#Enter version for checkout "7.0" for version 7.0, "saas-4, saas-5 (opendays version) and "master" for trunk +OE_VERSION="7.0" + +#set the superadmin password +OE_SUPERADMIN="c76EVdqj" +OE_CONFIG="$OE_USER-server" + +#-------------------------------------------------- +# Set Locale en_US.UTF-8 +#-------------------------------------------------- +#echo -e "\n---- Set en_US.UTF-8 Locale ----" +#sudo cp /etc/default/locale /etc/default/locale.BACKUP +#sudo rm -rf /etc/default/locale +#echo -e "* Change server config file" +#sudo su root -c "echo 'LC_ALL="en_US.UTF-8"' >> /etc/default/locale" +#sudo su root -c "echo 'LANG="en_US.UTF-8"' >> /etc/default/locale" +#sudo su root -c "echo 'LANGUAGE="en_US:en"' >> /etc/default/locale" + +#-------------------------------------------------- +# Update Server +#-------------------------------------------------- +echo -e "\n---- Update Server ----" +sudo apt-get upgrade -y +sudo apt-get update + +#-------------------------------------------------- +# Install PostgreSQL Server +#-------------------------------------------------- +echo -e "\n---- Install PostgreSQL Server ----" +sudo apt-get install postgresql -y + +#echo -e "\n---- PostgreSQL $PG_VERSION Settings ----" +#sudo sed -i s/"#listen_addresses = 'localhost'"/"listen_addresses = '*'"/g /etc/postgresql/9.3/main/postgresql.conf + +echo -e "\n---- Creating the ODOO PostgreSQL User ----" +sudo su - postgres -c "createuser -s $OE_USER" 2> /dev/null || true + +#-------------------------------------------------- +# Install Dependencies +#-------------------------------------------------- +echo -e "\n---- Install tool packages ----" +sudo apt-get install wget git bzr python-pip -y + +echo -e "\n---- Install python packages ----" +sudo apt-get install python-gevent python-dateutil python-feedparser python-ldap python-libxslt1 python-lxml python-mako python-openid python-psycopg2 python-pybabel python-pychart python-pydot python-pyparsing python-reportlab python-simplejson python-tz python-vatnumber python-vobject python-webdav python-werkzeug python-xlwt python-yaml python-zsi python-docutils python-psutil python-mock python-unittest2 python-jinja2 python-pypdf python-pdftools python-setuptools python-pybabel python-imaging python-matplotlib python-reportlab-accel python-openssl python-egenix-mxdatetime python-paramiko antiword python-decorator poppler-utils python-requests python-passlib -y + +sudo pip install gevent gevent_psycopg2 psycogreen passlib + +echo -e "\n---- Install latest gdata-python-client ----" +cd /tmp +wget http://gdata-python-client.googlecode.com/files/gdata-2.0.18.tar.gz +tar zxvf gdata-2.0.18.tar.gz +cd gdata-2.0.18/ +sudo python setup.py install + + +echo -e "\n---- Install Wkhtmltopdf 0.12.1 ----" +sudo wget http://downloads.sourceforge.net/project/wkhtmltopdf/0.12.1/wkhtmltox-0.12.1_linux-trusty-amd64.deb +sudo dpkg -i wkhtmltox-*.deb +sudo cp /usr/local/bin/wkhtmltopdf /usr/bin +sudo cp /usr/local/bin/wkhtmltoimage /usr/bin + +echo -e "\n---- Create ODOO system user ----" +sudo adduser --system --quiet --shell=/bin/bash --home=$OE_HOME --gecos 'ODOO' --group $OE_USER +sudo adduser $OE_USER sudo +sudo cp /root/.profile $OE_HOME +sudo chown $OE_USER:$OE_USER $OE_HOME/.profile +sudo cp /root/.bashrc $OE_HOME +sudo chown $OE_USER:$OE_USER $OE_HOME/.bashrc + +echo -e "\n---- Create Log directory ----" +sudo mkdir /var/log/$OE_USER +sudo chown $OE_USER:$OE_USER /var/log/$OE_USER +sudo chmod 700 /var/log/$OE_USER + +echo -e "\n---- Set Logrotate config ----" +sudo ln -s /opt/odoo/ext/config/logrotate /etc/logrotate.d/odoo + +#-------------------------------------------------- +# Install ODOO +#-------------------------------------------------- + +echo -e "\n---- Setting permissions on home folder ----" +sudo chown -R $OE_USER:$OE_USER $OE_HOME/* + +echo -e "Odoo Init File" +sudo ln -s /opt/odoo/exit/config/odoo-server.init /etc/init.d/odoo-server + +echo -e "\n---- Setup Git ----" +sudo -u odoo mkdir /opt/odoo/odoo.git +sudo -u odoo mkdir /opt/odoo/odoo +sudo -u odoo mkdir /opt/odoo/ext.git +sudo -u odoo mkdir /opt/odoo/ext +cd /opt/odoo/odoo.git +sudo -u odoo git init --bare +cd /opt/odoo/ext.git +sudo -u odoo git init --bare + +sudo -u odoo touch /opt/odoo/odoo.git/hooks/post-receive +sudo -u odoo echo -e '#!/bin/bash' >> /opt/odoo/odoo.git/hooks/post-receive +sudo -u odoo echo -e 'git --work-tree=/opt/odoo/odoo --git-dir=/opt/odoo/odoo.git checkout -f' >> /opt/odoo/odoo.git/hooks/post-receive +sudo -u odoo chmod +x /opt/odoo/odoo.git/hooks/post-receive + +sudo -u odoo touch /opt/odoo/ext.git/hooks/post-receive +sudo -u odoo echo -e '#!/bin/bash' >> /opt/odoo/ext.git/hooks/post-receive +sudo -u odoo echo -e 'git --work-tree=/opt/odoo/ext --git-dir=/opt/odoo/ext.git checkout -f' >> /opt/odoo/ext.git/hooks/post-receive +sudo -u odoo chmod +x /opt/odoo/ext.git/hooks/post-receive + +echo "Done! The ODOO server can be started with /etc/init.d/$OE_CONFIG" +echo "Please reboot the server now so that Wkhtmltopdf is working with your install." + +echo "Done! Please specify a password for user '$OE_USER'" +sudo passwd $OE_USER + +## +## HERE git push of local is required +## +## Local commands: +#git init +#git remote add odoo https://github.com/odoo/odoo.git +#git pull odoo 8.0 +#git remote add production odoo@134.119.17.66:/opt/odoo/odoo.git +#git config --global push.default simple # only push if on remote exists branch with same name +#git push --set-upstream production master + +echo -e "* Start ODOO on Startup" +sudo update-rc.d $OE_CONFIG defaults diff --git a/setup/install_nginx.sh b/setup/install_nginx.sh new file mode 100755 index 00000000..599ece6f --- /dev/null +++ b/setup/install_nginx.sh @@ -0,0 +1,34 @@ +#!/bin/bash +################################################################################ +# Script for Installation: Nginx for Odoo v8.0 on Ubuntu 14.04 LTS +# Author: Andreas Brückl | Camdeus Consulting +#------------------------------------------------------------------------------- +# +# This script will install nginx on +# clean Ubuntu 14.04 Server +#------------------------------------------------------------------------------- +################################################################################ + +#--------------------------------------------- +# Install +#-------------------------------------------------- +echo -e "\n---- Install nginx ----" +sudo apt-get install nginx -y + +#-------------------------------------------------- +# Configure Nginx +#-------------------------------------------------- +sudo ln -s /opt/odoo/ext/config/odoo-80.nginx /etc/nginx/sites-enabled/odoo-80 +sudo rm /etc/nginx/sites-enabled/default +sudo service nginx restart + +#-------------------------------------------------- +# Configure Nginx for SSL/HTTPS Port 443 +#-------------------------------------------------- + +#sudo touch /etc/nginx/sites-available/odoo-443 +#sudo ln -s /etc/nginx/sites-available/odoo-443 /etc/nginx/sites-enabled +#sudo mkdir /etc/nginx/ssl +#sudo chmod 600 ssl + +#sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/nginx/ssl/server.key -out /etc/nginx/ssl/server.crt diff --git a/setup/install_odoo.sh b/setup/install_odoo.sh new file mode 100755 index 00000000..6399d7a7 --- /dev/null +++ b/setup/install_odoo.sh @@ -0,0 +1,149 @@ +#!/bin/bash +################################################################################ +# Script for Installation: ODOO Saas4/Trunk server on Ubuntu 14.04 LTS +# Author: André Schenkels, ICTSTUDIO 2014 +#------------------------------------------------------------------------------- +# +# This script will install ODOO Server on +# clean Ubuntu 14.04 Server +#------------------------------------------------------------------------------- +# USAGE: +# +# odoo-install +# +# EXAMPLE: +# ./odoo-install +# +################################################################################ + +##fixed parameters +OE_USER="odoo" +OE_HOME="/opt/$OE_USER" +OE_HOME_EXT="/opt/$OE_USER/$OE_USER-server" + +#Enter version for checkout "7.0" for version 7.0, "saas-4, saas-5 (opendays version) and "master" for trunk +OE_VERSION="8.0" + +#set the superadmin password +OE_SUPERADMIN="PzdX2fYj" +OE_CONFIG="$OE_USER-server" + +#-------------------------------------------------- +# Set Locale en_US.UTF-8 +#-------------------------------------------------- +#echo -e "\n---- Set en_US.UTF-8 Locale ----" +#sudo cp /etc/default/locale /etc/default/locale.BACKUP +#sudo rm -rf /etc/default/locale +#echo -e "* Change server config file" +#sudo su root -c "echo 'LC_ALL="en_US.UTF-8"' >> /etc/default/locale" +#sudo su root -c "echo 'LANG="en_US.UTF-8"' >> /etc/default/locale" +#sudo su root -c "echo 'LANGUAGE="en_US:en"' >> /etc/default/locale" + +#-------------------------------------------------- +# Update Server +#-------------------------------------------------- +echo -e "\n---- Update Server ----" +sudo apt-get upgrade -y +sudo apt-get update + +#-------------------------------------------------- +# Install PostgreSQL Server +#-------------------------------------------------- +echo -e "\n---- Install PostgreSQL Server ----" +sudo apt-get install postgresql -y + +#echo -e "\n---- PostgreSQL $PG_VERSION Settings ----" +#sudo sed -i s/"#listen_addresses = 'localhost'"/"listen_addresses = '*'"/g /etc/postgresql/9.3/main/postgresql.conf + +echo -e "\n---- Creating the ODOO PostgreSQL User ----" +sudo su - postgres -c "createuser -s $OE_USER" 2> /dev/null || true + +#-------------------------------------------------- +# Install Dependencies +#-------------------------------------------------- +echo -e "\n---- Install tool packages ----" +sudo apt-get install wget git bzr python-pip -y + +echo -e "\n---- Install python packages ----" +sudo apt-get install python-gevent python-dateutil python-feedparser python-ldap python-libxslt1 python-lxml python-mako python-openid python-psycopg2 python-pybabel python-pychart python-pydot python-pyparsing python-reportlab python-simplejson python-tz python-vatnumber python-vobject python-webdav python-werkzeug python-xlwt python-yaml python-zsi python-docutils python-psutil python-mock python-unittest2 python-jinja2 python-pypdf python-pdftools python-setuptools python-pybabel python-imaging python-matplotlib python-reportlab-accel python-openssl python-egenix-mxdatetime python-paramiko antiword python-decorator poppler-utils python-requests python-passlib -y + +sudo pip install gevent gevent_psycopg2 psycogreen passlib psycogreen + +echo -e "\n---- Install latest gdata-python-client ----" +cd /tmp +wget http://gdata-python-client.googlecode.com/files/gdata-2.0.18.tar.gz +tar zxvf gdata-2.0.18.tar.gz +cd gdata-2.0.18/ +sudo python setup.py install + + +echo -e "\n---- Install Wkhtmltopdf 0.12.1 ----" +sudo wget http://downloads.sourceforge.net/project/wkhtmltopdf/0.12.1/wkhtmltox-0.12.1_linux-wheezy-amd64.deb +sudo dpkg -i wkhtmltox-0.12.1_linux-wheezy-amd64.deb +sudo cp /usr/local/bin/wkhtmltopdf /usr/bin +sudo cp /usr/local/bin/wkhtmltoimage /usr/bin + +echo -e "\n---- Create ODOO system user ----" +sudo adduser --system --quiet --shell /bin/bash --home $OE_HOME --gecos 'ODOO' --group $OE_USER +sudo adduser $OE_USER sudo +sudo cp /root/.profile $OE_HOME +sudo chown $OE_USER:$OE_USER $OE_HOME/.profile +sudo cp /root/.bashrc $OE_HOME +sudo chown $OE_USER:$OE_USER $OE_HOME/.bashrc + +echo -e "\n---- Create Log directory ----" +sudo mkdir /var/log/$OE_USER +sudo chown $OE_USER:$OE_USER /var/log/$OE_USER +sudo chmod 700 /var/log/$OE_USER + +echo -e "\n---- Set Logrotate config ----" +sudo ln -s /opt/odoo/odoo/config/logrotate /etc/logrotate.d/odoo + +#-------------------------------------------------- +# Install ODOO +#-------------------------------------------------- + +echo -e "\n---- Setting permissions on home folder ----" +sudo chown -R $OE_USER:$OE_USER $OE_HOME/* + +echo -e "Odoo Init File" +sudo ln -s /opt/odoo/ext/config/odoo-server.init /etc/init.d/odoo-server + +echo -e "\n---- Setup Git ----" +sudo -u odoo mkdir /opt/odoo/odoo.git +sudo -u odoo mkdir /opt/odoo/odoo +cd /opt/odoo/odoo.git +sudo -u odoo git init --bare +sudo -u odoo touch /opt/odoo/odoo.git/hooks/post-receive +sudo -u odoo echo -e '#!/bin/bash' >> /opt/odoo/odoo.git/hooks/post-receive +sudo -u odoo echo -e 'git --work-tree=/opt/odoo/odoo --git-dir=/opt/odoo/odoo.git checkout -f' >> /opt/odoo/odoo.git/hooks/post-receive +sudo -u odoo chmod +x /opt/odoo/odoo.git/hooks/post-receive + +sudo -u odoo mkdir /opt/odoo/ext.git +sudo -u odoo mkdir /opt/odoo/ext +cd /opt/odoo/ext.git +sudo -u odoo git init --bare +sudo -u odoo touch /opt/odoo/ext.git/hooks/post-receive +sudo -u odoo echo -e '#!/bin/bash' >> /opt/odoo/ext.git/hooks/post-receive +sudo -u odoo echo -e 'git --work-tree=/opt/odoo/ext --git-dir=/opt/odoo/ext.git checkout -f' >> /opt/odoo/ext.git/hooks/post-receive +sudo -u odoo chmod +x /opt/odoo/ext.git/hooks/post-receive + +echo "Done! The ODOO server can be started with /etc/init.d/$OE_CONFIG" +echo "Please reboot the server now so that Wkhtmltopdf is working with your install." + +echo "Done! Please specify a password for user '$OE_USER'" +sudo passwd $OE_USER + +## +## HERE git push of local is required +## +## Local commands: +#git init +#git remote add odoo https://github.com/odoo/odoo.git +#git pull odoo 8.0 +#git remote add production odoo@134.119.17.66:/opt/odoo/odoo.git +#git config --global push.default simple # only push if on remote exists branch with same name +#git push --set-upstream production master + +echo -e "* Start ODOO on Startup" +sudo update-rc.d $OE_CONFIG defaults diff --git a/setup/install_tools.sh b/setup/install_tools.sh new file mode 100755 index 00000000..6b1cc349 --- /dev/null +++ b/setup/install_tools.sh @@ -0,0 +1,28 @@ + +#!/bin/bash +################################################################################ +# Script for Installation: tools for Odoo v8.0 installation +# Author: Andreas Brückl | Camdeus Consulting +#------------------------------------------------------------------------------- +################################################################################ + +##fixed parameters +#openerp +OE_USER="odoo" + +# Execute with user "odoo" + +#--------------------------------------------- +# Setup daily backup +#-------------------------------------------------- +echo -e "\n---- Setup daily backup ----" +sudo mkdir /var/pgdump +sudo chown $OE_USER: /var/pgdump +sudo chmod 700 /var/pgdump + +# Install Cron job +sudo -u $OE_USER crontab -l > /tmp/tmpcron +echo "# Odoo backup daily at 1:30 a.m." >> /tmp/tmpcron +echo "30 01 * * * /opt/odoo/ext/scripts/odoo-backup.sh" >> /tmp/tmpcron +sudo -u $OE_USER crontab /tmp/tmpcron +sudo rm /tmp/tmpcron diff --git a/setup/lib/__init__.py b/setup/lib/__init__.py new file mode 100644 index 00000000..5bea60ea --- /dev/null +++ b/setup/lib/__init__.py @@ -0,0 +1,4 @@ +import cli +import config_at +import environments +import functions \ No newline at end of file diff --git a/setup/lib/cli.py b/setup/lib/cli.py new file mode 100755 index 00000000..12ab6d6a --- /dev/null +++ b/setup/lib/cli.py @@ -0,0 +1,89 @@ +# -*- coding: utf-8 -*- + +from functions import CamadeusFunctions +from config_at import Config +from environments import ENVIRONMENTS +import sys, getopt + +def main(): + + def _usage(): + print 'cam.py [create|setup|rollout|update] []' + sys.exit(3) + + argv = sys.argv[1:] + if not len(argv) == 2: + if len(argv) == 3 and argv[1] == 'update': # 'update' requires additional param 'module_name' + pass + else: + _usage() + + cmd = argv[1] + config = Config() + + env = ENVIRONMENTS.get(argv[0],False) + if not env: + _usage() + + instance = CamadeusFunctions(env, config) + + methods = False + + if cmd == 'test': + methods = [ + 'login', + ] + + if cmd == 'create': + methods = [ + 'create_db', + 'login', + 'install_module_sale', + 'setup_accounting', + 'setup_accounting2', + 'set_admin_rights', + ] + + if cmd == 'setup': + methods = [ + 'login', + 'uninstall_chat', + 'install_modules', + 'base_config', + 'sale_config', + 'set_date_format', + 'set_company', + 'set_taxes', + 'set_uom', + 'set_steuerzuordnung', + ] + + if cmd == 'rollout': + methods = [ + 'login', + 'set_dokumentennummern', + ] + + if cmd == 'update': + instance.config.module_name = argv[2] + methods = [ + 'login', + 'update_module', + ] + + + if not methods: + _usage() + + print env + + for method in methods: + res = getattr(instance, method)() + print "%s: %s" % (res and "OK " or "ERROR ", getattr(instance, method).__doc__) + if not res: + return False + + print "\nAbgeschlossen." + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/setup/lib/config_at.py b/setup/lib/config_at.py new file mode 100644 index 00000000..f72892ca --- /dev/null +++ b/setup/lib/config_at.py @@ -0,0 +1,111 @@ +# -*- coding: utf-8 -*- + +class Config(): + + def __init__(self): + + self.chart_of_accounts = 'l10n_at' + self.sales_tax = '20% MwSt' + self.purchase_tax = '20% VSt' + self.chart_template_id = 2 # Austrian Chart of Account + + self.company_data = { + 'name': 'Camadeus GmbH', + 'street': 'Kriehubergasse 16', + 'street2': False, + 'city': 'Wien', + 'zip': '1050', + 'phone': '+43 1 78910 96 70', + 'fax': False, + 'email': 'office@camadeus.at', + 'website': 'http://www.camadeus.at', + 'company_registry': '280076b ', + 'country_id': 'at', # "de" für deutschland + 'logo': False, + 'vat': 'ATU 62991855 ', + 'rml_header1': False, + 'vat_check_vies': True, + 'tax_calculation_rounding_method': 'round_globally', + #'rml_header' : './ext/addons/custom_reports/report/page.rml', # Report File + #'logo': './ext/addons/custom_reports/logo.png', + } + + self.valid_taxes = [ + '20% MwSt', + '10% MwSt', + '20% VSt', + '10% VSt', + ] + + # Aktive Steuerzuordnungen + self.valid_fiscal_positions = [ + #'Lieferant EU (ohne Ust-ID)', + #'Lieferant EU Unternehmen (mit USt-ID)', + #'Lieferant Ausland', + #'Kunde EU (ohne USt-ID)', + 'Kunde Ausland', + 'Kunde EU (ohne USt-ID)', + 'Kunde EU Unternehmen (mit USt-ID)', + ] + + # Allgemeine Einstellungen + self.base_config = { + 'module_portal': False, # Kundenportal + } + + # Einstellungen Verkauf + self.sale_config = { + 'group_sale_delivery_address': True, # Verschiedene Adressen für Rechnung und Lieferung + 'group_sale_pricelist': True, # Preislisten verwenden + 'group_discount_per_so_line': True, # Rabatte verwenden + 'group_uom': True, # Verwende Mengeneinheiten + } + + # Einstellungen Einkauf + self.purchase_config = { + 'group_purchase_pricelist': True, # Preislisten verwenden + } + + self.sequences = { + 'sale.order': { + 'number_next_actual': 2000, + 'prefix': 'A-', + 'padding': 5, + }, +# 'picking.out': { +# 'number_next_actual': 2000, +# 'prefix': 'L-', +# 'padding': 5, +# }, +# 'purchase.order': { +# 'number_next_actual': 2000, +# 'prefix': 'PO-', +# 'padding': 5, +# }, +# 'account.invoice': { +# 'number_next_actual': 2000, +# 'prefix': '14-', +# 'padding': 4, +# }, + } + + self.active_uoms = { + 'product.product_uom_unit': 'Stk.', + #'product.product_uom_meter': 'lfm', + #'product.product_uom_litre': 'l', + #'product.product_uom_hour': 'h', + } + + self.modules = [ + 'document', + 'auth_crypt', + 'cam_testenv', + #'cam_max_width', + #'oerp_no_phoning_home', + #'cam_custom', + #'custom_reports', + #'crm', + #'sale', + #'cam_hr_overtime', + #'cam_hr', + ] \ No newline at end of file diff --git a/setup/lib/environments.py b/setup/lib/environments.py new file mode 100644 index 00000000..5e629b70 --- /dev/null +++ b/setup/lib/environments.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- + +class Environment(): + + def __init__(self, host, port, dbname, username, pwd, admin_pw=False, basic_auth=False): + self.admin_pw = admin_pw + self.dbname = dbname + self.username = username + self.pwd = pwd + self.port = port + self.host = host + self.lang = 'de_DE' + self.basic_auth = basic_auth or ('user', 'pass') # HTTP authentification + + def __str__(self): + return """============================== +Host: %s +User: %s +DB: %s +Port: %s +==============================""" % (self.host, self.username, self.dbname, self.port) + + +ENVIRONMENTS = { + 'br': Environment('http://localhost', '8070', 'test13', 'admin', 'x', 'admin'), + 'br2': Environment('http://localhost', '8000', 'screenplane_1', 'admin', 'x', 'admin'), +} + \ No newline at end of file diff --git a/setup/lib/functions.py b/setup/lib/functions.py new file mode 100755 index 00000000..d029760d --- /dev/null +++ b/setup/lib/functions.py @@ -0,0 +1,321 @@ +# -*- coding: utf-8 -*- + +import xmlrpclib +import base64 +import os +import sys +import datetime +import json +import requests +from config_at import Config +from environments import ENVIRONMENTS + +class CamadeusFunctions(): + + def __init__(self, environment, config): + self.env = environment + self.config = config + + def create_db(self): + """Neue Datenbank erstellen""" + + payload = {'fields': [ {'name': 'super_admin_pwd', 'value': self.env.admin_pw}, + {'name': 'db_name', 'value': self.env.dbname}, + {'name': 'demo_data', 'value': False}, + {'name': 'db_lang', 'value': self.env.lang}, + {'name': 'create_admin_pwd', 'value': self.env.pwd}, + ] + } + payload = {'params': payload} + json_data = json.dumps(payload) + headers = {'content-type': 'application/json'} + r = requests.post('%s:%s/web/database/create' % (self.env.host,self.env.port), data=json_data, headers=headers, auth=self.env.basic_auth) + if r and r.json().get('result',False): + return True + else: + print "Error occured: %s" % r.json().get('error', '????') + return False + + def login(self): + """Login""" + + # Get the uid + sock_common = xmlrpclib.ServerProxy ('%s:%s/xmlrpc/common' % (self.env.host,self.env.port)) + self.uid = sock_common.login(self.env.dbname, self.env.username, self.env.pwd) + if not self.uid: + raise "Authentication Error" + self.sock = xmlrpclib.ServerProxy('%s:%s/xmlrpc/object' % (self.env.host,self.env.port)) + return True + + def _execute(self, *args): + return self.sock.execute(self.env.dbname, self.uid, self.env.pwd, *args) + + def _readAndReturnFile(self, filename, encode = ''): + fi = open (filename, 'r') + content = '' + if encode=='': + content = fi.read() + elif encode=='base64': + content = base64.b64encode(fi.read()) + else: + sys.exit(-1) + fi.close() + return content + + def set_company(self): + """Setze Unternehmensdaten (Allgemein, RML, Logo)""" + + vals = self.config.company_data + dummy,country_id = self._execute('ir.model.data', 'get_object_reference', 'base',vals['country_id']) + + # RML-Header ist nun ein function-Feld + #if vals.get('rml_header',False): + # vals['rml_header'] = self._readAndReturnFile(vals['rml_header']) + + if vals.get('logo',False): + vals['logo'] = self._readAndReturnFile(vals['logo'], encode = 'base64') + vals['country_id'] = country_id + c_ids = self._execute('res.company', 'search', [], ) + return self._execute('res.company', 'write', c_ids, vals) + + def set_taxes(self): + """Setze nicht benötigte Steuern auf inaktiv""" + + tax_ids = self._execute('account.tax', 'search', [('description','not in', self.config.valid_taxes)]) + return self._execute('account.tax', 'write', tax_ids, {'active': False}) + + def set_date_format(self): + """Setzen des Datumsformats """ + + lang_ids = self._execute('res.lang', 'search', [('code','=','de_DE')]) + if lang_ids: + vals = { + 'date_format': '%d.%m.%Y', + 'time_format': '%H:%M:%S', + 'grouping': '[3,3]', + 'thousands_sep': '.', + 'decimal_point': ',', + } + self._execute('res.lang', 'write', lang_ids, vals) + else: + return False + + lang_ids = self._execute('res.lang', 'search', [('code','=','en_US')]) + if lang_ids: + vals = { + 'grouping': '[3,3]', + } + self._execute('res.lang', 'write', lang_ids, vals) + else: + return False + + return True + +# def set_report_types(self): +# """Setzen der Report Types auf RML (PDF)""" +# +# report_names = ['purchase.report_purchaseorder', +# 'purchase.report_purchasequotation', +# 'account.report_invoice', +# 'sale.report_saleorder', +# 'stock.report_picking'] +# report_ids = self._execute('ir.actions.report.xml', 'search', [('report_name','in',report_names)]) +# return self._execute('ir.actions.report.xml', 'write', report_ids, {'report_type': 'pdf'}) + + def purchase_config(self): + """Basiskonfiguration für Einkauf laden""" + + if hasattr(self.config, 'purchase_config'): + vals = self._execute('purchase.config.settings', 'default_get', []) + vals.update(self.config.purchase_config) + wizard_id = self._execute('purchase.config.settings', 'create', vals) + return self._execute('purchase.config.settings', 'execute', [wizard_id]) + + def sale_config(self): + """Basiskonfiguration für Verkauf laden""" + + vals = self._execute('sale.config.settings', 'default_get', []) + vals.update(self.config.sale_config) + wizard_id = self._execute('sale.config.settings', 'create', vals) + return self._execute('sale.config.settings', 'execute', [wizard_id]) + + def base_config(self): + """Allgemeine Konfiguration laden""" + + vals = self._execute('base.config.settings', 'default_get', []) + vals.update(self.config.base_config) + wizard_id = self._execute('base.config.settings', 'create', vals) + return self._execute('base.config.settings', 'execute', [wizard_id]) + + def install_module_sale(self): + """Modul 'Sale' installieren""" + + modules_to_install = self._execute('ir.module.module', 'search', [('name','=','sale'),('state','!=','installed')]) + res = self._execute('ir.module.module', 'button_install', modules_to_install) + res = self._execute('base.module.upgrade', 'upgrade_module', modules_to_install) + return True + + def install_modules(self): + """Module installieren""" + + modules_to_install = self._execute('ir.module.module', 'search', [('name','in',self.config.modules),('state','!=','installed')]) + res = self._execute('ir.module.module', 'button_install', modules_to_install) + res = self._execute('base.module.upgrade', 'upgrade_module', modules_to_install) + return True + + def set_dokumentennummern(self): + """Dokumentennummern setzen""" + + seq_dict = self.config.sequences + + # Lieferschein + if seq_dict.get('picking.out',False): + picking_type_ids = self._execute('stock.picking.type', 'search', []) + picking_types = self._execute('stock.picking.type', 'read', picking_type_ids, ['sequence_id']) + s_ids = [t['sequence_id'][0] for t in picking_types] + if not self._execute('ir.sequence', 'write', s_ids, seq_dict.get('picking.out')): + return False + + # Angebot + if seq_dict.get('sale.order',False): + s_ids = self._execute('ir.sequence', 'search', [('code','=','sale.order')]) + if len(s_ids) != 1: + return False + if not self._execute('ir.sequence', 'write', s_ids, seq_dict.get('sale.order')): + return False + + # EK-Angebot + if seq_dict.get('purchase.order',False): + s_ids = self._execute('ir.sequence', 'search', [('code','=','purchase.order')]) + if len(s_ids) != 1: + return False + if not self._execute('ir.sequence', 'write', s_ids, seq_dict.get('purchase.order')): + return False + + # Rechnungsnummer + if seq_dict.get('account.invoice',False): + j_ids = self._execute('account.journal', 'search', [('code','=','VK')]) + if len(j_ids) != 1: + return False + journals = self._execute('account.journal', 'read', j_ids, ['sequence_id']) + s_ids = [t['sequence_id'][0] for t in journals] + if not self._execute('ir.sequence', 'write', s_ids, seq_dict.get('account.invoicer')): + return False + + return True + + def set_admin_rights(self): + """Setze Administrator Rechte""" + + dummy,user_id = self._execute('ir.model.data', 'get_object_reference', 'base', 'user_root') + groups = [] + + # Technische Eigenschaften + dummy,group_id = self._execute('ir.model.data', 'get_object_reference', 'base', 'group_no_one') + groups.append((4,group_id)) + + # Finanzmanager + dummy,group_id = self._execute('ir.model.data', 'get_object_reference', 'account', 'group_account_manager') + groups.append((4,group_id)) + + vals = { + 'groups_id': groups, + } + + return self._execute('res.users', 'write', [user_id], vals) + + def setup_accounting(self): + """Konfiguration Buchhaltung""" + + vals = self._execute('account.installer', 'default_get', []) + vals['charts'] = self.config.chart_of_accounts + wizard_id = self._execute('account.installer', 'create', vals) + res = self._execute('account.installer', 'action_next', [wizard_id]) + return True + + def setup_accounting2(self): + """Konfiguration Kontenplan""" + + c = self.config + sales_tax_ids = self._execute('account.tax.template', 'search', [('description','=', c.sales_tax),('parent_id','=',False)]) + if not sales_tax_ids: + return False + purchase_tax_ids = self._execute('account.tax.template', 'search', [('description','=', c.purchase_tax),('parent_id','=',False)]) + if not purchase_tax_ids: + return False + + #Set Your Accounting Options + dummy,currency_id = self._execute('ir.model.data', 'get_object_reference', 'base', 'EUR') + vals = {} + vals['chart_template_id'] = c.chart_template_id + vals['sale_tax'] = sales_tax_ids[0] + vals['purchase_tax'] = purchase_tax_ids[0] + vals['company_id'] = 1 # Default + vals['currency_id'] = currency_id + wizard_id = self._execute('wizard.multi.charts.accounts', 'create', vals) + res = self._execute('wizard.multi.charts.accounts', 'action_next', [wizard_id]) + return True + + def uninstall_chat(self): + """ Chat-Modul deinstallieren """ + + modules = ['im_chat','im_odoo_support','bus'] + modules_to_install = self._execute('ir.module.module', 'search', [('name','in',modules)]) + res = self._execute('ir.module.module', 'button_uninstall', modules_to_install) + res = self._execute('base.module.upgrade', 'upgrade_module', modules_to_install) + return True + + def set_uom(self): + """ Mengeneinheiten setzen""" + + context = {'lang': 'de_DE'} + c = self.config + active_uoms = c.active_uoms.keys() + + active_ids = [] + for uom_xml_id in active_uoms: + uom_id = self._execute('ir.model.data', 'xmlid_to_res_id', uom_xml_id) + active_ids.append(uom_id) + + # Set all other UOMs to inactive + inactive_ids = self._execute('product.uom', 'search', [('id','not in',active_ids)]) + res = self._execute('product.uom', 'write', inactive_ids, {'active': False}) + if not res: + return False + + # Update names + for uom_xml_id,name in c.active_uoms.items(): + uom_id = self._execute('ir.model.data', 'xmlid_to_res_id', uom_xml_id) + res = self._execute('product.uom', 'write', [uom_id], {'name': name}, context) + if not res: + return False + return True + + def set_steuerzuordnung(self): + """Steuerzuordnungen setzen""" + + c = self.config + + # Ungültige Steuerzuordnungen auf inaktiv setzen + invalid_ids = self._execute('account.fiscal.position', 'search', [('name','not in',c.valid_fiscal_positions)]) + self._execute('account.fiscal.position', 'write', invalid_ids, {'active': False}) + + # Mappings inaktiver Steuern löschen (also wenn rechte Seite eine inaktive Steuer ist, wie z.B "strf. i.g.L")) + valid_position_ids = self._execute('account.fiscal.position', 'search', [('name','in',c.valid_fiscal_positions)]) + valid_tax_ids = self._execute('account.tax', 'search', [('parent_id','=',False)]) + + position_tax_line_ids = self._execute('account.fiscal.position.tax', 'search', [('position_id','in',valid_position_ids),('tax_dest_id','not in',valid_tax_ids)]) + vals = {'tax_dest_id': False} + return self._execute('account.fiscal.position.tax', 'write', position_tax_line_ids, vals) + + def update_module(self): + """Aktualisiere Modul""" + module_name = self.config.module_name + mod_ids = self._execute('ir.module.module', 'search', [('name','=',module_name),('state','=','installed')]) + if not len(mod_ids) == 1: + raise "Module '%s' not found or ist not installed." % module_name + + res = self._execute('ir.module.module', 'button_upgrade', mod_ids) + res = self._execute('base.module.upgrade', 'upgrade_module', mod_ids) + return True + \ No newline at end of file