def upload_parties(self, api, party_name, party_type, attributes=None):
        """Upload party data.

        :param api: Api url to upload party
        :type api: str

        :param party_name: Party name
        :type party_name: str

        :param party_type: Party type
        :type party_type: str

        :param attributes: Project-specific attributes that are defined
                           through the project's questionnaire
        :type attributes: dict
        """
        post_data = {
            'name': party_name,
            'type': party_type
        }

        if attributes:
            post_data['attributes'] = attributes

        connector = ApiConnect(get_url_instance() + api)
        status, result = connector.patch_json(Utilities.json_dumps(post_data))

        if status:
            self.set_status(
                self.tr('Party updated.')
            )
        else:
            self.set_status(
                Utilities.extract_error_detail(result)
            )
    def upload_relationship(self, api, relationship_type, attributes=None):
        """Upload relationship data.

        :param api: Api url to upload party
        :type api: str

        :param relationship_type: Relationship type
        :type relationship_type: str

        :param attributes: Project-specific attributes that are defined
                           through the project's questionnaire
        :type attributes: dict
        """
        post_data = {
            'tenure_type': relationship_type,
        }

        if attributes:
            post_data['attributes'] = attributes

        connector = ApiConnect(get_url_instance() + api)
        status, result = connector.patch_json(Utilities.json_dumps(post_data))

        if status:
            self.set_status(
                self.tr('Relationship updated.')
            )
        else:
            self.set_status(
                Utilities.extract_error_detail(result)
            )
예제 #3
0
    def upload_parties(self):
        """Upload party from this project."""
        self.set_status(tr('Uploading parties'))

        party = 0

        # reset progress bar
        current_progress = 0
        self.set_progress_bar(current_progress)
        total_layer = len(self.data['locations']['features'])
        progress_block = 100 / total_layer

        post_url = self._url_post_parties()

        if not post_url:
            # Project is not uploaded
            return

        for layer in self.data['locations']['features']:
            if 'party_name' in layer['fields'] and \
                            'party_type' in layer['fields']:
                post_data = {
                    'name': layer['fields']['party_name'],
                    'type': layer['fields']['party_type']
                }

                post_data = Utilities.json_dumps(post_data)

                connector = ApiConnect(get_url_instance() + post_url)
                status, result = self._call_json_post(connector, post_data)

                if status:
                    party += 1
                    try:
                        result_dict = result
                        if 'id' in result_dict:
                            layer['party_id'] = result_dict['id']
                    except ValueError as e:
                        LOGGER.exception('message')
                else:
                    self.set_progress_bar(0)
                    self.set_status(Utilities.extract_error_detail(result))
            else:
                self.set_status(tr('No party attributes found'))
            current_progress += progress_block
            self.set_progress_bar(current_progress)

        if party == 0:
            self.set_status(tr('Not uploading any party'))
        else:
            self.set_status(
                tr('Finished uploading {party} party'.format(party=party)))

        self.set_progress_bar(100)
