Update wizard: remove date filters, add duplicate detection
This commit is contained in:
@@ -32,8 +32,6 @@ class WtImportTimelineWizard(models.TransientModel):
|
|||||||
|
|
||||||
timeline_file = fields.Binary(string='Timeline JSON File', required=True)
|
timeline_file = fields.Binary(string='Timeline JSON File', required=True)
|
||||||
timeline_filename = fields.Char(string='Filename')
|
timeline_filename = fields.Char(string='Filename')
|
||||||
date_from = fields.Date(string='Date From')
|
|
||||||
date_to = fields.Date(string='Date To')
|
|
||||||
min_stop_minutes = fields.Integer(
|
min_stop_minutes = fields.Integer(
|
||||||
string='Minimum Stop Duration (minutes)',
|
string='Minimum Stop Duration (minutes)',
|
||||||
default=5,
|
default=5,
|
||||||
@@ -43,6 +41,7 @@ class WtImportTimelineWizard(models.TransientModel):
|
|||||||
string='Resolve Addresses via OpenStreetMap',
|
string='Resolve Addresses via OpenStreetMap',
|
||||||
default=True,
|
default=True,
|
||||||
)
|
)
|
||||||
|
result_message = fields.Char(string='Result', readonly=True)
|
||||||
|
|
||||||
def action_import(self):
|
def action_import(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
@@ -56,19 +55,13 @@ class WtImportTimelineWizard(models.TransientModel):
|
|||||||
if not stops:
|
if not stops:
|
||||||
raise UserError(_('No location stops found in the uploaded file.'))
|
raise UserError(_('No location stops found in the uploaded file.'))
|
||||||
|
|
||||||
# Filter by date range
|
|
||||||
if self.date_from:
|
|
||||||
stops = [s for s in stops if s['arrived_at'].date() >= self.date_from]
|
|
||||||
if self.date_to:
|
|
||||||
stops = [s for s in stops if s['arrived_at'].date() <= self.date_to]
|
|
||||||
|
|
||||||
# Filter by minimum stop duration
|
# Filter by minimum stop duration
|
||||||
min_secs = self.min_stop_minutes * 60
|
min_secs = self.min_stop_minutes * 60
|
||||||
stops = [s for s in stops
|
stops = [s for s in stops
|
||||||
if (s['departed_at'] - s['arrived_at']).total_seconds() >= min_secs]
|
if (s['departed_at'] - s['arrived_at']).total_seconds() >= min_secs]
|
||||||
|
|
||||||
if not stops:
|
if not stops:
|
||||||
raise UserError(_('No stops found matching the selected filters.'))
|
raise UserError(_('No stops found matching the minimum duration filter.'))
|
||||||
|
|
||||||
# Compute distances and travel times between consecutive stops
|
# Compute distances and travel times between consecutive stops
|
||||||
for i, stop in enumerate(stops):
|
for i, stop in enumerate(stops):
|
||||||
@@ -85,12 +78,26 @@ class WtImportTimelineWizard(models.TransientModel):
|
|||||||
stop['distance_from_previous'] = 0.0
|
stop['distance_from_previous'] = 0.0
|
||||||
stop['travel_time_from_previous'] = 0.0
|
stop['travel_time_from_previous'] = 0.0
|
||||||
|
|
||||||
# Create wt.location.log records
|
# Get existing arrived_at timestamps to skip duplicates
|
||||||
LocationLog = self.env['wt.location.log']
|
LocationLog = self.env['wt.location.log']
|
||||||
|
existing = set(
|
||||||
|
LocationLog.search([]).mapped(
|
||||||
|
lambda r: r.arrived_at.strftime('%Y-%m-%d %H:%M:%S') if r.arrived_at else ''
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
created_ids = []
|
created_ids = []
|
||||||
|
skipped = 0
|
||||||
for stop in stops:
|
for stop in stops:
|
||||||
arrived = stop['arrived_at'].replace(tzinfo=None)
|
arrived = stop['arrived_at'].replace(tzinfo=None)
|
||||||
departed = stop['departed_at'].replace(tzinfo=None)
|
departed = stop['departed_at'].replace(tzinfo=None)
|
||||||
|
arrived_str = arrived.strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
|
# Skip if already imported
|
||||||
|
if arrived_str in existing:
|
||||||
|
skipped += 1
|
||||||
|
continue
|
||||||
|
|
||||||
log = LocationLog.create({
|
log = LocationLog.create({
|
||||||
'date': arrived.date(),
|
'date': arrived.date(),
|
||||||
'arrived_at': arrived,
|
'arrived_at': arrived,
|
||||||
@@ -103,15 +110,18 @@ class WtImportTimelineWizard(models.TransientModel):
|
|||||||
'source': 'google_timeline',
|
'source': 'google_timeline',
|
||||||
})
|
})
|
||||||
created_ids.append(log.id)
|
created_ids.append(log.id)
|
||||||
|
existing.add(arrived_str)
|
||||||
|
|
||||||
|
if not created_ids and skipped:
|
||||||
|
raise UserError(_('All %d stops already exist. Nothing new to import.') % skipped)
|
||||||
|
|
||||||
created = LocationLog.browse(created_ids)
|
created = LocationLog.browse(created_ids)
|
||||||
|
|
||||||
if self.geocode:
|
if self.geocode:
|
||||||
created.action_geocode()
|
created.action_geocode()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'type': 'ir.actions.act_window',
|
'type': 'ir.actions.act_window',
|
||||||
'name': _('Imported Location Logs (%d stops)') % len(created_ids),
|
'name': _('Imported %d new stops (%d skipped as duplicates)') % (len(created_ids), skipped),
|
||||||
'res_model': 'wt.location.log',
|
'res_model': 'wt.location.log',
|
||||||
'view_mode': 'list,form',
|
'view_mode': 'list,form',
|
||||||
'domain': [('id', 'in', created_ids)],
|
'domain': [('id', 'in', created_ids)],
|
||||||
@@ -157,7 +167,6 @@ class WtImportTimelineWizard(models.TransientModel):
|
|||||||
nearest = min(activities, key=lambda a: abs((a['ts'] - ts).total_seconds()))
|
nearest = min(activities, key=lambda a: abs((a['ts'] - ts).total_seconds()))
|
||||||
return nearest['type']
|
return nearest['type']
|
||||||
|
|
||||||
# Cluster consecutive STILL positions into stops
|
|
||||||
stops = []
|
stops = []
|
||||||
current_stop = []
|
current_stop = []
|
||||||
last_travel_mode = 'unknown'
|
last_travel_mode = 'unknown'
|
||||||
@@ -182,7 +191,6 @@ class WtImportTimelineWizard(models.TransientModel):
|
|||||||
})
|
})
|
||||||
current_stop = []
|
current_stop = []
|
||||||
|
|
||||||
# Handle last stop
|
|
||||||
if len(current_stop) >= 2:
|
if len(current_stop) >= 2:
|
||||||
avg_lat = sum(p['lat'] for p in current_stop) / len(current_stop)
|
avg_lat = sum(p['lat'] for p in current_stop) / len(current_stop)
|
||||||
avg_lng = sum(p['lng'] for p in current_stop) / len(current_stop)
|
avg_lng = sum(p['lng'] for p in current_stop) / len(current_stop)
|
||||||
|
|||||||
Reference in New Issue
Block a user