[IMP] mini imp

bzr revid: fp@openerp.com-20140125123758-4fhewd19ib38oal3
This commit is contained in:
Fabien Pinckaers 2014-01-25 13:37:58 +01:00
commit b15dbfa3a6
24 changed files with 1984 additions and 3 deletions

View File

@ -50,7 +50,7 @@ class mail_compose_message(osv.TransientModel):
res.update(
self.onchange_template_id(
cr, uid, [], context['default_template_id'], res.get('composition_mode'),
res.get('model'), res.get('res_id'), context=context
res.get('model'), res.get('res_id', context.get('active_id')), context=context
)['value']
)
return res

View File

@ -93,6 +93,8 @@ Example: 10% for retailers, promotion of 5 EUR on this product, etc."""),
help='This adds the \'Margin\' on sales order.\n'
'This gives the profitability by calculating the difference between the Unit Price and Cost Price.\n'
'-This installs the module sale_margin.'),
'module_website_quotation': fields.boolean("Allow online quotations and templates",
help='This adds the online quotation'),
'module_sale_journal': fields.boolean("Allow batch invoicing of delivery orders through journals",
help='Allows you to categorize your sales and deliveries (picking lists) between different journals, '
'and perform batch operations on journals.\n'

View File

@ -80,6 +80,10 @@
</group>
</group>
<div name="Sale Features" position="inside">
<div name="module_website_quotation">
<field name="module_website_quotation" class="oe_inline"/>
<label for="module_website_quotation"/>
</div>
<div name="module_sale_margin">
<field name="module_sale_margin" class="oe_inline"/>
<label for="module_sale_margin"/>

View File

@ -470,7 +470,7 @@
<div data-snippet-id="pricing" data-selector-children=".oe_structure, [data-oe-type=html]">
<div class="oe_snippet_thumbnail">
<img class="oe_snippet_thumbnail_img" src="/website/static/src/img/blocks/block_comparison.png"/>
<span class="oe_snippet_thumbnail_title">Comparisons</span>
<span class="oe_snippet_thumbnail_title">Comparisons</span>
</div>
<section class="oe_snippet_body">
<div class="container">

View File

@ -0,0 +1,2 @@
import controllers
import models

View File

@ -0,0 +1,24 @@
{
'name': 'Online Quotation',
'category': 'Website',
'summary': 'Send Live Quotation',
'version': '1.0',
'description': """
OpenERP Sale Quote Roller
==================
""",
'author': 'OpenERP SA',
'depends': ['website','sale', 'portal_sale', 'mail'],
'data': [
'views/website_quotation.xml',
'views/website_quotation_backend.xml',
'data/website_quotation_data.xml',
'security/ir.model.access.csv',
],
'demo': [
'data/website_quotation_demo.xml'
],
'qweb': ['static/src/xml/*.xml'],
'installable': True,
}

View File

@ -0,0 +1,3 @@
import main
# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,162 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2013-Today OpenERP SA (<http://www.openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import SUPERUSER_ID
from openerp.addons.web import http
from openerp.addons.web.http import request
from openerp.addons.website.models import website
import werkzeug
import datetime
from openerp.tools.translate import _
class sale_quote(http.Controller):
@http.route([
"/quote/<int:order_id>",
"/quote/<int:order_id>/<token>"
], type='http', auth="public", website=True)
def view(self, order_id, token=None, message=False, **post):
# use SUPERUSER_ID allow to access/view order for public user
order = request.registry.get('sale.order').browse(request.cr, token and SUPERUSER_ID or request.uid, order_id)
if token:
assert token == order.access_token, 'Access denied!'
body=_('Quotation viewed by customer')
self.message_post(body, order_id, type='comment')
# TODO: if not order.template_id: return to the URL of the portal view of SO
values = {
'quotation': order,
'message': message,
'new_post' : request.httprequest.session.get('new_post',False),
'option': self._check_option_len(order),
'date_diff': order.validity_date and (datetime.datetime.now() > datetime.datetime.strptime(order.validity_date , '%Y-%m-%d')) or False,
'salesperson' : False if token else True
}
return request.website.render('website_quotation.so_quotation', values)
def _check_option_len(self, order):
for option in order.options:
if not option.line_id:
return True
return False
@http.route(['/quote/accept'], type='json', auth="public", website=True)
def accept(self, order_id=None, token=None, signer=None, sign=None, **post):
order_obj = request.registry.get('sale.order')
order = order_obj.browse(request.cr, SUPERUSER_ID, order_id)
assert token == order.access_token, 'Access denied, wrong token!'
error = {}
if not signer: error['signer'] = 'missing'
if not sign: error['sign'] = 'missing'
if not error:
attachment = {
'name': 'sign.png',
'datas':sign,
'datas_fname': 'sign.png',
'res_model': 'sale.order',
'res_id': order_id,
}
request.registry['ir.attachment'].create(request.cr, request.uid, attachment, context=request.context)
order_obj.write(request.cr, request.uid, [order_id], {'signer_name':signer,'state': 'manual'})
return [error]
@http.route(['/quote/<int:order_id>/<token>/decline'], type='http', auth="public", website=True)
def decline(self, order_id, token, **post):
message = post.get('decline_message')
request.registry.get('sale.order').write(request.cr, request.uid, [order_id], {'state': 'cancel'})
if message:
self.message_post(message, order_id, type='comment', subtype='mt_comment')
return werkzeug.utils.redirect("/quote/%s/%s?message=2" % (order_id, token))
@http.route(['/quote/<int:order_id>/<token>/post'], type='http', auth="public", website=True)
def post(self, order_id, token, **post):
# use SUPERUSER_ID allow to access/view order for public user
order_obj = request.registry.get('sale.order')
order = order_obj.browse(request.cr, SUPERUSER_ID, order_id)
message = post.get('comment')
assert token == order.access_token, 'Access denied, wrong token!'
if message:
self.message_post(message, order_id, type='comment', subtype='mt_comment')
request.httprequest.session['new_post'] = True
return werkzeug.utils.redirect("/quote/%s/%s?message=1" % (order_id, token))
def message_post(self , message, order_id, type='comment', subtype=False):
request.session.body = message
cr, uid, context = request.cr, request.uid, request.context
user = request.registry['res.users'].browse(cr, SUPERUSER_ID, uid, context=context)
if 'body' in request.session and request.session.body:
request.registry.get('sale.order').message_post(cr, SUPERUSER_ID, order_id,
body=request.session.body,
type=type,
subtype=subtype,
author_id=user.partner_id.id,
context=context,
)
request.session.body = False
return True
@http.route(['/quote/update_line'], type='json', auth="public", website=True)
def update(self, line_id=None, remove=False, unlink=False, order_id=None, token=None, **post):
order = request.registry.get('sale.order').browse(request.cr, SUPERUSER_ID, int(order_id))
assert token == order.access_token, 'Access denied, wrong token!'
if unlink:
request.registry.get('sale.order.line').unlink(request.cr, SUPERUSER_ID, [int(line_id)], context=request.context)
return False
val = self._update_order_line(line_id=int(line_id), number=(remove and -1 or 1))
return [str(val), str(order.amount_total)]
def _update_order_line(self, line_id, number):
order_line_obj = request.registry.get('sale.order.line')
order_line_val = order_line_obj.read(request.cr, SUPERUSER_ID, [line_id], [], context=request.context)[0]
quantity = order_line_val['product_uom_qty'] + number
order_line_obj.write(request.cr, SUPERUSER_ID, [line_id], {'product_uom_qty': (quantity)}, context=request.context)
return quantity
@http.route(["/template/<model('sale.quote.template'):quote>"], type='http', auth="user", website=True)
def template_view(self, quote, **post):
values = {
'template': quote,
}
return request.website.render('website_quotation.so_template', values)
@http.route(["/quote/add_line/<int:option_id>/<int:order_id>/<token>"], type='http', auth="public", website=True)
def add(self, option_id, order_id, token, **post):
vals = {}
order = request.registry.get('sale.order').browse(request.cr, SUPERUSER_ID, order_id)
assert token == order.access_token, 'Access denied, wrong token!'
option_obj = request.registry.get('sale.option.line')
option = option_obj.browse(request.cr, SUPERUSER_ID, option_id)
vals.update({
'price_unit': option.price_unit,
'website_description': option.website_description,
'name': option.name,
'order_id': order.id,
'product_id' : option.product_id.id,
'product_uom_qty': option.quantity,
'product_uom_id': option.uom_id.id,
'discount': option.discount,
})
line = request.registry.get('sale.order.line').create(request.cr, SUPERUSER_ID, vals, context=request.context)
option_obj.write(request.cr, SUPERUSER_ID, [option.id], {'line_id': line}, context=request.context)
return werkzeug.utils.redirect("/quote/%s/%s#pricing" % (order.id, token))

View File

@ -0,0 +1,26 @@
<openerp>
<data>
<!--
Update Email template to send right quote url
-->
<record id="sale.email_template_edi_sale" model="email.template">
<field name="body_html"><![CDATA[
<div style="font-family: 'Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: rgb(255, 255, 255); ">
<p>Hello ${object.partner_id.name},</p>
<p>Here is your ${object.state in ('draft', 'sent') and 'quotation' or 'order confirmation'} from ${object.company_id.name}: </p>
<p>
You can access this document and pay online via our Customer Portal:
</p>
<a style="display:block; width: 150px; height:20px; margin-left: 120px; color: #DDD; font-family: 'Lucida Grande', Helvetica, Arial, sans-serif; font-size: 13px; font-weight: bold; text-align: center; text-decoration: none !important; line-height: 1; padding: 5px 0px 0px 0px; background-color: #8E0000; border-radius: 5px 5px; background-repeat: repeat no-repeat;"
href="/quote/${object.id}/${object.access_token}">View ${object.state in ('draft', 'sent') and 'Quotation' or 'Order'}</a>
</div>
]]></field>
</record>
</data>
</openerp>

View File

@ -0,0 +1,709 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="product_template_quote_1" model="product.template">
<field name="name">Functional Training</field>
<field name="categ_id" ref="product.product_category_5"/>
<field name="public_categ_id" ref="product.Computer_all_in_one"/>
<field name="standard_price">50000.0</field>
<field name="list_price">750000.0</field>
<field name="type">service</field>
<field name="uom_id" ref="product.product_uom_unit"/>
<field name="uom_po_id" ref="product.product_uom_unit"/>
<field name="description_sale">Learn directly from our team and network of OpenERP experts. Choose from the available training sessions for a better functional understanding of OpenERP</field>
</record>
<record id="product_product_quote_1" model="product.product">
<field name="product_tmpl_id" ref="product_template_quote_1"/>
<field name="default_code">QF11</field>
</record>
<record id="product_template_quote_2" model="product.template">
<field name="name">Technical Training</field>
<field name="categ_id" ref="product.product_category_5"/>
<field name="public_categ_id" ref="product.Computer_all_in_one"/>
<field name="standard_price">50000.0</field>
<field name="list_price">0.0</field>
<field name="type">service</field>
<field name="uom_id" ref="product.product_uom_unit"/>
<field name="uom_po_id" ref="product.product_uom_unit"/>
<field name="description_sale">Learn directly from our team and network of OpenERP experts. Choose from the available training sessions for a better technical understanding of OpenERP</field>
</record>
<record id="product_product_quote_2" model="product.product">
<field name="product_tmpl_id" ref="product_template_quote_2"/>
<field name="default_code">QF12</field>
</record>
<record id="product_template_quote_3" model="product.template">
<field name="name">Advanced CRM Functional</field>
<field name="categ_id" ref="product.product_category_5"/>
<field name="public_categ_id" ref="product.Computer_all_in_one"/>
<field name="standard_price">50000.0</field>
<field name="list_price">750000.0</field>
<field name="type">service</field>
<field name="uom_id" ref="product.product_uom_unit"/>
<field name="uom_po_id" ref="product.product_uom_unit"/>
<field name="description_sale">Learn directly from our team and network of OpenERP experts. Choose from the available training sessions for a better functional understanding of OpenERP</field>
</record>
<record id="product_product_quote_3" model="product.product">
<field name="product_tmpl_id" ref="product_template_quote_3"/>
<field name="default_code">QF13</field>
</record>
<record id="product_template_quote_4" model="product.template">
<field name="name">Advanced Account Functional </field>
<field name="categ_id" ref="product.product_category_6"/>
<field name="public_categ_id" ref="product.Computer_all_in_one"/>
<field name="standard_price">50000.0</field>
<field name="list_price">750000.0</field>
<field name="type">service</field>
<field name="uom_id" ref="product.product_uom_unit"/>
<field name="uom_po_id" ref="product.product_uom_unit"/>
<field name="description_sale">Learn directly from our team and network of OpenERP experts. Choose from the available training sessions for a better functional understanding of OpenERP</field>
</record>
<record id="product_product_quote_4" model="product.product">
<field name="product_tmpl_id" ref="product_template_quote_4"/>
<field name="default_code">QF14</field>
</record>
<record id="website_quote_template_1" model="sale.quote.template">
<field name="name">Partnership Contract</field>
<field name="website_description" type="xml">
<section data-snippet-id="title">
<h1 class="page-header">Our Partnership Offer</h1>
</section>
<section data-snippet-id="text-block">
<div class="row">
<div class="col-md-12">
<p>
Our partnership offer includes all you need to
grow your business and deliver quality services
with the OpenERP Partner Program.
</p><p>
It includes <strong>discounts on OpenERP
Enterprise</strong>, technical and/or functional
<strong>trainings</strong>,
<strong>support</strong> services,
<strong>marketing documents</strong>, access to
the <strong>partner portal</strong>, rights to
<strong>use the trademark</strong>, sales support
from a <strong>dedicated account manager</strong>.
</p>
</div>
</div>
</section>
<section data-snippet-id="pricing">
<div class="row mt32">
<div class="col-md-4">
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">A Valuable Product</h3>
</div>
<div class="panel-body">
<p>
Deliver <strong>strong value added services</strong> as you can
rely on a leading open source software, with
the support of the publisher.
<p></p>
<strong>Grow with your existing customer base</strong>
by continuously proposing new modules.
</p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">A Strong Demand</h3>
</div>
<div class="panel-body">
<p>
Enjoy the traction of the <strong>fastest growing
management software</strong> in the world.
</p><p>
Benefit from the growing customer demand
and our OpenERP brand.
</p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">High Margins</h3>
</div>
<div class="panel-body">
<p>
<strong>Get high billing rates</strong> as you deliver a
highly valuable software.
</p><p>
Grow by developing a <strong>recurring
revenue flow</strong> from OpenERP
Enterprise's commission system.
</p>
</div>
</div>
</div>
</div>
</section>
<section data-snippet-id="text-block">
<h2>Enterprise commissions</h2>
<p>
As an official partner, you benefit from OpenERP Enterprise
commissions, according to your partner grade, as well as
dedicated services restricted to partners like the technical
support.
</p>
<table class="table table-hover">
<tr>
<th>Grade</th>
<th>Your Commission</th>
</tr><tr>
<td>Ready</td>
<td></td>
</tr><tr>
<td>Silver</td>
<td></td>
</tr><tr>
<td>Gold</td>
<td></td>
</tr>
</table>
</section>
<section data-snippet-id="text-block">
<h2>A Dedicated Account Manager</h2>
<p>
We will assign you a dedicated account manager, an
experienced sales person, to help you develop your
OpenERP business. The account manager helps you get
leads, close deals, gives you feedback and best
practices, delivers sales training and is your direct
point of contact for any request you may have.
</p>
</section>
<section data-snippet-id="text-block">
<div class="row">
<div class="col-md-12">
<h2>Get access to our experts</h2>
</div>
<div class="col-md-7">
<p>
For an extra fee, partners can get access to OpenERP's
core developers and functional experts. This can help
you succeed in delivering more complex or bigger
projects by getting the support of highly experienced
consultants on demand.
</p>
</div>
<div class="col-md-5">
<img src="/website_quotation/static/src/img/partner_icon_01.png"/>
</div>
</div>
</section>
<section data-snippet-id="text-block">
<div class="row">
<div class="col-md-12">
<h2>Official certified partner</h2>
</div>
<div class="col-md-7">
<p>
OpenERP promotes its partners through various ways:
publication on our website, official communication,
publication of your success stories, etc. As soon as
you become an OpenERP partner and have followed the
official trainings, you will be visible on the partner
directory listing.
</p>
</div>
<div class="col-md-5">
<img src="/website_quotation/static/src/img/openerp_gold_partner.png"/>
</div>
</div>
</section>
<section data-snippet-id="text-block">
<div class="row">
<div class="col-md-12">
<h2>Access to the Lead</h2>
</div>
<div class="col-md-7">
<p>
Every year, we redirect more than 100,000 customer
requests to our official partners. These are prospects
that filled a form on the OpenERP website and wanted to
use OpenERP. The right partner to fulfill the customer
request is selected based on the customer localization
(nearest partner) and the grade of the partner.
</p>
</div>
<div class="col-md-5">
<img src="/website_quotation/static/src/img/partner_icon_02.png" class="img"/>
</div>
</div>
</section>
<section data-snippet-id="text-block">
<h2>Benefit from the OpenERP branding</h2>
<p>
Every year, we redirect more than 100,000 customer
requests to our official partners. These are prospects
that filled a form on the OpenERP website and wanted to
use OpenERP. The right partner to fulfill the customer
request is selected based on the customer localization
(nearest partner) and the grade of the partner.
</p>
</section>
<section class="mb32" data-snippet-id="text-block">
<h2>Test developments automatically</h2>
<div class="row">
<div class="col-md-5">
<img src="/website_quotation/static/src/img/partner_sc_01.png" class="img shadow"/>
</div>
<div class="col-md-7">
<p class="mt23">
Save time in your implementation project by having your
developments tested automatically by our automated test
servers. At every code commit, you get a full OpenERP
instance that you can try out online. When this
instance is deployed, your code is automatically put
through our 2000+ automated unit tests.
</p><p>
Our automated testing server software is called Runbot,
and you can try it out here: http://runbot.openerp.com.
A dedicated runbot server is available for every
partner.
</p>
</div>
</div>
</section>
</field>
</record>
<record id="website_sale_order_line_1" model="sale.quote.line">
<field name="quote_id" ref="website_quote_template_1"/>
<field name="name">Fuctional Training</field>
<field name="product_id" ref="product_product_quote_1"/>
<field name="product_uom_qty">1</field>
<field name="price_unit">12950.00</field>
<field name="website_description" type="html">
<section data-snippet-id="title">
<h1>Online Training + Certification</h1>
</section>
<section data-snippet-id="text-image">
<div class="row">
<div class="col-md-12 mb32">
<p>These courses feature the same high quality course content found in our traditional classroom trainings, supplemented with modular sessions and cloud-based labs. Many of our online learning courses also include dozens of recorded webinars and live sessions by our senior instructors. At the end of the training, you can pass the OpenERP Certification exam in one of the 5000+ Pearson VUE test centers worldwide.</p>
</div>
<div class="col-md-offset-1">
<h3>Your advantages</h3>
<ul>
<li>Modular approach applied to the learning method</li>
<li>New interactive learning experience</li>
<li>Lower training budget for the same quality courses</li>
<li>Better comfort to facilitate your learning process</li>
</ul>
</div>
<div class="col-md-12">
<h2>Structure of the Training</h2>
</div>
<div class="col-md-5 col-md-offset-1 mt16 mb16">
<img class="img img-responsive" src="https://www.openerp.com/saas_master/static/site_new/img/layout/online_training.png"/>
</div>
<div class="col-md-6 mt32">
<h4><strong>There are three components to the training</strong></h4>
<ul>
<li>Videos with detailed demos</li>
<li>Hands-on exercises and their solutions</li>
<li>Live Q&amp;A sessions with a trainer</li>
</ul>
</div>
</div>
</section>
</field>
</record>
<record id="website_sale_order_line_2" model="sale.quote.line">
<field name="quote_id" ref="website_quote_template_1"/>
<field name="name">Technical Training</field>
<field name="product_id" ref="product_product_quote_2"/>
<field name="product_uom_qty">1</field>
<field name="price_unit">00.00</field>
<field name="website_description" type="html">
<section data-snippet-id="title">
<h1>Technical Training</h1>
</section>
<section id="whatsuit" data-snippet-id="text-block">
<div class="container">
<div class="row">
<div class="col-md-12 text-center mb8 mt0" data-snippet-id="colmd">
<h2>Course Summary</h2>
</div>
<div class="col-md-12 mt16 mb0" data-snippet-id="colmd">
<p><span style="text-align: -webkit-center; ">This course is dedicated to developers who need to grasp knowledge of the <strong>business applications development </strong>process. This course is for new developers or for IT professionals eager to learn more about technical aspects.</span></p>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-12 text-center mt0 mb16" data-snippet-id="colmd">
<h2>What you will learn?</h2>
</div>
<div class="col-md-4" data-snippet-id="colmd">
<div class="panel panel-info">
<div class="panel-heading text-center">
<h3 style="margin: 0">Day 1</h3>
<p class="text-muted" style="margin: 0">Introduction to Javascript</p>
</div>
<ul class="list-group">
<li class="list-group-item">Hello World</li>
<li class="list-group-item">Variables &amp; Operators</li>
<li class="list-group-item">Dive into Strings</li>
<li class="list-group-item">Functions</li>
<li class="list-group-item">Loops</li>
<li class="list-group-item">Arrays</li>
</ul>
<div class="panel-footer text-center">
<p class="text-muted"><i>You will be able to develop simple dynamic compenents in HTML pages.</i></p>
</div>
</div>
</div>
<div class="col-md-4" data-snippet-id="colmd">
<div class="panel panel-info">
<div class="panel-heading text-center">
<h3 style="margin: 0">Day 2</h3>
<p class="text-muted" style="margin: 0">OpenERP Web Client</p>
</div>
<ul class="list-group">
<li class="list-group-item">Introduction to JQuery</li>
<li class="list-group-item">Advanced JQuery</li>
<li class="list-group-item">Underscore</li>
<li class="list-group-item">Introduction to QWeb</li>
<li class="list-group-item">Controlers and Views</li>
<li class="list-group-item">Bootstrap CSS</li>
<li class="list-group-item">Calling the ORM</li>
</ul>
<div class="panel-footer text-center">
<p class="text-muted"><i>You will be able to create dynamic page interacting with the ORM.</i></p>
</div>
</div>
</div>
<div class="col-md-4" data-snippet-id="colmd">
<div class="panel panel-info">
<div class="panel-heading text-center">
<h3 style="margin: 0">Day 3</h3>
<p class="text-muted" style="margin: 0">Building a Full Application</p>
</div>
<ul class="list-group">
<li class="list-group-item">Modules</li>
<li class="list-group-item">Python Objects</li>
<li class="list-group-item">Report Engine</li>
<li class="list-group-item">Workflows</li>
<li class="list-group-item">Training Center Module</li>
<li class="list-group-item">Integrated Help</li>
<li class="list-group-item">How to Debug</li>
</ul>
<div class="panel-footer text-center">
<p class="text-muted"><i>You will be able to develop a full application with backend and user interface.</i></p>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-12 text-center mb16 mt0" data-snippet-id="colmd">
<h2>Requirements</h2>
</div>
<div class="col-md-12 mb16 mt16" data-snippet-id="colmd">
<p><strong>Objectives:</strong></p>
<p><strong>Having attended this course, participants should be able to:</strong></p>
<ul><li>Understand the development concepts and architecture;</li>
<li>Install and administer your own server;</li>
<li>Develop a new module for a particular application.</li>
</ul><p></p>
<p><strong>Our prices include:</strong></p>
<ul><li>drinks and lunch;</li>
<li>training material.</li>
</ul><p></p>
<p><strong>Requirements:</strong></p>
<ul><li>Bring your own laptop.</li>
<li>Participants are expected to have some knowledge in programming. A basic knowledge of the Python programming is recommended.</li>
<li>Participants preferably have a functional knowledge of our software (see Functional Training).</li>
</ul><p></p>
<p>To get more information, visit the <a href="http://openerp.com/">OpenERP Official Website</a>.</p>
</div>
</div>
</div>
</section>
</field>
</record>
<record id="website_sale_option_line_1" model="sale.option.line">
<field name="temp_option_id" ref="website_quote_template_1"/>
<field name="name">Advanced CRM Functional</field>
<field name="product_id" ref="product_product_quote_3"/>
<field name="product_uom_qty">1</field>
<field name="uom_id" ref="product.product_uom_unit"/>
<field name="price_unit">9000.00</field>
<field name="discount">10</field>
<field name="website_description" type="html">
<section data-snippet-id="title">
<h1>Advanced CRM Functional</h1>
</section>
<section data-snippet-id="text-image">
<div class="container">
<div class="row">
<div class="col-md-12 text-center mb8 mt0" data-snippet-id="colmd">
<h2>Objectives</h2>
</div>
<div class="col-md-12 mt16 mb0" data-snippet-id="colmd">
<p><span style="text-align: -webkit-center; ">Upon completion of the training, the participant will be able to:</span></p>
<ul class="list-group">
<li class="list-group-item"> Install and administer OpenERP.</li>
<li class="list-group-item"> Become an OpenERP Consultant.</li>
<li class="list-group-item"> Do the GAP analysis of any Business Process.</li>
<li class="list-group-item"> Understand the functional concepts, business processes byOpenERP.</li>
<li class="list-group-item"> Operate/Work with OpenERP Smoothly on regular basis.</li>
<li class="list-group-item"> Configure OpenERP using the standard modules.</li>
<li class="list-group-item"> Change the look and feel from the front-end(GUI) rather than aneed of technical knowledge.</li>
</ul>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-12 text-center mt0 mb16" data-snippet-id="colmd">
<h2>What you will learn?</h2>
</div>
<div class="col-md-4" data-snippet-id="colmd">
<div class="panel panel-info">
<div class="panel-heading text-center">
<h3 style="margin: 0">Day 1</h3>
</div>
<ul class="list-group">
<li class="list-group-item">Introduction</li>
<li class="list-group-item">Installation and Configuration</li>
<li class="list-group-item">Database management</li>
<li class="list-group-item">Module Installation</li>
<li class="list-group-item">Company Configuration and Multi Company Management</li>
<li class="list-group-item">Multi Language Management</li>
<li class="list-group-item">Fetchmail Configuration</li>
</ul>
</div>
</div>
<div class="col-md-4" data-snippet-id="colmd">
<div class="panel panel-info">
<div class="panel-heading text-center">
<h3 style="margin: 0">Day 2</h3>
</div>
<ul class="list-group">
<li class="list-group-item">Product Category &amp; product Configuration with Order point</li>
<li class="list-group-item">Customers/Suppliers</li>
<li class="list-group-item">Pricelist and auto Segmentation</li>
<li class="list-group-item">Convert Lead to Opportunity &amp; Customer management</li>
<li class="list-group-item">Schedule Phone Calls and Meetings</li>
<li class="list-group-item">Negotiation and Quotation Revisions</li>
<li class="list-group-item">Generate Sale Order &amp; direct mail to customer</li>
</ul>
</div>
</div>
<div class="col-md-4" data-snippet-id="colmd">
<div class="panel panel-info">
<div class="panel-heading text-center">
<h3 style="margin: 0">Day 3</h3>
</div>
<ul class="list-group">
<li class="list-group-item">Warehouse Management Introduction</li>
<li class="list-group-item">Shop, Location &amp; Warehouse Configuration</li>
<li class="list-group-item">Opening Stock and Physical Inventory</li>
<li class="list-group-item">Purchase Requisition and Purchase Order Management</li>
<li class="list-group-item">Partial and Full Shipment / Delivery</li>
<li class="list-group-item">Product Expiry and Warranty</li>
<li class="list-group-item">After Sales Service (Helpdesk)</li>
</ul>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-12 mb16 mt16" data-snippet-id="colmd">
<h2>Requirements</h2>
<ul><li>Bring your own laptop.</li>
<li>Participants are expected to have some knowledge in programming. A basic knowledge of the Python programming is recommended.</li>
<li>Participants preferably have a functional knowledge of our software (see Functional Training).</li>
</ul><p></p>
<p>To get more information, visit the <a href="http://openerp.com/">OpenERP Official Website</a>.</p>
</div>
</div>
</div>
</section>
</field>
</record>
<record id="website_sale_option_line_2" model="sale.option.line">
<field name="temp_option_id" ref="website_quote_template_1"/>
<field name="name">Functional Webinar</field>
<field name="product_id" ref="product_product_quote_4"/>
<field name="product_uom_qty">1</field>
<field name="uom_id" ref="product.product_uom_unit"/>
<field name="price_unit">18000.00</field>
<field name="website_description" type="html">
<section data-snippet-id="title">
<h1>Functional Webinar</h1>
</section>
<section data-snippet-id="text-image">
<div class="container">
<div class="row">
<div class="col-md-12 text-center mb8 mt0" data-snippet-id="colmd">
<h2>Course Summary</h2>
</div>
<div class="col-md-12 mt16 mb0" data-snippet-id="colmd">
<p><span style="text-align: -webkit-center; ">This course is dedicated to developers who need to grasp knowledge of the <strong>business applications development </strong>process. This course is for new developers or for IT professionals eager to learn more about technical aspects.</span></p>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-12 text-center mt0 mb16" data-snippet-id="colmd">
<h2>What you will learn?</h2>
</div>
<div class="col-md-4" data-snippet-id="colmd">
<div class="panel panel-info">
<div class="panel-heading text-center">
<h2 style="margin: 0">Day 1</h2>
<p class="text-muted" style="margin: 0">Introduction to Javascript</p>
</div>
<ul class="list-group">
<li class="list-group-item">Hello World</li>
<li class="list-group-item">Variables &amp; Operators</li>
<li class="list-group-item">Dive into Strings</li>
<li class="list-group-item">Functions</li>
<li class="list-group-item">Loops</li>
<li class="list-group-item">Arrays</li>
</ul>
<div class="panel-footer text-center">
<p class="text-muted"><i>You will be able to develop simple dynamic compenents in HTML pages.</i></p>
</div>
</div>
</div>
<div class="col-md-4" data-snippet-id="colmd">
<div class="panel panel-info">
<div class="panel-heading text-center">
<h2 style="margin: 0">Day 2</h2>
<p class="text-muted" style="margin: 0">OpenERP Web Client</p>
</div>
<ul class="list-group">
<li class="list-group-item">Introduction to JQuery</li>
<li class="list-group-item">Advanced JQuery</li>
<li class="list-group-item">Underscore</li>
<li class="list-group-item">Introduction to QWeb</li>
<li class="list-group-item">Controlers and Views</li>
<li class="list-group-item">Bootstrap CSS</li>
<li class="list-group-item">Calling the ORM</li>
</ul>
<div class="panel-footer text-center">
<p class="text-muted"><i>You will be able to create dynamic page interacting with the ORM.</i></p>
</div>
</div>
</div>
<div class="col-md-4" data-snippet-id="colmd">
<div class="panel panel-info">
<div class="panel-heading text-center">
<h2 style="margin: 0">Day 3</h2>
<p class="text-muted" style="margin: 0">Building a Full Application</p>
</div>
<ul class="list-group">
<li class="list-group-item">Modules</li>
<li class="list-group-item">Python Objects</li>
<li class="list-group-item">Report Engine</li>
<li class="list-group-item">Workflows</li>
<li class="list-group-item">Training Center Module</li>
<li class="list-group-item">Integrated Help</li>
<li class="list-group-item">How to Debug</li>
</ul>
<div class="panel-footer text-center">
<p class="text-muted"><i>You will be able to develop a full application with backend and user interface.</i></p>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-12 text-center mb16 mt0" data-snippet-id="colmd">
<h2>Requirements</h2>
</div>
<div class="col-md-12 mb16 mt16" data-snippet-id="colmd">
<p><strong>Objectives:</strong></p>
<p><strong>Having attended this course, participants should be able to:</strong></p>
<ul>
<li>Understand the development concepts and architecture;</li>
<li>Install and administer your own server;</li>
<li>Develop a new module for a particular application.</li>
</ul><p></p>
<p><strong>Our prices include:</strong></p>
<ul>
<li>drinks and lunch;</li>
<li>training material.</li>
</ul><p></p>
<p><strong>Requirements:</strong></p>
<ul>
<li>Bring your own laptop.</li>
<li>Participants are expected to have some knowledge in programming. A basic knowledge of the Python programming is recommended.</li>
<li>Participants preferably have a functional knowledge of our software (see Functional Training).</li>
</ul><p></p>
<p>To get more information, visit the <a href="http://openerp.com/">OpenERP Official Website</a>.</p>
</div>
</div>
</div>
</section>
</field>
</record>
</data>
</openerp>

View File

@ -0,0 +1 @@
import order

View File

@ -0,0 +1,194 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2013-Today OpenERP SA (<http://www.openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.osv import osv, fields
import uuid
import time
import datetime
class sale_quote_template(osv.osv):
_name = "sale.quote.template"
_description = "Sale Quotation Template"
_columns = {
'name': fields.char('Quotation Template', size=256, required=True),
'website_description': fields.html('Description'),
'quote_line': fields.one2many('sale.quote.line', 'quote_id', 'Quote Template Lines'),
'note': fields.text('Terms and conditions'),
'options': fields.one2many('sale.option.line', 'temp_option_id', 'Optional Products Lines'),
'number_of_days': fields.integer('Quotation Period Validity'),
}
def open_template(self, cr, uid, quote_id, context=None):
return {
'type': 'ir.actions.act_url',
'target': 'self',
'url': '/template/%d' % quote_id[0]
}
class sale_quote_line(osv.osv):
_name = "sale.quote.line"
_description = "Quotation Template Lines"
_columns = {
'quote_id': fields.many2one('sale.quote.template', 'Quotation Template Reference', required=True, ondelete='cascade', select=True),
'name': fields.text('Description', required=True),
'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok', '=', True)], change_default=True),
'website_description': fields.html('Line Description'),
'price_unit': fields.float('Unit Price', required=True),
'product_uom_qty': fields.float('Quantity', required=True),
}
_defaults = {
'product_uom_qty': 1,
}
def on_change_product_id(self, cr, uid, ids, product, context=None):
vals = {}
product_obj = self.pool.get('product.product').browse(cr, uid, product, context=context)
vals.update({
'price_unit': product_obj.list_price,
'website_description': product_obj.website_description,
'name': product_obj.name,
})
return {'value': vals}
class sale_order_line(osv.osv):
_inherit = "sale.order.line"
_description = "Sales Order Line"
_columns = {
'website_description': fields.html('Line Description'),
'option_line_id':fields.one2many('sale.option.line', 'line_id', 'Optional Products Lines'),
}
def product_id_change(self, cr, uid, ids, pricelist, product, qty=0, uom=False, qty_uos=0, uos=False, name='', partner_id=False, lang=False, update_tax=True, date_order=False, packaging=False, fiscal_position=False, flag=False, context=None):
res = super(sale_order_line, self).product_id_change(cr, uid, ids, pricelist, product, qty, uom, qty_uos, uos, name, partner_id, lang, update_tax, date_order, packaging, fiscal_position, flag, context)
if product:
desc = self.pool.get('product.product').browse(cr, uid, product, context).website_description
res.get('value').update({'website_description': desc})
return res
class sale_order(osv.osv):
_inherit = 'sale.order'
def _get_total(self, cr, uid, ids, name, arg, context=None):
res = {}
for order in self.browse(cr, uid, ids, context=context):
total = 0.0
for line in order.order_line:
total += (line.product_uom_qty * line.price_unit)
res[order.id] = total
return res
_columns = {
'access_token': fields.char('Security Token', size=256, required=True),
'template_id': fields.many2one('sale.quote.template', 'Quote Template'),
'website_description': fields.html('Description'),
'options' : fields.one2many('sale.option.line', 'option_id', 'Optional Products Lines'),
'signer_name': fields.char('Signer Name', size=256),
'validity_date': fields.date('Validity Date'),
'before_discount': fields.function(_get_total, string='Amount Before Discount', type="float")
}
_defaults = {
'access_token': lambda self, cr, uid, ctx={}: str(uuid.uuid4())
}
def open_quotation(self, cr, uid, quote_id, context=None):
quote = self.browse(cr, uid, quote_id[0], context=context)
return {
'type': 'ir.actions.act_url',
'target': 'self',
'url': '/quote/%s' % (quote.id)
}
def onchange_template_id(self, cr, uid, ids, template_id, context=None):
lines = []
quote_template = self.pool.get('sale.quote.template').browse(cr, uid, template_id, context=context)
for line in quote_template.quote_line:
lines.append((0, 0, {
'name': line.name,
'price_unit': line.price_unit,
'product_uom_qty': line.product_uom_qty,
'product_id': line.product_id.id,
'product_uom_id': line.product_id.uom_id.id,
'website_description': line.website_description,
'state': 'draft',
}))
options = []
for option in quote_template.options:
options.append((0, 0, {
'product_id': option.product_id.id,
'name': option.name,
'quantity': option.quantity,
'uom_id': option.uom_id.id,
'price_unit': option.price_unit,
'discount': option.discount,
'website_description': option.website_description,
}))
date = False
if quote_template.number_of_days > 0:
date = (datetime.datetime.now() + datetime.timedelta(quote_template.number_of_days)).strftime("%Y-%m-%d")
data = {'order_line': lines, 'website_description': quote_template.website_description, 'note': quote_template.note, 'options': options, 'validity_date': date}
return {'value': data}
def recommended_products(self, cr, uid, ids, context=None):
order_line = self.browse(cr, uid, ids[0], context=context).order_line
product_pool = self.pool.get('product.product')
products = []
for line in order_line:
products += line.product_id.product_tmpl_id.recommended_products(context=context)
return products
class sale_option_line(osv.osv):
_name = "sale.option.line"
_description = "Sale Options"
_columns = {
'option_id': fields.many2one('sale.order', 'Sale Order Reference', ondelete='cascade', select=True),
'temp_option_id': fields.many2one('sale.quote.template', 'Quotation Template Reference', ondelete='cascade', select=True),
'line_id': fields.many2one('sale.order.line', on_delete="set null"),
'name': fields.text('Description', required=True),
'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok', '=', True)], change_default=True),
'website_description': fields.html('Line Description'),
'price_unit': fields.float('Unit Price', required=True),
'discount': fields.float('Discount (%)'),
'uom_id': fields.many2one('product.uom', 'Unit of Measure ', required=True),
'quantity': fields.float('Quantity', required=True),
}
_defaults = {
'quantity': 1,
}
def on_change_product_id(self, cr, uid, ids, product, context=None):
vals = {}
product_obj = self.pool.get('product.product').browse(cr, uid, product, context=context)
vals.update({
'price_unit': product_obj.list_price,
'website_description': product_obj.product_tmpl_id.website_description,
'name': product_obj.name,
'uom_id': product_obj.product_tmpl_id.uom_id.id,
})
return {'value': vals}
class product_template(osv.Model):
_inherit = "product.template"
_columns = {
'website_description': fields.html('Description for the website'),
}

View File

@ -0,0 +1,5 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_sale_order_portal,sale.order.portal,model_sale_order,base.group_portal,1,1,1,0
access_sale_order_public,sale.order.public,model_sale_order,base.group_public,1,1,1,0
access_sale_order_line_public,sale.order.line.public,model_sale_order_line,base.group_public,1,1,1,0
access_sale_options_line_public,sale.option.line.public,model_sale_option_line,base.group_public,1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_sale_order_portal sale.order.portal model_sale_order base.group_portal 1 1 1 0
3 access_sale_order_public sale.order.public model_sale_order base.group_public 1 1 1 0
4 access_sale_order_line_public sale.order.line.public model_sale_order_line base.group_public 1 1 1 0
5 access_sale_options_line_public sale.option.line.public model_sale_option_line base.group_public 1 1 1 0

View File

@ -0,0 +1,77 @@
/*
jSignature v2 "2012-11-01T22:48" "commit ID 1c15dfafecc75925c3b7d529356a558b59220edb"
Copyright (c) 2012 Willow Systems Corp http://willow-systems.com
Copyright (c) 2010 Brinley Ang http://www.unbolt.net
MIT License <http://www.opensource.org/licenses/mit-license.php>
Simplify.js BSD
(c) 2012, Vladimir Agafonkin
mourner.github.com/simplify-js
base64 encoder
MIT, GPL
http://phpjs.org/functions/base64_encode
+ original by: Tyler Akins (http://rumkin.com)
+ improved by: Bayron Guevara
+ improved by: Thunder.m
+ improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+ bugfixed by: Pellentesque Malesuada
+ improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+ improved by: Rafal Kukawski (http://kukawski.pl)
jSignature v2 jSignature's Undo Button and undo functionality plugin
jSignature v2 jSignature's custom "base30" format export and import plugins.
jSignature v2 SVG export plugin.
*/
(function(){function q(b){for(var j,s=b.css("color"),g,b=b[0],c=!1;b&&!g&&!c;){try{j=$(b).css("background-color")}catch(d){j="transparent"}"transparent"!==j&&"rgba(0, 0, 0, 0)"!==j&&(g=j);c=b.body;b=b.parentNode}var b=/rgb[a]*\((\d+),\s*(\d+),\s*(\d+)/,c=/#([AaBbCcDdEeFf\d]{2})([AaBbCcDdEeFf\d]{2})([AaBbCcDdEeFf\d]{2})/,a;j=void 0;(j=s.match(b))?a={r:parseInt(j[1],10),g:parseInt(j[2],10),b:parseInt(j[3],10)}:(j=s.match(c))&&(a={r:parseInt(j[1],16),g:parseInt(j[2],16),b:parseInt(j[3],16)});var f;g?
(j=void 0,(j=g.match(b))?f={r:parseInt(j[1],10),g:parseInt(j[2],10),b:parseInt(j[3],10)}:(j=g.match(c))&&(f={r:parseInt(j[1],16),g:parseInt(j[2],16),b:parseInt(j[3],16)})):f=a?127<Math.max.apply(null,[a.r,a.g,a.b])?{r:0,g:0,b:0}:{r:255,g:255,b:255}:{r:255,g:255,b:255};j=function(b){return"rgb("+[b.r,b.g,b.b].join(", ")+")"};a&&f?(b=Math.max.apply(null,[a.r,a.g,a.b]),a=Math.max.apply(null,[f.r,f.g,f.b]),a=Math.round(a+-0.75*(a-b)),a={r:a,g:a,b:a}):a?(a=Math.max.apply(null,[a.r,a.g,a.b]),b=1,127<a&&
(b=-1),a=Math.round(a+96*b),a={r:a,g:a,b:a}):a={r:191,g:191,b:191};return{color:s,"background-color":f?j(f):g,"decor-color":j(a)}}function m(b,j){this.x=b;this.y=j;this.reverse=function(){return new this.constructor(-1*this.x,-1*this.y)};this._length=null;this.getLength=function(){this._length||(this._length=Math.sqrt(Math.pow(this.x,2)+Math.pow(this.y,2)));return this._length};var s=function(b){return Math.round(b/Math.abs(b))};this.resizeTo=function(b){if(0===this.x&&0===this.y)this._length=0;else if(0===
this.x)this._length=b,this.y=b*s(this.y);else if(0===this.y)this._length=b,this.x=b*s(this.x);else{var j=Math.abs(this.y/this.x),a=Math.sqrt(Math.pow(b,2)/(1+Math.pow(j,2))),j=j*a;this._length=b;this.x=a*s(this.x);this.y=j*s(this.y)}return this};this.angleTo=function(b){var j=this.getLength()*b.getLength();return 0===j?0:Math.acos(Math.min(Math.max((this.x*b.x+this.y*b.y)/j,-1),1))/Math.PI}}function k(b,j){this.x=b;this.y=j;this.getVectorToCoordinates=function(b,j){return new m(b-this.x,j-this.y)};
this.getVectorFromCoordinates=function(b,j){return this.getVectorToCoordinates(b,j).reverse()};this.getVectorToPoint=function(b){return new m(b.x-this.x,b.y-this.y)};this.getVectorFromPoint=function(b){return this.getVectorToPoint(b).reverse()}}function t(b,j,a,g,c){this.data=b;this.context=j;if(b.length)for(var d=b.length,f,l,i=0;i<d;i++){f=b[i];l=f.x.length;a.call(j,f);for(var e=1;e<l;e++)g.call(j,f,e);c.call(j,f)}this.changed=function(){};this.startStrokeFn=a;this.addToStrokeFn=g;this.endStrokeFn=
c;this.inStroke=!1;this._stroke=this._lastPoint=null;this.startStroke=function(b){if(b&&"number"==typeof b.x&&"number"==typeof b.y){this._stroke={x:[b.x],y:[b.y]};this.data.push(this._stroke);this._lastPoint=b;this.inStroke=!0;var j=this._stroke,a=this.startStrokeFn,g=this.context;setTimeout(function(){a.call(g,j)},3);return b}return null};this.addToStroke=function(b){if(this.inStroke&&"number"===typeof b.x&&"number"===typeof b.y&&4<Math.abs(b.x-this._lastPoint.x)+Math.abs(b.y-this._lastPoint.y)){var j=
this._stroke.x.length;this._stroke.x.push(b.x);this._stroke.y.push(b.y);this._lastPoint=b;var a=this._stroke,g=this.addToStrokeFn,s=this.context;setTimeout(function(){g.call(s,a,j)},3);return b}return null};this.endStroke=function(){var b=this.inStroke;this.inStroke=!1;this._lastPoint=null;if(b){var j=this._stroke,a=this.endStrokeFn,g=this.context,s=this.changed;setTimeout(function(){a.call(g,j);s.call(g)},3);return!0}return null}}function r(b,j,a){var g=this.$parent=$(b),b=this.eventTokens={};this.events=
new v(this);var c=$.fn[e]("globalEvents"),d={width:"ratio",height:"ratio",sizeRatio:4,color:"#000","background-color":"#fff","decor-color":"#eee",lineWidth:0,minFatFingerCompensation:-10,showUndoButton:!1,data:[]};$.extend(d,q(g));j&&$.extend(d,j);this.settings=d;for(var f in a)a.hasOwnProperty(f)&&a[f].call(this,f);this.events.publish(e+".initializing");this.$controlbarUpper=$('<div style="padding:0 !important;margin:0 !important;width: 100% !important; height: 0 !important;margin-top:-1em !important;margin-bottom:1em !important;"></div>').appendTo(g);
this.isCanvasEmulator=!1;a=this.canvas=this.initializeCanvas(d);j=$(a);this.$controlbarLower=$('<div style="padding:0 !important;margin:0 !important;width: 100% !important; height: 0 !important;margin-top:-1.5em !important;margin-bottom:1.5em !important;"></div>').appendTo(g);this.canvasContext=a.getContext("2d");j.data(e+".this",this);g=(g=d.lineWidth)?g:Math.max(Math.round(a.width/400),2);d.lineWidth=g;this.lineCurveThreshold=3*d.lineWidth;d.cssclass&&""!=$.trim(d.cssclass)&&j.addClass(d.cssclass);
this.fatFingerCompensation=0;var g=function(b){var j,a,g=function(g){g=g.changedTouches&&0<g.changedTouches.length?g.changedTouches[0]:g;return new k(Math.round(g.pageX+j),Math.round(g.pageY+a)+b.fatFingerCompensation)},d=new y(750,function(){b.dataEngine.endStroke()});this.drawEndHandler=function(j){try{j.preventDefault()}catch(a){}d.clear();b.dataEngine.endStroke()};this.drawStartHandler=function(c){c.preventDefault();var s=$(b.canvas).offset();j=-1*s.left;a=-1*s.top;b.dataEngine.startStroke(g(c));
d.kick()};this.drawMoveHandler=function(j){j.preventDefault();b.dataEngine.inStroke&&(b.dataEngine.addToStroke(g(j)),d.kick())};return this}.call({},this),l=g.drawEndHandler,i=g.drawStartHandler,p=g.drawMoveHandler,h=this.canvas,j=$(h);this.isCanvasEmulator?(j.bind("mousemove."+e,p),j.bind("mouseup."+e,l),j.bind("mousedown."+e,i)):(h.ontouchstart=function(b){h.onmousedown=void 0;h.onmouseup=void 0;h.onmousemove=void 0;this.fatFingerCompensation=d.minFatFingerCompensation&&-3*d.lineWidth>d.minFatFingerCompensation?
-3*d.lineWidth:d.minFatFingerCompensation;i(b);h.ontouchend=l;h.ontouchstart=i;h.ontouchmove=p},h.onmousedown=function(b){h.ontouchstart=void 0;h.ontouchend=void 0;h.ontouchmove=void 0;i(b);h.onmousedown=i;h.onmouseup=l;h.onmousemove=p});b[e+".windowmouseup"]=c.subscribe(e+".windowmouseup",g.drawEndHandler);this.events.publish(e+".attachingEventHandlers");var n=this,b=d.width.toString(10),w=e;if("ratio"===b||"%"===b.split("")[b.length-1])this.eventTokens[w+".parentresized"]=c.subscribe(w+".parentresized",
function(b,j,a){return function(){var g=j.width();if(g!==a){for(var d in b)b.hasOwnProperty(d)&&(c.unsubscribe(b[d]),delete b[d]);var s=n.settings;n.$parent.children().remove();for(d in n)n.hasOwnProperty(d)&&delete n[d];d=s.data;var g=1*g/a,f=[],l,i,e,h,k,p;i=0;for(e=d.length;i<e;i++){p=d[i];l={x:[],y:[]};h=0;for(k=p.x.length;h<k;h++)l.x.push(p.x[h]*g),l.y.push(p.y[h]*g);f.push(l)}s.data=f;j[w](s)}}}(this.eventTokens,this.$parent,this.$parent.width(),1*this.canvas.width/this.canvas.height));this.resetCanvas(d.data);
this.events.publish(e+".initialized");return this}var e="jSignature",y=function(b,j){var a;this.kick=function(){clearTimeout(a);a=setTimeout(j,b)};this.clear=function(){clearTimeout(a)};return this},v=function(b){this.topics={};this.context=b?b:this;this.publish=function(b,a,g,d){if(this.topics[b]){var c=this.topics[b],f=Array.prototype.slice.call(arguments,1),l=[],i,e,h,p;e=0;for(h=c.length;e<h;e++)p=c[e],i=p[0],p[1]&&(p[0]=function(){},l.push(e)),i.apply(this.context,f);e=0;for(h=l.length;e<h;e++)c.splice(l[e],
1)}};this.subscribe=function(b,a,g){this.topics[b]?this.topics[b].push([a,g]):this.topics[b]=[[a,g]];return{topic:b,callback:a}};this.unsubscribe=function(b){if(this.topics[b.topic])for(var a=this.topics[b.topic],g=0,d=a.length;g<d;g++)a[g][0]===b.callback&&a.splice(g,1)}},z=function(b){var a=this.canvasContext,d=b.x[0],b=b.y[0],g=this.settings.lineWidth,c=a.fillStyle;a.fillStyle=a.strokeStyle;a.fillRect(d+g/-2,b+g/-2,g,g);a.fillStyle=c},u=function(b,a){var d=new k(b.x[a-1],b.y[a-1]),g=new k(b.x[a],
b.y[a]),c=d.getVectorToPoint(g);if(1<a){var f=new k(b.x[a-2],b.y[a-2]),l=f.getVectorToPoint(d),i;if(l.getLength()>this.lineCurveThreshold){i=2<a?(new k(b.x[a-3],b.y[a-3])).getVectorToPoint(f):new m(0,0);var e=0.35*l.getLength(),h=l.angleTo(i.reverse()),p=c.angleTo(l.reverse());i=(new m(i.x+l.x,i.y+l.y)).resizeTo(Math.max(0.05,h)*e);var n=(new m(l.x+c.x,l.y+c.y)).reverse().resizeTo(Math.max(0.05,p)*e),l=this.canvasContext,e=f.x,p=f.y,h=d.x,w=d.y,A=f.x+i.x,f=f.y+i.y;i=d.x+n.x;n=d.y+n.y;l.beginPath();
l.moveTo(e,p);l.bezierCurveTo(A,f,i,n,h,w);l.stroke()}}c.getLength()<=this.lineCurveThreshold&&(c=this.canvasContext,f=d.x,d=d.y,i=g.x,g=g.y,c.beginPath(),c.moveTo(f,d),c.lineTo(i,g),c.stroke())},x=function(b){var a=b.x.length-1;if(0<a){var d=new k(b.x[a],b.y[a]),g=new k(b.x[a-1],b.y[a-1]),c=g.getVectorToPoint(d);if(c.getLength()>this.lineCurveThreshold){if(1<a){var b=(new k(b.x[a-2],b.y[a-2])).getVectorToPoint(g),f=(new m(b.x+c.x,b.y+c.y)).resizeTo(c.getLength()/2),c=this.canvasContext,b=g.x,a=g.y,
l=d.x,i=d.y,e=g.x+f.x,g=g.y+f.y,f=d.x,d=d.y;c.beginPath();c.moveTo(b,a);c.bezierCurveTo(e,g,f,d,l,i)}else c=this.canvasContext,b=g.x,g=g.y,a=d.x,d=d.y,c.beginPath(),c.moveTo(b,g),c.lineTo(a,d);c.stroke()}}};r.prototype.resetCanvas=function(b){var a=this.canvas,d=this.settings,c=this.canvasContext,f=this.isCanvasEmulator,l=a.width,i=a.height;c.clearRect(0,0,l+30,i+30);c.shadowColor=c.fillStyle=d["background-color"];f&&c.fillRect(0,0,l+30,i+30);c.lineWidth=Math.ceil(parseInt(d.lineWidth,10));c.lineCap=
c.lineJoin="round";c.strokeStyle=d["decor-color"];c.shadowOffsetX=0;c.shadowOffsetY=0;var h=Math.round(i/5),p=1.5*h,k=i-h,l=l-1.5*h,i=i-h;c.beginPath();c.moveTo(p,k);c.lineTo(l,i);c.stroke();c.strokeStyle=d.color;f||(c.shadowColor=c.strokeStyle,c.shadowOffsetX=0.5*c.lineWidth,c.shadowOffsetY=-0.6*c.lineWidth,c.shadowBlur=0);b||(b=[]);c=this.dataEngine=new t(b,this,z,u,x);d.data=b;$(a).data(e+".data",b).data(e+".settings",d);var n=this.$parent,w=this.events,A=e;c.changed=function(){w.publish(A+".change");
n.trigger("change")};c.changed();return!0};r.prototype.initializeCanvas=function(b){var a=document.createElement("canvas"),c=$(a);b.width===b.height&&"ratio"===b.height&&(b.width="100%");c.css("margin",0).css("padding",0).css("border","none").css("height","ratio"===b.height||!b.height?1:b.height.toString(10)).css("width","ratio"===b.width||!b.width?1:b.width.toString(10));c.appendTo(this.$parent);"ratio"===b.height?c.css("height",Math.round(c.width()/b.sizeRatio)):"ratio"===b.width&&c.css("width",
Math.round(c.height()*b.sizeRatio));c.addClass(e);a.width=c.width();a.height=c.height();b=a;if(b.getContext)b=!1;else{var c=b.ownerDocument.parentWindow,d=c.FlashCanvas?b.ownerDocument.parentWindow.FlashCanvas:"undefined"===typeof FlashCanvas?void 0:FlashCanvas;if(d){b=d.initElement(b);d=1;c&&(c.screen&&c.screen.deviceXDPI&&c.screen.logicalXDPI)&&(d=1*c.screen.deviceXDPI/c.screen.logicalXDPI);if(1!==d)try{$(b).children("object").get(0).resize(Math.ceil(b.width*d),Math.ceil(b.height*d)),b.getContext("2d").scale(d,
d)}catch(f){}b=!0}else throw Error("Canvas element does not support 2d context. jSignature cannot proceed.");}this.isCanvasEmulator=b;a.onselectstart=function(b){b&&b.preventDefault&&b.preventDefault();b&&b.stopPropagation&&b.stopPropagation();return!1};return a};var p=window,h=function(b,a){var c=new Image,d=this;c.onload=function(){d.getContext("2d").drawImage(c,0,0,c.width<d.width?c.width:d.width,c.height<d.height?c.height:d.height)};c.src="data:"+a+","+b},a=function(b){this.find("canvas."+e).add(this.filter("canvas."+
e)).data(e+".this").resetCanvas(b);return this},f=function(b,a){if(void 0===a&&("string"===typeof b&&"data:"===b.substr(0,5))&&(a=b.slice(5).split(",")[0],b=b.slice(6+a.length),a===b))return;var c=this.find("canvas."+e).add(this.filter("canvas."+e));if(n.hasOwnProperty(a))0!==c.length&&n[a].call(c[0],b,a,function(b){return function(){return b.resetCanvas.apply(b,arguments)}}(c.data(e+".this")));else throw Error(e+" is unable to find import plugin with for format '"+String(a)+"'");return this},d=new v,
c=e,l,i=function(){d.publish(c+".parentresized")};$(p).bind("resize."+c,function(){l&&clearTimeout(l);l=setTimeout(i,500)}).bind("mouseup."+c,function(){d.publish(c+".windowmouseup")});var w={},A={"default":function(){return this.toDataURL()},"native":function(b){return b},image:function(){var b=this.toDataURL();if("string"===typeof b&&4<b.length&&"data:"===b.slice(0,5)&&-1!==b.indexOf(",")){var a=b.indexOf(",");return[b.slice(5,a),b.substr(a+1)]}return[]}},n={"native":function(b,a,c){c(b)},image:h,
"image/png;base64":h,"image/jpeg;base64":h,"image/jpg;base64":h},B={"export":A,"import":n,instance:w},C={init:function(b){return this.each(function(){var a,c=!1;for(a=this.parentNode;a&&!c;)c=a.body,a=a.parentNode;!c||new r(this,b,w)})},getSettings:function(){return this.find("canvas."+e).add(this.filter("canvas."+e)).data(e+".this").settings},clear:a,reset:a,addPlugin:function(b,a,c){B.hasOwnProperty(b)&&(B[b][a]=c);return this},listPlugins:function(b){var a=[];if(B.hasOwnProperty(b)){var b=B[b],
c;for(c in b)b.hasOwnProperty(c)&&a.push(c)}return a},getData:function(b){var a=this.find("canvas."+e).add(this.filter("canvas."+e));void 0===b&&(b="default");if(0!==a.length&&A.hasOwnProperty(b))return A[b].call(a.get(0),a.data(e+".data"))},importData:f,setData:f,globalEvents:function(){return d},events:function(){return this.find("canvas."+e).add(this.filter("canvas."+e)).data(e+".this").events}};$.fn[e]=function(b){if(!b||"object"===typeof b)return C.init.apply(this,arguments);if("string"===typeof b&&
C[b])return C[b].apply(this,Array.prototype.slice.call(arguments,1));$.error("Method "+String(b)+" does not exist on jQuery."+e)}})();
(function(){$.fn.jSignature("addPlugin","instance","UndoButton",function(q){this.events.subscribe("jSignature.attachingEventHandlers",function(){if(this.settings[q]){var m=this.settings[q];"function"!==typeof m&&(m=function(){var e=$('<input type="button" value="Undo last stroke" style="position:absolute;display:none;margin:0 !important;top:auto" />').appendTo(this.$controlbarLower),k=e.width();e.css("left",Math.round((this.canvas.width-k)/2));k!==e.width()&&e.width(k);return e});var k=m.call(this),
t=this;t.events.subscribe("jSignature.change",function(){t.dataEngine.data.length?k.show():k.hide()});var r=this,e=(this.events.topics.hasOwnProperty("jSignature.undo")?q:"jSignature")+".undo";k.bind("click",function(){r.events.publish(e)});r.events.subscribe(e,function(){var e=r.dataEngine.data;e.length&&(e.pop(),r.resetCanvas(e))})}})})})();
(function(){for(var q={},m={},k="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWX".split(""),t=k.length/2,r=t-1;-1<r;r--)q[k[r]]=k[r+t],m[k[r+t]]=k[r];var e=function(e){for(var e=e.split(""),h=e.length,a=1;a<h;a++)e[a]=q[e[a]];return e.join("")},y=function(k){for(var h=[],a=0,f=1,d=k.length,c,l,i=0;i<d;i++)c=Math.round(k[i]),l=c-a,a=c,0>l&&0<f?(f=-1,h.push("Z")):0<l&&0>f&&(f=1,h.push("Y")),c=Math.abs(l),c>=t?h.push(e(c.toString(t))):h.push(c.toString(t));return h.join("")},v=function(e){for(var h=
[],e=e.split(""),a=e.length,f,d=1,c=[],l=0,i=0;i<a;i++)f=e[i],f in q||"Z"===f||"Y"===f?(0!==c.length&&(c=parseInt(c.join(""),t)*d+l,h.push(c),l=c),"Z"===f?(d=-1,c=[]):"Y"===f?(d=1,c=[]):c=[f]):c.push(m[f]);h.push(parseInt(c.join(""),t)*d+l);return h},z=function(e){for(var h=[],a=e.length,f,d=0;d<a;d++)f=e[d],h.push(y(f.x)),h.push(y(f.y));return h.join("_")},u=function(e){for(var h=[],e=e.split("_"),a=e.length/2,f=0;f<a;f++)h.push({x:v(e[2*f]),y:v(e[2*f+1])});return h},k=function(e){return["image/jsignature;base30",
z(e)]},r=function(e,h,a){"string"===typeof e&&("image/jsignature;base30"===e.substring(0,23).toLowerCase()&&(e=e.substring(24)),a(u(e)))};if(null==this.jQuery)throw Error("We need jQuery for some of the functionality. jQuery is not detected. Failing to initialize...");var x=this.jQuery.fn.jSignature;x("addPlugin","export","base30",k);x("addPlugin","export","image/jsignature;base30",k);x("addPlugin","import","base30",r);x("addPlugin","import","image/jsignature;base30",r);this.jSignatureDebug&&(this.jSignatureDebug.base30=
{remapTailChars:e,compressstrokeleg:y,uncompressstrokeleg:v,compressstrokes:z,uncompressstrokes:u,charmap:q})}).call("undefined"!==typeof window?window:this);
(function(){function q(a,f){this.x=a;this.y=f;this.reverse=function(){return new this.constructor(-1*this.x,-1*this.y)};this._length=null;this.getLength=function(){this._length||(this._length=Math.sqrt(Math.pow(this.x,2)+Math.pow(this.y,2)));return this._length};var d=function(a){return Math.round(a/Math.abs(a))};this.resizeTo=function(a){if(0===this.x&&0===this.y)this._length=0;else if(0===this.x)this._length=a,this.y=a*d(this.y);else if(0===this.y)this._length=a,this.x=a*d(this.x);else{var f=Math.abs(this.y/
this.x),e=Math.sqrt(Math.pow(a,2)/(1+Math.pow(f,2))),f=f*e;this._length=a;this.x=e*d(this.x);this.y=f*d(this.y)}return this};this.angleTo=function(a){var d=this.getLength()*a.getLength();return 0===d?0:Math.acos(Math.min(Math.max((this.x*a.x+this.y*a.y)/d,-1),1))/Math.PI}}function m(a,f){this.x=a;this.y=f;this.getVectorToCoordinates=function(a,c){return new q(a-this.x,c-this.y)};this.getVectorFromCoordinates=function(a,c){return this.getVectorToCoordinates(a,c).reverse()};this.getVectorToPoint=function(a){return new q(a.x-
this.x,a.y-this.y)};this.getVectorFromPoint=function(a){return this.getVectorToPoint(a).reverse()}}function k(a,f){var d=Math.pow(10,f);return Math.round(a*d)/d}function t(a,f,d){var f=f+1,c=new m(a.x[f-1],a.y[f-1]),e=new m(a.x[f],a.y[f]),e=c.getVectorToPoint(e),i=new m(a.x[f-2],a.y[f-2]),c=i.getVectorToPoint(c);return c.getLength()>d?(d=2<f?(new m(a.x[f-3],a.y[f-3])).getVectorToPoint(i):new q(0,0),a=0.35*c.getLength(),i=c.angleTo(d.reverse()),f=e.angleTo(c.reverse()),d=(new q(d.x+c.x,d.y+c.y)).resizeTo(Math.max(0.05,
i)*a),e=(new q(c.x+e.x,c.y+e.y)).reverse().resizeTo(Math.max(0.05,f)*a),e=new q(c.x+e.x,c.y+e.y),["c",k(d.x,2),k(d.y,2),k(e.x,2),k(e.y,2),k(c.x,2),k(c.y,2)]):["l",k(c.x,2),k(c.y,2)]}function r(a,f){var d=a.x.length-1,c=new m(a.x[d],a.y[d]),e=new m(a.x[d-1],a.y[d-1]),c=e.getVectorToPoint(c);if(1<d&&c.getLength()>f){var d=(new m(a.x[d-2],a.y[d-2])).getVectorToPoint(e),e=c.angleTo(d.reverse()),i=0.35*c.getLength(),d=(new q(d.x+c.x,d.y+c.y)).resizeTo(Math.max(0.05,e)*i);return["c",k(d.x,2),k(d.y,2),k(c.x,
2),k(c.y,2),k(c.x,2),k(c.y,2)]}return["l",k(c.x,2),k(c.y,2)]}function e(a,e,d){for(var e=["M",k(a.x[0]-e,2),k(a.y[0]-d,2)],d=1,c=a.x.length-1;d<c;d++)e.push.apply(e,t(a,d,1));0<c?e.push.apply(e,r(a,d,1)):0===c&&e.push.apply(e,["l",1,1]);return e.join(" ")}function y(a){var f=['<?xml version="1.0" encoding="UTF-8" standalone="no"?>','<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'],d,c=a.length,l,i=[],h=[],k=l=d=0,n=0,p=[];if(0!==c){for(d=0;d<c;d++){k=
a[d];n=[];l={x:[],y:[]};for(var m=void 0,b=void 0,m=0,b=k.x.length;m<b;m++)n.push({x:k.x[m],y:k.y[m]});n=simplify(n,0.7,!0);m=0;for(b=n.length;m<b;m++)l.x.push(n[m].x),l.y.push(n[m].y);p.push(l);i=i.concat(l.x);h=h.concat(l.y)}a=Math.min.apply(null,i)-1;c=Math.max.apply(null,i)+1;i=Math.min.apply(null,h)-1;h=Math.max.apply(null,h)+1;k=0>a?0:a;n=0>i?0:i;d=c-a;l=h-i}f.push('<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="'+d.toString()+'" height="'+l.toString()+'">');d=0;for(c=p.length;d<
c;d++)l=p[d],f.push('<path fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="'+e(l,k,n)+'"/>');f.push("</svg>");return f.join("")}function v(a){return[p,y(a)]}function z(a){return[h,x(y(a))]}var u=window;"use strict";("undefined"!=typeof exports?exports:u).simplify=function(a,e,d){e=void 0!==e?e*e:1;if(!d){for(var c=a.length,l,i=a[0],h=[i],d=1;d<c;d++){l=a[d];var k=l.x-i.x,n=l.y-i.y;k*k+n*n>e&&(h.push(l),i=l)}a=(i!==l&&h.push(l),h)}l=a;var d=l.length,
c=new ("undefined"!=typeof Uint8Array?Uint8Array:Array)(d),i=0,h=d-1,m,p,b=[],j=[],s=[];for(c[i]=c[h]=1;h;){n=0;for(k=i+1;k<h;k++){m=l[k];var g=l[i],r=l[h],q=g.x,t=g.y,g=r.x-q,u=r.y-t,v=void 0;if(0!==g||0!==u)v=((m.x-q)*g+(m.y-t)*u)/(g*g+u*u),1<v?(q=r.x,t=r.y):0<v&&(q+=g*v,t+=u*v);m=(g=m.x-q,u=m.y-t,g*g+u*u);m>n&&(p=k,n=m)}n>e&&(c[p]=1,b.push(i),j.push(p),b.push(p),j.push(h));i=b.pop();h=j.pop()}for(k=0;k<d;k++)c[k]&&s.push(l[k]);return a=s,a};if("function"!==typeof x)var x=function(a){var e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".split(""),
d,c,h,i,k=0,m=0,n="",n=[];do d=a.charCodeAt(k++),c=a.charCodeAt(k++),h=a.charCodeAt(k++),i=d<<16|c<<8|h,d=i>>18&63,c=i>>12&63,h=i>>6&63,i&=63,n[m++]=e[d]+e[c]+e[h]+e[i];while(k<a.length);n=n.join("");a=a.length%3;return(a?n.slice(0,a-3):n)+"===".slice(a||3)};var p="image/svg+xml",h="image/svg+xml;base64";if("undefined"===typeof $)throw Error("We need jQuery for some of the functionality. jQuery is not detected. Failing to initialize...");u=$.fn.jSignature;u("addPlugin","export","svg",v);u("addPlugin",
"export",p,v);u("addPlugin","export","svgbase64",z);u("addPlugin","export",h,z)})();

View File

@ -0,0 +1,73 @@
.bs-sidebar {
position: fixed;
top: 110px;
z-index : 1;
background-color: #f7f5fa;
border-radius: 5px;
}
.bs-sidenav {
padding-top: 10px;
padding-bottom: 10px;
}
.bs-sidebar .nav > li > a {
display: block;
color: #716b7a;
padding: 5px 20px;
}
.bs-sidebar .nav > .active > a,
.bs-sidebar .nav > .active:hover > a,
.bs-sidebar .nav > .active:focus > a {
font-weight: bold;
color: #563d7c;
background-color: transparent;
border-right: 1px solid #563d7c;
}
.bs-sidebar .nav .nav {
display: none;
margin-bottom: 8px;
}
.bs-sidebar .nav .nav > li > a {
padding-top: 3px;
padding-bottom: 3px;
padding-left: 30px;
font-size: 90%;
}
@media (min-width: 992px) {
.bs-sidebar .nav > .active > ul {
display: block;
}
.bs-sidebar {
width: 213px;
}
}
@media (min-width: 1200px) {
.bs-sidebar {
width: 263px;
}
}
@media print {
body {
padding : 0 !important;
}
}
#countdown {
padding-left : 10px;
padding-top: 10px;
padding-bottom: 5px;
font-size: 1.4em;
}
.day_counter{
font-size: 2.4em;
padding-left : 5px;
}
.days_left {
font-size: 1.4em;
text-align: center;
padding-left : 3px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View File

@ -0,0 +1,102 @@
$(document).ready(function () {
$('a.js_update_line_json').on('click', function (ev) {
ev.preventDefault();
var $link = $(ev.currentTarget);
var href = $link.attr("href");
var order_id = href.match(/order_id=([0-9]+)/);
var line_id = href.match(/update_line\/([0-9]+)/);
var token = href.match(/token=(.*)/);
openerp.jsonRpc("/quote/update_line/", 'call', {
'line_id': line_id[1],
'order_id': parseInt(order_id[1]),
'token': token[1],
'remove': $link.is('[href*="remove"]'),
'unlink': $link.is('[href*="unlink"]')
})
.then(function (data) {
if(!data){
location.reload();
}
$link.parents('.input-group:first').find('.js_quantity').val(data[0]);
$('[data-id="total_amount"]>span').html(data[1]);
});
return false;
});
$('#modelaccept').on('shown.bs.modal', function (e) {
$("#signature").empty().jSignature({'decor-color' : '#D1D0CE'});
});
$('#sign_clean').on('click', function (e) {
$("#signature").jSignature('reset');
});
$('form.js_accept_json').submit(function(ev){
ev.preventDefault();
var $link = $(ev.currentTarget);
var href = $link.attr("action");
var order_id = href.match(/accept\/([0-9]+)/);
var token = href.match(/token=(.*)/);
var sign = false;
var signer_name = false;
if($('#signature').length > 0){
var isSignature=$("#signature").jSignature('getData','base30')[1].length>1?true:false;
if (isSignature)
{
sign = JSON.stringify($("#signature").jSignature("getData",'image')[1]);
}
signer_name = $("#name").val();
}
openerp.jsonRpc("/quote/accept/", 'call', {
'order_id': parseInt(order_id[1]),
'token': token[1],
'signer': signer_name,
'sign': sign,
})
.then(function (data) {
if(_.isEmpty(data[0])){
$('#modelaccept').modal('hide');
var url = location.protocol+'//'+location.hostname+(location.port ? ':'+location.port : "")
window.location.replace(url +'/quote/'+order_id[1]+'/'+token[1]+'?message=3');
} else{
if (data[0]['signer']) $('#signer').addClass('has-error'); else $('#signer').removeClass('has-error');
if (data[0]['sign']) $('#drawsign').addClass('panel-danger'); else $('#drawsign').removeClass('panel-danger');
}
});
return false
});
// automatically generate a menu from h1 and h2 tag in content
var ul = $('[data-id="quote_sidebar"]');
var sub_li = null;
var sub_ul = null;
$("section h1, section h2").each(function() {
switch (this.tagName.toLowerCase()) {
case "h1":
id = _.uniqueId('quote_header_')
$(this.parentNode).attr('id',id);
sub_li = $("<li>").html('<a href="#'+id+'">'+$(this).text()+'</a>').appendTo(ul);
sub_ul = null;
break;
case "h2":
id = _.uniqueId('quote_')
if (sub_li) {
if (!sub_ul) {
sub_ul = $("<ul class='nav'>").appendTo(sub_li);
}
$(this.parentNode).attr('id',id)
$("<li>").html('<a href="#'+id+'">'+$(this).text()+'</a>').appendTo(sub_ul);
}
break;
}
});
var target_date = new Date($('#validity_date').val());
setInterval(function () {
var current_date = new Date();
var days_left = Math.floor((target_date - current_date)/86400000);
$('#countdown').html('<span><i class="fa fa-clock-o fa-2x"/><span class="day_counter">'+((days_left > 0) ? days_left : 0)+'</span><small class="days_left">Day(s)</small></span>')
}, 1000);
//vim:et fdc=0 fdl=0 foldnestmax=3 fdm=syntax:
});

View File

@ -0,0 +1,468 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<template id="pricing" name="Price">
<section data-snippet-id="title">
<h1 class="page-header">Pricing</h1>
</section>
<section id="quote">
<table class="table table-hover">
<thead>
<tr>
<th>Products</th>
<th>Quantity</th>
<th>Discount(%)</th>
<th class="text-right">Unit Price</th>
<th class="text-right">Price</th>
</tr>
</thead>
<tbody>
<tr t-foreach="quotation.order_line" t-as="line">
<td>
<div t-field="line.name"/>
</td>
<td>
<div id="quote_qty">
<t t-esc="line.product_uom_qty"/>
</div>
</td>
<td>
<div id="quote_discount" t-if="line.discount">
<t t-esc="line.discount"/>
</div>
</td>
<td>
<strong class="text-right">
<div t-field="line.price_unit"
t-field-options='{"widget": "monetary", "display_currency": "quotation.pricelist_id.currency_id"}'
t-att-style="line.discount and 'text-decoration: line-through' or ''"
t-att-class="line.discount and 'text-danger' or ''"/>
<!-- TODO: apply monetary widget formating -->
<div t-if="line.discount">
<t t-esc="'%.2f' % ((1-line.discount) * line.price_unit)"/>
</div>
</strong>
</td>
<td>
<div class="text-right"
t-field="line.price_subtotal"
t-field-options='{"widget": "monetary", "display_currency": "quotation.pricelist_id.currency_id"}'/>
</td>
<td>
<a t-href="./update_line/#{ line.id }/?order_id=#{ quotation.id }&amp;unlink=True&amp;token=#{ quotation.access_token }" class="mb8 js_update_line_json pull-right hidden-print" t-if="line.option_line_id">
<span class="fa fa-trash-o"></span>
</a>
</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td><h3 class="text-right">Total</h3></td>
<td class="text-right" colspan="2">
<h3>
<strong data-id="total_amount" t-field="quotation.amount_total" t-field-options='{"widget": "monetary","display_currency": "quotation.pricelist_id.currency_id"}'/>
</h3>
</td>
</tr>
</tbody>
</table>
</section>
<t t-call="website_quotation.quotation_toolbar"/>
<section id="terms" class="container" t-if="quotation.note">
<h2 class="page-header">Terms &amp; Conditions</h2>
<p t-field="quotation.note"/>
</section>
</template>
<template id="change_quantity" inherit_option_id="website_quotation.pricing" name="Change Quantity">
<xpath expr="//div[@id='quote_qty']" position="replace">
<div class="input-group">
<span class="input-group-addon hidden-print">
<a t-href="./update_line/#{ line.id }/?order_id=#{ quotation.id }&amp;remove=True&amp;token=#{ quotation.access_token }" class="mb8 js_update_line_json">
<span class="fa fa-minus"/>
</a>
</span>
<input type="text" class="js_quantity form-control" t-att-data-id="line.id" t-att-value="line.product_uom_qty"/>
<span class="input-group-addon hidden-print">
<a t-href="./update_line/#{ line.id }/?order_id=#{ quotation.id }&amp;token=#{ quotation.access_token }" class="mb8 js_update_line_json">
<span class="fa fa-plus"/>
</a>
</span>
</div>
</xpath>
</template>
<template id="chatter">
<h1 class="page-header hidden-print">History</h1>
<ul class="media-list hidden-print" id="comments-list">
<li t-foreach="quotation.message_ids" t-as="message" class="media">
<div class="media-body">
<img class="media-object pull-left" t-att-src="'/website/image?model=res.partner&amp;field=image_small&amp;id='+str(message.author_id.id)" style="width: 50px; margin-right: 10px;"/>
<div class="media-body">
<h5 class="media-heading">
<span t-field="message.author_id"/> <small>on <span t-field="message.date"/></small>
</h5>
<div t-field="message.body"/>
</div>
</div>
</li>
</ul>
</template>
<!-- Options:Quotation Chatter: user can reply -->
<template id="opt_quotation_chatter_post_complete_comment" name="Allow Comments" inherit_option_id="website_quotation.chatter" inherit_id="website_quotation.chatter">
<xpath expr="//h1" position="after">
<section class="mb32 css_editable_mode_hidden hidden-print">
<form id="comment" t-attf-action="/quote/#{quotation.id}/#{quotation.access_token}/post" method="POST">
<img class="img pull-left img-rounded" t-att-src="'/website/image?model=res.partner&amp;field=image_small&amp;id='+str(user_id.partner_id.id)" style="width: 50px; margin-right: 10px;"/>
<div class="pull-left mb32" style="width: 75%%">
<textarea rows="4" name="comment" class="form-control" placeholder="Send us a note..."></textarea>
<button type="submit" class="btn btn-primary mt8">Send</button>
</div>
</form>
</section>
<div class="clearfix"/>
</xpath>
</template>
<template id="quotation_toolbar">
<div class="text-center hidden-print" t-if="quotation.state in ('draft', 'sent', 'waiting_date')">
<a class="btn btn-success fa fa-check" data-toggle="modal" data-target="#modelaccept">
Accept
</a>
<a class="btn btn-info fa fa-comment" type="submit" href="#discussion">
Feedback
</a>
<a class="btn btn-danger fa fa-times" data-toggle="modal" data-target="#modeldecline">
Reject
</a>
</div>
</template>
<template id="so_quotation" name="Product Quotation">
<t t-call="website.layout">
<t t-set="head">
<script type="text/javascript" src="/website_quotation/static/src/js/website_quotation.js"></script>
<script type="text/javascript" src="/website_quotation/static/lib/jSignature/jSignature.min.js"></script>
<link rel='stylesheet' href='/website_quotation/static/src/css/website_quotation.css'/>
<t t-raw="head or ''"/>
</t>
<body data-spy="scroll" data-target=".navspy">
<div class="container">
<div class="row mt16">
<div class="col-md-3">
<div class="bs-sidebar">
<div class="text-center hidden-print" t-if="quotation.state in ('draft', 'sent', 'waiting_date')" style="padding: 10px">
<a t-if="not date_diff" class="btn btn-primary btn-block fa fa-check" data-toggle="modal" data-target="#modelaccept">
Accept Order
</a>
<a t-if="date_diff">
<strong>This offer expired!.</strong> <a href="#discussion">Contact us</a> for new quote.
</a>
<div class="mt8">
<a type="submit" href="#discussion">
Ask Changes
</a> or
<a data-toggle="modal" data-target="#modeldecline">
Reject
</a>
</div>
</div>
<hr class="mt0 mb0"/>
<t t-call="website_quotation.navigation_menu"/>
<hr class="mt0 mb0"/>
<div t-if="not date_diff" class="text-center hidden-print">
<input type="hidden" t-att-value="quotation.validity_date" id="validity_date"/>
<div class="mt8" t-if="(quotation.before_discount - quotation.amount_total) > 0.0">
<strong>This offer at </strong>
<em t-field="quotation.amount_total"
t-field-options='{"widget": "monetary", "display_currency": "quotation.pricelist_id.currency_id"}'></em>
<em t-field="quotation.before_discount"
t-field-options='{"widget": "monetary", "display_currency": "quotation.pricelist_id.currency_id"}'
style="text-decoration: line-through"
class="text-danger"></em>
</div>
<strong class="text-center" t-if="(quotation.before_discount - quotation.amount_total) > 0.0">Expire in :</strong>
<strong class="text-center" t-if="not((quotation.before_discount - quotation.amount_total) > 0.0)">This offer Expire in:</strong>
<div id="countdown"/>
<strong t-if="(quotation.before_discount - quotation.amount_total) > 0.0" class="text-center">(<t t-esc="(quotation.before_discount - quotation.amount_total)"/> Discount)</strong>
</div>
</div>
</div>
<div class="col-md-9">
<div class="alert alert-success alert-dismissable" t-if="message==1">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&amp;times;</button>
Your message has been successfully sent!
</div>
<div class="alert alert-warning alert-dismissable" t-if="message==2">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&amp;times;</button>
This quotation has been rejected. <a href="#discussion">Contact us</a> if you want a new one.
</div>
<div class="alert alert-warning alert-dismissable" t-if="message==3">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">&amp;times;</button>
This order has been validated. Thanks for your trust
and do not hesitate to <a href="#discussion">contact us</a> for
any question.
</div>
<a id="introduction"/>
<h1 class="page-header mt16">
<span t-if="quotation.state in ('draft','sent','cancel')">Your Quotation</span>
<span t-if="quotation.state not in ('draft','sent','cancel')">Your Order</span>
<em t-esc="quotation.name"/>
<small t-field="quotation.state"/>
<div groups="base.group_website_publisher" t-ignore="true" class="pull-right css_editable_mode_hidden">
<a class="btn btn-info hidden-print" t-att-href="'/web#return_label=Website&amp;model=%s&amp;id=%s' % (quotation._name, quotation.id)">Update Quote</a>
</div>
</h1>
<div class="modal fade" id="modelaccept" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<form id="accept" method="POST" t-attf-action="/quote/accept/#{quotation.id}/?token=#{quotation.access_token}" class="js_accept_json modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&amp;times;</button>
<h4 class="modal-title">Validate Order</h4>
</div>
<div class="modal-body">
<p t-if="not salesperson">
I agree that by signing this proposal, I
accept it on the behalf of <b t-field="quotation.company_id"/>,
for an amount of
<b data-id="total_amount" t-field="quotation.amount_total"
t-field-options='{"widget": "monetary", "display_currency": "quotation.pricelist_id.currency_id"}'/>
with payment terms: <b t-field="quotation.payment_term"/>.
</p>
<p t-if="salesperson">
Only customer can validate this quotation.
</p>
</div>
<div class="modal-footer">
<button type="submit" t-attf-class="btn btn-primary #{salesperson and 'disabled' or ''}">Sign Order</button> or
<button type="button" class="btn btn-link" data-dismiss="modal" style="padding: 0">Cancel</button>
</div>
</form>
</div>
</div>
<div class="alert alert-warning alert-dismissable" t-if="quotation.state == 'cancel'">
<button type="button" class="close hidden-print" data-dismiss="alert" aria-hidden="true">&amp;times;</button>
<strong>This quotation has been canceled.</strong> Contact <span t-field="quotation.user_id"/> ( <span t-if="quotation.user_id.email"> <span class="fa fa-envelope" t-field="quotation.user_id.email" /></span> <span t-if="quotation.user_id.phone"> <span class="fa fa-phone" t-field="quotation.user_id.phone"/></span> ) in order to ask a new quote.
</div>
<div class="modal fade" id="modeldecline" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<form id="decline" method="POST" t-attf-action="/quote/#{quotation.id}/#{quotation.access_token}/decline" class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&amp;times;</button>
<h4 class="modal-title">Reject This Quote</h4>
</div>
<div class="modal-body">
<p>
Tell us why you are refusing this quotation, this will help us improve our services.
</p>
<textarea rows="4" name="decline_message" placeholder="Your feedback....." class="form-control"/>
</div>
<div class="modal-footer">
<button type="submit" t-att-id="quotation.id" class="btn btn-primary">Reject</button> or
<button type="button" class="btn btn-link" data-dismiss="modal" style="padding: 0">Cancel</button>
</div>
</form>
</div>
</div>
<div class="row mt32">
<div class="col-md-6">
<div class="row">
<label class="col-sm-4 text-right">Customer:</label>
<div class="col-sm-8">
<div t-field="quotation.partner_id"/>
</div>
</div>
<div class="row">
<label class="col-sm-4 text-right">Bill To:</label>
<div class="col-sm-8">
<div t-field="quotation.partner_invoice_id" t-field-options='{
"widget": "contact",
"fields": ["address", "name", "phone", "email"]
}'/>
</div>
</div>
<div t-if="quotation.partner_shipping_id.id != quotation.partner_invoice_id.id" class="row">
<label class="col-sm-4 text-right">Ship To:</label>
<div class="col-sm-8">
<div t-field="quotation.partner_shipping_id" t-field-options='{
"widget": "contact",
"fields": ["address", "name", "phone"]
}'/>
</div>
</div>
</div>
<div class="col-md-6">
<div class="row">
<label class="col-sm-5 text-right">Your Contact:</label>
<div class="col-sm-7">
<div t-field="quotation.user_id" t-field-options='{
"widget": "contact",
"fields": ["name", "phone", "email"]
}'/>
</div>
</div>
<div class="row">
<label class="col-sm-5 text-right">Quote Date:</label>
<div class="col-sm-7">
<span t-field="quotation.date_order"/>
</div>
<div class="clearfix"/>
<div t-if="quotation.client_order_ref">
<label class="col-sm-5 text-right">Your Reference:</label>
<div class="col-sm-7">
<span t-field="quotation.client_order_ref"/>
</div>
</div>
</div>
</div>
</div>
<a id="offer"/>
<div t-field="quotation.website_description"/>
<t t-foreach="quotation.order_line" t-as="line">
<a t-att-id="line.id"/>
<div t-field="line.website_description"/>
</t>
<div class="oe_structure"/>
<a id="pricing"/>
<t t-call="website_quotation.pricing"/>
<a id="options"/>
<t t-call="website_quotation.optional_products"/>
<a id="discussion"/>
<t t-call="website_quotation.chatter"/>
</div>
</div>
</div>
</body>
</t>
</template>
<template id="navigation_menu">
<div class="hidden-print navspy" data-editable="0" role="complementary">
<ul class="nav bs-sidenav" data-id="quote_sidebar">
<li><a href="#introduction">Introduction</a></li>
</ul>
</div>
</template>
<!-- Options:Quotation Signature -->
<template id="opt_quotation_signature" name="Signature" inherit_option_id="website_quotation.so_quotation" inherit_id="website_quotation.so_quotation">
<xpath expr="//div[@class='modal-body']" position="inside">
<div id="signer" class="form-group" t-if="not salesperson">
<label class="control-label" for="name">Your Name:</label>
<input type="text" name="signer" id="name" class="form-control"/>
</div>
<div class="panel panel-default mt16 mb0" id="drawsign" t-if="not salesperson">
<div class="panel-heading">
<div class="pull-right">
<a id="sign_clean" class="btn btn-xs">Clear</a>
</div>
<strong>Draw your signature</strong>
</div>
<div id="signature" class="panel-body" style="padding: 0"/>
</div>
</xpath>
</template>
<template id="optional_products">
<div class="container mt32" t-if="option">
<section data-snippet-id="title">
<h1 class="page-header">Options</h1>
</section>
<section id="options">
<table class="table table-hover">
<thead>
<tr>
<th>Products</th>
<th>Discription</th>
<th>Discount(%)</th>
<th class="text-right">Price</th>
</tr>
</thead>
<tbody>
<tr t-foreach="quotation.options" t-as="option">
<t t-if="not option.line_id">
<td>
<div t-field="option.product_id.name"/>
</td>
<td>
<div t-field="option.name"/>
</td>
<td>
<div id="quote_discount" t-if="option.discount">
<t t-esc="option.discount"/>
</div>
</td>
<td>
<strong class="text-right">
<div t-field="option.price_unit"
t-field-options='{"widget": "monetary", "display_currency": "quotation.pricelist_id.currency_id"}'
t-att-style="option.discount and 'text-decoration: line-through' or ''"
t-att-class="option.discount and 'text-danger' or ''"/>
<div t-if="option.discount">
<t t-esc="'%.2f' % ((1-option.discount) * option.price_unit)"/>
</div>
</strong>
</td>
<td class="pull-right">
<a t-href="/quote/add_line/#{ option.id }/#{ quotation.id }/#{ quotation.access_token }" class="mb8 hidden-print">
<span class="fa fa-shopping-cart"/>
</a>
</td>
</t>
</tr>
</tbody>
</table>
</section>
</div>
</template>
<template id="so_template" name="SO Template">
<t t-call="website.layout">
<t t-set="head">
<script type="text/javascript" src="/website_quotation/static/src/js/website_quotation.js"></script>
<link rel='stylesheet' href='/website_quotation/static/src/css/website_quotation.css'/>
<t t-raw="head or ''"/>
</t>
<body data-spy="scroll" data-target=".navspy">
<div class="container">
<div class="row mt16">
<div class="col-md-3">
<div class="bs-sidebar">
<div class="hidden-print navspy" role="complementary">
<ul class="nav bs-sidenav" data-id="quote_sidebar">
</ul>
</div>
</div>
</div>
<div class="col-md-9">
<div id="template_introduction" t-field="template.website_description"/>
<t t-foreach="template.quote_line" t-as="line">
<a t-att-id="line.id"/>
<div t-field="line.website_description"/>
</t>
<div class="oe_structure"/>
<section id="terms" class="container" t-if="template.note">
<h2 class="page-header">Terms &amp; Conditions</h2>
<p t-field="template.note"/>
</section>
</div>
</div>
</div>
</body>
</t>
</template>
</data>
</openerp>

View File

@ -0,0 +1,129 @@
<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="sale_order_form_quote">
<field name="name">sale.order.form.payment</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<xpath expr="//header/button[@name='invoice_corrected']" position="after">
<button name="open_quotation" string="View Quotation" type="object"
attrs="{'invisible': [('template_id','=',False)]}"/>
</xpath>
<xpath expr="//page[@string='Order Lines']" position="after">
<page string="Suggested Products">
<label string="Optional Products &amp; Services" for="options"/>
<field name="options">
<tree string="Sales Quote Template Lines" editable="bottom">
<field name="product_id" on_change="on_change_product_id(product_id)"/>
<field name="name"/>
<field name="quantity"/>
<field name="uom_id"/>
<field name="price_unit"/>
<field name="discount"/>
<field name="website_description" invisible="1"/>
</tree>
</field>
</page>
</xpath>
<xpath expr="//field[@name='client_order_ref']" position="after">
<field name="template_id" on_change="onchange_template_id(template_id)"/>
<field name="validity_date"/>
<field name="website_description" invisible="1"/>
</xpath>
</field>
</record>
<record model="ir.ui.view" id="view_sale_quote_template_form">
<field name="name">sale.quote.template.form</field>
<field name="model">sale.quote.template</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Sale Quotation Template" version="7.0">
<sheet>
<button string="Edit Template" type="object" name="open_template" class="oe_link oe_right"/>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1>
<field name="name"/>
</h1>
</div>
<group>
<group>
<field name="number_of_days"/>
</group>
</group>
<notebook>
<page string="Lines">
<field name="quote_line">
<form string="Sales Quote Template Lines" version="7.0">
<group>
<group>
<field name="product_id" on_change="on_change_product_id(product_id)"/>
<label for="product_uom_qty"/>
<div>
<field
name="product_uom_qty" class="oe_inline"/>
</div>
<field name="price_unit"/>
</group>
</group>
<notebook colspan="4">
<page string="Description">
<field name="name" />
</page>
<page string="Website Description">
<field name="website_description" />
</page>
</notebook>
</form>
<tree string="Sales Quote Template Lines" editable="bottom">
<field name="product_id" on_change="on_change_product_id(product_id)"/>
<field name="name"/>
<field name="product_uom_qty"/>
<field name="price_unit"/>
<field name="website_description" invisible="1"/>
</tree>
</field>
</page>
<page string="Suggested Products">
<field name="options">
<tree string="Sales Quote Template Lines" editable="bottom">
<field name="product_id" on_change="on_change_product_id(product_id)"/>
<field name="name"/>
<field name="quantity"/>
<field name="uom_id"/>
<field name="price_unit"/>
<field name="discount"/>
<field name="website_description" invisible="1"/>
</tree>
</field>
</page>
</notebook>
<field name="website_description" invisible="1"/>
<field name="note" placeholder="Terms and conditions..." nolable="1"/>
</sheet>
</form>
</field>
</record>
<record model="ir.ui.view" id="view_sale_quote_template_tree">
<field name="name">sale.quote.template.tree</field>
<field name="model">sale.quote.template</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Sale Quote Template">
<field name="name"/>
</tree>
</field>
</record>
<record id="action_sale_quotation_template" model="ir.actions.act_window">
<field name="name">Sales Template</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">sale.quote.template</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem action="action_sale_quotation_template" id="menu_sale_quote_template" parent="base.menu_base_config" sequence="6" groups="base.group_sale_salesman,base.group_sale_manager"/>
</data>
</openerp>

View File

@ -24,4 +24,4 @@
</record>
</data>
</openerp>
</openerp>