예제 #4
0
    def upload_project(self):
        """Upload project to cadasta."""
        # check requirement attributes
        if self.check_requirement():
            return

        self.set_status(tr('Uploading project'))
        self.current_progress = 0
        self.set_progress_bar(self.current_progress)

        post_data = {
            'name': self.data['project_name'],
            'description': self.data['description'],
            'extent': self.data['extent'],
            'access': 'private' if self.data['private'] else 'public',
            'contacts': self.data['contacts']
        }

        if self.data['project_url']:
            post_data['urls'] = [self.data['project_url']]

        post_url = '/api/v1/organizations/%s/projects/' % (
            self.data['organisation']['slug'])

        post_data = Utilities.json_dumps(post_data)

        connector = ApiConnect(get_url_instance() + post_url)
        status, result = self._call_json_post(connector, post_data)

        self.set_progress_bar(self.current_progress + self.upload_increment)
        self.set_status(tr('Finished uploading project'))

        if status:
            self.project_upload_result = result
            upload_questionnaire_attribute = False
            # create questionnaire first
            # after creating location, questionnaire is blocked
            if self.data['questionnaire']:
                upload_questionnaire_attribute = True
                self.upload_questionnaire_project()
            total_locations = len(self.data['locations']['features'])
            if total_locations > 0:
                self.upload_locations(upload_questionnaire_attribute)
                self.upload_parties()
                self.upload_relationships()
            self.rerender_saved_layer()
            self.set_progress_bar(100)
        else:
            self.set_progress_bar(0)
            self.set_status(Utilities.extract_error_detail(result))

        self.set_status(tr('Finished'))
        self.parent.close()
    def organization_projects_spatial_call_finished(self, result):
        """Function when Organization Project Spatial Api finished.

        :param result: result of request
        :type result: (bool, list/dict/str)
        """
        self.save_organizations()
        if result[0]:
            # save result to local file
            organization_slug = result[2]
            project_slug = result[3]
            vlayers = Utilities.save_layer(result[1], organization_slug,
                                           project_slug)
            self.progress_bar.setValue(50)

            download_relationship_and_party = False

            if self.project['access'] == 'public':
                # Get organization
                status, results = self.organisation_api.summary_organization(
                    organization_slug)

                if status and 'users' in results:
                    for user in results['users']:
                        if user['username'] == get_setting('username'):
                            download_relationship_and_party = True
                            break
            else:
                download_relationship_and_party = True

            relationship_layer_id = None
            party_layer_id = None

            if download_relationship_and_party:
                relationship_layer = self.relationships_layer(vlayers)
                if relationship_layer:
                    relationship_layer_id = relationship_layer.id()

                party_layer = self.parties_layer()
                if party_layer:
                    party_layer_id = party_layer.id()

            self.progress_bar.setValue(80)

            QCoreApplication.processEvents()
            Utilities.save_project_basic_information(self.project, vlayers,
                                                     relationship_layer_id,
                                                     party_layer_id)
        else:
            pass
        self.progress_bar.setValue(self.progress_bar.maximum())
        self.warning_label.setText(self.loaded_label_string)
        self.parent.close()
