[FR] Add last updated column for supplier parts (#4214)

* Move to updated Meta mixin

* [FR] Add last updated column for supplier parts
Fixes #3327

* add updated to table

* bump API version

* add missing migration

* incremetn api ;-)
This commit is contained in:
Matthias Mair 2023-01-25 02:18:52 +01:00 committed by GitHub
parent af0bc90e48
commit 0e0d961205
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 139 additions and 21 deletions

View File

@ -2,10 +2,13 @@
# InvenTree API version
INVENTREE_API_VERSION = 88
INVENTREE_API_VERSION = 89
"""
Increment this API version number whenever there is a significant change to the API that any clients need to know about
v89 -> 2023-01-25 : https://github.com/inventree/InvenTree/pull/4214
- Adds updated field to SupplierPart API
- Adds API date orddering for supplier part list
v88 -> 2023-01-17: https://github.com/inventree/InvenTree/pull/4225
- Adds 'priority' field to Build model and api endpoints
v87 -> 2023-01-04 : https://github.com/inventree/InvenTree/pull/4067

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.16 on 2023-01-15 14:04
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('common', '0015_newsfeedentry'),
]
operations = [
migrations.AlterField(
model_name='notificationentry',
name='updated',
field=models.DateTimeField(auto_now=True, help_text='Timestamp of last update', null=True, verbose_name='Updated'),
),
]

View File

@ -49,6 +49,25 @@ import order.validators
logger = logging.getLogger('inventree')
class MetaMixin(models.Model):
"""A base class for InvenTree models to include shared meta fields.
Attributes:
- updated: The last time this object was updated
"""
class Meta:
"""Meta options for MetaMixin."""
abstract = True
updated = models.DateTimeField(
verbose_name=_('Updated'),
help_text=_('Timestamp of last update'),
auto_now=True,
null=True,
)
class EmptyURLValidator(URLValidator):
"""Validator for filed with url - that can be empty."""
@ -1875,7 +1894,7 @@ class InvenTreeUserSetting(BaseInvenTreeSetting):
}
class PriceBreak(models.Model):
class PriceBreak(MetaMixin):
"""Represents a PriceBreak model."""
class Meta:
@ -2246,7 +2265,7 @@ class WebhookMessage(models.Model):
)
class NotificationEntry(models.Model):
class NotificationEntry(MetaMixin):
"""A NotificationEntry records the last time a particular notifaction was sent out.
It is recorded to ensure that notifications are not sent out "too often" to users.
@ -2272,11 +2291,6 @@ class NotificationEntry(models.Model):
uid = models.IntegerField(
)
updated = models.DateTimeField(
auto_now=True,
null=False,
)
@classmethod
def check_recent(cls, key: str, uid: int, delta: timedelta):
"""Test if a particular notification has been sent in the specified time period."""

View File

@ -364,6 +364,7 @@ class SupplierPartList(ListCreateDestroyAPIView):
'packaging',
'pack_size',
'in_stock',
'updated',
]
ordering_field_aliases = {

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.16 on 2023-01-15 14:04
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('company', '0051_alter_supplierpricebreak_price'),
]
operations = [
migrations.AlterField(
model_name='supplierpricebreak',
name='updated',
field=models.DateTimeField(auto_now=True, help_text='Timestamp of last update', null=True, verbose_name='Updated'),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.16 on 2023-01-17 20:13
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('company', '0052_alter_supplierpricebreak_updated'),
]
operations = [
migrations.AddField(
model_name='supplierpart',
name='updated',
field=models.DateTimeField(auto_now=True, help_text='Timestamp of last update', null=True, verbose_name='Updated'),
),
]

View File

@ -396,7 +396,7 @@ class SupplierPartManager(models.Manager):
)
class SupplierPart(InvenTreeBarcodeMixin, models.Model):
class SupplierPart(InvenTreeBarcodeMixin, common.models.MetaMixin):
"""Represents a unique part as provided by a Supplier Each SupplierPart is identified by a SKU (Supplier Part Number) Each SupplierPart is also linked to a Part or ManufacturerPart object. A Part may be available from multiple suppliers.
Attributes:
@ -412,6 +412,7 @@ class SupplierPart(InvenTreeBarcodeMixin, models.Model):
lead_time: Supplier lead time
packaging: packaging that the part is supplied in, e.g. "Reel"
pack_size: Quantity of item supplied in a single pack (e.g. 30ml in a single tube)
updated: Date that the SupplierPart was last updated
"""
objects = SupplierPartManager()
@ -683,8 +684,6 @@ class SupplierPriceBreak(common.models.PriceBreak):
part = models.ForeignKey(SupplierPart, on_delete=models.CASCADE, related_name='pricebreaks', verbose_name=_('Part'),)
updated = models.DateTimeField(auto_now=True, null=True, verbose_name=_('last updated'))
class Meta:
"""Metaclass defines extra model options"""
unique_together = ("part", "quantity")

