class RetailMachine(models.Model): """GEO OSV SAMPLE""" _name = "geoengine.demo.automatic.retailing.machine" the_point = fields.GeoPoint('Coordinate') the_line = fields.GeoLine('Power supply line', index=True) total_sales = fields.Float('Total sale', index=True) money_level = fields.Char('Money level', size=32, index=True) state = fields.Selection([('hs', 'HS'), ('ok', 'OK')], 'State', index=True) name = fields.Char('Serial number', size=64, required=True) zip_id = fields.Many2one('dummy.zip') @api.onchange('the_point') def onchange_geo_point(self): """ Exemple of on change on the point Lookup in zips if the code is within an area. Change the zip_id field accordingly """ if self.the_point: zip_match = self.env['dummy.zip'].geo_search(geo_domain=[ ('the_geom', 'geo_contains', self.the_point) ], limit=1) if zip_match: self.zip_id = zip_match[0]
class FSMOrder(models.Model): _inherit = 'fsm.order' # Geometry Field shape = fields.GeoPoint('Coordinate') @api.model def create(self, vals): res = super(FSMOrder, self).create(vals) res.create_geometry() return res @api.onchange('location_id') def onchange_location_id(self): res = super(FSMOrder, self).onchange_location_id() if self.location_id: self.create_geometry() return res def create_geometry(self): for order in self: lat = order.location_id.partner_latitude lng = order.location_id.partner_longitude point = geo_fields.GeoPoint.from_latlon(cr=order.env.cr, latitude=lat, longitude=lng) order.shape = point @api.multi def geo_localize(self): for order in self: order.location_id.partner_id.geo_localize()
class DemoWebsiteLeafletMapFeature(models.Model): _name = "demo.website_leaflet.map.feature" _description = "Map Feature" name = fields.Char(required=True) active = fields.Boolean(default=True) category_id = fields.Many2one( comodel_name="demo.website_leaflet.category", string="Category", ondelete="restrict", ) geo_line = fields.GeoLine() geo_point = fields.GeoPoint() geo_polygon = fields.GeoPolygon() html_text = fields.Html(string="Popup text") open_popup = fields.Boolean(string="Popup opened on map") type = fields.Selection( selection=[ ("geo_point", "Geo Point"), ("geo_line", "Geo Line"), ("geo_polygon", "Geo Polygon"), ], required=True, default="geo_point", )
class DummyModel(models.Model): _name = 'test.dummy' _description = 'test.dummy' name = fields.Char() geo_multipolygon = fields.GeoMultiPolygon() geo_point = fields.GeoPoint()
class FSMLocation(models.Model): _inherit = 'fsm.location' # Geometry Field shape = fields.GeoPoint('Coordinate') @api.model def create(self, vals): vals.update({'fsm_location': True}) res = super(FSMLocation, self).create(vals) lat = self.partner_id.partner_latitude lng = self.partner_id.partner_longitude if lat == 0.0 and lng == 0.0: res.geo_localize() else: point = fields.GeoPoint.from_latlon(cr=self.env.cr, latitude=lat, longitude=lng) self.shape = point return res def geo_localize(self): for loc in self: if loc.partner_id: loc.partner_id.geo_localize() lat = loc.partner_latitude lng = loc.partner_longitude point = fields.GeoPoint.from_latlon(cr=loc.env.cr, latitude=lat, longitude=lng) loc.shape = point def _update_order_geometries(self): for loc in self: orders = loc.env['fsm.order'].search([('location_id', '=', loc.id) ]) for order in orders: order.create_geometry() @api.multi def write(self, vals): res = super(FSMLocation, self).write(vals) if ('partner_latitude' in vals) and ('partner_longitude' in vals): self.shape = fields.GeoPoint.from_latlon( cr=self.env.cr, latitude=vals['partner_latitude'], longitude=vals['partner_longitude']) self._update_order_geometries() return res
class CompassionProject(models.Model): """Add geo_point to compassion.project""" _inherit = "compassion.project" _description = "Project Geolocation Point" geo_point = fields.GeoPoint(readonly=True, store=True) @api.multi def details_answer(self, vals): super().details_answer(vals) self.compute_geopoint() return True @api.multi def compute_geopoint(self): """ Compute geopoints. """ for project in self.filtered(lambda p: p.gps_latitude and p.gps_longitude): geo_point = fields.GeoPoint.from_latlon( self.env.cr, project.gps_latitude, project.gps_longitude ) project.write({"geo_point": geo_point.wkt}) return True
class DemoWebsiteLeafletMapFeature(models.Model): _name = 'demo.website_leaflet.map.feature' _description = 'Map Feature' active = fields.Boolean( string='Active', default=True, ) category_id = fields.Many2one( string='Category', comodel_name='demo.website_leaflet.category', ondelete='restrict', ) geo_line = fields.GeoLine(string='Geo Line') geo_point = fields.GeoPoint(string='Geo Point') geo_polygon = fields.GeoPolygon(string='Geo Polygon') html_text = fields.Html(string='Popup text') name = fields.Char( string='Name', required=True, ) open_popup = fields.Boolean(string='Popup opened on map') type = fields.Selection( string='Type', selection=[('geo_point', _('Geo Point')), ('geo_line', _('Geo Line')), ('geo_polygon', _('Geo Polygon'))], default='point', required=True, )
class ResPartner(models.Model): """Add geo_point to partner using a function field""" _inherit = "res.partner" @api.multi @api.depends("partner_latitude", "partner_longitude") def _compute_geo_point(self): """ Set the `geo_point` of the partner depending of its `partner_latitude` and its `partner_longitude` **Notes** If one of those parameters is not set then reset the partner's geo_point and do not recompute it """ for rec in self: if not rec.partner_latitude or not rec.partner_longitude: rec.geo_point = False else: rec.geo_point = fields.GeoPoint.from_latlon( rec.env.cr, rec.partner_latitude, rec.partner_longitude) geo_point = fields.GeoPoint(store=True, compute="_compute_geo_point", inverse="_inverse_geo_point") @api.multi def _inverse_geo_point(self): for rec in self: if not rec.geo_point: rec.partner_longitude, rec.partner_latitude = False, False else: ( rec.partner_longitude, rec.partner_latitude, ) = fields.GeoPoint.to_latlon(rec.env.cr, rec.geo_point)
class ResPartner(models.Model): """Add geo_point to partner using a function field""" _inherit = "res.partner" geo_point = fields.GeoPoint("Address coordinates")
class AdvocateDetails(models.Model): _name = "advocate.details" _description = "Advocate Details" _rec_name = "partner_id" _inherit = "mail.thread" partner_id = fields.Many2one( "res.partner", "Partner", required=True, ondelete="cascade", readonly=False ) description = fields.Text(translate=False) quote = fields.Text(translate=False) picture_large = fields.Binary( string="Large picture", attachment=True, help="Optional large picture for your profile page", ) picture_filename = fields.Char(compute="_compute_filename") thank_you_quote = fields.Html( compute="_compute_thank_you_quote", help="Used in thank you letters for donations linked to an event " "and to this partner.", ) mail_copy_when_donation = fields.Boolean() number_surveys = fields.Integer( related="partner_id.survey_input_count", readonly=False ) # Advocacy fields ################# active_since = fields.Date() end_date = fields.Date() last_event = fields.Date(compute="_compute_events") state = fields.Selection( [ ("new", "New advocate"), ("active", "Active"), ("on_break", "On break"), ("inactive", "Inactive"), ], default="new", required=True, track_visibility="onchange", ) break_end = fields.Date() advocacy_source = fields.Text( help="Describe how this advocate has partnered with us." ) has_car = fields.Selection([("yes", "Yes"), ("no", "No")], "Has a car") formation_ids = fields.Many2many( "calendar.event", string="Formation taken", compute="_compute_formation", inverse="_inverse_formation", groups="base.group_user", readonly=False, ) engagement_ids = fields.Many2many( "advocate.engagement", "advocate_engagement_rel", "advocate_details_id", "engagement_id", "Engagement type", readonly=False, ) t_shirt_size = fields.Selection( [("S", "S"), ("M", "M"), ("L", "L"), ("XL", "XL"), ("XXL", "XXL")] ) t_shirt_type = fields.Selection([("shirt", "Shirt"), ("bikeshirt", "Bikeshirt"), ]) event_ids = fields.Many2many( "crm.event.compassion", string="Events", compute="_compute_events", readonly=False, ) event_type_formation = fields.Integer(compute="_compute_formation") number_events = fields.Integer(compute="_compute_events") # Partner related fields ######################## birthdate = fields.Date( related="partner_id.birthdate_date", store=True, readonly=True ) lang = fields.Selection(related="partner_id.lang", store=True, readonly=True) zip = fields.Char(related="partner_id.zip", store=True, readonly=True) city = fields.Char(related="partner_id.city", store=True, readonly=True) email = fields.Char(related="partner_id.email", store=True, readonly=True) geo_point = fields.GeoPoint(readonly=True) _sql_constraints = [ ( "details_unique", "unique(partner_id)", "Only one details per ambassador is allowed!", ) ] @api.multi def _compute_filename(self): for details in self: partner_name = details.display_name details.picture_filename = partner_name + "-large.jpg" @api.multi def _compute_thank_you_quote(self): html_file = file_open( "partner_compassion/static/src/html/thank_you_quote_template.html" ) template_html = str(html_file.read()) for details in self: firstname = details.partner_id.firstname lastname = details.partner_id.lastname html_vals = { "img_alt": details.display_name, "image_data": details.partner_id.with_context(bin_size=False) .image.decode("utf-8"), "text": details.quote or "", "attribution": _("Quote from %s %s" % (firstname, lastname)) if details.quote else "", } details.thank_you_quote = template_html.format(**html_vals) @api.multi def _compute_events(self): for details in self: details.event_ids = self.env["crm.event.compassion"].search( [ ("staff_ids", "=", details.partner_id.id), ("end_date", "<", fields.Datetime.now()), ] ) details.number_events = len(details.event_ids) if details.event_ids: details.last_event = details.event_ids[:1].end_date.date() @api.multi def _compute_formation(self): formation_cated_id = self.env.ref("partner_compassion.event_type_formation").id for details in self: details.formation_ids = self.env["calendar.event"].search( [ ("partner_ids", "=", details.partner_id.id), ("categ_ids", "=", formation_cated_id), ] ) details.event_type_formation = formation_cated_id @api.multi def _inverse_formation(self): # Allows to create formation event from ambassador details return True @api.multi def set_geo_point(self): for advocate in self: advocate.geo_point = advocate.partner_id.geo_point @api.model def create(self, vals): # Link partner to the advocate details advocate = super().create(vals) advocate.partner_id.advocate_details_id = advocate advocate.set_geo_point() return advocate @api.multi def open_events(self): return { "name": _("Events"), "type": "ir.actions.act_window", "view_type": "form", "view_mode": "tree,form", "res_model": "crm.event.compassion", "target": "current", "domain": [("id", "in", self.event_ids.ids)], } @api.multi def open_surveys(self): return { "name": _("Surveys"), "type": "ir.actions.act_window", "view_type": "form", "view_mode": "tree,form", "res_model": "survey.user_input", "target": "current", "domain": [("partner_id", "=", self.partner_id.id)], } def set_on_break(self): self.env.user.notify_info( _("Please don't forget to put a break end date"), sticky=True ) return self.write({"state": "on_break"}) def set_inactive(self): return self.write({"state": "inactive", "end_date": fields.Date.today()}) def set_active(self): return self.write({"state": "active", "end_date": False, "break_end": False}) @api.model def advocate_cron(self): three_open_days = datetime.today() + BDay(3) birthday_advocates = self.search( [ ("state", "in", ["active", "on_break"]), ("birthdate", "like", three_open_days.strftime("%m-%d")), ] ) birthday_advocates = birthday_advocates.filtered( lambda a: a.engagement_ids != self.env.ref("partner_compassion.engagement_sport") ) for advocate in birthday_advocates: lang = advocate.partner_id.lang[:2] notify_partner_id = ( self.env["res.config.settings"] .sudo() .get_param(f"advocate_birthday_{lang}_id") ) preferred_name = advocate.partner_id.preferred_name date = advocate.partner_id.get_date("birthdate_date", "d MMMM") display_name = advocate.display_name advocate.message_post( body=_( "This is a reminder that %s will have birthday on %s." ) % (preferred_name, date), subject=_("[%s] Advocate birthday reminder") % display_name, partner_ids=[notify_partner_id], type="comment", subtype="mail.mt_comment", content_subtype="html", ) break_advocates = self.search( [ ("state", "=", "on_break"), ("break_end", "<", fields.Date.today()), ("break_end", "!=", False), ] ) break_advocates.set_active()
class ResPartner(models.Model): _inherit = "res.partner" # Geometry Field shape = fields.GeoPoint('Coordinate') # partner_latitude = fields.Float(string='Geo Latitude', digits=(16, 5)) # partner_longitude = fields.Float(string='Geo Longitude', digits=(16, 5)) # date_localization = fields.Date(string='Geolocation Date') def create_geometry(self): for partner in self: lat = partner.partner_latitude lng = partner.partner_longitude point = geo_fields.GeoPoint.from_latlon(cr=partner.env.cr, latitude=lat, longitude=lng) partner.shape = point @api.model def create(self, vals): res = super(ResPartner, self).create(vals) lat = self.partner_latitude lng = self.partner_longitude if lat == 0.0 and lng == 0.0: res.geo_localize() else: self.create_geometry() return res @classmethod def _geo_localize_cn(cls, apikey, street='', zip='', city='', state='', country=''): search = geo_query_address(street=street, zip=zip, city=city, state=state, country=country) result = geo_find_baidu(search, city, apikey) if result is None: search = geo_query_address(city=city, state=state, country=country) result = geo_find_baidu(search, city, apikey) return result @classmethod def _geo_localize_en(cls, apikey, street='', zip='', city='', state='', country=''): search = geo_query_address(street=street, zip=zip, city=city, state=state, country=country) result = geo_find_bing(search, apikey) if result is None: search = geo_query_address(city=city, state=state, country=country) result = geo_find_bing(search, apikey) return result @api.multi def geo_localize(self): # We need country names in English below lang = self.env.lang if self.env.lang else self.env.user.lang for partner in self.with_context(lang=lang): street = partner.street if partner.street2: street += partner.street2 if partner.country_id.code == 'CN': apikey = self.env['ir.config_parameter'].sudo().get_param( 'baidu.api_key_geocode', default='LSh6ALesEBqAus4GCDurc0sRSkbrqfjH') result = partner._geo_localize_cn(apikey, street, partner.zip, partner.city, partner.state_id.name, partner.country_id.name) else: apikey = self.env['ir.config_parameter'].sudo().get_param( 'bing.api_key_geocode', default= 'AqY4IFeQhJPHi5FjGBNc7hfgUNcaVf7S_qyyP_dlVCesSJUqI7dBA-gsyoAIUvGu' ) result = partner._geo_localize_en(apikey, street, partner.zip, partner.city, partner.state_id.name, partner.country_id.name) if result: lat = result[0] lng = result[1] point = geo_fields.GeoPoint.from_latlon(cr=partner.env.cr, latitude=lat, longitude=lng) partner.write({ 'partner_latitude': result[0], 'partner_longitude': result[1], 'date_localization': fields.Date.context_today(partner), 'shape': point }) return True @api.multi def write(self, vals): res = super(ResPartner, self).write(vals) if ('partner_latitude' in vals) or ('partner_longitude' in vals): self.create_geometry() elif (('street' in vals) or ('street2' in vals) or ('city' in vals) or ('country_id' in vals) or ('zip' in vals) or ('state_id' in vals) or ('zip_id' in vals)): self.geo_localize() if 'shape' in vals: self.env.cr.execute( """ UPDATE res_partner SET partner_latitude = ST_Y(ST_Transform(shape,4326)), partner_longitude = ST_X(ST_Transform(shape,4326)) WHERE id = %(id)s """, {'id': self.id}) return res @api.multi def baidu_map_img(self, zoom=8, width=298, height=298): baidu_maps_api_key = self.env['ir.config_parameter'].sudo().get_param( 'baidu.api_key_geocode', default='LSh6ALesEBqAus4GCDurc0sRSkbrqfjH') country_name = self.country_id and self.country_id.name or '' state_name = self.state_id and self.state_id.name or '' city_name = self.city or '' street_name = self.street or '' street2_name = self.street2 or '' params = { 'markers': '%s' % street2_name, 'center': '%s%s%s%s' % (country_name, state_name, city_name, street_name), 'height': "%s" % height, 'width': "%s" % width, 'zoom': zoom, 'ak': baidu_maps_api_key, } # http://api.map.baidu.com/staticimage/v2 return urlplus('//api.map.baidu.com/staticimage', params) @api.multi def baidu_map_link(self, zoom=10): baidu_maps_api_key = self.env['ir.config_parameter'].sudo().get_param( 'baidu.api_key_geocode', default='LSh6ALesEBqAus4GCDurc0sRSkbrqfjH') partner_name = self.name city_name = self.city or '' street2_name = self.street2 or '' params = { 'address': '%s,%s,%s' % (city_name, street2_name, partner_name), 'output': 'html', 'src': 'e2yun', 'ak': baidu_maps_api_key } # http://lbsyun.baidu.com/index.php?title=uri return urlplus('//api.map.baidu.com/geocoder', params)