예제 #6
0
    def upload_relationships(self):
        """Upload relationships attribute to cadasta."""
        self.set_status(tr('Uploading relationship'))

        # reset progress bar
        current_progress = 0
        self.set_progress_bar(current_progress)
        total_layer = len(self.data['locations']['features'])
        progress_block = 100 / total_layer

        relationship = 0

        url = self._url_post_relationships()

        for layer in self.data['locations']['features']:

            if 'relationship_type' in layer['fields'] and \
                            'spatial_id' in layer and \
                            'party_id' in layer:

                post_data = {
                    'tenure_type': layer['fields']['relationship_type'],
                    'spatial_unit': layer['spatial_id'],
                    'party': layer['party_id']
                }

                post_data = Utilities.json_dumps(post_data)

                connector = ApiConnect(get_url_instance() + url)
                status, result = self._call_json_post(connector, post_data)

                if status:
                    relationship += 1
                else:
                    self.set_progress_bar(0)
                    self.set_status(Utilities.extract_error_detail(result))
            else:
                self.set_status(tr('No relationship attributes found'))

            current_progress += progress_block
            self.set_progress_bar(current_progress)

        if relationship == 0:
            self.set_status(tr('Not uploading any relationship'))
        else:
            self.set_status(
                tr('Finished uploading {num} relationship'.format(
                    num=relationship)))

        self.set_progress_bar(100)
    def update_project(self):
        """Update a basic project information in an organization."""
        step2 = self.parent.step_project_update02

        contact_item_list = step2.project_contact_list.selectedItems()
        contacts = []
        for contact_item in contact_item_list:
            contact = contact_item.data(Qt.UserRole)
            contact_data = {}
            if contact.name:
                contact_data['name'] = contact.name
            if contact.phone:
                contact_data['tel'] = contact.phone
            if contact.email:
                contact_data['email'] = contact.email
            contacts.append(contact_data)

        access = 'private' if step2.access_checkbox.isChecked() else 'public'
        post_data = {
            'name': step2.project_name_text.displayText(),
            'description': step2.project_desc_text.toPlainText(),
            'access': access,
            'contacts': contacts
        }

        if step2.project_url_text.displayText():
            post_data['urls'] = [
                step2.project_url_text.displayText()
            ]

        status, response = step2.send_update_request(post_data)
        if status:
            Utilities.update_project_basic_information(
                information=response,
                vlayers=self.vlayers
            )
            self.set_status(
                self.tr('Update success')
            )
        else:
            self.set_status(
                Utilities.extract_error_detail(response)
            )
    def add_new_locations(self, geometry, location_type, attributes=None):
        """Add new location

        :param geometry: Location geojson geometry
        :type geometry: str

        :param location_type: Location type
        :type location_type: str

        :param attributes: Project-specific attributes that are defined
           through the project's questionnaire
        :type attributes: dict
        """
        api = u'/api/v1/organizations/{organization_slug}/projects/' \
              u'{project_slug}/spatial/'.format(
                organization_slug=self.project['organization']['slug'],
                project_slug=self.project['slug'])

        post_data = {
            'geometry': geometry
        }

        if location_type:
            post_data['type'] = location_type

        if attributes:
            post_data['attributes'] = attributes

        connector = ApiConnect(get_url_instance() + api)
        status, result = connector.post_json(Utilities.json_dumps(post_data))

        if status:
            self.set_status(
                self.tr('Location added.')
            )
            return result['properties']['id']
        else:
            self.set_status(
                Utilities.extract_error_detail(result)
            )
            return None
    def upload_update_locations(
            self,
            api,
            geometry,
            location_type,
            attributes=None):
        """Upload update location data.

        :param api: Api url to upload location
        :type api: str

        :param geometry: Location geojson geometry
        :type geometry: str

        :param location_type: Location type
        :type location_type: str

        :param attributes: Project-specific attributes that are defined
                   through the project's questionnaire
        :type attributes: dict
        """
        post_data = {
            'geometry': geometry,
            'type': location_type
        }

        if attributes:
            post_data['attributes'] = attributes

        connector = ApiConnect(get_url_instance() + api)
        status, result = connector.patch_json(Utilities.json_dumps(post_data))

        if status:
            self.set_status(
                self.tr('Location updated.')
            )
        else:
            self.set_status(
                Utilities.extract_error_detail(result)
            )
예제 #10
0
    def layer_will_be_removed(self, layer_id):
        """Function that triggered when layer will be removed.

        :param layer_id: Removed layer id.
        :type layer_id: QString
        """
        layer = QgsMapLayerRegistry.instance().mapLayer(layer_id)
        layer_names = layer.name().split('/')
        if len(layer_names) > 1 and \
                ('relationships' in layer.name() or 'parties' in layer.name()):
            try:
                organization_slug, project_slug, attribute = layer_names
                Utilities.add_tabular_layer(
                    layer,
                    organization_slug,
                    project_slug,
                    attribute
                )

                setting_value = '%s/%s' % (
                    organization_slug,
                    project_slug
                )

                setting_file = get_setting('layers_added')

                if setting_file:
                    setting_files = setting_file.split(',')
                    setting_files.remove(setting_value)
                    setting_file = ','.join(setting_files)
                    set_setting('layers_added', setting_file)
                else:
                    self.project_update_wizard.setEnabled(False)

                if not get_setting('layers_added'):
                    self.project_update_wizard.setEnabled(False)

            except ValueError:
                return
예제 #11
0
    def organization_projects_spatial_call_finished(self, result):
        """Function when Organization Project Spatial Api finished.

        :param result: result of request
        :type result: (bool, list/dict/str)
        """
        if result[0]:
            # save result to local file
            organization_slug = result[2]
            project_slug = result[3]
            vlayers = Utilities.save_layer(result[1], organization_slug,
                                           project_slug)
            relationship_layer = self.relationships_layer(
                vlayers, organization_slug, project_slug)
            party_layer = self.parties_layer(organization_slug, project_slug)
            QCoreApplication.processEvents()
            Utilities.save_project_basic_information(
                information=self.project_upload_result,
                vlayers=vlayers,
                relationship_layer_id=relationship_layer.id(),
                party_layer_id=party_layer.id())
        else:
            pass
