mirror of
https://github.com/inventree/InvenTree.git
synced 2026-09-01 17:51:23 +00:00
[UI] Reimplement calendar views (#8933)
* Add deps for @fullcalendar * Basic calendar setup * Add locale support * Add custom <SegmentedIconControl> component * optional 'control' for panel * Scaffolding out build index page * Fetch build orders based on calendar dates * Display builds * Click to navigate to build * Working on custom header * Implement button functionality * Display current month name * Implement datepicker dropdown * Adjust layout * Custom rendering * Include part detail * Implement hook to track calendar state * Clearing search causes immediate update * Offload core functionality into hook - Adds search input * Spread props correctly * Cleanup * Allow build orders to be edited directly from calendar view * Cleanup * Fix for InvenTreeCalendarProps * Improve date range filtering for Build model * Simplify BuildFilter * Refactoring * PurchaseOrder calendar implementation * Allow edit of purchase orders * Refactor and implement for all order types - Add missing "issue_date" field for SalesOrder - Refactor API for other order types - Fix rendering issues * Bump API version * Add playwright tests for calendar (simple) * Fix migrations * Simplify notifications * Refactor filter components - Make them more generic * Enable custom filters for calendars * Custom filters per table * Display status label * Refactoring * Update playwright tests * Update build order docs * Bug fix for order date editing * Update purchase order docs * Return Order docs * Update date formatting
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
"""Order model definitions."""
|
||||
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
@@ -389,6 +388,13 @@ class Order(
|
||||
verbose_name=_('Created By'),
|
||||
)
|
||||
|
||||
issue_date = models.DateField(
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_('Issue Date'),
|
||||
help_text=_('Date order was issued'),
|
||||
)
|
||||
|
||||
responsible = models.ForeignKey(
|
||||
UserModels.Owner,
|
||||
on_delete=models.SET_NULL,
|
||||
@@ -482,50 +488,6 @@ class PurchaseOrder(TotalPriceMixin, Order):
|
||||
"""Return the associated barcode model type code for this model."""
|
||||
return 'PO'
|
||||
|
||||
@staticmethod
|
||||
def filterByDate(queryset, min_date, max_date):
|
||||
"""Filter by 'minimum and maximum date range'.
|
||||
|
||||
- Specified as min_date, max_date
|
||||
- Both must be specified for filter to be applied
|
||||
- Determine which "interesting" orders exist between these dates
|
||||
|
||||
To be "interesting":
|
||||
- A "received" order where the received date lies within the date range
|
||||
- A "pending" order where the target date lies within the date range
|
||||
- TODO: An "overdue" order where the target date is in the past
|
||||
"""
|
||||
date_fmt = '%Y-%m-%d' # ISO format date string
|
||||
|
||||
# Ensure that both dates are valid
|
||||
try:
|
||||
min_date = datetime.strptime(str(min_date), date_fmt).date()
|
||||
max_date = datetime.strptime(str(max_date), date_fmt).date()
|
||||
except (ValueError, TypeError):
|
||||
# Date processing error, return queryset unchanged
|
||||
return queryset
|
||||
|
||||
# Construct a queryset for "received" orders within the range
|
||||
received = (
|
||||
Q(status=PurchaseOrderStatus.COMPLETE.value)
|
||||
& Q(complete_date__gte=min_date)
|
||||
& Q(complete_date__lte=max_date)
|
||||
)
|
||||
|
||||
# Construct a queryset for "pending" orders within the range
|
||||
pending = (
|
||||
Q(status__in=PurchaseOrderStatusGroups.OPEN)
|
||||
& ~Q(target_date=None)
|
||||
& Q(target_date__gte=min_date)
|
||||
& Q(target_date__lte=max_date)
|
||||
)
|
||||
|
||||
# TODO - Construct a queryset for "overdue" orders within the range
|
||||
|
||||
queryset = queryset.filter(received | pending)
|
||||
|
||||
return queryset
|
||||
|
||||
def __str__(self):
|
||||
"""Render a string representation of this PurchaseOrder."""
|
||||
return f'{self.reference} - {self.supplier.name if self.supplier else _("deleted")}'
|
||||
@@ -584,13 +546,6 @@ class PurchaseOrder(TotalPriceMixin, Order):
|
||||
verbose_name=_('received by'),
|
||||
)
|
||||
|
||||
issue_date = models.DateField(
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_('Issue Date'),
|
||||
help_text=_('Date order was issued'),
|
||||
)
|
||||
|
||||
complete_date = models.DateField(
|
||||
blank=True,
|
||||
null=True,
|
||||
@@ -1054,50 +1009,6 @@ class SalesOrder(TotalPriceMixin, Order):
|
||||
"""Return the associated barcode model type code for this model."""
|
||||
return 'SO'
|
||||
|
||||
@staticmethod
|
||||
def filterByDate(queryset, min_date, max_date):
|
||||
"""Filter by "minimum and maximum date range".
|
||||
|
||||
- Specified as min_date, max_date
|
||||
- Both must be specified for filter to be applied
|
||||
- Determine which "interesting" orders exist between these dates
|
||||
|
||||
To be "interesting":
|
||||
- A "completed" order where the completion date lies within the date range
|
||||
- A "pending" order where the target date lies within the date range
|
||||
- TODO: An "overdue" order where the target date is in the past
|
||||
"""
|
||||
date_fmt = '%Y-%m-%d' # ISO format date string
|
||||
|
||||
# Ensure that both dates are valid
|
||||
try:
|
||||
min_date = datetime.strptime(str(min_date), date_fmt).date()
|
||||
max_date = datetime.strptime(str(max_date), date_fmt).date()
|
||||
except (ValueError, TypeError):
|
||||
# Date processing error, return queryset unchanged
|
||||
return queryset
|
||||
|
||||
# Construct a queryset for "completed" orders within the range
|
||||
completed = (
|
||||
Q(status__in=SalesOrderStatusGroups.COMPLETE)
|
||||
& Q(shipment_date__gte=min_date)
|
||||
& Q(shipment_date__lte=max_date)
|
||||
)
|
||||
|
||||
# Construct a queryset for "pending" orders within the range
|
||||
pending = (
|
||||
Q(status__in=SalesOrderStatusGroups.OPEN)
|
||||
& ~Q(target_date=None)
|
||||
& Q(target_date__gte=min_date)
|
||||
& Q(target_date__lte=max_date)
|
||||
)
|
||||
|
||||
# TODO: Construct a queryset for "overdue" orders within the range
|
||||
|
||||
queryset = queryset.filter(completed | pending)
|
||||
|
||||
return queryset
|
||||
|
||||
def __str__(self):
|
||||
"""Render a string representation of this SalesOrder."""
|
||||
return f'{self.reference} - {self.customer.name if self.customer else _("deleted")}'
|
||||
@@ -2363,13 +2274,6 @@ class ReturnOrder(TotalPriceMixin, Order):
|
||||
help_text=_('Customer order reference code'),
|
||||
)
|
||||
|
||||
issue_date = models.DateField(
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_('Issue Date'),
|
||||
help_text=_('Date order was issued'),
|
||||
)
|
||||
|
||||
complete_date = models.DateField(
|
||||
blank=True,
|
||||
null=True,
|
||||
|
||||
Reference in New Issue
Block a user