def load_layer(self, schema, layer_name, geometry, sql, display_name, id_col='', epsg=None): settings = Settings() uri = QgsDataSourceUri() uri.setConnection(settings.value("db_host"), str(settings.value("db_port")), settings.value("db_name"), settings.value("db_username"), settings.value("db_password")) uri.setDataSource(schema, layer_name, geometry, sql, id_col) layer = QgsVectorLayer(uri.uri(), display_name, "postgres") if epsg is not None: crs = QgsCoordinateReferenceSystem(epsg) layer.setCrs(crs) QgsProject.instance().addMapLayer(layer, addToLegend=False) return layer
def connect_to_db(): settings = Settings() db = QSqlDatabase.addDatabase("QPSQL", str(datetime.now())) db.setHostName(settings.value("db_host")) db.setPort(settings.value("db_port")) db.setDatabaseName(settings.value("db_name")) db.setUserName(settings.value("db_username")) db.setPassword(settings.value("db_password")) db.open() return db
def load_layers(self): settings = Settings() group_comptages = QgsProject.instance().layerTreeRoot().findGroup( 'Comptages') group_extra = QgsProject.instance().layerTreeRoot().findGroup('Extra') if group_comptages is None: group_comptages = QgsProject.instance().layerTreeRoot().addGroup( 'Comptages') if group_extra is None and settings.value("extra_layers"): group_extra = group_comptages.addGroup('Extra') for key in LAYER_DEFINITIONS: layer_definition = LAYER_DEFINITIONS[key] if not QgsProject.instance().mapLayersByName( layer_definition['display_name']): layer = self.load_layer( 'comptages', # Schema layer_definition['table'], layer_definition['geometry'], layer_definition['sql'], layer_definition['display_name'], layer_definition['id'], layer_definition['epsg'], ) if layer_definition['legend']: group_comptages.addLayer(layer) elif settings.value("extra_layers"): group_extra.addLayer(layer) self.layers[key] = layer self.apply_qml_styles() self.add_layer_actions() self.create_virtual_fields() self.create_joins() self.create_relations() iface.setActiveLayer(self.layers['section']) self.populate_list_of_highlighted_sections() self.layers['count'].featureAdded.connect(self.on_count_added) from qgis.core import QgsExpressionContextUtils QgsExpressionContextUtils.setProjectVariable( QgsProject.instance(), 'highlighted_installation', '')
def prepare_django(default_db=None, **additional_settings): if django_settings.configured: return if not additional_settings: additional_settings = {} # If the default db doesn't arrives from the manage.py script # (i.e. the command is lauched from the QGIS python console), we # use the one in the plugin settings if not default_db: from comptages.core.settings import Settings as PluginSettings plugin_settings = PluginSettings() default_db = { "ENGINE": "django.contrib.gis.db.backends.postgis", "HOST": plugin_settings.value("db_host"), "PORT": plugin_settings.value("db_port"), "NAME": plugin_settings.value("db_name"), "USER": plugin_settings.value("db_username"), "PASSWORD": plugin_settings.value("db_password"), } # Allow to configure GDAL/GEOS/Spatialite libraries from env vars # see https://docs.djangoproject.com/en/3.2/ref/contrib/gis/install/geolibs/#geos-library-path GDAL_LIBRARY_PATH_ENV = os.getenv("GDAL_LIBRARY_PATH") GEOS_LIBRARY_PATH_ENV = os.getenv("GEOS_LIBRARY_PATH") SPATIALITE_LIBRARY_PATH_ENV = os.getenv("SPATIALITE_LIBRARY_PATH") if GDAL_LIBRARY_PATH_ENV: additional_settings["GDAL_LIBRARY_PATH"] = GDAL_LIBRARY_PATH_ENV if GEOS_LIBRARY_PATH_ENV: additional_settings["GEOS_LIBRARY_PATH"] = GEOS_LIBRARY_PATH_ENV if SPATIALITE_LIBRARY_PATH_ENV: additional_settings["SPATIALITE_LIBRARY_PATH"] = SPATIALITE_LIBRARY_PATH_ENV django_settings.configure( BASE_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir), DATABASES={"default": default_db}, INSTALLED_APPS=('comptages.datamodel.apps.ComptagesConfig',), USE_TZ=True, TIME_ZONE='Europe/Zurich', SECRET_KEY='09n+dhzh+02+_#$!1+8h-&(s-wbda#0*2mrv@lx*y#&fzlv&l)', **additional_settings ) django.setup()
class Comptages(QObject): def __init__(self, iface): QObject.__init__(self) self.iface = iface self.settings = Settings() self.settings_dialog = SettingsDialog() self.layers = Layers() self.chart_dock = ChartDock(self.iface, self.layers) self.iface.addDockWidget(Qt.BottomDockWidgetArea, self.chart_dock) self.filter_start_date = None self.filter_end_date = None self.filter_installation = None self.filter_sensor = None self.filter_tjm = None self.filter_axe = None self.filter_sector = None self.tm = QgsApplication.taskManager() def initGui(self): self.connect_db_action = QAction( QIcon(':/plugins/Comptages/images/power.png'), 'Connection DB', self.iface.mainWindow()) self.create_new_action = QAction( QIcon(':/plugins/Comptages/images/measure.png'), 'Créer un nouveau comptage', None) self.select_edit_action = QAction( QIcon(':/plugins/Comptages/images/select_edit.png'), 'Modifier comptage', None) self.import_files_action = QAction( QIcon(':/plugins/Comptages/images/import.png'), 'Importation', None) self.validate_imported_files = QAction( QIcon(':/plugins/Comptages/images/validate.png'), 'Validation', None) self.filter_action = QAction( QIcon(':/plugins/Comptages/images/filter.png'), 'Filtrer', None) self.yearly_report_action = QAction( QIcon(':/plugins/Comptages/images/filled_file.png'), 'Rapport annuel', None) self.import_ics_action = QAction( QIcon(':/plugins/Comptages/images/calendar.png'), 'Importer fichier ics', None) self.settings_action = QAction( QIcon(':/plugins/Comptages/images/settings.png'), 'Réglages', None) self.connect_db_action.triggered.connect(self.do_connect_db_action) self.create_new_action.triggered.connect(self.do_create_new_action) self.select_edit_action.triggered.connect(self.do_select_edit_action) self.import_files_action.triggered.connect(self.do_import_files_action) self.validate_imported_files.triggered.connect( self.do_validate_imported_files_action) self.filter_action.triggered.connect(self.do_filter_action) self.yearly_report_action.triggered.connect( self.do_yearly_report_action) self.import_ics_action.triggered.connect(self.do_import_ics_action) self.settings_action.triggered.connect(self.do_settings_action) self.create_new_action.setEnabled(False) self.select_edit_action.setEnabled(False) self.import_files_action.setEnabled(False) self.validate_imported_files.setEnabled(False) self.filter_action.setEnabled(False) self.yearly_report_action.setEnabled(False) self.import_ics_action.setEnabled(False) self.iface.addPluginToMenu('Comptages', self.connect_db_action) self.iface.addPluginToMenu('Comptages', self.create_new_action) self.iface.addPluginToMenu('Comptages', self.select_edit_action) self.iface.addPluginToMenu('Comptages', self.import_files_action) self.iface.addPluginToMenu('Comptages', self.validate_imported_files) self.iface.addPluginToMenu('Comptages', self.filter_action) self.iface.addPluginToMenu('Comptages', self.yearly_report_action) self.iface.addPluginToMenu('Comptages', self.import_ics_action) self.iface.addPluginToMenu('Comptages', self.settings_action) self.toolbar = self.iface.addToolBar('Comptages') self.toolbar.setObjectName('Comptages') self.toolbar.setToolTip('Comptages toolbar') self.toolbar.addAction(self.connect_db_action) self.toolbar.addSeparator() self.toolbar.addAction(self.create_new_action) self.toolbar.addAction(self.select_edit_action) self.toolbar.addAction(self.import_files_action) self.toolbar.addAction(self.validate_imported_files) self.toolbar.addAction(self.filter_action) self.toolbar.addAction(self.yearly_report_action) self.toolbar.addAction(self.import_ics_action) self.toolbar.addSeparator() self.toolbar.addAction(self.settings_action) def unload(self): self.iface.removePluginMenu('Comptages', self.connect_db_action) self.iface.removePluginMenu('Comptages', self.create_new_action) self.iface.removePluginMenu('Comptages', self.select_edit_action) self.iface.removePluginMenu('Comptages', self.filter_action) self.iface.removePluginMenu('Comptages', self.yearly_report_action) self.iface.removePluginMenu('Comptages', self.import_ics_action) self.iface.removePluginMenu('Comptages', self.settings_action) del self.connect_db_action del self.create_new_action del self.select_edit_action del self.filter_action del self.yearly_report_action del self.import_ics_action del self.settings_action del self.toolbar def do_connect_db_action(self): self.layers.load_layers() self.enable_actions_if_needed() def do_create_new_action(self): if self.tm.countActiveTasks() > 0: push_info(("Veuillez patienter jusqu'à ce que l'importation " "soit terminée.")) return self.layers.create_count() def do_select_edit_action(self): if self.tm.countActiveTasks() > 0: push_info(("Veuillez patienter jusqu'à ce que l'importation " "soit terminée.")) return self.layers.edit_count() def do_import_files_action(self): if self.tm.countActiveTasks() > 0: push_info(("Veuillez patienter jusqu'à ce que l'importation " "soit terminée.")) return file_dialog = QFileDialog() title = 'Importer' path = self.settings.value('data_import_directory') files = QFileDialog.getOpenFileNames( file_dialog, title, path, "Data file (*.A?? *.aV? *.I?? *.V?? *.txt)")[0] self.tm.allTasksFinished.connect( partial(self.all_tasks_finished, 'import')) tasks = [] for file_path in files: tasks.append(self.import_file(file_path)) for t in tasks: self.tm.addTask(t) def import_file(self, file_path, count_id=None): QgsMessageLog.logMessage( '{} - Prepare import file {} started'.format( datetime.now(), os.path.basename(file_path)), 'Comptages', Qgis.Info) # Manage binary files with open(file_path, 'rb') as fd: file_head = fd.read(24) if file_head == b'Golden River Traffic Ltd': # is a binary file formatter = self.layers.get_formatter_name('GoldenRiver') file_path_formatted = "{}_for".format(file_path) os.system("{} {} {}".format(formatter, file_path, file_path_formatted)) file_path = file_path_formatted if count_id: count = models.Count.objects.get(id=count_id) else: count = importer.guess_count(file_path) if not count: QgsMessageLog.logMessage( "Impossible de trouver le comptage associé {}".format( file_path, ), 'Comptages', Qgis.Critical) return QgsMessageLog.logMessage( '{} - Prepare import file {}'.format(datetime.now(), os.path.basename(file_path)), 'Comptages', Qgis.Info) QgsMessageLog.logMessage( '{} - Import file {} started'.format(datetime.now(), os.path.basename(file_path)), 'Comptages', Qgis.Info) task = importer_task.ImporterTask(file_path, count) return task def all_tasks_finished(self, task='import'): # Check if actually all tasks are finished because apparently it doesn't # work the same on all systems if not self.tm.countActiveTasks() == 0: QgsMessageLog.logMessage( '{} - all_tasks_finished signal raised, but active tasks still exist, ignoring it' .format(datetime.now()), 'Comptages', Qgis.Warning) return self.tm.allTasksFinished.disconnect() push_info(('Toutes les tâches sont terminées. Consultez le journal ' 'pour plus de détails.')) QgsMessageLog.logMessage('{} - All tasks ended'.format(datetime.now()), 'Comptages', Qgis.Info) if task == 'import': self.chart_dock.show_next_quarantined_chart() def do_validate_imported_files_action(self): if self.tm.countActiveTasks() > 0: push_info(("Veuillez patienter jusqu'à ce que l'importation " "soit terminée.")) return self.chart_dock.show_next_quarantined_chart() def do_filter_action(self): dlg = FilterDialog(self.iface) # Set last values in the filter if self.filter_start_date: dlg.start_date.setDateTime(self.filter_start_date) else: dlg.start_date.setDateTime(QDateTime()) if self.filter_end_date: dlg.end_date.setDateTime(self.filter_end_date) else: dlg.end_date.setDateTime(QDateTime()) if self.filter_installation: dlg.installation.setCurrentIndex(self.filter_installation) if self.filter_sensor: dlg.sensor.setCurrentIndex(self.filter_sensor) if self.filter_tjm: dlg.tjm.setRange(self.filter_tjm[0], self.filter_tjm[1]) else: dlg.tjm.setRange(0, 30000) if self.filter_axe: dlg.axe.setCurrentIndex(self.filter_axe) if self.filter_sector: dlg.sector.setCurrentIndex(self.filter_sector) if dlg.exec_(): self.filter_start_date = dlg.start_date.dateTime() self.filter_end_date = dlg.end_date.dateTime() self.filter_installation = dlg.installation.currentIndex() self.filter_sensor = dlg.sensor.currentIndex() self.filter_tjm = [dlg.tjm.lowerValue(), dlg.tjm.upperValue()] self.filter_axe = dlg.axe.currentIndex() self.filter_sector = dlg.sector.currentIndex() self.layers.apply_filter( dlg.start_date.dateTime().toString('yyyy-MM-dd'), dlg.end_date.dateTime().toString('yyyy-MM-dd'), dlg.installation.currentIndex(), dlg.sensor.currentIndex(), [self.filter_tjm[0], self.filter_tjm[1]], dlg.axe.currentData(), dlg.sector.currentData(), ) if (not dlg.start_date.dateTime()) and (not dlg.end_date.dateTime()) and (dlg.installation.currentIndex() == 0) and \ (dlg.sensor.currentIndex() == 0) and (dlg.tjm.lowerValue() == 0) and (dlg.tjm.upperValue() == 30000) and \ (dlg.axe.currentText() == 'Tous') and (dlg.sector.currentText() == 'Tous'): self.filter_action.setIcon( QIcon(':/plugins/Comptages/images/filter.png')) else: self.filter_action.setIcon( QIcon(':/plugins/Comptages/images/filter_active.png')) def do_yearly_report_action(self): QgsMessageLog.logMessage( '{} - Generate yearly report action started'.format( datetime.now()), 'Comptages', Qgis.Info) if self.tm.countActiveTasks() > 0: push_info(("Veuillez patienter jusqu'à ce que l'importation " "soit terminée.")) return layer = self.layers.layers['section'] selected_count = layer.selectedFeatureCount() if selected_count == 0: push_info("Veuillez sélectionner un tronçon") return elif selected_count > 1: push_info("Veuillez ne sélectionner qu'un tronçon") return else: selected_feature = next(layer.getSelectedFeatures()) section_id = selected_feature.attribute('id') classes = self.layers.get_classes_of_section(section_id) dlg = YearlyReportDialog(self.iface) dlg.section.insert(section_id) dlg.classi.addItems(classes) if dlg.exec_(): year = dlg.year.value() clazz = dlg.classi.currentText() file_dialog = QFileDialog() title = 'Exporter un rapport' path = self.settings.value('report_export_directory') file_path = QFileDialog.getExistingDirectory( file_dialog, title, path) if not file_path: QgsMessageLog.logMessage( '{} - Generate yearly report action ended: No file_path given' .format(datetime.now()), 'Comptages', Qgis.Info) return QgsMessageLog.logMessage( '{} - Generate yearly report action can really begin now for count {} with file_path: {}' .format(datetime.now(), selected_count, file_path), 'Comptages', Qgis.Info) if clazz.startswith("SPCH-MD"): yrb = YearlyReportBike(file_path, year, section_id) yrb.run() else: self.tm.allTasksFinished.connect( partial(self.all_tasks_finished, report)) # TODO: consider the chosed class too self.tm.addTask( report_task.ReportTask(file_path=file_path, template="yearly", year=year, section_id=section_id)) # TODO: check if there are comptages for this section and year def do_import_ics_action(self): IcsImporter(self.layers) def do_settings_action(self): self.settings_dialog.exec_() def do_export_configuration_action(self, count_id): config_creator = ConfigCreatorCmd(self.layers, count_id) config_creator.set_section_commands() installation_name = self.layers.get_installation_name_of_count( count_id) file_dialog = QFileDialog() file_dialog.setDefaultSuffix('*.CMD') title = 'Exporter la configuration' path = os.path.join(self.settings.value('config_export_directory'), "{}.CMD".format(installation_name)) file = QFileDialog.getSaveFileName(file_dialog, title, path, "Config file (*.CMD)")[0] if not file: return config_creator.write_file(file) push_info('Written config file {}'.format(file)) def do_import_single_file_action(self, count_id): file_dialog = QFileDialog() title = 'Importation' path = self.settings.value('data_import_directory') file_path = QFileDialog.getOpenFileName( file_dialog, title, path, "Data file (*.A?? *.aV? *.I?? *.V?? *.txt)")[0] if not file_path: return self.tm.allTasksFinished.connect( partial(self.all_tasks_finished, 'import')) self.tm.addTask(self.import_file(file_path, count_id)) def do_generate_report_action(self, count_id): QgsMessageLog.logMessage( '{} - Generate report action started'.format(datetime.now()), 'Comptages', Qgis.Info) count = models.Count.objects.get(id=count_id) if self.tm.countActiveTasks() > 0: push_info(("Veuillez patienter jusqu'à ce que l'importation " "soit terminée.")) return # Show message if there are no data to process if not models.CountDetail.objects.filter(id_count=count).exists(): push_info( "Installation {}: Il n'y a pas de données à traiter pour " "le comptage {}".format(count.id_installation.name, count.id)) QgsMessageLog.logMessage( '{} - Generate report action ended: No data for count {}'. format(datetime.now(), count.id), 'Comptages', Qgis.Info) return file_dialog = QFileDialog() title = 'Exporter un rapport' path = self.settings.value('report_export_directory') file_path = QFileDialog.getExistingDirectory(file_dialog, title, path) if not file_path: QgsMessageLog.logMessage( '{} - Generate report action ended: No file_path given'.format( datetime.now()), 'Comptages', Qgis.Info) return QgsMessageLog.logMessage( '{} - Generate report action can really begin now for count {} with file_path: {}' .format(datetime.now(), count.id, file_path), 'Comptages', Qgis.Info) self.tm.allTasksFinished.connect( partial(self.all_tasks_finished, 'report')) self.tm.addTask( report_task.ReportTask( file_path=file_path, count=count, )) def do_export_plan_action(self, count_id): plan_creator = PlanCreator(self.layers) file_dialog = QFileDialog() file_dialog.setDefaultSuffix('*.PDF') title = 'Exporter plan de pose' path = os.path.join(self.settings.value('config_export_directory'), "{}.pdf".format("plan_de_pose")) file = QFileDialog.getSaveFileName(file_dialog, title, path, "Config file (*.PDF)")[0] if not file: return # Highlight the current sections and installation in the layout previous_highlightes_sections = self.layers.highlighted_sections self.layers.highlighted_sections = \ self.layers.get_section_ids_of_count(count_id) QgsExpressionContextUtils.setProjectVariable( QgsProject.instance(), 'highlighted_installation', self.layers.get_installation_name_of_count(count_id)) plan_creator.export_pdf(count_id, file) self.layers.highlighted_sections = previous_highlightes_sections QgsExpressionContextUtils.setProjectVariable( QgsProject.instance(), 'highlighted_installation', '') self.layers.layers['section'].triggerRepaint() def do_generate_chart_action(self, count_id): QgsMessageLog.logMessage( '{} - Generate chart action started'.format(datetime.now()), 'Comptages', Qgis.Info) if self.tm.countActiveTasks() > 0: push_info(("Veuillez patienter jusqu'à ce que l'importation " "soit terminée.")) return count = models.Count.objects.get(id=count_id) self.chart_dock.set_attributes(count) QgsMessageLog.logMessage( '{} - Generate chart action ended'.format(datetime.now()), 'Comptages', Qgis.Info) def do_delete_data_action(self, count_id): dlg = DeleteDialog(self.iface) tz = pytz.timezone("Europe/Zurich") if dlg.exec_(): start = tz.localize(dlg.start_date.dateTime().toPyDateTime()) end = tz.localize(dlg.end_date.dateTime().toPyDateTime()) definitive = dlg.definitive.isChecked() quarantine = dlg.quarantine.isChecked() count = models.Count.objects.get(id=count_id) msg = QMessageBox() msg.setIcon(QMessageBox.Warning) msg.setText("Effacement des données") # msg.setInformativeText(f"Effacement des données") msg.setDetailedText("Les données suivantes seront supprimées:\n" f"comptage: {count_id}\n" f"de: {start.strftime('%d.%m.%Y')}\n" f"à: {end.strftime('%d.%m.%Y')} inclus\n" f"provisoires: {quarantine}\n" f"définitives: {definitive}") msg.setWindowTitle("Effacement des données") msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) retval = msg.exec_() if retval == QMessageBox.Ok: qs = models.CountDetail.objects.filter( id_count=count, timestamp__range=(start, end + timedelta(days=1)), ) if not definitive: qs = qs.filter(status=definitions.IMPORT_STATUS_QUARANTINE) if not quarantine: qs = qs.filter(status=definitions.IMPORT_STATUS_DEFINITIVE) qs.delete() def enable_actions_if_needed(self): """Enable actions if the plugin is connected to the db otherwise disable them""" self.create_new_action.setEnabled(True) self.select_edit_action.setEnabled(True) self.import_files_action.setEnabled(True) self.validate_imported_files.setEnabled(True) self.import_ics_action.setEnabled(True) self.filter_action.setEnabled(True) self.yearly_report_action.setEnabled(True) def is_section_highlighted(self, section_id): return self.layers.is_section_highlighted(section_id) @qgsfunction(args="auto", group="Comptages") def is_highlighted(feature, parent): """Used by section layer to apply a style to the sections related to a count""" # Call the method of the current instance of the plugin return plugins['comptages'].is_section_highlighted( feature.attribute('id')) @qgsfunction(args="auto", group="Comptages") def check_dates(feature, parent): """Used by count layer to show if a count was during a special period""" return plugins['comptages'].layers.check_dates( feature.attribute('start_process_date'), feature.attribute('end_process_date'))
class TestImportDetail(unittest.TestCase): @classmethod def setUpClass(self): self.settings = Settings() self.layers = plugins['comptages'].layers self.layers.load_layers() self.comptages = plugins['comptages'] self.db = QSqlDatabase.addDatabase( "QPSQL", "test_import_detail_connection") self.db.setHostName(self.settings.value("db_host")) self.db.setPort(self.settings.value("db_port")) self.db.setDatabaseName(self.settings.value("db_name")) self.db.setUserName(self.settings.value("db_username")) self.db.setPassword(self.settings.value("db_password")) self.test_data_path = os.path.join( os.path.dirname(os.path.realpath(__file__)), 'test_data/') def setUp(self): self.db.open() query = QSqlQuery(self.db) query.exec_("DELETE FROM comptages.count;") query.exec_("DELETE FROM comptages.count_detail;") self.db.close() def test_simple_import_detail_data_multi_lane(self): self.db.open() query = QSqlQuery(self.db) query.exec_("SELECT id FROM comptages.installation \ WHERE name = '00056520';") query.next() installation_id = query.value(0) query.exec_("SELECT id FROM comptages.model \ WHERE name = 'M660_LT';") query.next() model_id = query.value(0) query.exec_("SELECT id FROM comptages.lane \ WHERE id_installation = {} ORDER BY number;".format( installation_id)) query.next() lane_1_id = query.value(0) query.next() lane_2_id = query.value(0) query.exec_("select id from comptages.sensor_type \ where name = 'Tube'") query.next() sensor_type_id = query.value(0) query_str = ( "INSERT INTO comptages.count(id, " "start_process_date, end_process_date, start_service_date, " "end_service_date, id_sensor_type, id_model, id_installation) " "VALUES (1, '2018-09-23', '2018-09-26', '2018-09-23', " "'2018-09-26', {}, {}, {});".format( sensor_type_id, model_id, installation_id)) query.exec_(query_str) task = self.comptages.import_file( os.path.join( self.test_data_path, 'simple_detail_multi_lane.V01'), 1) task.waitForFinished() # Let the time to the db to finish the writing time.sleep(1) query.exec_( "SELECT numbering, timestamp, distance_front_front, \ distance_front_back, speed, length, height, fixed, wrong_way, \ file_name, import_status, id_lane, id_count, id_category \ FROM comptages.count_detail \ WHERE file_name = 'simple_detail_multi_lane.V01' ORDER BY id;") self.assertEqual(2, query.size()) query.next() self.assertEqual(1, query.value(0)) self.assertEqual( '240918 1545 49 800', query.value(1).toString('ddMMyy HHmm ss zzz')) self.assertEqual(12.3, query.value(2)) self.assertEqual(99.9, query.value(3)) self.assertEqual(50, query.value(4)) self.assertEqual(428, query.value(5)) self.assertEqual('L', query.value(6).strip()) self.assertNotEqual(True, query.value(7)) self.assertNotEqual(True, query.value(8)) self.assertEqual('simple_detail_multi_lane.V01', query.value(9)) self.assertEqual(self.layers.IMPORT_STATUS_QUARANTINE, query.value(10)) self.assertEqual(lane_1_id, query.value(11)) self.assertEqual(1, query.value(12)) self.assertEqual(24, query.value(13)) query.next() self.assertEqual(2, query.value(0)) self.assertEqual( '240918 1545 50 900', query.value(1).toString('ddMMyy HHmm ss zzz')) self.assertEqual(3.8, query.value(2)) self.assertEqual(1.4, query.value(3)) self.assertEqual(51, query.value(4)) self.assertEqual(416, query.value(5)) self.assertEqual('VL', query.value(6).strip()) self.assertNotEqual(True, query.value(7)) self.assertNotEqual(True, query.value(8)) self.assertEqual('simple_detail_multi_lane.V01', query.value(9)) self.assertEqual(self.layers.IMPORT_STATUS_QUARANTINE, query.value(10)) self.assertEqual(lane_2_id, query.value(11)) self.assertEqual(1, query.value(12)) self.assertEqual(25, query.value(13)) self.db.close() def test_special_case(self): self.db.open() query = QSqlQuery(self.db) query.exec_("SELECT id FROM comptages.installation \ WHERE name = '53109999';") query.next() installation_id = query.value(0) query.exec_("SELECT id FROM comptages.model \ WHERE name = 'M660_LT';") query.next() model_id = query.value(0) query.exec_("SELECT id FROM comptages.lane \ WHERE id_installation = {} ORDER BY number;".format( installation_id)) lane_ids = [] while query.next(): lane_ids.append(query.value(0)) query.exec_("select id from comptages.sensor_type \ where name = 'Boucle'") query.next() sensor_type_id = query.value(0) query_str = ( "INSERT INTO comptages.count(id, " "start_process_date, end_process_date, start_service_date, " "end_service_date, id_sensor_type, id_model, id_installation) " "VALUES (1, '2017-03-17', '2017-04-04', '2017-03-17', " "'2017-04-04', {}, {}, {});".format( sensor_type_id, model_id, installation_id)) query.exec_(query_str) task = self.comptages.import_file( os.path.join( self.test_data_path, 'simple_detail_special_case.V01'), 1) task.waitForFinished() # Let the time to the db to finish the writing time.sleep(1) query.exec_( "SELECT * \ FROM comptages.count_detail WHERE file_name = \ 'simple_detail_special_case.V01';") self.assertEqual(12, query.size()) query.exec_( "SELECT * \ FROM comptages.count_detail WHERE file_name = \ 'simple_detail_special_case.V01' and id_lane = {};".format( lane_ids[0])) self.assertEqual(1, query.size()) query.exec_( "SELECT * \ FROM comptages.count_detail WHERE file_name = \ 'simple_detail_special_case.V01' and id_lane = {};".format( lane_ids[1])) self.assertEqual(2, query.size()) query.exec_( "SELECT * \ FROM comptages.count_detail WHERE file_name = \ 'simple_detail_special_case.V01' and id_lane = {};".format( lane_ids[2])) self.assertEqual(4, query.size()) query.exec_( "SELECT * \ FROM comptages.count_detail WHERE file_name = \ 'simple_detail_special_case.V01' and id_lane = {};".format( lane_ids[3])) self.assertEqual(5, query.size()) self.db.close() def test_validate_special_case(self): self.db.open() query = QSqlQuery(self.db) query.exec_("SELECT id FROM comptages.installation \ WHERE name = '53109999';") query.next() installation_id = query.value(0) query.exec_("SELECT id FROM comptages.model \ WHERE name = 'M660_LT';") query.next() model_id = query.value(0) query.exec_("select id from comptages.sensor_type \ where name = 'Boucle'") query.next() sensor_type_id = query.value(0) query_str = ( "INSERT INTO comptages.count(id, " "start_process_date, end_process_date, start_service_date, " "end_service_date, id_sensor_type, id_model, id_installation) " "VALUES (1, '2017-03-17', '2017-04-04', '2017-03-17', " "'2017-04-04', {}, {}, {});".format( sensor_type_id, model_id, installation_id)) query.exec_(query_str) task = self.comptages.import_file( os.path.join( self.test_data_path, 'simple_detail_special_case.V01'), 1) task.waitForFinished() # Let the time to the db to finish the writing time.sleep(1) query.exec_( "SELECT * \ FROM comptages.count_detail WHERE file_name = \ 'simple_detail_special_case.V01' and import_status = {}".format( self.layers.IMPORT_STATUS_QUARANTINE)) self.assertEqual(12, query.size()) self.layers.change_status_of_count_data( 1, '53116845', self.layers.IMPORT_STATUS_DEFINITIVE) query.exec_( "SELECT * \ FROM comptages.count_detail WHERE file_name = \ 'simple_detail_special_case.V01' and import_status = {}".format( self.layers.IMPORT_STATUS_QUARANTINE)) self.assertEqual(11, query.size()) self.layers.change_status_of_count_data( 1, '53136855', self.layers.IMPORT_STATUS_DEFINITIVE) query.exec_( "SELECT * \ FROM comptages.count_detail WHERE file_name = \ 'simple_detail_special_case.V01' and import_status = {}".format( self.layers.IMPORT_STATUS_QUARANTINE)) self.assertEqual(7, query.size()) self.layers.change_status_of_count_data( 1, '53126850', self.layers.IMPORT_STATUS_DEFINITIVE) query.exec_( "SELECT * \ FROM comptages.count_detail WHERE file_name = \ 'simple_detail_special_case.V01' and import_status = {}".format( self.layers.IMPORT_STATUS_QUARANTINE)) self.assertEqual(5, query.size()) self.layers.change_status_of_count_data( 1, '53146860', self.layers.IMPORT_STATUS_DEFINITIVE) query.exec_( "SELECT * \ FROM comptages.count_detail WHERE file_name = \ 'simple_detail_special_case.V01' and import_status = {}".format( self.layers.IMPORT_STATUS_QUARANTINE)) self.assertEqual(0, query.size()) self.db.close() def test_refuse_special_case(self): self.db.open() query = QSqlQuery(self.db) query.exec_("SELECT id FROM comptages.installation \ WHERE name = '53109999';") query.next() installation_id = query.value(0) query.exec_("SELECT id FROM comptages.model \ WHERE name = 'M660_LT';") query.next() model_id = query.value(0) query.exec_("select id from comptages.sensor_type \ where name = 'Boucle'") query.next() sensor_type_id = query.value(0) query_str = ( "INSERT INTO comptages.count(id, " "start_process_date, end_process_date, start_service_date, " "end_service_date, id_sensor_type, id_model, id_installation) " "VALUES (1, '2017-03-17', '2017-04-04', '2017-03-17', " "'2017-04-04', {}, {}, {});".format( sensor_type_id, model_id, installation_id)) query.exec_(query_str) task = self.comptages.import_file( os.path.join( self.test_data_path, 'simple_detail_special_case.V01'), 1) task.waitForFinished() # Let the time to the db to finish the writing time.sleep(1) query.exec_( "SELECT * \ FROM comptages.count_detail WHERE file_name = \ 'simple_detail_special_case.V01';") self.assertEqual(12, query.size()) self.layers.delete_count_data( 1, '53116845', self.layers.IMPORT_STATUS_QUARANTINE) query.exec_( "SELECT * \ FROM comptages.count_detail WHERE file_name = \ 'simple_detail_special_case.V01';") self.assertEqual(11, query.size()) self.layers.delete_count_data( 1, '53136855', self.layers.IMPORT_STATUS_QUARANTINE) query.exec_( "SELECT * \ FROM comptages.count_detail WHERE file_name = \ 'simple_detail_special_case.V01';") self.assertEqual(7, query.size()) self.layers.delete_count_data( 1, '53126850', self.layers.IMPORT_STATUS_QUARANTINE) query.exec_( "SELECT * \ FROM comptages.count_detail WHERE file_name = \ 'simple_detail_special_case.V01';") self.assertEqual(5, query.size()) self.layers.delete_count_data( 1, '53146860', self.layers.IMPORT_STATUS_QUARANTINE) query.exec_( "SELECT * \ FROM comptages.count_detail WHERE file_name = \ 'simple_detail_special_case.V01';") self.assertEqual(0, query.size()) self.db.close()
class TestChartData(unittest.TestCase): @classmethod def setUpClass(self): self.settings = Settings() self.layers = plugins['comptages'].layers self.layers.load_layers() self.comptages = plugins['comptages'] self.db = QSqlDatabase.addDatabase("QPSQL", "test_chart_data_connection") self.db.setHostName(self.settings.value("db_host")) self.db.setPort(self.settings.value("db_port")) self.db.setDatabaseName(self.settings.value("db_name")) self.db.setUserName(self.settings.value("db_username")) self.db.setPassword(self.settings.value("db_password")) self.test_data_path = os.path.join( os.path.dirname(os.path.realpath(__file__)), 'test_data/') def setUp(self): self.db.open() query = QSqlQuery(self.db) query.exec_("DELETE FROM comptages.count;") query.exec_("DELETE FROM comptages.count_detail;") query.exec_("DELETE FROM comptages.count_aggregate;") query.exec_("DELETE FROM comptages.count_aggregate_value_cls;") query.exec_("DELETE FROM comptages.count_aggregate_value_cnt;") query.exec_("DELETE FROM comptages.count_aggregate_value_drn;") query.exec_("DELETE FROM comptages.count_aggregate_value_len;") query.exec_("DELETE FROM comptages.count_aggregate_value_spd;") query.exec_("DELETE FROM comptages.count_aggregate_value_sds;") self.db.close() def test_speed_chart_aggregate(self): self.db.open() query = QSqlQuery(self.db) query.exec_("SELECT id FROM comptages.installation \ WHERE name = '64080011';") query.next() installation_id = query.value(0) query.exec_("SELECT id FROM comptages.model \ WHERE name = 'M660_LT';") query.next() model_id = query.value(0) query.exec_("select id from comptages.sensor_type \ where name = 'Tube'") query.next() sensor_type_id = query.value(0) query_str = ( "INSERT INTO comptages.count(id, " "start_process_date, end_process_date, start_service_date, " "end_service_date, id_sensor_type, id_model, id_installation) " "VALUES (1, '2018-12-18', '2018-12-20', '2018-12-18', " "'2018-12-20', {}, {}, {});".format(sensor_type_id, model_id, installation_id)) query.exec_(query_str) task = self.comptages.import_file( os.path.join(self.test_data_path, 'speed_chart_aggregate.i00'), 1) task.waitForFinished() # Let the time to the db to finish the writing time.sleep(1) x, y = self.layers.get_aggregate_speed_chart_data( 1, self.layers.IMPORT_STATUS_QUARANTINE, '64080011') self.assertEqual([ '0-15 km/h', '15-30 km/h', '30-40 km/h', '40-50 km/h', '50-60 km/h', '60-70 km/h', '70-80 km/h', '80-90 km/h', '90-100 km/h', '100-110 km/h', '110-120 km/h', '120-999 km/h' ], x) self.assertEqual([10, 55, 55, 130, 140, 110, 70, 60, 50, 40, 90, 100], y) def test_speed_chart_detail(self): self.db.open() query = QSqlQuery(self.db) query.exec_("SELECT id FROM comptages.installation \ WHERE name = '64080011';") query.next() installation_id = query.value(0) query.exec_("SELECT id FROM comptages.model \ WHERE name = 'M660_LT';") query.next() model_id = query.value(0) query.exec_("select id from comptages.sensor_type \ where name = 'Tube'") query.next() sensor_type_id = query.value(0) query_str = ( "INSERT INTO comptages.count(id, " "start_process_date, end_process_date, start_service_date, " "end_service_date, id_sensor_type, id_model, id_installation) " "VALUES (1, '2018-12-18', '2018-12-20', '2018-12-18', " "'2018-12-20', {}, {}, {});".format(sensor_type_id, model_id, installation_id)) query.exec_(query_str) task = self.comptages.import_file( os.path.join(self.test_data_path, 'speed_chart_detail.V01'), 1) task.waitForFinished() # Let the time to the db to finish the writing time.sleep(1) x, y = self.layers.get_detail_speed_chart_data( 1, self.layers.IMPORT_STATUS_QUARANTINE, '64080011') self.assertEqual([ '0-10 km/h', '10-20 km/h', '20-30 km/h', '30-40 km/h', '40-50 km/h', '50-60 km/h', '60-70 km/h', '70-80 km/h', '80-90 km/h', '90-100 km/h', '100-110 km/h', '110-120 km/h', '120-999 km/h' ], x) self.assertEqual([1, 0, 3, 0, 0, 4, 0, 0, 1, 0, 0, 0, 2], y) def test_category_chart_aggregate(self): self.db.open() query = QSqlQuery(self.db) query.exec_("SELECT id FROM comptages.installation \ WHERE name = '64080011';") query.next() installation_id = query.value(0) query.exec_("SELECT id FROM comptages.model \ WHERE name = 'M660_LT';") query.next() model_id = query.value(0) query.exec_("select id from comptages.sensor_type \ where name = 'Tube'") query.next() sensor_type_id = query.value(0) query_str = ( "INSERT INTO comptages.count(id, " "start_process_date, end_process_date, start_service_date, " "end_service_date, id_sensor_type, id_model, id_installation) " "VALUES (1, '2018-12-18', '2018-12-20', '2018-12-18', " "'2018-12-20', {}, {}, {});".format(sensor_type_id, model_id, installation_id)) query.exec_(query_str) task = self.comptages.import_file( os.path.join(self.test_data_path, 'category_chart_aggregate.i00'), 1) task.waitForFinished() # Let the time to the db to finish the writing time.sleep(1) label, values = self.layers.get_aggregate_category_chart_data( 1, self.layers.IMPORT_STATUS_QUARANTINE, '64080011') self.assertEqual(label.index('CAR (1)'), values.index(10)) self.assertEqual(label.index('MR (2)'), values.index(20)) self.assertEqual(label.index('PW (3)'), values.index(30)) self.assertEqual(label.index('PW+ANH (4)'), values.index(40)) self.assertEqual(label.index('LIE (5)'), values.index(50)) self.assertEqual(label.index('LIE+ANH (6)'), values.index(60)) self.assertEqual(label.index('LIE+AUFL (7)'), values.index(70)) self.assertEqual(label.index('LW (8)'), values.index(80)) self.assertEqual(label.index('LZ (9)'), values.index(90)) self.assertEqual(label.index('SZ (10)'), values.index(100)) def test_category_chart_detail(self): self.db.open() query = QSqlQuery(self.db) query.exec_("SELECT id FROM comptages.installation \ WHERE name = '64080011';") query.next() installation_id = query.value(0) query.exec_("SELECT id FROM comptages.model \ WHERE name = 'M660_LT';") query.next() model_id = query.value(0) query.exec_("select id from comptages.sensor_type \ where name = 'Tube'") query.next() sensor_type_id = query.value(0) query_str = ( "INSERT INTO comptages.count(id, " "start_process_date, end_process_date, start_service_date, " "end_service_date, id_sensor_type, id_model, id_installation) " "VALUES (1, '2018-12-18', '2018-12-20', '2018-12-18', " "'2018-12-20', {}, {}, {});".format(sensor_type_id, model_id, installation_id)) query.exec_(query_str) task = self.comptages.import_file( os.path.join(self.test_data_path, 'category_chart_detail.V01'), 1) task.waitForFinished() # Let the time to the db to finish the writing time.sleep(1) label, values = self.layers.get_detail_category_chart_data( 1, self.layers.IMPORT_STATUS_QUARANTINE, '64080011') self.assertEqual(label.index('CAR (1)'), values.index(3)) self.assertEqual(label.index('MR (2)'), values.index(2)) self.assertEqual(label.index('PW (3)'), values.index(5)) self.assertEqual(label.index('SZ (10)'), values.index(1)) def test_time_chart_by_lane_aggregate(self): self.db.open() query = QSqlQuery(self.db) query.exec_("SELECT id FROM comptages.installation \ WHERE name = '64080011';") query.next() installation_id = query.value(0) query.exec_("SELECT id FROM comptages.model \ WHERE name = 'M660_LT';") query.next() model_id = query.value(0) query.exec_("SELECT id FROM comptages.lane \ WHERE id_installation = {};".format(installation_id)) lanes_id = [] while query.next(): lanes_id.append(query.value(0)) query.exec_("select id from comptages.sensor_type \ where name = 'Boucle'") query.next() sensor_type_id = query.value(0) query_str = ( "INSERT INTO comptages.count(id, " "start_process_date, end_process_date, start_service_date, " "end_service_date, id_sensor_type, id_model, id_installation) " "VALUES (1, '2018-12-18', '2018-12-20', '2018-12-18', " "'2018-12-20', {}, {}, {});".format(sensor_type_id, model_id, installation_id)) query.exec_(query_str) task = self.comptages.import_file( os.path.join(self.test_data_path, 'time_chart_aggregate.i00'), 1) task.waitForFinished() # Let the time to the db to finish the writing time.sleep(1) xs, ys, days = self.layers.get_aggregate_time_chart_data_by_lane( 1, self.layers.IMPORT_STATUS_QUARANTINE, lanes_id[0], '64080011') self.assertTrue(2, len(days)) self.assertEqual([ '00h-01h', '01h-02h', '02h-03h', '03h-04h', '04h-05h', '05h-06h', '06h-07h', '07h-08h', '08h-09h', '09h-10h', '10h-11h', '11h-12h', '12h-13h', '13h-14h', '14h-15h', '15h-16h', '16h-17h', '17h-18h', '18h-19h', '19h-20h', '20h-21h', '21h-22h', '22h-23h', '23h-00h' ], xs[0]) self.assertEqual([ '00h-01h', '01h-02h', '02h-03h', '03h-04h', '04h-05h', '05h-06h', '06h-07h', '07h-08h', '08h-09h', '09h-10h', '10h-11h', '11h-12h', '12h-13h', '13h-14h', '14h-15h', '15h-16h', '16h-17h', '17h-18h', '18h-19h', '19h-20h', '20h-21h', '21h-22h', '22h-23h', '23h-00h' ], xs[1]) self.assertEqual([ None, None, None, None, None, None, None, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, None, None, None, None, None, None, None ], ys[0]) self.assertEqual([ None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, 55, None, None, None, None, None, None, None ], ys[1]) xs, ys, days = self.layers.get_aggregate_time_chart_data_by_lane( 1, self.layers.IMPORT_STATUS_QUARANTINE, lanes_id[1], '64080011') self.assertTrue(2, len(days)) self.assertEqual([ '00h-01h', '01h-02h', '02h-03h', '03h-04h', '04h-05h', '05h-06h', '06h-07h', '07h-08h', '08h-09h', '09h-10h', '10h-11h', '11h-12h', '12h-13h', '13h-14h', '14h-15h', '15h-16h', '16h-17h', '17h-18h', '18h-19h', '19h-20h', '20h-21h', '21h-22h', '22h-23h', '23h-00h' ], xs[0]) self.assertEqual([ '00h-01h', '01h-02h', '02h-03h', '03h-04h', '04h-05h', '05h-06h', '06h-07h', '07h-08h', '08h-09h', '09h-10h', '10h-11h', '11h-12h', '12h-13h', '13h-14h', '14h-15h', '15h-16h', '16h-17h', '17h-18h', '18h-19h', '19h-20h', '20h-21h', '21h-22h', '22h-23h', '23h-00h' ], xs[1]) self.assertEqual([ None, None, None, None, None, None, None, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, None, None, None, None, None, None, None ], ys[0]) self.assertEqual([ None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, 10, None, None, None, None, None, None, None ], ys[1]) def test_time_chart_by_direction_aggregate(self): self.db.open() query = QSqlQuery(self.db) query.exec_("SELECT id FROM comptages.installation \ WHERE name = '00056520';") query.next() installation_id = query.value(0) query.exec_("SELECT id FROM comptages.model \ WHERE name = 'M660_LT';") query.next() model_id = query.value(0) query.exec_("select id from comptages.sensor_type \ where name = 'Tube'") query.next() sensor_type_id = query.value(0) query_str = ( "INSERT INTO comptages.count(id, " "start_process_date, end_process_date, start_service_date, " "end_service_date, id_sensor_type, id_model, id_installation) " "VALUES (1, '2018-12-18', '2018-12-20', '2018-12-18', " "'2018-12-20', {}, {}, {});".format(sensor_type_id, model_id, installation_id)) query.exec_(query_str) task = self.comptages.import_file( os.path.join(self.test_data_path, 'time_chart_aggregate_direction.i00'), 1) task.waitForFinished() # Let the time to the db to finish the writing time.sleep(1) xs, ys, days = self.layers.get_aggregate_time_chart_data_by_direction( 1, self.layers.IMPORT_STATUS_QUARANTINE, 1, '00056520') self.assertTrue(1, len(days)) self.assertEqual([ '00h-01h', '01h-02h', '02h-03h', '03h-04h', '04h-05h', '05h-06h', '06h-07h', '07h-08h', '08h-09h', '09h-10h', '10h-11h', '11h-12h', '12h-13h', '13h-14h', '14h-15h', '15h-16h', '16h-17h', '17h-18h', '18h-19h', '19h-20h', '20h-21h', '21h-22h', '22h-23h', '23h-00h' ], xs[0]) self.assertEqual([ None, None, None, None, None, None, None, 66, 66, 66, 66, 66, None, None, None, None, None, None, None, None, None, None, None, None ], ys[0]) xs, ys, days = self.layers.get_aggregate_time_chart_data_by_direction( 1, self.layers.IMPORT_STATUS_QUARANTINE, 2, '00056520') self.assertTrue(1, len(days)) self.assertEqual([ '00h-01h', '01h-02h', '02h-03h', '03h-04h', '04h-05h', '05h-06h', '06h-07h', '07h-08h', '08h-09h', '09h-10h', '10h-11h', '11h-12h', '12h-13h', '13h-14h', '14h-15h', '15h-16h', '16h-17h', '17h-18h', '18h-19h', '19h-20h', '20h-21h', '21h-22h', '22h-23h', '23h-00h' ], xs[0]) self.assertEqual([ None, None, None, None, None, None, None, 70, 70, 70, 70, 70, None, None, None, None, None, None, None, None, None, None, None, None ], ys[0]) def test_time_chart_by_lane_detail(self): self.db.open() query = QSqlQuery(self.db) query.exec_("SELECT id FROM comptages.installation \ WHERE name = '00056520';") query.next() installation_id = query.value(0) query.exec_("SELECT id FROM comptages.model \ WHERE name = 'M660_LT';") query.next() model_id = query.value(0) query.exec_("SELECT id FROM comptages.lane \ WHERE id_installation = {};".format(installation_id)) lanes_id = [] while query.next(): lanes_id.append(query.value(0)) query.exec_("select id from comptages.sensor_type \ where name = 'Boucle'") query.next() sensor_type_id = query.value(0) query_str = ( "INSERT INTO comptages.count(id, " "start_process_date, end_process_date, start_service_date, " "end_service_date, id_sensor_type, id_model, id_installation) " "VALUES (1, '2018-09-23', '2018-09-29', '2018-09-23', " "'2018-09-29', {}, {}, {});".format(sensor_type_id, model_id, installation_id)) query.exec_(query_str) task = self.comptages.import_file( os.path.join(self.test_data_path, 'time_chart_detail.V01'), 1) task.waitForFinished() # Let the time to the db to finish the writing time.sleep(1) xs, ys, days = self.layers.get_detail_time_chart_data_by_lane( 1, self.layers.IMPORT_STATUS_QUARANTINE, lanes_id[0], '00056520') self.assertTrue(1, len(days)) self.assertEqual([ '00h-01h', '01h-02h', '02h-03h', '03h-04h', '04h-05h', '05h-06h', '06h-07h', '07h-08h', '08h-09h', '09h-10h', '10h-11h', '11h-12h', '12h-13h', '13h-14h', '14h-15h', '15h-16h', '16h-17h', '17h-18h', '18h-19h', '19h-20h', '20h-21h', '21h-22h', '22h-23h', '23h-00h' ], xs[0]) self.assertEqual([ None, None, None, None, None, None, None, None, None, None, None, 1, 1, 1, None, None, 1, 1, 1, None, None, 1, None, None ], ys[0]) xs, ys, days = self.layers.get_detail_time_chart_data_by_lane( 1, self.layers.IMPORT_STATUS_QUARANTINE, lanes_id[1], '00056520') self.assertTrue(1, len(days)) self.assertEqual([ '00h-01h', '01h-02h', '02h-03h', '03h-04h', '04h-05h', '05h-06h', '06h-07h', '07h-08h', '08h-09h', '09h-10h', '10h-11h', '11h-12h', '12h-13h', '13h-14h', '14h-15h', '15h-16h', '16h-17h', '17h-18h', '18h-19h', '19h-20h', '20h-21h', '21h-22h', '22h-23h', '23h-00h' ], xs[0]) self.assertEqual([ None, None, None, None, None, None, None, None, None, None, None, None, None, None, 1, 1, None, None, None, 1, 1, None, None, None ], ys[0]) def test_time_chart_by_direction_detail(self): self.db.open() query = QSqlQuery(self.db) query.exec_("SELECT id FROM comptages.installation \ WHERE name = '00056520';") query.next() installation_id = query.value(0) query.exec_("SELECT id FROM comptages.model \ WHERE name = 'M660_LT';") query.next() model_id = query.value(0) query.exec_("select id from comptages.sensor_type \ where name = 'Tube'") query.next() sensor_type_id = query.value(0) query_str = ( "INSERT INTO comptages.count(id, " "start_process_date, end_process_date, start_service_date, " "end_service_date, id_sensor_type, id_model, id_installation) " "VALUES (1, '2018-12-18', '2018-12-20', '2018-12-18', " "'2018-12-20', {}, {}, {});".format(sensor_type_id, model_id, installation_id)) query.exec_(query_str) task = self.comptages.import_file( os.path.join(self.test_data_path, 'time_chart_detail_direction.V01'), 1) task.waitForFinished() # Let the time to the db to finish the writing time.sleep(1) xs, ys, days = self.layers.get_detail_time_chart_data_by_direction( 1, self.layers.IMPORT_STATUS_QUARANTINE, 1, '00056520') self.assertTrue(1, len(days)) self.assertEqual([ '00h-01h', '01h-02h', '02h-03h', '03h-04h', '04h-05h', '05h-06h', '06h-07h', '07h-08h', '08h-09h', '09h-10h', '10h-11h', '11h-12h', '12h-13h', '13h-14h', '14h-15h', '15h-16h', '16h-17h', '17h-18h', '18h-19h', '19h-20h', '20h-21h', '21h-22h', '22h-23h', '23h-00h' ], xs[0]) self.assertEqual([ None, None, None, None, None, None, None, None, None, None, None, 8, None, None, None, None, None, None, None, None, None, None, None, None ], ys[0]) xs, ys, days = self.layers.get_detail_time_chart_data_by_direction( 1, self.layers.IMPORT_STATUS_QUARANTINE, 2, '00056520') self.assertTrue(1, len(days)) self.assertEqual([ '00h-01h', '01h-02h', '02h-03h', '03h-04h', '04h-05h', '05h-06h', '06h-07h', '07h-08h', '08h-09h', '09h-10h', '10h-11h', '11h-12h', '12h-13h', '13h-14h', '14h-15h', '15h-16h', '16h-17h', '17h-18h', '18h-19h', '19h-20h', '20h-21h', '21h-22h', '22h-23h', '23h-00h' ], xs[0]) self.assertEqual([ None, None, None, None, None, None, None, None, None, None, None, 3, None, None, None, None, None, None, None, None, None, None, None, None ], ys[0]) def test_time_chart_special_case_detail(self): self.db.open() query = QSqlQuery(self.db) query.exec_("SELECT id FROM comptages.installation \ WHERE name = '53109999';") query.next() installation_id = query.value(0) query.exec_("SELECT id FROM comptages.model \ WHERE name = 'M660_LT';") query.next() model_id = query.value(0) query.exec_("SELECT id FROM comptages.lane \ WHERE id_installation = {};".format(installation_id)) lanes_id = [] while query.next(): lanes_id.append(query.value(0)) query.exec_("select id from comptages.sensor_type \ where name = 'Boucle'") query.next() sensor_type_id = query.value(0) query_str = ( "INSERT INTO comptages.count(id, " "start_process_date, end_process_date, start_service_date, " "end_service_date, id_sensor_type, id_model, id_installation) " "VALUES (1, '2017-03-17', '2017-04-04', '2017-03-17', " "'2017-04-04', {}, {}, {});".format(sensor_type_id, model_id, installation_id)) query.exec_(query_str) task = self.comptages.import_file( os.path.join(self.test_data_path, 'simple_detail_special_case.V01'), 1) task.waitForFinished() # Let the time to the db to finish the writing time.sleep(1) xs, ys, days = self.layers.get_detail_time_chart_data_by_lane( 1, self.layers.IMPORT_STATUS_QUARANTINE, lanes_id[0], '53116845') self.assertTrue(1, len(days)) self.assertEqual([ '00h-01h', '01h-02h', '02h-03h', '03h-04h', '04h-05h', '05h-06h', '06h-07h', '07h-08h', '08h-09h', '09h-10h', '10h-11h', '11h-12h', '12h-13h', '13h-14h', '14h-15h', '15h-16h', '16h-17h', '17h-18h', '18h-19h', '19h-20h', '20h-21h', '21h-22h', '22h-23h', '23h-00h' ], xs[0]) self.assertEqual([ None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, 1, None, None, None, None, None, None, None, None ], ys[0]) xs, ys, days = self.layers.get_detail_time_chart_data_by_lane( 1, self.layers.IMPORT_STATUS_QUARANTINE, lanes_id[1], '53126850') self.assertTrue(1, len(days)) self.assertEqual([ '00h-01h', '01h-02h', '02h-03h', '03h-04h', '04h-05h', '05h-06h', '06h-07h', '07h-08h', '08h-09h', '09h-10h', '10h-11h', '11h-12h', '12h-13h', '13h-14h', '14h-15h', '15h-16h', '16h-17h', '17h-18h', '18h-19h', '19h-20h', '20h-21h', '21h-22h', '22h-23h', '23h-00h' ], xs[0]) self.assertEqual([ None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, 2, None, None, None, None, None, None, None, None ], ys[0]) xs, ys, days = self.layers.get_detail_time_chart_data_by_lane( 1, self.layers.IMPORT_STATUS_QUARANTINE, lanes_id[2], '53136855') self.assertTrue(1, len(days)) self.assertEqual([ '00h-01h', '01h-02h', '02h-03h', '03h-04h', '04h-05h', '05h-06h', '06h-07h', '07h-08h', '08h-09h', '09h-10h', '10h-11h', '11h-12h', '12h-13h', '13h-14h', '14h-15h', '15h-16h', '16h-17h', '17h-18h', '18h-19h', '19h-20h', '20h-21h', '21h-22h', '22h-23h', '23h-00h' ], xs[0]) self.assertEqual([ None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, 4, None, None, None, None, None, None, None, None ], ys[0]) xs, ys, days = self.layers.get_detail_time_chart_data_by_lane( 1, self.layers.IMPORT_STATUS_QUARANTINE, lanes_id[3], '53146860') self.assertTrue(1, len(days)) self.assertEqual([ '00h-01h', '01h-02h', '02h-03h', '03h-04h', '04h-05h', '05h-06h', '06h-07h', '07h-08h', '08h-09h', '09h-10h', '10h-11h', '11h-12h', '12h-13h', '13h-14h', '14h-15h', '15h-16h', '16h-17h', '17h-18h', '18h-19h', '19h-20h', '20h-21h', '21h-22h', '22h-23h', '23h-00h' ], xs[0]) self.assertEqual([ None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, 5, None, None, None, None, None, None, None, None ], ys[0]) def test_time_chart_special_case_aggregate(self): self.db.open() query = QSqlQuery(self.db) query.exec_("SELECT id FROM comptages.installation \ WHERE name = '53109999';") query.next() installation_id = query.value(0) query.exec_("SELECT id FROM comptages.model \ WHERE name = 'M660_LT';") query.next() model_id = query.value(0) query.exec_("SELECT id FROM comptages.lane \ WHERE id_installation = {};".format(installation_id)) lanes_id = [] while query.next(): lanes_id.append(query.value(0)) query.exec_("select id from comptages.sensor_type \ where name = 'Boucle'") query.next() sensor_type_id = query.value(0) query_str = ( "INSERT INTO comptages.count(id, " "start_process_date, end_process_date, start_service_date, " "end_service_date, id_sensor_type, id_model, id_installation) " "VALUES (1, '2017-03-17', '2017-04-04', '2017-03-17', " "'2017-04-04', {}, {}, {});".format(sensor_type_id, model_id, installation_id)) query.exec_(query_str) task = self.comptages.import_file( os.path.join(self.test_data_path, 'simple_aggregate_special_case.A01'), 1) task.waitForFinished() # Let the time to the db to finish the writing time.sleep(1) xs, ys, days = self.layers.get_aggregate_time_chart_data_by_lane( 1, self.layers.IMPORT_STATUS_QUARANTINE, lanes_id[0], '53116845') self.assertTrue(1, len(days)) self.assertEqual([ '00h-01h', '01h-02h', '02h-03h', '03h-04h', '04h-05h', '05h-06h', '06h-07h', '07h-08h', '08h-09h', '09h-10h', '10h-11h', '11h-12h', '12h-13h', '13h-14h', '14h-15h', '15h-16h', '16h-17h', '17h-18h', '18h-19h', '19h-20h', '20h-21h', '21h-22h', '22h-23h', '23h-00h' ], xs[0]) self.assertEqual([ None, None, None, None, None, None, None, None, None, None, None, None, 65, None, None, None, None, None, None, None, None, None, None, None ], ys[0]) xs, ys, days = self.layers.get_aggregate_time_chart_data_by_lane( 1, self.layers.IMPORT_STATUS_QUARANTINE, lanes_id[1], '53126850') self.assertTrue(1, len(days)) self.assertEqual([ '00h-01h', '01h-02h', '02h-03h', '03h-04h', '04h-05h', '05h-06h', '06h-07h', '07h-08h', '08h-09h', '09h-10h', '10h-11h', '11h-12h', '12h-13h', '13h-14h', '14h-15h', '15h-16h', '16h-17h', '17h-18h', '18h-19h', '19h-20h', '20h-21h', '21h-22h', '22h-23h', '23h-00h' ], xs[0]) self.assertEqual([ None, None, None, None, None, None, None, None, None, None, None, None, 53, None, None, None, None, None, None, None, None, None, None, None ], ys[0]) xs, ys, days = self.layers.get_aggregate_time_chart_data_by_lane( 1, self.layers.IMPORT_STATUS_QUARANTINE, lanes_id[2], '53136855') self.assertTrue(1, len(days)) self.assertEqual([ '00h-01h', '01h-02h', '02h-03h', '03h-04h', '04h-05h', '05h-06h', '06h-07h', '07h-08h', '08h-09h', '09h-10h', '10h-11h', '11h-12h', '12h-13h', '13h-14h', '14h-15h', '15h-16h', '16h-17h', '17h-18h', '18h-19h', '19h-20h', '20h-21h', '21h-22h', '22h-23h', '23h-00h' ], xs[0]) self.assertEqual([ None, None, None, None, None, None, None, None, None, None, None, None, 37, None, None, None, None, None, None, None, None, None, None, None ], ys[0]) xs, ys, days = self.layers.get_aggregate_time_chart_data_by_lane( 1, self.layers.IMPORT_STATUS_QUARANTINE, lanes_id[3], '53146860') self.assertTrue(1, len(days)) self.assertEqual([ '00h-01h', '01h-02h', '02h-03h', '03h-04h', '04h-05h', '05h-06h', '06h-07h', '07h-08h', '08h-09h', '09h-10h', '10h-11h', '11h-12h', '12h-13h', '13h-14h', '14h-15h', '15h-16h', '16h-17h', '17h-18h', '18h-19h', '19h-20h', '20h-21h', '21h-22h', '22h-23h', '23h-00h' ], xs[0]) self.assertEqual([ None, None, None, None, None, None, None, None, None, None, None, None, 18, None, None, None, None, None, None, None, None, None, None, None ], ys[0])
class Comptages(QObject): def __init__(self, iface): QObject.__init__(self) self.iface = iface self.settings = Settings() self.settings_dialog = SettingsDialog() self.layers = Layers() self.chart_dock = ChartDock(self.iface, self.layers) self.iface.addDockWidget(Qt.BottomDockWidgetArea, self.chart_dock) self.filter_start_date = None self.filter_end_date = None self.filter_installation = None self.filter_sensor = None self.tm = QgsApplication.taskManager() def initGui(self): self.connect_db_action = QAction( QIcon(':/plugins/Comptages/images/power.png'), 'Connection DB', self.iface.mainWindow() ) self.create_new_action = QAction( QIcon(':/plugins/Comptages/images/measure.png'), 'Créer un nouveau comptage', None ) self.select_edit_action = QAction( QIcon(':/plugins/Comptages/images/select_edit.png'), 'Modifier comptage', None ) self.import_files_action = QAction( QIcon(':/plugins/Comptages/images/import.png'), 'Importation', None ) self.validate_imported_files = QAction( QIcon(':/plugins/Comptages/images/validate.png'), 'Validation', None ) self.filter_action = QAction( QIcon(':/plugins/Comptages/images/filter.png'), 'Filtrer', None ) self.import_ics_action = QAction( QIcon(':/plugins/Comptages/images/calendar.png'), 'Importer fichier ics', None ) self.settings_action = QAction( QIcon(':/plugins/Comptages/images/settings.png'), 'Réglages', None ) self.connect_db_action.triggered.connect( self.do_connect_db_action) self.create_new_action.triggered.connect( self.do_create_new_action) self.select_edit_action.triggered.connect( self.do_select_edit_action) self.import_files_action.triggered.connect( self.do_import_files_action) self.validate_imported_files.triggered.connect( self.do_validate_imported_files_action) self.filter_action.triggered.connect( self.do_filter_action) self.import_ics_action.triggered.connect( self.do_import_ics_action) self.settings_action.triggered.connect( self.do_settings_action) self.create_new_action.setEnabled(False) self.select_edit_action.setEnabled(False) self.import_files_action.setEnabled(False) self.validate_imported_files.setEnabled(False) self.filter_action.setEnabled(False) self.import_ics_action.setEnabled(False) self.iface.addPluginToMenu('Comptages', self.connect_db_action) self.iface.addPluginToMenu('Comptages', self.create_new_action) self.iface.addPluginToMenu('Comptages', self.select_edit_action) self.iface.addPluginToMenu('Comptages', self.import_files_action) self.iface.addPluginToMenu('Comptages', self.validate_imported_files) self.iface.addPluginToMenu('Comptages', self.filter_action) self.iface.addPluginToMenu('Comptages', self.import_ics_action) self.iface.addPluginToMenu('Comptages', self.settings_action) self.toolbar = self.iface.addToolBar('Comptages') self.toolbar.setObjectName('Comptages') self.toolbar.setToolTip('Comptages toolbar') self.toolbar.addAction(self.connect_db_action) self.toolbar.addSeparator() self.toolbar.addAction(self.create_new_action) self.toolbar.addAction(self.select_edit_action) self.toolbar.addAction(self.import_files_action) self.toolbar.addAction(self.validate_imported_files) self.toolbar.addAction(self.filter_action) self.toolbar.addAction(self.import_ics_action) self.toolbar.addSeparator() self.toolbar.addAction(self.settings_action) def unload(self): self.iface.removePluginMenu('Comptages', self.connect_db_action) self.iface.removePluginMenu('Comptages', self.create_new_action) self.iface.removePluginMenu('Comptages', self.select_edit_action) self.iface.removePluginMenu('Comptages', self.filter_action) self.iface.removePluginMenu('Comptages', self.import_ics_action) self.iface.removePluginMenu('Comptages', self.settings_action) del self.connect_db_action del self.create_new_action del self.select_edit_action del self.filter_action del self.import_ics_action del self.settings_action del self.toolbar def do_connect_db_action(self): self.layers.load_layers() self.enable_actions_if_needed() def do_create_new_action(self): if self.tm.countActiveTasks() > 0: push_info(("Veuillez patienter jusqu'à ce que l'importation " "soit terminée.")) return self.layers.create_count() def do_select_edit_action(self): if self.tm.countActiveTasks() > 0: push_info(("Veuillez patienter jusqu'à ce que l'importation " "soit terminée.")) return self.layers.edit_count() def do_import_files_action(self): if self.tm.countActiveTasks() > 0: push_info(("Veuillez patienter jusqu'à ce que l'importation " "soit terminée.")) return file_dialog = QFileDialog() title = 'Importer' path = self.settings.value('data_import_directory') files = QFileDialog.getOpenFileNames( file_dialog, title, path, "Data file (*.A?? *.aV? *.I?? *.V?? *.txt)")[0] for file_path in files: self.import_file(file_path) def import_file(self, file_path, count_id=None): # Manage binary files with open(file_path, 'rb') as fd: file_head = fd.read(24) if file_head == b'Golden River Traffic Ltd': # is a binary file formatter = self.layers.get_formatter_name('GoldenRiver') file_path_formatted = "{}_for".format(file_path) os.system("{} {} {}".format( formatter, file_path, file_path_formatted)) file_path = file_path_formatted file_header = DataImporter.parse_file_header(file_path) if not count_id: count_id = self.layers.guess_count_id( file_header['SITE'], datetime.strptime(file_header['STARTREC'], "%H:%M %d/%m/%y"), datetime.strptime(file_header['STOPREC'], "%H:%M %d/%m/%y")) if not count_id: QgsMessageLog.logMessage( """Impossible de trouver le comptage associé {}: section: {} start: {} end: {}""".format( file_path, file_header['SITE'], datetime.strptime(file_header['STARTREC'], "%H:%M %d/%m/%y"), datetime.strptime(file_header['STOPREC'], "%H:%M %d/%m/%y") ), 'Comptages', Qgis.Critical) return QgsMessageLog.logMessage( 'Importation {}'.format(os.path.basename(file_path)), 'Comptages', Qgis.Info) file_format = file_header['FORMAT'] if file_format == 'VBV-1': task = DataImporterVbv1(file_path, count_id) elif file_format == 'INT-2': task = DataImporterInt2(file_path, count_id) elif file_format == 'MC': task = DataImporterMC(file_path, count_id) else: push_info('Format {} of {} not supported'.format( file_format, os.path.basename(file_path))) return self.tm.allTasksFinished.connect(self.task_finished) self.tm.addTask(task) return task def task_finished(self): self.tm.allTasksFinished.disconnect(self.task_finished) push_info(('Toutes les tâches sont terminées. Consultez le journal ' 'pour plus de détails.')) self.chart_dock.show_next_quarantined_chart() def do_validate_imported_files_action(self): if self.tm.countActiveTasks() > 0: push_info(("Veuillez patienter jusqu'à ce que l'importation " "soit terminée.")) return self.chart_dock.show_next_quarantined_chart() def do_filter_action(self): dlg = FilterDialog(self.iface) # Set last values in the filter if self.filter_start_date: dlg.start_date.setDateTime(self.filter_start_date) else: dlg.start_date.setDateTime(QDateTime()) if self.filter_end_date: dlg.end_date.setDateTime(self.filter_end_date) else: dlg.end_date.setDateTime(QDateTime()) if self.filter_installation: dlg.installation.setCurrentIndex(self.filter_installation) if self.filter_sensor: dlg.sensor.setCurrentIndex(self.filter_sensor) if dlg.exec_(): self.filter_start_date = dlg.start_date.dateTime() self.filter_end_date = dlg.end_date.dateTime() self.filter_installation = dlg.installation.currentIndex() self.filter_sensor = dlg.sensor.currentIndex() self.layers.apply_filter( dlg.start_date.dateTime().toString('yyyy-MM-dd'), dlg.end_date.dateTime().toString('yyyy-MM-dd'), dlg.installation.currentIndex(), dlg.sensor.currentIndex()) def do_import_ics_action(self): IcsImporter(self.layers) def do_settings_action(self): self.settings_dialog.exec_() def do_export_configuration_action(self, count_id): config_creator = ConfigCreatorCmd(self.layers, count_id) config_creator.set_section_commands() installation_name = self.layers.get_installation_name_of_count( count_id) file_dialog = QFileDialog() file_dialog.setDefaultSuffix('*.CMD') title = 'Exporter la configuration' path = os.path.join( self.settings.value('config_export_directory'), "{}.CMD".format(installation_name)) file = QFileDialog.getSaveFileName( file_dialog, title, path, "Config file (*.CMD)")[0] if not file: return config_creator.write_file(file) push_info('Written config file {}'.format(file)) def do_import_single_file_action(self, count_id): file_dialog = QFileDialog() title = 'Importation' path = self.settings.value('data_import_directory') file_path = QFileDialog.getOpenFileName( file_dialog, title, path, "Data file (*.A?? *.aV? *.I?? *.V?? *.txt)")[0] if not file_path: return self.import_file(file_path, count_id) def do_generate_report_action(self, count_id): if self.tm.countActiveTasks() > 0: push_info(("Veuillez patienter jusqu'à ce que l'importation " "soit terminée.")) return # Show message if there are no data to process contains_data = self.layers.count_contains_data(count_id) if not contains_data : push_info("Installation {}: Il n'y a pas de données à traiter pour " "le comptage {}".format( self.layers.get_installation_name_of_count(count_id),count_id)) return file_dialog = QFileDialog() title = 'Exporter un rapport' path = self.settings.value('report_export_directory') file_path = QFileDialog.getExistingDirectory( file_dialog, title, path) print(file_path) if not file_path: return report_creator = ReportCreator(count_id, file_path, self.layers) report_creator.run() push_info("Installation {} (count={}): Génération du rapport terminée." .format(self.layers.get_installation_name_of_count(count_id),count_id)) def do_export_plan_action(self, count_id): plan_creator = PlanCreator(self.layers) file_dialog = QFileDialog() file_dialog.setDefaultSuffix('*.PDF') title = 'Exporter plan de pose' path = os.path.join( self.settings.value('config_export_directory'), "{}.pdf".format("plan_de_pose")) file = QFileDialog.getSaveFileName( file_dialog, title, path, "Config file (*.PDF)")[0] if not file: return # Highlight the current sections and installation in the layout previous_highlightes_sections = self.layers.highlighted_sections self.layers.highlighted_sections = \ self.layers.get_section_ids_of_count(count_id) QgsExpressionContextUtils.setProjectVariable( QgsProject.instance(), 'highlighted_installation', self.layers.get_installation_name_of_count(count_id)) plan_creator.export_pdf(count_id, file) self.layers.highlighted_sections = previous_highlightes_sections QgsExpressionContextUtils.setProjectVariable( QgsProject.instance(), 'highlighted_installation', '') self.layers.layers['section'].triggerRepaint() def do_generate_chart_action(self, count_id): if self.tm.countActiveTasks() > 0: push_info(("Veuillez patienter jusqu'à ce que l'importation " "soit terminée.")) return self.chart_dock.set_attributes(count_id) def enable_actions_if_needed(self): """Enable actions if the plugin is connected to the db otherwise disable them""" self.create_new_action.setEnabled(True) self.select_edit_action.setEnabled(True) self.import_files_action.setEnabled(True) self.validate_imported_files.setEnabled(True) self.import_ics_action.setEnabled(True) self.filter_action.setEnabled(True) def is_section_highlighted(self, section_id): return self.layers.is_section_highlighted(section_id) @qgsfunction(args="auto", group="Comptages") def is_highlighted(feature, parent): """Used by section layer to apply a style to the sections related to a count""" # Call the method of the current instance of the plugin return plugins['comptages'].is_section_highlighted( feature.attribute('id')) @qgsfunction(args="auto", group="Comptages") def check_dates(feature, parent): """Used by count layer to show if a count was during a special period""" return plugins['comptages'].layers.check_dates( feature.attribute('start_process_date'), feature.attribute('end_process_date') )
class PlanCreator(): def __init__(self, layers): self.layers = layers self.settings = Settings() def export_pdf(self, count_id, file_name): current_dir = os.path.dirname(os.path.abspath(__file__)) qpt_file_path = os.path.join( current_dir, os.pardir, 'qml', 'plan.qpt') self.layout = PlanCreator.create_layout_from_template( qpt_file_path) self.set_fields(count_id) # self.layers.select_and_zoom_on_section_of_count(count_id) canvas = iface.mapCanvas() map_item = self.layout.itemById('map') map_item.setExtent(canvas.extent()) exporter = QgsLayoutExporter(self.layout) exporter.exportToPdf( file_name, exporter.PdfExportSettings()) def set_fields(self, count_id): count = self.layers.get_count(count_id) installation = self.layers.get_installation_of_count(count_id) sections = self.layers.get_sections_of_count(count_id) self.set_text_item('f_01', installation.attribute('name')) self.set_text_item('f_03', '') self.set_text_item('f_04', sections[0].attribute('owner')) self.set_text_item('f_05', sections[0].attribute('road')) self.set_text_item('f_06', sections[0].attribute('way')) self.set_text_item( 'f_07', '{} + {} m'.format( sections[0].attribute('start_pr'), sections[0].attribute('start_dist'))) self.set_text_item( 'f_08', '{} + {} m'.format( sections[0].attribute('end_pr'), sections[0].attribute('end_dist'))) self.set_text_item('f_09', sections[0].attribute('place_name')) self.set_text_item( 'f_10', count.attribute('start_process_date').toString( 'dd.MM.yyyy (dddd)')) self.set_text_item( 'f_11', count.attribute('end_process_date').toString( 'dd.MM.yyyy (dddd)')) self.set_text_item('f_14', '') self.set_text_item('f_15', '') # Page 2 self.set_text_item('f_17', 'Campagne de comptage') self.set_text_item( 'f_18', 'Pose {}'.format(count.attribute('start_put_date').toString( 'dddd dd.MM.yyyy'))) self.set_text_item( 'f_19', 'Dépose {}'.format(count.attribute('end_put_date').toString( 'dddd dd.MM.yyyy'))) self.set_text_item('f_20', sections[0].attribute('place_name')) self.set_text_item('f_21', installation.attribute('name')) self.set_text_item('f_22', '') self.set_text_item('f_23', '') self.set_picture_item('picture_1', installation.attribute('picture')) current_dir = os.path.dirname(os.path.abspath(__file__)) self.set_picture_item( 'logo', os.path.join(current_dir, os.pardir, 'images', 'logo_ne.png')) def set_text_item(self, name, text): self.layout.itemById(name).setText(text) def set_picture_item(self, name, file_name): if not file_name: return picture_path = os.path.join( self.settings.value('picture_directory'), file_name) self.layout.itemById(name).setPicturePath(picture_path) @staticmethod def create_layout_from_template(template_filename): layout = QgsPrintLayout(QgsProject().instance()) document = QDomDocument() with open(os.path.join('data', 'general', template_filename)) as template_file: template_content = template_file.read() document.setContent(template_content) layout.loadFromTemplate(document, QgsReadWriteContext()) return layout
class TestData(unittest.TestCase): @classmethod def setUpClass(self): self.settings = Settings() self.layers = plugins['comptages'].layers self.layers.load_layers() self.comptages = plugins['comptages'] self.db = QSqlDatabase.addDatabase("QPSQL", "test_data_connection") self.db.setHostName(self.settings.value("db_host")) self.db.setPort(self.settings.value("db_port")) self.db.setDatabaseName(self.settings.value("db_name")) self.db.setUserName(self.settings.value("db_username")) self.db.setPassword(self.settings.value("db_password")) self.test_data_path = os.path.join( os.path.dirname(os.path.realpath(__file__)), 'test_data/') def setUp(self): self.db.open() query = QSqlQuery(self.db) query.exec_("DELETE FROM comptages.count;") query.exec_("DELETE FROM comptages.count_detail;") query.exec_("DELETE FROM comptages.count_aggregate;") query.exec_("DELETE FROM comptages.count_aggregate_value_cls;") query.exec_("DELETE FROM comptages.count_aggregate_value_cnt;") query.exec_("DELETE FROM comptages.count_aggregate_value_drn;") query.exec_("DELETE FROM comptages.count_aggregate_value_len;") query.exec_("DELETE FROM comptages.count_aggregate_value_spd;") query.exec_("DELETE FROM comptages.count_aggregate_value_sds;") self.db.close() def test_data_detail(self): self.db.open() query = QSqlQuery(self.db) query.exec_("SELECT id FROM comptages.installation \ WHERE name = '64080011';") query.next() installation_id = query.value(0) query.exec_("SELECT id FROM comptages.model \ WHERE name = 'M660_LT';") query.next() model_id = query.value(0) query.exec_("select id from comptages.sensor_type \ where name = 'Tube'") query.next() sensor_type_id = query.value(0) query.exec_("select id from comptages.class \ where name = 'SWISS10'") query.next() class_id = query.value(0) query_str = ( "INSERT INTO comptages.count(id, " "start_process_date, end_process_date, start_service_date, " "end_service_date, id_sensor_type, id_model, id_class, " "id_installation) " "VALUES (1, '2018-12-18', '2018-12-20', '2018-12-18', " "'2018-12-20', {}, {}, {}, {});".format(sensor_type_id, model_id, class_id, installation_id)) query.exec_(query_str) task = self.comptages.import_file( os.path.join(self.test_data_path, 'data_loader_simple_detail.V01'), 1) task.waitForFinished() # Let the time to the db to finish the writing time.sleep(1) data_loader = DataLoader(1, '64080011', self.layers.IMPORT_STATUS_QUARANTINE) count_data = data_loader.load() self.assertEqual( [1, 0, 3, 0, 0, 4, 0, 0, 1, 0, 0, 0, 2], count_data.day_data[0].hour_data[15].direction_data[0].speed_data) self.assertEqual([1, 1, 2, 1, 1, 1, 1, 1, 1, 1], count_data.day_data[0].hour_data[15]. direction_data[0].category_data) self.assertEqual(20, count_data.day_data[0].total()) self.assertEqual(16, count_data.day_data[0].light_vehicles()) self.assertEqual(4, count_data.day_data[0].heavy_vehicles()) self.assertEqual(20.0, count_data.day_data[0].percent_heavy_vehicles()) def test_data_aggregate(self): self.db.open() query = QSqlQuery(self.db) query.exec_("SELECT id FROM comptages.installation \ WHERE name = '64080011';") query.next() installation_id = query.value(0) query.exec_("SELECT id FROM comptages.model \ WHERE name = 'M660_LT';") query.next() model_id = query.value(0) query.exec_("select id from comptages.sensor_type \ where name = 'Tube'") query.next() sensor_type_id = query.value(0) query.exec_("select id from comptages.class \ where name = 'SWISS10'") query.next() class_id = query.value(0) query_str = ( "INSERT INTO comptages.count(id, " "start_process_date, end_process_date, start_service_date, " "end_service_date, id_sensor_type, id_model, id_class, " "id_installation) " "VALUES (1, '2018-12-18', '2018-12-20', '2018-12-18', " "'2018-12-20', {}, {}, {}, {});".format(sensor_type_id, model_id, class_id, installation_id)) query.exec_(query_str) task = self.comptages.import_file( os.path.join(self.test_data_path, 'data_loader_simple_aggregate.i00'), 1) task.waitForFinished() # Let the time to the db to finish the writing time.sleep(1) data_loader = DataLoader(1, '64080011', self.layers.IMPORT_STATUS_QUARANTINE) count_data = data_loader.load() self.assertEqual( [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], count_data.day_data[1].hour_data[8].direction_data[0].speed_data) self.assertEqual([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ], count_data.day_data[1].hour_data[8].direction_data[0].category_data)