예제 #12
0
    def layer_added(self, layer):
        """Function that triggered when layer was added.

        :param layer: Added layer.
        :type layer: QgsVectorLayer
        """

        # Load csv file
        layer_names = layer.name().split('/')
        if len(layer_names) > 2 and \
                ('relationships' in layer.name() or 'parties' in layer.name()):
            try:
                organization_slug, project_slug, attribute = layer_names
                Utilities.load_csv_file_to_layer(
                    layer,
                    organization_slug,
                    project_slug,
                    attribute)
                self.project_update_wizard.setEnabled(True)

                setting_value = '%s/%s' % (
                    organization_slug,
                    project_slug
                )

                setting_file = get_setting('layers_added')

                if not setting_file:
                    set_setting('layers_added', setting_value)
                else:
                    if setting_value not in setting_file:
                        set_setting(
                            'layers_added',
                            setting_file + ',' + setting_value
                        )
            except ValueError:
                return
    def get_downloaded_project(self, results):
        """Get downloaded project from organization slug.

        :param results: result of request
        :type results: (bool, list/dict/str)
        """
        projects = []
        if not results[0]:
            self.throbber_loader.setVisible(False)
            return

        for organization in results[1]:
            projects.extend(
                Utilities.get_downloaded_projects(organization['slug']))
        self.get_available_projects_finished(projects)
예제 #14
0
    def check_requirement(self):
        """Checking attributes that required.

        :return: Is missed
        :rtype: bool
        """
        requirement_miss = False
        for location in self.data['locations']['features']:
            try:
                location['fields']['location_type']
            except KeyError:
                self.set_progress_bar(0)
                self.set_status(
                    Utilities.extract_error_detail(
                        tr('Location_type is not found in attribute. '
                           'Please update before uploading again.')))
                requirement_miss = True
                break
        return requirement_miss
예제 #15
0
    def get_available_projects_finished(self, result):
        """Function when Project Api finished.

        :param result: result of request
        :type result: (bool, list/dict/str)
        """
        self.throbber_loader.setVisible(False)
        self.project_combo_box.clear()
        self.public_projects_checkbox.setEnabled(True)
        if result[0]:
            projects = sorted(result[1], key=itemgetter('slug'))

            processed_downloaded_projects = []
            downloaded_projects = Utilities.get_all_downloaded_projects()

            for downloaded_project in downloaded_projects:
                project_descriptions = downloaded_project['name'].split('/')
                organization = project_descriptions[0]
                name = project_descriptions[1]
                processed_downloaded_projects.append(
                    (organization + '-' + name).encode('utf-8'))

            for index, project in enumerate(projects):

                project_slug = '{organization_slug}-{project_slug}'.format(
                    organization_slug=project['organization']['slug'].encode(
                        'utf-8'),
                    project_slug=project['slug'].encode('utf-8'))

                self.project_combo_box.addItem(project['name'], project)
                self.project_combo_box.setCurrentIndex(index)

                self.project_combo_box.model().item(index).setEnabled(
                    project_slug not in processed_downloaded_projects)

            # Set selected to first item
            self.project_combo_box.setCurrentIndex(0)

        else:
            pass
