[MERGE] event and google maps, i live the way i type: fast with a lot of mistakes

bzr revid: al@openerp.com-20120525200514-oyq2jdfbegm3k72m
This commit is contained in:
Antony Lesuisse 2012-05-25 22:05:14 +02:00
commit 64a1e59bb6
12 changed files with 164 additions and 139 deletions

View File

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
##############################################################################
#
@ -38,7 +39,7 @@ Note that:
Association / Configuration / Types of Events
""",
'author': 'OpenERP SA',
'depends': ['email_template'],
'depends': ['email_template','google_map'],
'init_xml': [],
'update_xml': [
'security/event_security.xml',

View File

@ -103,6 +103,14 @@ class event_event(osv.osv):
if total_confirmed < self.event.register_min or total_confirmed > self.event.register_max and self.event.register_max!=0:
raise osv.except_osv(_('Error!'),_("The total of confirmed registration for the event '%s' does not meet the expected minimum/maximum. You should maybe reconsider those limits before going further") % (self.event.name))
def check_registration_limits_before(self, cr, uid, ids, no_of_registration, context=None):
for event in self.browse(cr, uid, ids, context=context):
available_seats = event.register_avail
if available_seats and no_of_registration > available_seats:
raise osv.except_osv(_('Warning!'),_("Only %d Seats are Available!") % (available_seats))
elif available_seats == 0:
raise osv.except_osv(_('Warning!'),_("No Tickets Available!"))
def confirm_event(self, cr, uid, ids, context=None):
register_pool = self.pool.get('event.registration')
if self.event.email_confirmation_id:
@ -179,7 +187,7 @@ class event_event(osv.osv):
'register_current': fields.function(_get_register, string='Confirmed Registrations', multi='register_numbers'),
'register_avail': fields.function(_get_register, string='Available Registrations', multi='register_numbers',type='integer'),
'register_prospect': fields.function(_get_register, string='Unconfirmed Registrations', multi='register_numbers'),
'register_attended': fields.function(_get_register, string='Attended Registrations', multi='register_numbers'),
'register_attended': fields.function(_get_register, string='# of Participations', multi='register_numbers'),
'registration_ids': fields.one2many('event.registration', 'event_id', 'Registrations', readonly=False, states={'done': [('readonly', True)]}),
'date_begin': fields.datetime('Start Date', required=True, readonly=True, states={'draft': [('readonly', False)]}),
'date_end': fields.datetime('End Date', required=True, readonly=True, states={'draft': [('readonly', False)]}),
@ -195,7 +203,6 @@ class event_event(osv.osv):
'full_name' : fields.function(_name_get_fnc, type="char", string='Name'),
'reply_to': fields.char('Reply-To Email', size=64, readonly=False, states={'done': [('readonly', True)]}, help="The email address of the organizer is likely to be put here, with the effect to be in the 'Reply-To' of the mails sent automatically at event or registrations confirmation. You can also put the email address of your mail gateway if you use one."),
'main_speaker_id': fields.many2one('res.partner','Main Speaker', readonly=False, states={'done': [('readonly', True)]}, help="Speaker who will be giving speech at the event."),
'speaker_ids': fields.many2many('res.partner', 'event_speaker_rel', 'speaker_id', 'partner_id', 'Other Speakers', readonly=False, states={'done': [('readonly', True)]}),
'address_id': fields.many2one('res.partner','Location Address', readonly=False, states={'done': [('readonly', True)]}),
'speaker_confirmed': fields.boolean('Speaker Confirmed', readonly=False, states={'done': [('readonly', True)]}),
'country_id': fields.related('address_id', 'country_id',
@ -204,21 +211,23 @@ class event_event(osv.osv):
'company_id': fields.many2one('res.company', 'Company', required=False, change_default=True, readonly=False, states={'done': [('readonly', True)]}),
'is_subscribed' : fields.function(_subscribe_fnc, type="boolean", string='Subscribed'),
}
_defaults = {
'state': 'draft',
'company_id': lambda self,cr,uid,c: self.pool.get('res.company')._company_default_get(cr, uid, 'event.event', context=c),
'user_id': lambda obj, cr, uid, context: uid,
}
def subscribe_to_event(self, cr, uid, ids, context=None):
register_pool = self.pool.get('event.registration')
user_pool = self.pool.get('res.users')
num_of_seats = int(context.get('ticket', 1))
self.check_registration_limits_before(cr, uid, ids, num_of_seats, context=context)
user = user_pool.browse(cr, uid, uid, context=context)
curr_reg_ids = register_pool.search(cr, uid, [('user_id', '=', user.id), ('event_id', '=' , ids[0])])
#the subscription is done with UID = 1 because in case we share the kanban view, we want anyone to be able to subscribe
if not curr_reg_ids:
curr_reg_ids = [register_pool.create(cr, 1, {'event_id': ids[0] ,'email': user.user_email, 'name':user.name, 'user_id': user.id,})]
curr_reg_ids = [register_pool.create(cr, 1, {'event_id': ids[0] ,'email': user.user_email, 'name':user.name, 'user_id': user.id, 'nb_register': num_of_seats})]
else:
register_pool.write(cr, uid, curr_reg_ids, {'nb_register': num_of_seats}, context=context)
return register_pool.confirm_registration(cr, 1, curr_reg_ids, context=context)
def unsubscribe_to_event(self, cr, uid, ids, context=None):
@ -236,7 +245,6 @@ class event_event(osv.osv):
_constraints = [
(_check_closing_date, 'Error ! Closing Date cannot be set before Beginning Date.', ['date_end']),
]
def onchange_event_type(self, cr, uid, ids, type_event, context=None):
if type_event:
type_info = self.pool.get('event.type').browse(cr,uid,type_event,context)
@ -295,6 +303,11 @@ class event_registration(osv.osv):
def registration_open(self, cr, uid, ids, context=None):
""" Open Registration
"""
event_obj = self.pool.get('event.event')
for register in self.browse(cr, uid, ids, context=context):
event_id = register.event_id.id
no_of_registration = register.nb_register
event_obj.check_registration_limits_before(cr, uid, [event_id], no_of_registration, context=context)
res = self.confirm_registration(cr, uid, ids, context=context)
self.mail_user(cr, uid, ids, context=context)
return res
@ -384,5 +397,4 @@ class event_registration(osv.osv):
event_registration()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -38,16 +38,16 @@
<record id="event_1" model="event.event">
<field name="name">Opera of Verdi</field>
<field eval="time.strftime('%Y-%m-05 18:00:00')" name="date_begin"/>
<field eval="time.strftime('%Y-%m-05 21:00:00')" name="date_end"/>
<field eval="(DateTime.today()+ timedelta(days=1)).strftime('%Y-%m-%d 18:00:00')" name="date_begin"/>
<field eval="(DateTime.today()+ timedelta(days=2)).strftime('%Y-%m-%d 21:00:00')" name="date_end"/>
<field name="type" ref="event_type_1"/>
<field name="register_min">50</field>
<field name="register_max">350</field>
</record>
<record id="event_2" model="event.event">
<field name="name">Conference on ERP Business</field>
<field eval="time.strftime('%Y-%m-05 14:00:00')" name="date_begin"/>
<field eval="time.strftime('%Y-%m-05 16:30:00')" name="date_end"/>
<field eval="(DateTime.today()+ timedelta(days=2)).strftime('%Y-%m-%d 14:00:00')" name="date_begin"/>
<field eval="(DateTime.today()+ timedelta(days=2)).strftime('%Y-%m-%d 16:30:00')" name="date_end"/>
<field name="type" ref="event_type_2"/>
<field name="register_max">200</field>
</record>

View File

@ -50,10 +50,10 @@
<field name="model">event.event</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form layout="manual">
<form string="Events" layout="manual">
<div class="oe_form_topbar">
<button string="Confirm Event" name="button_confirm" states="draft" type="object"/>
<button string="Mark Done" name="button_done" states="confirm" type="object"/>
<button string="Event Ended" name="button_done" states="confirm" type="object"/>
<button string="Set To Draft" name="button_draft" states="cancel,done" type="object"/>
<button string="Cancel Event" name="button_cancel" states="draft,confirm" type="object"/>
<div class="oe_right">
@ -61,19 +61,40 @@
</div>
<div class="oe_clear"/>
</div>
<sheet string="Events" layout="auto">
<group col="6" colspan="4" class="oe_form_header">
<field name="name"/>
<field name="date_begin"/>
<field name="date_end"/>
<sheet layout="manual">
<field name="name" required="1" nolabel="1" class="oe_form_title" colspan="4"/>
<group colspan="4" col="5">
<group col="2" colspan="2" class="oe_form_group_label_border" style="margin-top: 20px;">
<field name="type" on_change="onchange_event_type(type,context)"/>
<field name="user_id"/>
<field name="address_id" />
<field name="address_id" widget="many2one_address_google_map" widget_option="{'placeholder':'.oe_form_google_map'}"/>
</group>
<notebook colspan="4">
<page string="Event">
<separator string="Description" colspan="4"/>
<group col="2" colspan="2" class="oe_form_group_label_border" style="margin-top: 20px;">
<field name="date_begin"/>
<field name="date_end"/>
<field name="register_min"/>
<field name="register_max"/>
</group>
</group>
<div class="oe_form_google_map" style="height: 200px"></div>
<notebook colspan="4">
<page string="Event Description">
<field name="note" colspan="4" nolabel="1"/>
</page>
<page string="Internal Data">
<group class="oe_form_group_label_border" colspan="2" col="2">
<field name="register_current"/>
<field name="register_prospect"/>
<field name="register_attended"/>
</group>
<group class="oe_form_group_label_border" colspan="2" col="2">
<field name="main_speaker_id" domain="[('speaker','=',True)]" context="{'default_speaker':1}"/>
<field name="speaker_confirmed"/>
</group>
<field name="registration_ids" colspan="4" nolabel="1" groups="event.group_event_manager,event.group_event_user">
<tree string="Registration" editable="top">
<field name="name" />
@ -108,30 +129,8 @@
</form>
</field>
</page>
<page string="Speakers">
<field name="main_speaker_id" domain="[('speaker','=',True)]" context="{'default_speaker':1}"/>
<field name="speaker_confirmed"/>
<separator string="Other Speakers" colspan="4"/>
<field name="speaker_ids" domain="[('speaker','=',True)]" context="{'default_speaker':1}" colspan="4" nolabel="1"/>
</page>
<page string="Extra Info">
<group col="2" colspan="2">
<separator string="Registrations" colspan="2"/>
<field name="register_min"/>
<field name="register_max"/>
<field name="register_prospect"/>
<field name="register_current"/>
<field name="register_attended"/>
</group>
<group col="2" colspan="2">
<separator string="Emails" colspan="2"/>
<field name="reply_to"/>
<field name="email_registration_id" domain="[('model_id.model','=','event.registration')]"/>
<field name="email_confirmation_id" domain="[('model_id.model','=','event.registration')]"/>
</group>
</page>
</notebook>
</sheet>
</sheet>
</form>
</field>
</record>
@ -162,9 +161,10 @@
</field>
</record>
<!-- Event Kanban View -->
<record model="ir.ui.view" id="view_event_kanban">
<record model="ir.ui.view" id="view_event_kanban">
<field name="name">event.event.kanban</field>
<field name="model">event.event</field>
<field name="type">kanban</field>
@ -208,13 +208,14 @@
</p>
<t t-if="record.register_avail.raw_value != 0">
<t t-if="!record.is_subscribed.raw_value">
<button type="object" name="subscribe_to_event" class="subscribe_button oe_event_button_subscribe">
<input t-att-id="record.id.raw_value" type="text" name="subscribe" class="no_of_seats" value="1" onchange="document.getElementById('btn_sub' +this.id).setAttribute('data-context',JSON.stringify({'ticket':this.value}))"/>
<button t-att-id="'btn_sub'+record.id.raw_value" type="object" name="subscribe_to_event" class="oe_mail_button_follow">
<span >Subscribe</span>
</button>
</t>
</t>
<t t-if="record.is_subscribed.raw_value">
<button type="object" name="unsubscribe_to_event" class="unsubscribe_button oe_event_button_unsubscribe">
<button type="object" name="unsubscribe_to_event" class="oe_mail_button_unfollow">
<span>Subscribed</span>
<span class="unsubscribe">Unsubscribe</span>
</button>
@ -488,7 +489,7 @@
<field name="view_mode">tree,form,calendar,graph</field>
<field name="context">{}</field>
<field name="search_view_id" ref="view_registration_search"/>
</record>
</record>view_
<menuitem
name="Registrations"

View File

@ -29,90 +29,17 @@
color: #FFFFFF;
background-color: #8A89BA;
}
div.oe_fold_column{
padding:0px !important;
}
.oe_event_button_subscribe {
display: inline-block;
border: 1px solid #ababab;
color: #404040;
font-size: 12px;
padding: 3px 10px;
text-align: center;
-o-background-size: 100% 100%;
-moz-background-size: 100% 100%;
-webkit-background-size: auto auto !important;
background-size: 100% 100%;
background: #d8d8d8 none;
background: none, -webkit-gradient(linear, left top, left bottom, from(#efefef), to(#d8d8d8));
background: none, -webkit-linear-gradient(#efefef, #d8d8d8);
background: none, -moz-linear-gradient(#efefef, #d8d8d8);
background: none, -o-linear-gradient(top, #efefef, #d8d8d8);
background: none, -khtml-gradient(linear, left top, left bottom, from(#efefef), to(#d8d8d8));
background: -ms-linear-gradient(top, #efefef, #d8d8d8);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#efefef', endColorstr='#d8d8d8',GradientType=0 );
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
-o-border-radius: 3px;
-ms-border-radius: 3px;
border-radius: 3px;
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
-o-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
-webkit-font-smoothing: antialiased;
outline: none;
}
.oe_event_button_unsubscribe {
display: inline-block;
border: 1px solid #AAA;
color: #404040;
font-size: 12px;
padding: 3px 10px;
text-align: center;
-o-background-size: 100% 100%;
-moz-background-size: 100% 100%;
-webkit-background-size: auto auto !important;
background-size: 100% 100%;
background: #AAA none;
background: none, -webkit-gradient(linear, left top, left bottom, from(#AAA), to(#AAA));
background: none, -webkit-linear-gradient(#AAA, #AAA);
background: none, -moz-linear-gradient(#AAA, #AAA);
background: none, -o-linear-gradient(top, #AAA, #AAA);
background: none, -khtml-gradient(linear, left top, left bottom, from(#AAA), to(#AAA));
background: -ms-linear-gradient(top, #AAA, #AAA);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#AAA, endColorstr='#AAA',GradientType=0 );
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
-o-border-radius: 3px;
-ms-border-radius: 3px;
border-radius: 3px;
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
-o-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(255, 255, 255, 0.8) inset;
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
-webkit-font-smoothing: antialiased;
outline: none;
}
.oe_event_button_subscribe:hover {
cursor: pointer;
background-size: 100% 100%;
/*background: #DC5F59 none;*/
.no_of_seats{
width:35px;
}
.oe_mapbox
{
position: relative;
float: right;
height:200px;
width:256px;
border: 1px solid #eeeeee;
}
.oe_event_button_unsubscribe:hover {
cursor: pointer;
background-size: 100% 100%;
background: #DC5F59 none;
}
.unsubscribe, .unsubscribe_button:hover span {
display: none;
background-color: #DC5F59
}
.unsubscribe_button:hover .unsubscribe {
display: inline;
background-color: #DC5F59;
}

View File

@ -9,6 +9,7 @@
name: event
date_begin: 2012-01-01 19:05:15
date_end: 2012-01-01 20:05:15
register_max: 10
-
I create a registration for the event
-
@ -32,6 +33,15 @@
I confirm the registration1
-
!python {model: event.registration}: |
event_pool = self.pool.get("event.event")
for register in self.browse(cr, uid, [ref("event_registration1")], context):
nb_register = register.nb_register
event_id = register.event_id.id
available_seats = event_pool.check_available_seats(cr, uid, [event_id], context=context)
if available_seats and nb_register > available_seats:
assert available_seats, "seats available."
elif available_seats == 0:
assert available_seats, "No Tickets Available."
self.registration_open(cr, uid, [ref("event_registration1")],context=context)
-
I check that registration is "confirmed"

View File

@ -70,7 +70,6 @@ class sale_order_line(osv.osv):
def button_confirm(self, cr, uid, ids, context=None):
'''
create registration with sale order
'''
registration_obj = self.pool.get('event.registration')
sale_obj = self.pool.get('sale.order')
@ -92,4 +91,3 @@ class sale_order_line(osv.osv):
message = _("The registration %s has been created from the Sale Order %s.") % (registration_id, order_line.order_id.name)
registration_obj.log(cr, uid, registration_id, message)
return super(sale_order_line, self).button_confirm(cr, uid, ids, context=context)

View File

@ -38,6 +38,7 @@ Using this you can directly open Google Map from the URL widget.""",
'google_map_view.xml',
],
'demo_xml': [],
'js': ['static/src/js/google_map.js'],
'installable': True,
'auto_install': False,
'certificate': '0029498930765',

