mirror of
https://github.com/inventree/InvenTree.git
synced 2026-03-04 03:11:46 +00:00
Add "updated_at" field to Orders model (#11374)
* add "updated_at" field to PurchaseOrder model * change to use abstract po instead * add api filters * add show, order and filter by po updated_at date to frontend * add tests and increment api_version * change updated_at to null by default * never trust github conflict resolution * bump docker image to python 3.14 (#11414) * chore(deps): bump the dependencies group across 1 directory with 4 updates (#11416) Bumps the dependencies group with 4 updates in the / directory: [depot/setup-action](https://github.com/depot/setup-action), [depot/build-push-action](https://github.com/depot/build-push-action), [anchore/sbom-action](https://github.com/anchore/sbom-action) and [actions/stale](https://github.com/actions/stale). Updates `depot/setup-action` from 1.6.0 to 1.7.1 - [Release notes](https://github.com/depot/setup-action/releases) - [Commits](b0b1ea4f69...15c09a5f77) Updates `depot/build-push-action` from 1.16.2 to 1.17.0 - [Release notes](https://github.com/depot/build-push-action/releases) - [Commits](9785b135c3...5f3b3c2e5a) Updates `anchore/sbom-action` from 0.21.1 to 0.22.2 - [Release notes](https://github.com/anchore/sbom-action/releases) - [Changelog](https://github.com/anchore/sbom-action/blob/main/RELEASE.md) - [Commits](0b82b0b1a2...28d71544de) Updates `actions/stale` from 10.1.1 to 10.2.0 - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](997185467f...b5d41d4e1d) --- updated-dependencies: - dependency-name: depot/setup-action dependency-version: 1.7.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies - dependency-name: depot/build-push-action dependency-version: 1.17.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies - dependency-name: anchore/sbom-action dependency-version: 0.22.2 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies - dependency-name: actions/stale dependency-version: 10.2.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [UI] Copy cells expansion (#11410) * Prevent copy button if copy value is null * Add "link" columns to order tables * Support copy for default column types * Tweak padding to avoid flickering issues * Refactor IPNColumn * Adjust visual styling * Copy for SKU and MPN columns * Add more copy columns * More tweaks * Tweak playwright testing * Further cleanup * More copy cols * Fix auto pricing overwriting manual purchase price #10846 (#11411) * Fix auto pricing overwriting manual purchase price #10846 * Added entry to api_version.py --------- Co-authored-by: Oliver <oliver.henry.walters@gmail.com> * [UI] Default locale (#11412) * [UI] Support default server language * Handle faulty theme * Add option for default language * Improve language selection * Brief docs entry * Fix typo * Fix yarn build * Remove debug msg * Fix calendar locale * feat(backend): ensure restore of backups only works in correct enviroments (#11372) * [FR] ensure restore of backups only works in correct enviroments Fixes #11214 * update PR nbr * fix wrong ty detection * fix link * ensure tracing does not enagage while running backup ops * fix import * remove debugging string * add error codes * add tests for backup and restore * complete test for restore * we do not need e2e on every matrix entry there is no realy db dep here * fix changelog format * add flag to allow bypass * update CHANGELOG.md --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Oliver <oliver.henry.walters@gmail.com> Co-authored-by: Matthias Mair <code@mjmair.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: JustusRijke <53965859+JustusRijke@users.noreply.github.com>
This commit is contained in:
@@ -1,11 +1,16 @@
|
||||
"""InvenTree API version information."""
|
||||
|
||||
# InvenTree API version
|
||||
INVENTREE_API_VERSION = 459
|
||||
INVENTREE_API_VERSION = 460
|
||||
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
|
||||
|
||||
INVENTREE_API_TEXT = """
|
||||
|
||||
v460 -> 2026-02-25 : https://github.com/inventree/InvenTree/pull/11374
|
||||
- Adds "updated_at" field to PurchaseOrder, SalesOrder and ReturnOrder API endpoints
|
||||
- Adds "updated_before" and "updated_after" date filters to all three order list endpoints
|
||||
- Adds "updated_at" ordering option to all three order list endpoints
|
||||
|
||||
v459 -> 2026-02-23 : https://github.com/inventree/InvenTree/pull/11411
|
||||
- Changed PurchaseOrderLine "auto_pricing" default value from true to false
|
||||
|
||||
|
||||
@@ -228,6 +228,14 @@ class OrderFilter(FilterSet):
|
||||
label=_('Target Date After'), field_name='target_date', lookup_expr='gt'
|
||||
)
|
||||
|
||||
updated_before = InvenTreeDateFilter(
|
||||
label=_('Updated Before'), field_name='updated_at', lookup_expr='lt'
|
||||
)
|
||||
|
||||
updated_after = InvenTreeDateFilter(
|
||||
label=_('Updated After'), field_name='updated_at', lookup_expr='gt'
|
||||
)
|
||||
|
||||
min_date = InvenTreeDateFilter(label=_('Min Date'), method='filter_min_date')
|
||||
|
||||
def filter_min_date(self, queryset, name, value):
|
||||
@@ -420,6 +428,7 @@ class PurchaseOrderList(
|
||||
'responsible',
|
||||
'total_price',
|
||||
'project_code',
|
||||
'updated_at',
|
||||
]
|
||||
|
||||
ordering = '-reference'
|
||||
@@ -882,6 +891,7 @@ class SalesOrderList(
|
||||
'shipment_date',
|
||||
'total_price',
|
||||
'project_code',
|
||||
'updated_at',
|
||||
]
|
||||
|
||||
search_fields = [
|
||||
@@ -1549,6 +1559,7 @@ class ReturnOrderList(
|
||||
'target_date',
|
||||
'complete_date',
|
||||
'project_code',
|
||||
'updated_at',
|
||||
]
|
||||
|
||||
search_fields = [
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
# Generated by Django 5.2.11 on 2026-02-19 22:31
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("order", "0114_purchaseorderextraline_project_code_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="purchaseorder",
|
||||
name="updated_at",
|
||||
field=models.DateTimeField(
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text="Timestamp of last update",
|
||||
verbose_name="Updated At",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="returnorder",
|
||||
name="updated_at",
|
||||
field=models.DateTimeField(
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text="Timestamp of last update",
|
||||
verbose_name="Updated At",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="salesorder",
|
||||
name="updated_at",
|
||||
field=models.DateTimeField(
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text="Timestamp of last update",
|
||||
verbose_name="Updated At",
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -9,7 +9,7 @@ from django.core.validators import MinValueValidator
|
||||
from django.db import models, transaction
|
||||
from django.db.models import F, Q, QuerySet, Sum
|
||||
from django.db.models.functions import Coalesce
|
||||
from django.db.models.signals import post_save
|
||||
from django.db.models.signals import post_delete, post_save
|
||||
from django.dispatch.dispatcher import receiver
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
@@ -331,6 +331,8 @@ class Order(
|
||||
if not self.creation_date:
|
||||
self.creation_date = InvenTree.helpers.current_date()
|
||||
|
||||
self.updated_at = InvenTree.helpers.current_time()
|
||||
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
def check_locked(self, db: bool = False) -> bool:
|
||||
@@ -498,6 +500,13 @@ class Order(
|
||||
help_text=_('Date order was issued'),
|
||||
)
|
||||
|
||||
updated_at = models.DateTimeField(
|
||||
null=True,
|
||||
blank=True,
|
||||
verbose_name=_('Updated At'),
|
||||
help_text=_('Timestamp of last update'),
|
||||
)
|
||||
|
||||
responsible = models.ForeignKey(
|
||||
UserModels.Owner,
|
||||
on_delete=models.SET_NULL,
|
||||
@@ -3072,3 +3081,43 @@ class ReturnOrderExtraLine(OrderExtraLine):
|
||||
verbose_name=_('Order'),
|
||||
help_text=_('Return Order'),
|
||||
)
|
||||
|
||||
|
||||
def _touch_order_updated_at(instance):
|
||||
"""Bump updated_at on the parent order without triggering a full save."""
|
||||
if not InvenTree.ready.canAppAccessDatabase(allow_test=True):
|
||||
return
|
||||
instance.order.__class__.objects.filter(pk=instance.order_id).update(
|
||||
updated_at=InvenTree.helpers.current_time()
|
||||
)
|
||||
|
||||
|
||||
@receiver(post_save, sender=PurchaseOrderLineItem, dispatch_uid='po_lineitem_post_save')
|
||||
@receiver(
|
||||
post_delete, sender=PurchaseOrderLineItem, dispatch_uid='po_lineitem_post_delete'
|
||||
)
|
||||
@receiver(
|
||||
post_save, sender=PurchaseOrderExtraLine, dispatch_uid='po_extraline_post_save'
|
||||
)
|
||||
@receiver(
|
||||
post_delete, sender=PurchaseOrderExtraLine, dispatch_uid='po_extraline_post_delete'
|
||||
)
|
||||
@receiver(post_save, sender=SalesOrderLineItem, dispatch_uid='so_lineitem_post_save')
|
||||
@receiver(
|
||||
post_delete, sender=SalesOrderLineItem, dispatch_uid='so_lineitem_post_delete'
|
||||
)
|
||||
@receiver(post_save, sender=SalesOrderExtraLine, dispatch_uid='so_extraline_post_save')
|
||||
@receiver(
|
||||
post_delete, sender=SalesOrderExtraLine, dispatch_uid='so_extraline_post_delete'
|
||||
)
|
||||
@receiver(post_save, sender=ReturnOrderLineItem, dispatch_uid='ro_lineitem_post_save')
|
||||
@receiver(
|
||||
post_delete, sender=ReturnOrderLineItem, dispatch_uid='ro_lineitem_post_delete'
|
||||
)
|
||||
@receiver(post_save, sender=ReturnOrderExtraLine, dispatch_uid='ro_extraline_post_save')
|
||||
@receiver(
|
||||
post_delete, sender=ReturnOrderExtraLine, dispatch_uid='ro_extraline_post_delete'
|
||||
)
|
||||
def update_order_on_lineitem_change(sender, instance, **kwargs):
|
||||
"""Update parent order updated_at when any line item is saved or deleted."""
|
||||
_touch_order_updated_at(instance)
|
||||
|
||||
@@ -373,8 +373,14 @@ class PurchaseOrderSerializer(
|
||||
'total_price',
|
||||
'order_currency',
|
||||
'destination',
|
||||
'updated_at',
|
||||
])
|
||||
read_only_fields = ['issue_date', 'complete_date', 'creation_date']
|
||||
read_only_fields = [
|
||||
'issue_date',
|
||||
'complete_date',
|
||||
'creation_date',
|
||||
'updated_at',
|
||||
]
|
||||
extra_kwargs = {
|
||||
'supplier': {'required': True},
|
||||
'order_currency': {'required': False},
|
||||
@@ -1026,8 +1032,9 @@ class SalesOrderSerializer(
|
||||
'shipments_count',
|
||||
'completed_shipments_count',
|
||||
'allocated_lines',
|
||||
'updated_at',
|
||||
])
|
||||
read_only_fields = ['status', 'creation_date', 'shipment_date']
|
||||
read_only_fields = ['status', 'creation_date', 'shipment_date', 'updated_at']
|
||||
extra_kwargs = {'order_currency': {'required': False}}
|
||||
|
||||
def skip_create_fields(self):
|
||||
@@ -1918,8 +1925,9 @@ class ReturnOrderSerializer(
|
||||
'customer_reference',
|
||||
'order_currency',
|
||||
'total_price',
|
||||
'updated_at',
|
||||
])
|
||||
read_only_fields = ['creation_date']
|
||||
read_only_fields = ['creation_date', 'updated_at']
|
||||
|
||||
def skip_create_fields(self):
|
||||
"""Skip these fields when instantiating a new object."""
|
||||
|
||||
@@ -25,7 +25,17 @@ from part.models import Part
|
||||
from stock.models import StockItem, StockLocation
|
||||
from users.models import Owner
|
||||
|
||||
from .models import PurchaseOrder, PurchaseOrderExtraLine, PurchaseOrderLineItem
|
||||
from .models import (
|
||||
PurchaseOrder,
|
||||
PurchaseOrderExtraLine,
|
||||
PurchaseOrderLineItem,
|
||||
ReturnOrder,
|
||||
ReturnOrderExtraLine,
|
||||
ReturnOrderLineItem,
|
||||
SalesOrder,
|
||||
SalesOrderExtraLine,
|
||||
SalesOrderLineItem,
|
||||
)
|
||||
|
||||
|
||||
class OrderTest(ExchangeRateMixin, PluginRegistryMixin, TestCase):
|
||||
@@ -369,7 +379,8 @@ class OrderTest(ExchangeRateMixin, PluginRegistryMixin, TestCase):
|
||||
order=po,
|
||||
part=sp_1,
|
||||
quantity=3,
|
||||
purchase_price=Money(1000, 'USD'), # "Unit price" should be $100USD
|
||||
# "Unit price" should be $100USD
|
||||
purchase_price=Money(1000, 'USD'),
|
||||
)
|
||||
|
||||
# 13 x 0.1 = 1.3
|
||||
@@ -569,3 +580,151 @@ class OrderTest(ExchangeRateMixin, PluginRegistryMixin, TestCase):
|
||||
p.set_metadata(k, k)
|
||||
|
||||
self.assertEqual(len(p.metadata.keys()), 4)
|
||||
|
||||
|
||||
class OrderUpdatedAtTest(TestCase):
|
||||
"""Tests to verify that the updated_at field is correctly maintained on all order types."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up objects for all three order types."""
|
||||
self.supplier = Company.objects.filter(is_supplier=True).first()
|
||||
self.customer = Company.objects.filter(is_customer=True).first()
|
||||
|
||||
self.po = PurchaseOrder.objects.create(
|
||||
reference='PO-TEST-001', supplier=self.supplier
|
||||
)
|
||||
self.so = SalesOrder.objects.create(
|
||||
reference='SO-TEST-001', customer=self.customer
|
||||
)
|
||||
self.ro = ReturnOrder.objects.create(
|
||||
reference='RO-TEST-001', customer=self.customer
|
||||
)
|
||||
|
||||
self.part = Part.objects.create(name='Test Part', description='Test Part')
|
||||
self.stock_item = StockItem.objects.create(part=self.part, quantity=10)
|
||||
|
||||
def _refresh(self, instance):
|
||||
"""Return a fresh copy of the instance from the database."""
|
||||
return instance.__class__.objects.get(pk=instance.pk)
|
||||
|
||||
def test_updated_at_set_on_save(self):
|
||||
"""updated_at should be populated after the order is saved."""
|
||||
for instance in [self.po, self.so, self.ro]:
|
||||
self.assertIsNotNone(self._refresh(instance).updated_at)
|
||||
|
||||
def test_updated_at_changes_on_save(self):
|
||||
"""updated_at should advance when the order is saved again."""
|
||||
for instance in [self.po, self.so, self.ro]:
|
||||
original = self._refresh(instance).updated_at
|
||||
|
||||
instance.description = 'Updated description'
|
||||
instance.save()
|
||||
|
||||
refreshed = self._refresh(instance)
|
||||
self.assertGreaterEqual(refreshed.updated_at, original)
|
||||
|
||||
def test_updated_at_on_extra_line_add(self):
|
||||
"""updated_at should advance on the parent order when an extra line is added."""
|
||||
for instance, ExtraLine in [
|
||||
(self.po, PurchaseOrderExtraLine),
|
||||
(self.so, SalesOrderExtraLine),
|
||||
(self.ro, ReturnOrderExtraLine),
|
||||
]:
|
||||
before = self._refresh(instance).updated_at
|
||||
|
||||
ExtraLine.objects.create(order=instance, quantity=1)
|
||||
|
||||
after = self._refresh(instance).updated_at
|
||||
self.assertGreaterEqual(after, before)
|
||||
|
||||
def test_updated_at_on_extra_line_update(self):
|
||||
"""updated_at should advance on the parent order when an extra line is updated."""
|
||||
for instance, ExtraLine in [
|
||||
(self.po, PurchaseOrderExtraLine),
|
||||
(self.so, SalesOrderExtraLine),
|
||||
(self.ro, ReturnOrderExtraLine),
|
||||
]:
|
||||
line = ExtraLine.objects.create(order=instance, quantity=1)
|
||||
|
||||
before = self._refresh(instance).updated_at
|
||||
|
||||
line.quantity = 5
|
||||
line.save()
|
||||
|
||||
after = self._refresh(instance).updated_at
|
||||
self.assertGreaterEqual(after, before)
|
||||
|
||||
def test_updated_at_on_extra_line_delete(self):
|
||||
"""updated_at should advance on the parent order when an extra line is deleted."""
|
||||
for instance, ExtraLine in [
|
||||
(self.po, PurchaseOrderExtraLine),
|
||||
(self.so, SalesOrderExtraLine),
|
||||
(self.ro, ReturnOrderExtraLine),
|
||||
]:
|
||||
line = ExtraLine.objects.create(order=instance, quantity=1)
|
||||
|
||||
before = self._refresh(instance).updated_at
|
||||
|
||||
line.delete()
|
||||
|
||||
after = self._refresh(instance).updated_at
|
||||
self.assertGreaterEqual(after, before)
|
||||
|
||||
def test_updated_at_on_line_item_add(self):
|
||||
"""updated_at should advance on the parent order when a regular line item is added."""
|
||||
before_po = self._refresh(self.po).updated_at
|
||||
PurchaseOrderLineItem.objects.create(order=self.po, part=None, quantity=1)
|
||||
self.assertGreaterEqual(self._refresh(self.po).updated_at, before_po)
|
||||
|
||||
before_so = self._refresh(self.so).updated_at
|
||||
SalesOrderLineItem.objects.create(order=self.so, part=None, quantity=1)
|
||||
self.assertGreaterEqual(self._refresh(self.so).updated_at, before_so)
|
||||
|
||||
before_ro = self._refresh(self.ro).updated_at
|
||||
ReturnOrderLineItem.objects.create(
|
||||
order=self.ro, item=self.stock_item, quantity=1
|
||||
)
|
||||
self.assertGreaterEqual(self._refresh(self.ro).updated_at, before_ro)
|
||||
|
||||
def test_updated_at_on_line_item_update(self):
|
||||
"""updated_at should advance on the parent order when a regular line item is updated."""
|
||||
po_line = PurchaseOrderLineItem.objects.create(
|
||||
order=self.po, part=None, quantity=1
|
||||
)
|
||||
so_line = SalesOrderLineItem.objects.create(
|
||||
order=self.so, part=None, quantity=1
|
||||
)
|
||||
ro_line = ReturnOrderLineItem.objects.create(
|
||||
order=self.ro, item=self.stock_item, quantity=1
|
||||
)
|
||||
|
||||
for instance, line in [
|
||||
(self.po, po_line),
|
||||
(self.so, so_line),
|
||||
(self.ro, ro_line),
|
||||
]:
|
||||
before = self._refresh(instance).updated_at
|
||||
line.quantity = 5
|
||||
line.save()
|
||||
self.assertGreaterEqual(self._refresh(instance).updated_at, before)
|
||||
|
||||
def test_updated_at_on_line_item_delete(self):
|
||||
"""updated_at should advance on the parent order when a regular line item is deleted."""
|
||||
po_line = PurchaseOrderLineItem.objects.create(
|
||||
order=self.po, part=None, quantity=1
|
||||
)
|
||||
so_line = SalesOrderLineItem.objects.create(
|
||||
order=self.so, part=None, quantity=1
|
||||
)
|
||||
ro_line = ReturnOrderLineItem.objects.create(
|
||||
order=self.ro, item=self.stock_item, quantity=1
|
||||
)
|
||||
|
||||
for instance, line in [
|
||||
(self.po, po_line),
|
||||
(self.so, so_line),
|
||||
(self.ro, ro_line),
|
||||
]:
|
||||
before = self._refresh(instance).updated_at
|
||||
line.delete()
|
||||
self.assertGreaterEqual(self._refresh(instance).updated_at, before)
|
||||
|
||||
@@ -54,10 +54,16 @@ export type DetailsField = {
|
||||
type BadgeType = 'owner' | 'user' | 'group';
|
||||
type ValueFormatterReturn = string | number | null | React.ReactNode;
|
||||
|
||||
type StringDetailField = {
|
||||
type: 'string' | 'text' | 'date';
|
||||
unit?: boolean;
|
||||
};
|
||||
type StringDetailField =
|
||||
| {
|
||||
type: 'string' | 'text';
|
||||
unit?: boolean;
|
||||
}
|
||||
| {
|
||||
type: 'date';
|
||||
unit?: boolean;
|
||||
showTime?: boolean;
|
||||
};
|
||||
|
||||
type NumberDetailField = {
|
||||
type: 'number';
|
||||
@@ -260,7 +266,13 @@ function NameBadge({
|
||||
}
|
||||
|
||||
function DateValue(props: Readonly<FieldProps>) {
|
||||
return <Text size='sm'>{formatDate(props.field_value?.toString())}</Text>;
|
||||
return (
|
||||
<Text size='sm'>
|
||||
{formatDate(props.field_value?.toString(), {
|
||||
showTime: props.field_data?.showTime
|
||||
})}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
|
||||
// Return a formatted "number" value, with optional unit
|
||||
|
||||
@@ -304,6 +304,15 @@ export default function PurchaseOrderDetail() {
|
||||
label: t`Completion Date`,
|
||||
copy: true,
|
||||
hidden: !order.complete_date
|
||||
},
|
||||
{
|
||||
type: 'date',
|
||||
name: 'updated_at',
|
||||
label: t`Last Updated`,
|
||||
icon: 'calendar',
|
||||
copy: true,
|
||||
showTime: true,
|
||||
hidden: !order.updated_at
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -282,6 +282,15 @@ export default function ReturnOrderDetail() {
|
||||
label: t`Completion Date`,
|
||||
copy: true,
|
||||
hidden: !order.complete_date
|
||||
},
|
||||
{
|
||||
type: 'date',
|
||||
name: 'updated_at',
|
||||
label: t`Last Updated`,
|
||||
icon: 'calendar',
|
||||
copy: true,
|
||||
showTime: true,
|
||||
hidden: !order.updated_at
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -273,6 +273,15 @@ export default function SalesOrderDetail() {
|
||||
label: t`Completion Date`,
|
||||
hidden: !order.shipment_date,
|
||||
copy: true
|
||||
},
|
||||
{
|
||||
type: 'date',
|
||||
name: 'updated_at',
|
||||
label: t`Last Updated`,
|
||||
icon: 'calendar',
|
||||
copy: true,
|
||||
showTime: true,
|
||||
hidden: !order.updated_at
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -725,6 +725,16 @@ export function ShipmentDateColumn(props: TableColumnProps): TableColumn {
|
||||
});
|
||||
}
|
||||
|
||||
export function UpdatedAtColumn(props: TableColumnProps): TableColumn {
|
||||
return DateColumn({
|
||||
accessor: 'updated_at',
|
||||
title: t`Updated`,
|
||||
defaultVisible: false,
|
||||
extra: { showTime: true },
|
||||
...props
|
||||
});
|
||||
}
|
||||
|
||||
export function CurrencyColumn({
|
||||
accessor,
|
||||
title,
|
||||
|
||||
@@ -286,6 +286,24 @@ export function CompletedAfterFilter(): TableFilter {
|
||||
};
|
||||
}
|
||||
|
||||
export function UpdatedAfterFilter(): TableFilter {
|
||||
return {
|
||||
name: 'updated_after',
|
||||
label: t`Updated After`,
|
||||
description: t`Show orders updated after this date`,
|
||||
type: 'date'
|
||||
};
|
||||
}
|
||||
|
||||
export function UpdatedBeforeFilter(): TableFilter {
|
||||
return {
|
||||
name: 'updated_before',
|
||||
label: t`Updated Before`,
|
||||
description: t`Show orders updated before this date`,
|
||||
type: 'date'
|
||||
};
|
||||
}
|
||||
|
||||
export function HasProjectCodeFilter(): TableFilter {
|
||||
const globalSettings = useGlobalSettingsState.getState();
|
||||
const enabled = globalSettings.isSet('PROJECT_CODES_ENABLED', true);
|
||||
|
||||
@@ -25,7 +25,8 @@ import {
|
||||
ResponsibleColumn,
|
||||
StartDateColumn,
|
||||
StatusColumn,
|
||||
TargetDateColumn
|
||||
TargetDateColumn,
|
||||
UpdatedAtColumn
|
||||
} from '../ColumnRenderers';
|
||||
import {
|
||||
AssignedToMeFilter,
|
||||
@@ -45,7 +46,9 @@ import {
|
||||
StartDateAfterFilter,
|
||||
StartDateBeforeFilter,
|
||||
TargetDateAfterFilter,
|
||||
TargetDateBeforeFilter
|
||||
TargetDateBeforeFilter,
|
||||
UpdatedAfterFilter,
|
||||
UpdatedBeforeFilter
|
||||
} from '../Filter';
|
||||
import { InvenTreeTable } from '../InvenTreeTable';
|
||||
|
||||
@@ -99,6 +102,8 @@ export function PurchaseOrderTable({
|
||||
},
|
||||
CompletedBeforeFilter(),
|
||||
CompletedAfterFilter(),
|
||||
UpdatedBeforeFilter(),
|
||||
UpdatedAfterFilter(),
|
||||
ProjectCodeFilter(),
|
||||
HasProjectCodeFilter(),
|
||||
ResponsibleFilter(),
|
||||
@@ -142,6 +147,9 @@ export function PurchaseOrderTable({
|
||||
CompletionDateColumn({
|
||||
accessor: 'complete_date'
|
||||
}),
|
||||
UpdatedAtColumn({
|
||||
defaultVisible: false
|
||||
}),
|
||||
{
|
||||
accessor: 'total_price',
|
||||
title: t`Total Price`,
|
||||
|
||||
@@ -25,7 +25,8 @@ import {
|
||||
ResponsibleColumn,
|
||||
StartDateColumn,
|
||||
StatusColumn,
|
||||
TargetDateColumn
|
||||
TargetDateColumn,
|
||||
UpdatedAtColumn
|
||||
} from '../ColumnRenderers';
|
||||
import {
|
||||
AssignedToMeFilter,
|
||||
@@ -46,7 +47,9 @@ import {
|
||||
StartDateAfterFilter,
|
||||
StartDateBeforeFilter,
|
||||
TargetDateAfterFilter,
|
||||
TargetDateBeforeFilter
|
||||
TargetDateBeforeFilter,
|
||||
UpdatedAfterFilter,
|
||||
UpdatedBeforeFilter
|
||||
} from '../Filter';
|
||||
import { InvenTreeTable } from '../InvenTreeTable';
|
||||
|
||||
@@ -99,6 +102,8 @@ export function ReturnOrderTable({
|
||||
},
|
||||
CompletedBeforeFilter(),
|
||||
CompletedAfterFilter(),
|
||||
UpdatedBeforeFilter(),
|
||||
UpdatedAfterFilter(),
|
||||
HasProjectCodeFilter(),
|
||||
ProjectCodeFilter(),
|
||||
ResponsibleFilter(),
|
||||
@@ -146,6 +151,9 @@ export function ReturnOrderTable({
|
||||
CompletionDateColumn({
|
||||
accessor: 'complete_date'
|
||||
}),
|
||||
UpdatedAtColumn({
|
||||
defaultVisible: false
|
||||
}),
|
||||
ResponsibleColumn({}),
|
||||
{
|
||||
accessor: 'total_price',
|
||||
|
||||
@@ -27,7 +27,8 @@ import {
|
||||
ShipmentDateColumn,
|
||||
StartDateColumn,
|
||||
StatusColumn,
|
||||
TargetDateColumn
|
||||
TargetDateColumn,
|
||||
UpdatedAtColumn
|
||||
} from '../ColumnRenderers';
|
||||
import {
|
||||
AssignedToMeFilter,
|
||||
@@ -48,7 +49,9 @@ import {
|
||||
StartDateAfterFilter,
|
||||
StartDateBeforeFilter,
|
||||
TargetDateAfterFilter,
|
||||
TargetDateBeforeFilter
|
||||
TargetDateBeforeFilter,
|
||||
UpdatedAfterFilter,
|
||||
UpdatedBeforeFilter
|
||||
} from '../Filter';
|
||||
import { InvenTreeTable } from '../InvenTreeTable';
|
||||
|
||||
@@ -97,6 +100,8 @@ export function SalesOrderTable({
|
||||
},
|
||||
CompletedBeforeFilter(),
|
||||
CompletedAfterFilter(),
|
||||
UpdatedBeforeFilter(),
|
||||
UpdatedAfterFilter(),
|
||||
HasProjectCodeFilter(),
|
||||
ProjectCodeFilter(),
|
||||
ResponsibleFilter(),
|
||||
@@ -182,6 +187,9 @@ export function SalesOrderTable({
|
||||
}),
|
||||
TargetDateColumn({}),
|
||||
ShipmentDateColumn({}),
|
||||
UpdatedAtColumn({
|
||||
defaultVisible: false
|
||||
}),
|
||||
ResponsibleColumn({}),
|
||||
{
|
||||
accessor: 'total_price',
|
||||
|
||||
Reference in New Issue
Block a user