예제 #16
0
    def upload_questionnaire_project(self):
        """Upload questionnaire."""
        self.set_status(tr('Update questionnaire'))
        post_url = '/api/v1/organizations/' \
                   '%s/projects/%s/questionnaire/' % (
                       self.data['organisation']['slug'],
                       self.project_upload_result['slug']
                   )

        post_data = QByteArray()
        post_data.append(self.data['questionnaire'])

        connector = ApiConnect(get_url_instance() + post_url)
        status, result = self._call_json_put(connector, post_data)

        self.set_status(tr('Finished update questionnaire'))
        if status:
            self.set_progress_bar(self.current_progress +
                                  self.upload_increment)
        else:
            self.set_progress_bar(0)
            self.set_status(Utilities.extract_error_detail(result))
    def relationships_layer(self, vector_layers):
        """Create relationship layer.

        :param vector_layers: List of QGS vector layer in memory
        :type vector_layers: list of QgsVectorLayer

        :return: Relationship layer
        :rtype: QgsVectorLayer
        """

        organization_slug = self.project['organization']['slug']
        project_slug = self.project['slug']
        attribute = 'relationships'

        api = u'/api/v1/organizations/{organization_slug}/projects/' \
              u'{project_slug}/spatial/{spatial_unit_id}/relationships/'

        csv_path = get_csv_path(organization_slug, project_slug, attribute)

        if os.path.isfile(csv_path):
            os.remove(csv_path)

        relationship_layer = tools.create_memory_layer(
            layer_name='%s/%s/%s' %
            (organization_slug, project_slug, attribute),
            geometry=QGis.NoGeometry,
            fields=[
                QgsField('spatial_id', QVariant.String, "string"),
                QgsField('rel_id', QVariant.String, "string"),
                QgsField('rel_name', QVariant.String, "string"),
                QgsField('party_id', QVariant.String, "string"),
                QgsField('attributes', QVariant.String, "string"),
            ])

        QgsMapLayerRegistry.instance().addMapLayer(relationship_layer)

        for vector_layer in vector_layers:
            # Add relationship layer id to spatial attribute table
            spatial_id_index = vector_layer.fieldNameIndex('id')

            for index, feature in enumerate(vector_layer.getFeatures()):
                attributes = feature.attributes()
                spatial_unit_id = attributes[spatial_id_index]
                spatial_api = api.format(organization_slug=organization_slug,
                                         project_slug=project_slug,
                                         spatial_unit_id=spatial_unit_id)
                connector = ApiConnect(get_url_instance() + spatial_api)
                status, results = connector.get(paginated=True)

                if not status or len(results) == 0:
                    continue

                try:
                    for result in results:
                        relationship_layer.startEditing()
                        fet = QgsFeature()
                        questionnaire_attr = result['attributes']
                        if not questionnaire_attr:
                            questionnaire_attr = '-'
                        else:
                            questionnaire_attr = json.dumps(questionnaire_attr)
                        fet.setAttributes([
                            attributes[spatial_id_index],
                            result['id'],
                            result['tenure_type'],
                            result['party']['id'],
                            questionnaire_attr,
                        ])
                        relationship_layer.addFeature(fet, True)
                        relationship_layer.commitChanges()
                except (IndexError, KeyError):
                    continue

        self.process_attributes(relationship_layer)

        Utilities.add_tabular_layer(relationship_layer, organization_slug,
                                    project_slug, attribute)

        return relationship_layer
    def parties_layer(self):
        """Create parties layer.

        :param vector_layer: QGS vector layer in memory
        :type vector_layer: QgsVectorLayer
        """

        organization_slug = self.project['organization']['slug']
        project_slug = self.project['slug']
        attribute = 'parties'

        csv_path = get_csv_path(organization_slug, project_slug, attribute)

        if os.path.isfile(csv_path):
            os.remove(csv_path)

        api = u'/api/v1/organizations/{organization_slug}/projects/' \
              u'{project_slug}/parties/'.format(
                organization_slug=organization_slug,
                project_slug=project_slug)

        connector = ApiConnect(get_url_instance() + api)
        status, results = connector.get(paginated=True)

        if not status:
            return

        party_layer = tools.create_memory_layer(
            layer_name='%s/%s/%s' %
            (organization_slug, project_slug, attribute),
            geometry=QGis.NoGeometry,
            fields=[
                QgsField('id', QVariant.String, "string"),
                QgsField('name', QVariant.String, "string"),
                QgsField('type', QVariant.String, "string"),
                QgsField('attributes', QVariant.String, "string"),
            ])

        QgsMapLayerRegistry.instance().addMapLayer(party_layer)

        for party in results:
            party_layer.startEditing()
            feature = QgsFeature()
            questionnaire_attr = party['attributes']
            if not questionnaire_attr:
                questionnaire_attr = '-'
            else:
                questionnaire_attr = json.dumps(questionnaire_attr)
            feature.setAttributes([
                party['id'], party['name'], party['type'], questionnaire_attr
            ])
            party_layer.addFeature(feature, True)
            party_layer.commitChanges()
            QCoreApplication.processEvents()

        self.process_attributes(party_layer)

        Utilities.add_tabular_layer(party_layer, organization_slug,
                                    project_slug, attribute)

        return party_layer
