diff --git a/InvenTree/InvenTree/api_version.py b/InvenTree/InvenTree/api_version.py index fc42c67ccc..4971e2782e 100644 --- a/InvenTree/InvenTree/api_version.py +++ b/InvenTree/InvenTree/api_version.py @@ -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 diff --git a/InvenTree/common/migrations/0016_alter_notificationentry_updated.py b/InvenTree/common/migrations/0016_alter_notificationentry_updated.py new file mode 100644 index 0000000000..077fe4cb95 --- /dev/null +++ b/InvenTree/common/migrations/0016_alter_notificationentry_updated.py @@ -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'), + ), + ] diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index f414d4260c..52d2bc3666 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -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.""" diff --git a/InvenTree/company/api.py b/InvenTree/company/api.py index a5d376bb42..7095b2fff8 100644 --- a/InvenTree/company/api.py +++ b/InvenTree/company/api.py @@ -364,6 +364,7 @@ class SupplierPartList(ListCreateDestroyAPIView): 'packaging', 'pack_size', 'in_stock', + 'updated', ] ordering_field_aliases = { diff --git a/InvenTree/company/migrations/0052_alter_supplierpricebreak_updated.py b/InvenTree/company/migrations/0052_alter_supplierpricebreak_updated.py new file mode 100644 index 0000000000..a1689bf886 --- /dev/null +++ b/InvenTree/company/migrations/0052_alter_supplierpricebreak_updated.py @@ -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'), + ), + ] diff --git a/InvenTree/company/migrations/0053_supplierpart_updated.py b/InvenTree/company/migrations/0053_supplierpart_updated.py new file mode 100644 index 0000000000..4c150893d0 --- /dev/null +++ b/InvenTree/company/migrations/0053_supplierpart_updated.py @@ -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'), + ), + ] diff --git a/InvenTree/company/models.py b/InvenTree/company/models.py index 2693b13932..6add14d125 100644 --- a/InvenTree/company/models.py +++ b/InvenTree/company/models.py @@ -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") diff --git a/InvenTree/company/serializers.py b/InvenTree/company/serializers.py index 11e69120ad..52d4f55921 100644 --- a/InvenTree/company/serializers.py +++ b/InvenTree/company/serializers.py @@ -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 = [ diff --git a/InvenTree/part/migrations/0093_auto_20230115_1404.py b/InvenTree/part/migrations/0093_auto_20230115_1404.py new file mode 100644 index 0000000000..9fbd5aee12 --- /dev/null +++ b/InvenTree/part/migrations/0093_auto_20230115_1404.py @@ -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'), + ), + ] diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index 448f084175..21cceacaec 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -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, ) diff --git a/InvenTree/stock/migrations/0092_alter_stockitem_updated.py b/InvenTree/stock/migrations/0092_alter_stockitem_updated.py new file mode 100644 index 0000000000..9252b12f62 --- /dev/null +++ b/InvenTree/stock/migrations/0092_alter_stockitem_updated.py @@ -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'), + ), + ] diff --git a/InvenTree/stock/models.py b/InvenTree/stock/models.py index b651580a21..58c9065e49 100644 --- a/InvenTree/stock/models.py +++ b/InvenTree/stock/models.py @@ -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'), diff --git a/InvenTree/templates/js/translated/company.js b/InvenTree/templates/js/translated/company.js index ebdaf4bbe1..16b3ae9458 100644 --- a/InvenTree/templates/js/translated/company.js +++ b/InvenTree/templates/js/translated/company.js @@ -1043,6 +1043,11 @@ function loadSupplierPartTable(table, url, options) { } } }, + { + field: 'updated', + title: '{% trans "Last Updated" %}', + sortable: true, + }, { field: 'actions', title: '',