View File

@ -12,8 +12,7 @@
<label string="Street2 : " align="1.0"/>
<group colspan="1" col="2">
<field name="street2" nolabel="1"/>
<button name="open_map"
string="Map" type="object" icon="gtk-zoom-in"/>
<button name="open_map" string="Map" type="object" icon="gtk-zoom-in"/>
</group>
</field>
</field>

View File

@ -0,0 +1,75 @@
openerp.event = function(instance, mod) {
instance.web.form.widgets.add('many2one_address_google_map', 'instance.google_map.Many2OneAddress');
var googleMapsLoaded = null;
instance.google_map.GoogleMapConnector = instance.web.Class.extend({
map_load: function() {
var self = this;
if(googleMapsLoaded === null) {
googleMapsLoaded = $.Deferred();
// global
openerp_googleMapsCallback = googleMapsLoaded.resolve;
$.ajax({
url: "https://maps.googleapis.com/maps/api/js?v=3&callback=openerp_googleMapsCallback&sensor=false",
dataType: "script"
}).fail(googleMapsLoaded.reject);
}
return googleMapsLoaded;
},
render_map: function(address,element) {
this.map_load().then(function() {
var geocoder = new google.maps.Geocoder();
geocoder.geocode({'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var lat = results[0].geometry.location.lat();
var lng = results[0].geometry.location.lng();
var myOptions = {
zoom: 17,
center: new google.maps.LatLng(lat,lng),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(element,myOptions);
var position = new google.maps.LatLng(lat,lng);
var marker = new google.maps.Marker({ map: map, position: position });
return marker;
}
});
});
},
});
instance.google_map.Many2OneAddress = instance.web.form.FieldMany2One.extend({
init: function(field_manager, node){
this._super(field_manager, node);
this.map = new instance.google_map.GoogleMapConnector();
},
get_address:function(value){
var self = this;
if (!value || value.length == 0){
return $.Deferred().reject();
}
(value instanceof Array)?value = parseInt(value[0]):false;
var data = new instance.web.DataSet(this,this.field.relation, this.build_context());
data.read_ids(value,["street","city","zip","country_id"]).done(function(value){
var address;
if (value['country_id']) {
address = _.str.sprintf('%(street)s, %(zip)s %(city)s, %(country_id[1])s', value);
} else {
address = _.str.sprintf('%(street)s, %(zip)s %(city)s', value);
}
// TODO repalce by widget_option selector self.options.selector
var el = self.view.$element.find(".oe_form_google_map")[0];
self.map.render_map(address,el);
});
},
set_value:function(value){
this._super(value);
this.get_address(value);
},
render_value:function(no_recurse){
this.get_address(this.get("value"));
this._super(no_recurse);
}
});
};

View File

@ -1,3 +1,4 @@
/* ------------------------------ */
/* Wall */
/* ------------------------------ */

View File

@ -132,7 +132,7 @@
</group>
<notebook colspan="5">
<page string="Sales Order">
<field name="partner_id" on_change="onchange_partner_id(partner_id)" domain="[('customer','=',True)]" context="{'search_default_customer':1}" required="1"/>
<field name="partner_id" on_change="onchange_partner_id(partner_id)" domain="[('customer','=',True)]" context="{'search_default_customer':1}" />
<field domain="[('parent_id','=',partner_id)]" name="partner_invoice_id" groups="sale.group_delivery_invoice_address" options='{"quick_create": false}'/>
<field domain="[('parent_id','=',partner_id)]" name="partner_shipping_id" groups="sale.group_delivery_invoice_address" options='{"quick_create": false}'/>
<field domain="[('type','=','sale')]" name="pricelist_id" groups="product.group_sale_pricelist" on_change="onchange_pricelist_id(pricelist_id,order_line)"/>