We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Adding new dimension name to indicator should propagate to children
Adding dimension names to indicators after an import should update the child indicators and add the corresponding indicator dimension names to the children too. 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `akvo/rsr/models/result/indicator.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 
3 # Akvo RSR is covered by the GNU Affero General Public License.
4 # See more details in the license.txt file located at the root folder of the Akvo RSR module.
5 # For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.
6 
7 from akvo.codelists.models import IndicatorMeasure
8 from akvo.codelists.store.default_codelists import INDICATOR_MEASURE as IM
9 from akvo.rsr.fields import ValidXMLCharField
10 from akvo.utils import codelist_choices, codelist_value
11 
12 from django.core.exceptions import ValidationError
13 from django.db import models
14 from django.utils.translation import ugettext_lazy as _
15 from django.db.models.signals import post_save
16 from django.dispatch import receiver
17 
18 from .indicator_period import IndicatorPeriod
19 from .indicator_label import IndicatorLabel
20 from .result import Result
21 from .utils import PERCENTAGE_MEASURE, QUALITATIVE, QUANTITATIVE
22 
23 # Currently we support only Unit, Percentage measures. Qualitative is
24 # implemented as a different Indicator type, and hence we drop that from the
25 # measure list. We also drop nominal and ordinal since we don't support those.
26 INDICATOR_MEASURE = IM[:3]
27 
28 
29 class Indicator(models.Model):
30     project_relation = 'results__indicators__in'
31 
32     INDICATOR_TYPES = (
33         (QUANTITATIVE, _('Quantitative')),
34         (QUALITATIVE, _('Qualitative')),
35     )
36 
37     result = models.ForeignKey('Result', verbose_name=_(u'result'), related_name='indicators')
38     parent_indicator = models.ForeignKey(
39         'self', blank=True, null=True, default=None,
40         verbose_name=_(u'parent indicator'), related_name='child_indicators'
41     )
42     title = ValidXMLCharField(
43         _(u'indicator title'), blank=True, max_length=500,
44         help_text=_(u'Within each result indicators can be defined. Indicators should be items '
45                     u'that can be counted and evaluated as the project continues and is completed.')
46     )
47     # NOTE: type and measure should probably only be one field measure, wit the values Unit,
48     # Percentage and Qualitative. However since the project editor design splits the choice we use
49     # two fields, type and measure to simplify the interaction between front and back end.
50     type = models.PositiveSmallIntegerField(
51         _('indicator type'), choices=INDICATOR_TYPES, default=QUANTITATIVE
52     )
53     measure = ValidXMLCharField(
54         _(u'indicator measure'), blank=True, max_length=1,
55         choices=codelist_choices(INDICATOR_MEASURE),
56         help_text=_(u'Choose how the indicator will be measured (in percentage or units).')
57     )
58     ascending = models.NullBooleanField(
59         _(u'ascending'), blank=True,
60         help_text=_(u'Choose ascending if the target value of the indicator is higher than the '
61                     u'baseline value (eg. people with access to sanitation). Choose descending if '
62                     u'the target value of the indicator is lower than the baseline value '
63                     u'(eg. people with diarrhea).'))
64     description = ValidXMLCharField(
65         _(u'indicator description'), blank=True, max_length=2000,
66         help_text=_(u'You can provide further information of the indicator here.')
67     )
68     baseline_year = models.PositiveIntegerField(
69         _(u'baseline year'), blank=True, null=True,
70         help_text=_(u'The year the baseline value was taken.')
71     )
72     baseline_value = ValidXMLCharField(
73         _(u'baseline value'), blank=True, max_length=200,
74         help_text=_(u'The value of the baseline at the start of the project.')
75     )
76     baseline_comment = ValidXMLCharField(
77         _(u'baseline comment'), blank=True, max_length=2000,
78         help_text=_(u'Here you can provide extra information on the baseline value, if needed.')
79     )
80     order = models.PositiveSmallIntegerField(_(u'indicator order'), null=True, blank=True)
81     default_periods = models.NullBooleanField(
82         _(u'default indicator periods'), default=False, blank=True,
83         help_text=_(u'Determines whether periods of indicator are used by default.')
84     )
85     export_to_iati = models.BooleanField(
86         _(u'Include indicator in IATI exports'), default=True,
87         help_text=_(u'Choose whether this indicator will be included in IATI exports. '
88                     u'If you are not exporting to IATI, you may ignore this option.')
89     )
90     dimension_names = models.ManyToManyField('IndicatorDimensionName', related_name=u'indicators')
91 
92     def __unicode__(self):
93         indicator_unicode = self.title if self.title else u'%s' % _(u'No indicator title')
94 
95         if self.periods.all():
96             indicator_unicode += u' - %s %s' % (unicode(self.periods.count()),
97                                                 _(u'period(s)'))
98 
99         indicator_unicode += u' - %s' % dict(self.INDICATOR_TYPES)[self.type]
100 
101         return indicator_unicode
102 
103     def save(self, *args, **kwargs):
104         """Update the values of child indicators, if a parent indicator is updated."""
105 
106         new_indicator = not self.pk
107 
108         if new_indicator and Indicator.objects.filter(result_id=self.result.id).exists():
109             prev_indicator = Indicator.objects.filter(result_id=self.result.id).reverse()[0]
110             if prev_indicator.order:
111                 self.order = prev_indicator.order + 1
112 
113         # HACK: Delete IndicatorLabels on non-qualitative indicators
114         if new_indicator and self.type != QUALITATIVE:
115             IndicatorLabel.objects.filter(indicator=self).delete()
116 
117         super(Indicator, self).save(*args, **kwargs)
118 
119         for child_result in self.result.child_results.all():
120             if new_indicator:
121                 child_result.project.copy_indicator(child_result, self, set_parent=True)
122             else:
123                 child_result.project.update_indicator(child_result, self)
124 
125     def clean(self):
126         validation_errors = {}
127 
128         if self.pk and self.is_child_indicator():
129             orig_indicator = Indicator.objects.get(pk=self.pk)
130 
131             # Don't allow some values to be changed when it is a child indicator
132             if self.result != orig_indicator.result:
133                 validation_errors['result'] = u'%s' % \
134                     _(u'It is not possible to update the result of this indicator, '
135                       u'because it is linked to a parent result.')
136             if self.title != orig_indicator.title:
137                 validation_errors['title'] = u'%s' % \
138                     _(u'It is not possible to update the title of this indicator, '
139                       u'because it is linked to a parent result.')
140             if self.measure != orig_indicator.measure:
141                 validation_errors['measure'] = u'%s' % \
142                     _(u'It is not possible to update the measure of this indicator, '
143                       u'because it is linked to a parent result.')
144             if self.ascending != orig_indicator.ascending:
145                 validation_errors['ascending'] = u'%s' % \
146                     _(u'It is not possible to update the ascending value of this indicator, '
147                       u'because it is linked to a parent result.')
148 
149         if validation_errors:
150             raise ValidationError(validation_errors)
151 
152     def delete(self, *args, **kwargs):
153         """
154         Check if indicator is ordered manually, and cascade following indicators if needed
155         """
156         if self.order:
157             sibling_indicators = Indicator.objects.filter(result_id=self.result.id)
158 
159             if not self == sibling_indicators.reverse()[0]:
160                 for ind in range(self.order + 1, len(sibling_indicators)):
161                     sibling_indicators[ind].order -= 1
162                     sibling_indicators[ind].save()
163 
164         super(Indicator, self).delete(*args, **kwargs)
165 
166     def iati_measure(self):
167         return codelist_value(IndicatorMeasure, self, 'measure')
168 
169     def iati_measure_unicode(self):
170         return str(self.iati_measure())
171 
172     def is_calculated(self):
173         return self.result.project.is_impact_project
174 
175     def is_child_indicator(self):
176         """
177         Indicates whether this indicator is linked to a parent indicator.
178         """
179         return bool(self.parent_indicator)
180 
181     def is_parent_indicator(self):
182         """
183         Indicates whether this indicator has children.
184         """
185         return self.child_indicators.count() > 0
186 
187     @property
188     def children_aggregate_percentage(self):
189         """
190         Returns True if this indicator has percentage as a measure and has children that aggregate
191         to this indicator.
192         """
193         if self.measure == PERCENTAGE_MEASURE and self.is_parent_indicator() and \
194                 self.result.project.aggregate_children and \
195                 any(self.child_indicators.values_list('result__project__aggregate_to_parent', flat=True)):
196             return True
197         return False
198 
199     class Meta:
200         app_label = 'rsr'
201         ordering = ['order', 'id']
202         verbose_name = _(u'indicator')
203         verbose_name_plural = _(u'indicators')
204         unique_together = ('result', 'parent_indicator')
205 
206 
207 # Add default indicator periods if necessary
208 @receiver(post_save, sender=Indicator, dispatch_uid='add_default_periods')
209 def add_default_periods(sender, instance, created, **kwargs):
210     if created:
211         project = instance.result.project
212         results = Result.objects.filter(project_id=project)
213         default_indicator = Indicator.objects.filter(result_id__in=results,
214                                                      default_periods=True).first()
215 
216         if default_indicator:
217             default_periods = IndicatorPeriod.objects.filter(indicator_id=default_indicator)
218 
219             for period in default_periods:
220                 period.pk = None
221 
222                 # Blank all values except id and locked status
223                 period.target_value = ''
224                 period.target_comment = ''
225                 period.actual_value = ''
226                 period.actual_comment = ''
227 
228                 period.indicator_id = instance.id
229                 period.save()
230
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/akvo/rsr/models/result/indicator.py b/akvo/rsr/models/result/indicator.py
--- a/akvo/rsr/models/result/indicator.py
+++ b/akvo/rsr/models/result/indicator.py
@@ -12,7 +12,7 @@
 from django.core.exceptions import ValidationError
 from django.db import models
 from django.utils.translation import ugettext_lazy as _
-from django.db.models.signals import post_save
+from django.db.models.signals import post_save, m2m_changed
 from django.dispatch import receiver
 
 from .indicator_period import IndicatorPeriod
@@ -227,3 +227,25 @@
 
                 period.indicator_id = instance.id
                 period.save()
+
+
+@receiver(m2m_changed, sender=Indicator.dimension_names.through)
+def add_dimension_names_to_children(sender, instance, action, **kwargs):
+    if not action.startswith('post_'):
+        return
+
+    if not instance.child_indicators.exists():
+        return
+
+    dimension_name = kwargs['model'].objects.filter(id__in=kwargs['pk_set']).first()
+    for indicator in instance.child_indicators.all():
+        child_dimension_name, _ = dimension_name.child_dimension_names.get_or_create(
+            name=dimension_name.name,
+            parent_dimension_name=dimension_name,
+            project=indicator.result.project)
+
+        if action == 'post_add':
+            indicator.dimension_names.add(child_dimension_name)
+
+        elif action == 'post_remove':
+            indicator.dimension_names.remove(child_dimension_name)

{"golden_diff": "diff --git a/akvo/rsr/models/result/indicator.py b/akvo/rsr/models/result/indicator.py\n--- a/akvo/rsr/models/result/indicator.py\n+++ b/akvo/rsr/models/result/indicator.py\n@@ -12,7 +12,7 @@\n from django.core.exceptions import ValidationError\n from django.db import models\n from django.utils.translation import ugettext_lazy as _\n-from django.db.models.signals import post_save\n+from django.db.models.signals import post_save, m2m_changed\n from django.dispatch import receiver\n \n from .indicator_period import IndicatorPeriod\n@@ -227,3 +227,25 @@\n \n                 period.indicator_id = instance.id\n                 period.save()\n+\n+\n+@receiver(m2m_changed, sender=Indicator.dimension_names.through)\n+def add_dimension_names_to_children(sender, instance, action, **kwargs):\n+    if not action.startswith('post_'):\n+        return\n+\n+    if not instance.child_indicators.exists():\n+        return\n+\n+    dimension_name = kwargs['model'].objects.filter(id__in=kwargs['pk_set']).first()\n+    for indicator in instance.child_indicators.all():\n+        child_dimension_name, _ = dimension_name.child_dimension_names.get_or_create(\n+            name=dimension_name.name,\n+            parent_dimension_name=dimension_name,\n+            project=indicator.result.project)\n+\n+        if action == 'post_add':\n+            indicator.dimension_names.add(child_dimension_name)\n+\n+        elif action == 'post_remove':\n+            indicator.dimension_names.remove(child_dimension_name)\n", "issue": "Adding new dimension name to indicator should propagate to children\nAdding dimension names to indicators after an import should update the child indicators and add the corresponding indicator dimension names to the children too. \n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n\n# Akvo RSR is covered by the GNU Affero General Public License.\n# See more details in the license.txt file located at the root folder of the Akvo RSR module.\n# For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.\n\nfrom akvo.codelists.models import IndicatorMeasure\nfrom akvo.codelists.store.default_codelists import INDICATOR_MEASURE as IM\nfrom akvo.rsr.fields import ValidXMLCharField\nfrom akvo.utils import codelist_choices, codelist_value\n\nfrom django.core.exceptions import ValidationError\nfrom django.db import models\nfrom django.utils.translation import ugettext_lazy as _\nfrom django.db.models.signals import post_save\nfrom django.dispatch import receiver\n\nfrom .indicator_period import IndicatorPeriod\nfrom .indicator_label import IndicatorLabel\nfrom .result import Result\nfrom .utils import PERCENTAGE_MEASURE, QUALITATIVE, QUANTITATIVE\n\n# Currently we support only Unit, Percentage measures. Qualitative is\n# implemented as a different Indicator type, and hence we drop that from the\n# measure list. We also drop nominal and ordinal since we don't support those.\nINDICATOR_MEASURE = IM[:3]\n\n\nclass Indicator(models.Model):\n    project_relation = 'results__indicators__in'\n\n    INDICATOR_TYPES = (\n        (QUANTITATIVE, _('Quantitative')),\n        (QUALITATIVE, _('Qualitative')),\n    )\n\n    result = models.ForeignKey('Result', verbose_name=_(u'result'), related_name='indicators')\n    parent_indicator = models.ForeignKey(\n        'self', blank=True, null=True, default=None,\n        verbose_name=_(u'parent indicator'), related_name='child_indicators'\n    )\n    title = ValidXMLCharField(\n        _(u'indicator title'), blank=True, max_length=500,\n        help_text=_(u'Within each result indicators can be defined. Indicators should be items '\n                    u'that can be counted and evaluated as the project continues and is completed.')\n    )\n    # NOTE: type and measure should probably only be one field measure, wit the values Unit,\n    # Percentage and Qualitative. However since the project editor design splits the choice we use\n    # two fields, type and measure to simplify the interaction between front and back end.\n    type = models.PositiveSmallIntegerField(\n        _('indicator type'), choices=INDICATOR_TYPES, default=QUANTITATIVE\n    )\n    measure = ValidXMLCharField(\n        _(u'indicator measure'), blank=True, max_length=1,\n        choices=codelist_choices(INDICATOR_MEASURE),\n        help_text=_(u'Choose how the indicator will be measured (in percentage or units).')\n    )\n    ascending = models.NullBooleanField(\n        _(u'ascending'), blank=True,\n        help_text=_(u'Choose ascending if the target value of the indicator is higher than the '\n                    u'baseline value (eg. people with access to sanitation). Choose descending if '\n                    u'the target value of the indicator is lower than the baseline value '\n                    u'(eg. people with diarrhea).'))\n    description = ValidXMLCharField(\n        _(u'indicator description'), blank=True, max_length=2000,\n        help_text=_(u'You can provide further information of the indicator here.')\n    )\n    baseline_year = models.PositiveIntegerField(\n        _(u'baseline year'), blank=True, null=True,\n        help_text=_(u'The year the baseline value was taken.')\n    )\n    baseline_value = ValidXMLCharField(\n        _(u'baseline value'), blank=True, max_length=200,\n        help_text=_(u'The value of the baseline at the start of the project.')\n    )\n    baseline_comment = ValidXMLCharField(\n        _(u'baseline comment'), blank=True, max_length=2000,\n        help_text=_(u'Here you can provide extra information on the baseline value, if needed.')\n    )\n    order = models.PositiveSmallIntegerField(_(u'indicator order'), null=True, blank=True)\n    default_periods = models.NullBooleanField(\n        _(u'default indicator periods'), default=False, blank=True,\n        help_text=_(u'Determines whether periods of indicator are used by default.')\n    )\n    export_to_iati = models.BooleanField(\n        _(u'Include indicator in IATI exports'), default=True,\n        help_text=_(u'Choose whether this indicator will be included in IATI exports. '\n                    u'If you are not exporting to IATI, you may ignore this option.')\n    )\n    dimension_names = models.ManyToManyField('IndicatorDimensionName', related_name=u'indicators')\n\n    def __unicode__(self):\n        indicator_unicode = self.title if self.title else u'%s' % _(u'No indicator title')\n\n        if self.periods.all():\n            indicator_unicode += u' - %s %s' % (unicode(self.periods.count()),\n                                                _(u'period(s)'))\n\n        indicator_unicode += u' - %s' % dict(self.INDICATOR_TYPES)[self.type]\n\n        return indicator_unicode\n\n    def save(self, *args, **kwargs):\n        \"\"\"Update the values of child indicators, if a parent indicator is updated.\"\"\"\n\n        new_indicator = not self.pk\n\n        if new_indicator and Indicator.objects.filter(result_id=self.result.id).exists():\n            prev_indicator = Indicator.objects.filter(result_id=self.result.id).reverse()[0]\n            if prev_indicator.order:\n                self.order = prev_indicator.order + 1\n\n        # HACK: Delete IndicatorLabels on non-qualitative indicators\n        if new_indicator and self.type != QUALITATIVE:\n            IndicatorLabel.objects.filter(indicator=self).delete()\n\n        super(Indicator, self).save(*args, **kwargs)\n\n        for child_result in self.result.child_results.all():\n            if new_indicator:\n                child_result.project.copy_indicator(child_result, self, set_parent=True)\n            else:\n                child_result.project.update_indicator(child_result, self)\n\n    def clean(self):\n        validation_errors = {}\n\n        if self.pk and self.is_child_indicator():\n            orig_indicator = Indicator.objects.get(pk=self.pk)\n\n            # Don't allow some values to be changed when it is a child indicator\n            if self.result != orig_indicator.result:\n                validation_errors['result'] = u'%s' % \\\n                    _(u'It is not possible to update the result of this indicator, '\n                      u'because it is linked to a parent result.')\n            if self.title != orig_indicator.title:\n                validation_errors['title'] = u'%s' % \\\n                    _(u'It is not possible to update the title of this indicator, '\n                      u'because it is linked to a parent result.')\n            if self.measure != orig_indicator.measure:\n                validation_errors['measure'] = u'%s' % \\\n                    _(u'It is not possible to update the measure of this indicator, '\n                      u'because it is linked to a parent result.')\n            if self.ascending != orig_indicator.ascending:\n                validation_errors['ascending'] = u'%s' % \\\n                    _(u'It is not possible to update the ascending value of this indicator, '\n                      u'because it is linked to a parent result.')\n\n        if validation_errors:\n            raise ValidationError(validation_errors)\n\n    def delete(self, *args, **kwargs):\n        \"\"\"\n        Check if indicator is ordered manually, and cascade following indicators if needed\n        \"\"\"\n        if self.order:\n            sibling_indicators = Indicator.objects.filter(result_id=self.result.id)\n\n            if not self == sibling_indicators.reverse()[0]:\n                for ind in range(self.order + 1, len(sibling_indicators)):\n                    sibling_indicators[ind].order -= 1\n                    sibling_indicators[ind].save()\n\n        super(Indicator, self).delete(*args, **kwargs)\n\n    def iati_measure(self):\n        return codelist_value(IndicatorMeasure, self, 'measure')\n\n    def iati_measure_unicode(self):\n        return str(self.iati_measure())\n\n    def is_calculated(self):\n        return self.result.project.is_impact_project\n\n    def is_child_indicator(self):\n        \"\"\"\n        Indicates whether this indicator is linked to a parent indicator.\n        \"\"\"\n        return bool(self.parent_indicator)\n\n    def is_parent_indicator(self):\n        \"\"\"\n        Indicates whether this indicator has children.\n        \"\"\"\n        return self.child_indicators.count() > 0\n\n    @property\n    def children_aggregate_percentage(self):\n        \"\"\"\n        Returns True if this indicator has percentage as a measure and has children that aggregate\n        to this indicator.\n        \"\"\"\n        if self.measure == PERCENTAGE_MEASURE and self.is_parent_indicator() and \\\n                self.result.project.aggregate_children and \\\n                any(self.child_indicators.values_list('result__project__aggregate_to_parent', flat=True)):\n            return True\n        return False\n\n    class Meta:\n        app_label = 'rsr'\n        ordering = ['order', 'id']\n        verbose_name = _(u'indicator')\n        verbose_name_plural = _(u'indicators')\n        unique_together = ('result', 'parent_indicator')\n\n\n# Add default indicator periods if necessary\n@receiver(post_save, sender=Indicator, dispatch_uid='add_default_periods')\ndef add_default_periods(sender, instance, created, **kwargs):\n    if created:\n        project = instance.result.project\n        results = Result.objects.filter(project_id=project)\n        default_indicator = Indicator.objects.filter(result_id__in=results,\n                                                     default_periods=True).first()\n\n        if default_indicator:\n            default_periods = IndicatorPeriod.objects.filter(indicator_id=default_indicator)\n\n            for period in default_periods:\n                period.pk = None\n\n                # Blank all values except id and locked status\n                period.target_value = ''\n                period.target_comment = ''\n                period.actual_value = ''\n                period.actual_comment = ''\n\n                period.indicator_id = instance.id\n                period.save()\n", "path": "akvo/rsr/models/result/indicator.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n\n# Akvo RSR is covered by the GNU Affero General Public License.\n# See more details in the license.txt file located at the root folder of the Akvo RSR module.\n# For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.\n\nfrom akvo.codelists.models import IndicatorMeasure\nfrom akvo.codelists.store.default_codelists import INDICATOR_MEASURE as IM\nfrom akvo.rsr.fields import ValidXMLCharField\nfrom akvo.utils import codelist_choices, codelist_value\n\nfrom django.core.exceptions import ValidationError\nfrom django.db import models\nfrom django.utils.translation import ugettext_lazy as _\nfrom django.db.models.signals import post_save, m2m_changed\nfrom django.dispatch import receiver\n\nfrom .indicator_period import IndicatorPeriod\nfrom .indicator_label import IndicatorLabel\nfrom .result import Result\nfrom .utils import PERCENTAGE_MEASURE, QUALITATIVE, QUANTITATIVE\n\n# Currently we support only Unit, Percentage measures. Qualitative is\n# implemented as a different Indicator type, and hence we drop that from the\n# measure list. We also drop nominal and ordinal since we don't support those.\nINDICATOR_MEASURE = IM[:3]\n\n\nclass Indicator(models.Model):\n    project_relation = 'results__indicators__in'\n\n    INDICATOR_TYPES = (\n        (QUANTITATIVE, _('Quantitative')),\n        (QUALITATIVE, _('Qualitative')),\n    )\n\n    result = models.ForeignKey('Result', verbose_name=_(u'result'), related_name='indicators')\n    parent_indicator = models.ForeignKey(\n        'self', blank=True, null=True, default=None,\n        verbose_name=_(u'parent indicator'), related_name='child_indicators'\n    )\n    title = ValidXMLCharField(\n        _(u'indicator title'), blank=True, max_length=500,\n        help_text=_(u'Within each result indicators can be defined. Indicators should be items '\n                    u'that can be counted and evaluated as the project continues and is completed.')\n    )\n    # NOTE: type and measure should probably only be one field measure, wit the values Unit,\n    # Percentage and Qualitative. However since the project editor design splits the choice we use\n    # two fields, type and measure to simplify the interaction between front and back end.\n    type = models.PositiveSmallIntegerField(\n        _('indicator type'), choices=INDICATOR_TYPES, default=QUANTITATIVE\n    )\n    measure = ValidXMLCharField(\n        _(u'indicator measure'), blank=True, max_length=1,\n        choices=codelist_choices(INDICATOR_MEASURE),\n        help_text=_(u'Choose how the indicator will be measured (in percentage or units).')\n    )\n    ascending = models.NullBooleanField(\n        _(u'ascending'), blank=True,\n        help_text=_(u'Choose ascending if the target value of the indicator is higher than the '\n                    u'baseline value (eg. people with access to sanitation). Choose descending if '\n                    u'the target value of the indicator is lower than the baseline value '\n                    u'(eg. people with diarrhea).'))\n    description = ValidXMLCharField(\n        _(u'indicator description'), blank=True, max_length=2000,\n        help_text=_(u'You can provide further information of the indicator here.')\n    )\n    baseline_year = models.PositiveIntegerField(\n        _(u'baseline year'), blank=True, null=True,\n        help_text=_(u'The year the baseline value was taken.')\n    )\n    baseline_value = ValidXMLCharField(\n        _(u'baseline value'), blank=True, max_length=200,\n        help_text=_(u'The value of the baseline at the start of the project.')\n    )\n    baseline_comment = ValidXMLCharField(\n        _(u'baseline comment'), blank=True, max_length=2000,\n        help_text=_(u'Here you can provide extra information on the baseline value, if needed.')\n    )\n    order = models.PositiveSmallIntegerField(_(u'indicator order'), null=True, blank=True)\n    default_periods = models.NullBooleanField(\n        _(u'default indicator periods'), default=False, blank=True,\n        help_text=_(u'Determines whether periods of indicator are used by default.')\n    )\n    export_to_iati = models.BooleanField(\n        _(u'Include indicator in IATI exports'), default=True,\n        help_text=_(u'Choose whether this indicator will be included in IATI exports. '\n                    u'If you are not exporting to IATI, you may ignore this option.')\n    )\n    dimension_names = models.ManyToManyField('IndicatorDimensionName', related_name=u'indicators')\n\n    def __unicode__(self):\n        indicator_unicode = self.title if self.title else u'%s' % _(u'No indicator title')\n\n        if self.periods.all():\n            indicator_unicode += u' - %s %s' % (unicode(self.periods.count()),\n                                                _(u'period(s)'))\n\n        indicator_unicode += u' - %s' % dict(self.INDICATOR_TYPES)[self.type]\n\n        return indicator_unicode\n\n    def save(self, *args, **kwargs):\n        \"\"\"Update the values of child indicators, if a parent indicator is updated.\"\"\"\n\n        new_indicator = not self.pk\n\n        if new_indicator and Indicator.objects.filter(result_id=self.result.id).exists():\n            prev_indicator = Indicator.objects.filter(result_id=self.result.id).reverse()[0]\n            if prev_indicator.order:\n                self.order = prev_indicator.order + 1\n\n        # HACK: Delete IndicatorLabels on non-qualitative indicators\n        if new_indicator and self.type != QUALITATIVE:\n            IndicatorLabel.objects.filter(indicator=self).delete()\n\n        super(Indicator, self).save(*args, **kwargs)\n\n        for child_result in self.result.child_results.all():\n            if new_indicator:\n                child_result.project.copy_indicator(child_result, self, set_parent=True)\n            else:\n                child_result.project.update_indicator(child_result, self)\n\n    def clean(self):\n        validation_errors = {}\n\n        if self.pk and self.is_child_indicator():\n            orig_indicator = Indicator.objects.get(pk=self.pk)\n\n            # Don't allow some values to be changed when it is a child indicator\n            if self.result != orig_indicator.result:\n                validation_errors['result'] = u'%s' % \\\n                    _(u'It is not possible to update the result of this indicator, '\n                      u'because it is linked to a parent result.')\n            if self.title != orig_indicator.title:\n                validation_errors['title'] = u'%s' % \\\n                    _(u'It is not possible to update the title of this indicator, '\n                      u'because it is linked to a parent result.')\n            if self.measure != orig_indicator.measure:\n                validation_errors['measure'] = u'%s' % \\\n                    _(u'It is not possible to update the measure of this indicator, '\n                      u'because it is linked to a parent result.')\n            if self.ascending != orig_indicator.ascending:\n                validation_errors['ascending'] = u'%s' % \\\n                    _(u'It is not possible to update the ascending value of this indicator, '\n                      u'because it is linked to a parent result.')\n\n        if validation_errors:\n            raise ValidationError(validation_errors)\n\n    def delete(self, *args, **kwargs):\n        \"\"\"\n        Check if indicator is ordered manually, and cascade following indicators if needed\n        \"\"\"\n        if self.order:\n            sibling_indicators = Indicator.objects.filter(result_id=self.result.id)\n\n            if not self == sibling_indicators.reverse()[0]:\n                for ind in range(self.order + 1, len(sibling_indicators)):\n                    sibling_indicators[ind].order -= 1\n                    sibling_indicators[ind].save()\n\n        super(Indicator, self).delete(*args, **kwargs)\n\n    def iati_measure(self):\n        return codelist_value(IndicatorMeasure, self, 'measure')\n\n    def iati_measure_unicode(self):\n        return str(self.iati_measure())\n\n    def is_calculated(self):\n        return self.result.project.is_impact_project\n\n    def is_child_indicator(self):\n        \"\"\"\n        Indicates whether this indicator is linked to a parent indicator.\n        \"\"\"\n        return bool(self.parent_indicator)\n\n    def is_parent_indicator(self):\n        \"\"\"\n        Indicates whether this indicator has children.\n        \"\"\"\n        return self.child_indicators.count() > 0\n\n    @property\n    def children_aggregate_percentage(self):\n        \"\"\"\n        Returns True if this indicator has percentage as a measure and has children that aggregate\n        to this indicator.\n        \"\"\"\n        if self.measure == PERCENTAGE_MEASURE and self.is_parent_indicator() and \\\n                self.result.project.aggregate_children and \\\n                any(self.child_indicators.values_list('result__project__aggregate_to_parent', flat=True)):\n            return True\n        return False\n\n    class Meta:\n        app_label = 'rsr'\n        ordering = ['order', 'id']\n        verbose_name = _(u'indicator')\n        verbose_name_plural = _(u'indicators')\n        unique_together = ('result', 'parent_indicator')\n\n\n# Add default indicator periods if necessary\n@receiver(post_save, sender=Indicator, dispatch_uid='add_default_periods')\ndef add_default_periods(sender, instance, created, **kwargs):\n    if created:\n        project = instance.result.project\n        results = Result.objects.filter(project_id=project)\n        default_indicator = Indicator.objects.filter(result_id__in=results,\n                                                     default_periods=True).first()\n\n        if default_indicator:\n            default_periods = IndicatorPeriod.objects.filter(indicator_id=default_indicator)\n\n            for period in default_periods:\n                period.pk = None\n\n                # Blank all values except id and locked status\n                period.target_value = ''\n                period.target_comment = ''\n                period.actual_value = ''\n                period.actual_comment = ''\n\n                period.indicator_id = instance.id\n                period.save()\n\n\n@receiver(m2m_changed, sender=Indicator.dimension_names.through)\ndef add_dimension_names_to_children(sender, instance, action, **kwargs):\n    if not action.startswith('post_'):\n        return\n\n    if not instance.child_indicators.exists():\n        return\n\n    dimension_name = kwargs['model'].objects.filter(id__in=kwargs['pk_set']).first()\n    for indicator in instance.child_indicators.all():\n        child_dimension_name, _ = dimension_name.child_dimension_names.get_or_create(\n            name=dimension_name.name,\n            parent_dimension_name=dimension_name,\n            project=indicator.result.project)\n\n        if action == 'post_add':\n            indicator.dimension_names.add(child_dimension_name)\n\n        elif action == 'post_remove':\n            indicator.dimension_names.remove(child_dimension_name)\n", "path": "akvo/rsr/models/result/indicator.py"}]}