예제 #19
0
    def upload_locations(self, update_questionnaire_attribute):
        """Upload project locations to cadasta.

        :param update_questionnaire_attribute: Boolean to check if it need to
         upload the attributes
        :type update_questionnaire_attribute: bool
        """
        self.set_status(tr('Uploading locations'))
        total_locations = len(self.data['locations']['features'])
        progress_left = \
            (100 - self.current_progress - self.upload_increment) \
            / total_locations

        post_url = '/api/v1/organizations/%s/projects/%s/spatial/' % (
            self.data['organisation']['slug'],
            self.project_upload_result['slug'])

        failed = 0

        try:
            questionnaire = json.loads(self.questionnaire)
        except ValueError:
            questionnaire = {}

        for location in self.data['locations']['features']:
            post_data = {
                'geometry': location['geometry'],
                'type': location['fields']['location_type']
            }

            if update_questionnaire_attribute:
                if location['properties']:
                    post_data['attributes'] = location['properties']
                for key, value in post_data['attributes'].iteritems():
                    # Set None to empty string
                    if not value:
                        post_data['attributes'][key] = u''
                if 'id' in post_data['attributes']:
                    del post_data['attributes']['id']

                for question in \
                        questionnaire['question_groups'][0]['questions']:
                    if question['name'] not in post_data['attributes']:
                        post_data['attributes'][question['name']] = u''

            connector = ApiConnect(get_url_instance() + post_url)
            post_data = Utilities.json_dumps(post_data)
            status, result = self._call_json_post(connector, post_data)

            if status:
                self.set_progress_bar(self.current_progress + progress_left)
                try:
                    result_obj = result
                    if 'properties' in result_obj:
                        location['spatial_id'] = result_obj['properties']['id']
                except ValueError as e:
                    LOGGER.exception('message')
            else:
                self.set_progress_bar(0)
                self.set_status(Utilities.extract_error_detail(result))
                failed += 1

        self.set_progress_bar(100)

        if failed == 0:
            self.set_status(tr('Finished uploading all locations'))
        else:
            self.set_status(tr('Finish with %d failed' % failed))
    def update_party_attributes(self):
        """Update party attribute for this project."""
        information = Utilities.get_basic_information_by_vector(self.layer)

        if not information:
            return

        if 'party_layer_id' not in information:
            return

        party_id = information['party_layer_id']

        party_layer = QgsMapLayerRegistry.instance().mapLayer(party_id)
        if not party_layer:
            return

        party_feats = party_layer.getFeatures()
        id_idx = 0
        name_idx = 1
        type_idx = 2

        update_api = u'/api/v1/organizations/{organization_slug}/projects/' \
                     u'{project_slug}/parties/{party_id}/'

        # Get field names
        field_names = []
        layer_prefix = self.project['organization']['slug'] + '/' + \
                       self.project['slug']

        for field_name in party_layer.pendingFields():
            if layer_prefix not in field_name.name() and \
                            'relationships_' not in field_name.name() and \
                            'parties_' not in field_name.name():
                field_names.append(field_name.name())

        # Remove unneeded fields
        field_names.remove('id')
        field_names.remove('name')
        field_names.remove('type')

        for feature in party_feats:
            attributes = feature.attributes()
            api = update_api.format(
                organization_slug=self.project['organization']['slug'],
                project_slug=self.project['slug'],
                party_id=attributes[id_idx]
            )

            # Check if there are questionnaire attributes
            questionnaire_attributes = dict()
            for field_name in field_names:
                index = party_layer.fieldNameIndex(field_name)
                if index == -1:
                    continue
                questionnaire = attributes[index]
                if questionnaire and questionnaire != '-':
                    questionnaire_attributes[field_name] = questionnaire

            self.upload_parties(
                api,
                attributes[name_idx],
                attributes[type_idx],
                questionnaire_attributes
            )