View File

@ -282,6 +282,9 @@ class SupplierPartSerializer(InvenTreeModelSerializer):
url = serializers.CharField(source='get_absolute_url', read_only=True)
# Date fields
updated = serializers.DateTimeField(allow_null=True, read_only=True)
class Meta:
"""Metaclass options."""
@ -309,6 +312,7 @@ class SupplierPartSerializer(InvenTreeModelSerializer):
'supplier',
'supplier_detail',
'url',
'updated',
]
read_only_fields = [

View File

@ -0,0 +1,28 @@
# Generated by Django 3.2.16 on 2023-01-15 14:04
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('part', '0092_part_last_stocktake'),
]
operations = [
migrations.AddField(
model_name='partinternalpricebreak',
name='updated',
field=models.DateTimeField(auto_now=True, help_text='Timestamp of last update', null=True, verbose_name='Updated'),
),
migrations.AddField(
model_name='partsellpricebreak',
name='updated',
field=models.DateTimeField(auto_now=True, help_text='Timestamp of last update', null=True, verbose_name='Updated'),
),
migrations.AlterField(
model_name='partpricing',
name='updated',
field=models.DateTimeField(auto_now=True, help_text='Timestamp of last update', null=True, verbose_name='Updated'),
),
]

View File

@ -2275,7 +2275,7 @@ def after_save_part(sender, instance: Part, created, **kwargs):
pass
class PartPricing(models.Model):
class PartPricing(common.models.MetaMixin):
"""Model for caching min/max pricing information for a particular Part
It is prohibitively expensive to calculate min/max pricing for a part "on the fly".
@ -2785,12 +2785,6 @@ class PartPricing(models.Model):
choices=common.settings.currency_code_mappings(),
)
updated = models.DateTimeField(
verbose_name=_('Updated'),
help_text=_('Timestamp of last pricing update'),
auto_now=True
)
scheduled_for_update = models.BooleanField(
default=False,
)

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.16 on 2023-01-15 14:04
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('stock', '0091_alter_stockitem_delete_on_deplete'),
]
operations = [
migrations.AlterField(
model_name='stockitem',
name='updated',
field=models.DateTimeField(auto_now=True, help_text='Timestamp of last update', null=True, verbose_name='Updated'),
),
]

View File

@ -266,7 +266,7 @@ def default_delete_on_deplete():
return True
class StockItem(InvenTreeBarcodeMixin, MetadataMixin, MPTTModel):
class StockItem(InvenTreeBarcodeMixin, MetadataMixin, common.models.MetaMixin, MPTTModel):
"""A StockItem object represents a quantity of physical instances of a part.
Attributes:
@ -729,8 +729,6 @@ class StockItem(InvenTreeBarcodeMixin, MetadataMixin, MPTTModel):
default=1
)
updated = models.DateField(auto_now=True, null=True)
build = models.ForeignKey(
'build.Build', on_delete=models.SET_NULL,
verbose_name=_('Source Build'),

View File

@ -1043,6 +1043,11 @@ function loadSupplierPartTable(table, url, options) {
}
}
},
{
field: 'updated',
title: '{% trans "Last Updated" %}',
sortable: true,
},
{
field: 'actions',
title: '',