def reinit_configurations(self, request):
        """ Re-initialize configuration for resource if it has been changed.

            This method should be called if resource consumption strategy was changed.
        """
        now = timezone.now()

        # Step 1. Collect all resources with changed configuration.
        changed_resources = []
        for resource_model in CostTrackingRegister.registered_resources:
            for resource in resource_model.objects.all():
                try:
                    pe = models.PriceEstimate.objects.get(
                        scope=resource, month=now.month, year=now.year
                    )
                except models.PriceEstimate.DoesNotExist:
                    changed_resources.append(resource)
                else:
                    new_configuration = CostTrackingRegister.get_configuration(resource)
                    if new_configuration != pe.consumption_details.configuration:
                        changed_resources.append(resource)

        # Step 2. Re-init configuration and recalculate estimate for changed resources.
        for resource in changed_resources:
            models.PriceEstimate.update_resource_estimate(
                resource, CostTrackingRegister.get_configuration(resource)
            )

        message = _('Configuration was reinitialized for %(count)s resources') % {
            'count': len(changed_resources)
        }
        self.message_user(request, message)

        return redirect(reverse('admin:cost_tracking_defaultpricelistitem_changelist'))
def resource_quota_update(sender, instance, **kwargs):
    """ Update resource consumption details and price estimate if its configuration has changed """
    quota = instance
    resource = quota.scope
    try:
        new_configuration = CostTrackingRegister.get_configuration(resource)
    except ResourceNotRegisteredError:
        return
    models.PriceEstimate.update_resource_estimate(
        resource, new_configuration, raise_exception=not _is_in_celery_task())
 def handle(self, *args, **options):
     today = timezone.now()
     with transaction.atomic():
         # Delete current month price estimates
         models.PriceEstimate.objects.filter(month=today.month, year=today.year).delete()
         # Create new estimates for resources and ancestors
         for resource_model in CostTrackingRegister.registered_resources:
             for resource in resource_model.objects.all():
                 configuration = CostTrackingRegister.get_configuration(resource)
                 date = max(core_utils.month_start(today), resource.created)
                 models.PriceEstimate.create_historical(resource, configuration, date)
         # recalculate consumed estimate
         tasks.recalculate_estimate()
def resource_update(sender, instance, created=False, **kwargs):
    """ Update resource consumption details and price estimate if its configuration has changed.
        Create estimates for previous months if resource was created not in current month.
    """
    resource = instance
    try:
        new_configuration = CostTrackingRegister.get_configuration(resource)
    except ResourceNotRegisteredError:
        return
    models.PriceEstimate.update_resource_estimate(
        resource, new_configuration, raise_exception=not _is_in_celery_task())
    # Try to create historical price estimates
    if created:
        _create_historical_estimates(resource, new_configuration)