Skip to content

Commit

Permalink
Calculate free used accessory (#3621)
Browse files Browse the repository at this point in the history
* Changed manufacturer and accessory_type - to be picked from table.

* repair make flake error.

* Added condition about release accessory to users.

* code style repair

* mysql error repair

* Calculate free/used accessory

* Calculate free/used accessory

* changed migrations

* changed release accessories.

* changed release accessories.

* changed migrations.

* flake fix

Co-authored-by: Szymon Jasinski <[email protected]>
  • Loading branch information
lukaszkarykowski and szymi- authored May 19, 2021
1 parent f27e496 commit ced9b6e
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/ralph/accessories/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class AccessoryAdmin(TransitionAdminMixin, RalphAdmin):
show_transition_history = True
list_display = ['status', 'manufacturer', 'accessory_name',
'product_number', 'number_bought']
readonly_fields = ['used', 'free']
list_select_related = ['owner']
raw_id_fields = ['owner', 'region']
list_filter = ['status', 'manufacturer', 'accessory_name',
Expand All @@ -39,7 +40,7 @@ class AccessoryAdmin(TransitionAdminMixin, RalphAdmin):
'fields': ('manufacturer', 'accessory_name',
'category', 'product_number',
'region', 'warehouse', 'number_bought',
)
'used', 'free',)
}
),
(
Expand Down
77 changes: 77 additions & 0 deletions src/ralph/accessories/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,53 @@
from django.conf import settings
from django.contrib.auth import get_user_model
from django.db import models
from django.db.models import Sum
from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _
from mptt.fields import TreeForeignKey

from ralph.accounts.models import RalphUser, Regionalizable
from ralph.assets.models import Category, Manufacturer
from ralph.back_office.models import Warehouse
from ralph.lib.mixins.models import AdminAbsoluteUrlMixin, TimeStampMixin
from ralph.lib.polymorphic.models import PolymorphicQuerySet
from ralph.lib.transitions.decorators import transition_action
from ralph.lib.transitions.fields import TransitionField
from ralph.lib.transitions.models import TransitionWorkflowBaseWithPermissions

_SELECT_USED_ACCESSORY_QUERY = """
SELECT COALESCE(SUM({assignment_table}.{quantity_column}), 0)
FROM {assignment_table}
WHERE {assignment_table}.{accessory_id_column} = {accessory_table}.{id_column} # noqa
"""


class AccessoryUsedFreeManager(models.Manager):
def get_queryset(self):
id_column = Accessory.baseobject_ptr.field.column

user_quantity_field = Accessory.users.through._meta.get_field('quantity') # noqa
user_accessory_field = Accessory.users.through._meta.get_field('accessory') # noqa
user_count_query = _SELECT_USED_ACCESSORY_QUERY.format(
assignment_table=Accessory.users.through._meta.db_table,
quantity_column=user_quantity_field.db_column or user_quantity_field.column, # noqa
accessory_id_column=user_accessory_field.db_column or user_accessory_field, # noqa
accessory_table=Accessory._meta.db_table,
id_column=id_column,
)

return super().get_queryset().extra(
select={
'user_count': user_count_query,
}
)


class AccessoryUsedFreeRelatedObjectsManager(
AccessoryUsedFreeManager
):
pass


class AccessoryStatus(Choices):
_ = Choices.Choice
Expand Down Expand Up @@ -122,6 +158,47 @@ def release_accessories(cls, instances, **kwargs):
accessory_user.quantity += quantity
accessory_user.save()

polymorphic_objects = PolymorphicQuerySet.as_manager()
objects_used_free = AccessoryUsedFreeManager()
objects_used_free_with_related = AccessoryUsedFreeRelatedObjectsManager()

def __str__(self):
return "{} x {} - ({})".format(
self.number_bought,
self.accessory_name,
self.product_number,
)

@cached_property
def autocomplete_str(self):
return "{} ({} free) x {} - ({})".format(
self.number_bought,
self.free,
self.accessory_name,
self.product_number,
)

@cached_property
def used(self):
if not self.pk:
return 0
try:
return (self.user_count or 0)
except AttributeError:
users_qs = self.user.through.objects.filter(accessory=self)

def get_sum(qs):
return qs.aggregate(sum=Sum('quantity'))['sum'] or 0
return sum(map(get_sum, [users_qs]))
used._permission_field = 'number_bought'

@cached_property
def free(self):
if not self.pk:
return 0
return self.number_bought - self.used
free._permission_field = 'number_bought'


@reversion.register()
class AccessoryUser(models.Model):
Expand Down

0 comments on commit ced9b6e

Please sign in to comment.