mirror of
https://github.com/inventree/InvenTree.git
synced 2025-07-01 03:00:54 +00:00
[plugin] Auto issue orders (#9565)
* Add builtin plugin for auto-issuing orders * Add plugin to auto-issue orders * Add placeholder documentation * Fix typo * Adds image macro - To replace img.html - includes checking if file exists * Fix tooltips * More docs * Adjust plugin settings filters * docs * More docs * More docs * Updates * Less restrictive URL checking * Refactor build order page * Fix typo * Allow 429 * Debug output * More debug * Construct assets dir * Cleanup * Update docs README * Refactoring more pages * Fix image link * Fix SSO settings * Add hook to check for missing settings - Ensure that all settings are documented! * Add missing user settings * Update docstring * Tweak SSO.md * Image updates * More updates * Tweaks * Exclude orders without a target_date * Fix for issuing build orders * Further refactoring * Fixes * Image refactoring * More refactoring * More refactoring * Refactor app images * Fix pathing issues * Suppress some openapidocs warnings in logs (much easier to debug docs build issues) * Fix image reference * Reduce error messages * Fix image links * Fix image links * Reduce docs log output * Ensure settings are loaded before displaying them * Fix for UI test * Fix unit test * Test tweaks
This commit is contained in:
@ -461,12 +461,6 @@ SYSTEM_SETTINGS: dict[str, InvenTreeSettingsKeyType] = {
|
||||
'default': False,
|
||||
'validator': bool,
|
||||
},
|
||||
'PART_SHOW_IMPORT': {
|
||||
'name': _('Show Import in Views'),
|
||||
'description': _('Display the import wizard in some part views'),
|
||||
'default': False,
|
||||
'validator': bool,
|
||||
},
|
||||
'PART_SHOW_RELATED': {
|
||||
'name': _('Show related parts'),
|
||||
'description': _('Display related parts for a part'),
|
||||
|
130
src/backend/InvenTree/plugin/builtin/events/auto_issue_orders.py
Normal file
130
src/backend/InvenTree/plugin/builtin/events/auto_issue_orders.py
Normal file
@ -0,0 +1,130 @@
|
||||
"""Plugin to automatically issue orders on the assigned target date."""
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
import structlog
|
||||
|
||||
from InvenTree.helpers import current_date
|
||||
from plugin import InvenTreePlugin
|
||||
from plugin.mixins import ScheduleMixin, SettingsMixin
|
||||
|
||||
logger = structlog.get_logger('inventree')
|
||||
|
||||
|
||||
class AutoIssueOrdersPlugin(ScheduleMixin, SettingsMixin, InvenTreePlugin):
|
||||
"""Plugin to automatically issue orders on the assigned target date."""
|
||||
|
||||
NAME = _('Auto Issue Orders')
|
||||
SLUG = 'autoiissueorders'
|
||||
AUTHOR = _('InvenTree contributors')
|
||||
DESCRIPTION = _('Automatically issue orders on the assigned target date')
|
||||
VERSION = '1.0.0'
|
||||
|
||||
# Set the scheduled tasks for this plugin
|
||||
SCHEDULED_TASKS = {
|
||||
'auto_issue_orders': {'func': 'auto_issue_orders', 'schedule': 'D'}
|
||||
}
|
||||
|
||||
SETTINGS = {
|
||||
'AUTO_ISSUE_BUILD_ORDERS': {
|
||||
'name': _('Auto Issue Build Orders'),
|
||||
'description': _(
|
||||
'Automatically issue build orders on the assigned target date'
|
||||
),
|
||||
'validator': bool,
|
||||
'default': True,
|
||||
},
|
||||
'AUTO_ISSUE_PURCHASE_ORDERS': {
|
||||
'name': _('Auto Issue Purchase Orders'),
|
||||
'description': _(
|
||||
'Automatically issue purchase orders on the assigned target date'
|
||||
),
|
||||
'validator': bool,
|
||||
'default': True,
|
||||
},
|
||||
'AUTO_ISSUE_SALES_ORDERS': {
|
||||
'name': _('Auto Issue Sales Orders'),
|
||||
'description': _(
|
||||
'Automatically issue sales orders on the assigned target date'
|
||||
),
|
||||
'validator': bool,
|
||||
'default': True,
|
||||
},
|
||||
'AUTO_ISSUE_RETURN_ORDERS': {
|
||||
'name': _('Auto Issue Return Orders'),
|
||||
'description': _(
|
||||
'Automatically issue return orders on the assigned target date'
|
||||
),
|
||||
'validator': bool,
|
||||
'default': True,
|
||||
},
|
||||
'ISSUE_BACKDATED_ORDERS': {
|
||||
'name': _('Issue Backdated Orders'),
|
||||
'description': _('Automatically issue orders that are backdated'),
|
||||
'validator': bool,
|
||||
'default': False,
|
||||
},
|
||||
}
|
||||
|
||||
def auto_issue_orders(self):
|
||||
"""Automatically issue orders on the assigned target date."""
|
||||
if self.get_setting('AUTO_ISSUE_BUILD_ORDERS', backup_value=True):
|
||||
self.auto_issue_build_orders()
|
||||
|
||||
if self.get_setting('AUTO_ISSUE_PURCHASE_ORDERS', backup_value=True):
|
||||
self.auto_issue_purchase_orders()
|
||||
|
||||
if self.get_setting('AUTO_ISSUE_SALES_ORDERS', backup_value=True):
|
||||
self.auto_issue_sales_orders()
|
||||
|
||||
if self.get_setting('AUTO_ISSUE_RETURN_ORDERS', backup_value=True):
|
||||
self.auto_issue_return_orders()
|
||||
|
||||
def issue_func(self, model, status: int, func_name: str = 'issue_order'):
|
||||
"""Helper function to issue orders of a given model and status."""
|
||||
orders = model.objects.filter(status=status)
|
||||
orders = orders.filter(target_date__isnull=False)
|
||||
|
||||
if self.get_setting('ISSUE_BACKDATED_ORDERS', backup_value=False):
|
||||
orders = orders.filter(target_date__lte=current_date())
|
||||
else:
|
||||
orders = orders.filter(target_date=current_date())
|
||||
|
||||
if orders.count() == 0:
|
||||
return
|
||||
|
||||
logger.info('Auto-issuing %d orders for %s', orders.count(), model.__name__)
|
||||
|
||||
for order in orders:
|
||||
try:
|
||||
getattr(order, func_name)()
|
||||
except Exception as e:
|
||||
logger.error('Failed to issue order %s: %s', order.pk, str(e))
|
||||
|
||||
def auto_issue_build_orders(self):
|
||||
"""Automatically issue build orders on the assigned target date."""
|
||||
from build.models import Build
|
||||
from build.status_codes import BuildStatus
|
||||
|
||||
self.issue_func(Build, BuildStatus.PENDING, func_name='issue_build')
|
||||
|
||||
def auto_issue_purchase_orders(self):
|
||||
"""Automatically issue purchase orders on the assigned target date."""
|
||||
from order.models import PurchaseOrder
|
||||
from order.status_codes import PurchaseOrderStatus
|
||||
|
||||
self.issue_func(PurchaseOrder, PurchaseOrderStatus.PENDING)
|
||||
|
||||
def auto_issue_sales_orders(self):
|
||||
"""Automatically issue sales orders on the assigned target date."""
|
||||
from order.models import SalesOrder
|
||||
from order.status_codes import SalesOrderStatus
|
||||
|
||||
self.issue_func(SalesOrder, SalesOrderStatus.PENDING)
|
||||
|
||||
def auto_issue_return_orders(self):
|
||||
"""Automatically issue return orders on the assigned target date."""
|
||||
from order.models import ReturnOrder
|
||||
from order.status_codes import ReturnOrderStatus
|
||||
|
||||
self.issue_func(ReturnOrder, ReturnOrderStatus.PENDING)
|
@ -15,7 +15,7 @@ class DigiKeyPlugin(SupplierBarcodeMixin, SettingsMixin, InvenTreePlugin):
|
||||
NAME = 'DigiKeyPlugin'
|
||||
TITLE = _('Supplier Integration - DigiKey')
|
||||
DESCRIPTION = _('Provides support for scanning DigiKey barcodes')
|
||||
VERSION = '1.0.0'
|
||||
VERSION = '1.0.1'
|
||||
AUTHOR = _('InvenTree contributors')
|
||||
|
||||
DEFAULT_SUPPLIER_NAME = 'DigiKey'
|
||||
@ -25,6 +25,7 @@ class DigiKeyPlugin(SupplierBarcodeMixin, SettingsMixin, InvenTreePlugin):
|
||||
'name': _('Supplier'),
|
||||
'description': _("The Supplier which acts as 'DigiKey'"),
|
||||
'model': 'company.company',
|
||||
'model_filters': {'is_supplier': True},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ class LCSCPlugin(SupplierBarcodeMixin, SettingsMixin, InvenTreePlugin):
|
||||
NAME = 'LCSCPlugin'
|
||||
TITLE = _('Supplier Integration - LCSC')
|
||||
DESCRIPTION = _('Provides support for scanning LCSC barcodes')
|
||||
VERSION = '1.0.0'
|
||||
VERSION = '1.0.1'
|
||||
AUTHOR = _('InvenTree contributors')
|
||||
|
||||
DEFAULT_SUPPLIER_NAME = 'LCSC'
|
||||
@ -26,6 +26,7 @@ class LCSCPlugin(SupplierBarcodeMixin, SettingsMixin, InvenTreePlugin):
|
||||
'name': _('Supplier'),
|
||||
'description': _("The Supplier which acts as 'LCSC'"),
|
||||
'model': 'company.company',
|
||||
'model_filters': {'is_supplier': True},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ class MouserPlugin(SupplierBarcodeMixin, SettingsMixin, InvenTreePlugin):
|
||||
NAME = 'MouserPlugin'
|
||||
TITLE = _('Supplier Integration - Mouser')
|
||||
DESCRIPTION = _('Provides support for scanning Mouser barcodes')
|
||||
VERSION = '1.0.0'
|
||||
VERSION = '1.0.1'
|
||||
AUTHOR = _('InvenTree contributors')
|
||||
|
||||
DEFAULT_SUPPLIER_NAME = 'Mouser'
|
||||
@ -24,6 +24,7 @@ class MouserPlugin(SupplierBarcodeMixin, SettingsMixin, InvenTreePlugin):
|
||||
'name': _('Supplier'),
|
||||
'description': _("The Supplier which acts as 'Mouser'"),
|
||||
'model': 'company.company',
|
||||
'model_filters': {'is_supplier': True},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ class TMEPlugin(SupplierBarcodeMixin, SettingsMixin, InvenTreePlugin):
|
||||
NAME = 'TMEPlugin'
|
||||
TITLE = _('Supplier Integration - TME')
|
||||
DESCRIPTION = _('Provides support for scanning TME barcodes')
|
||||
VERSION = '1.0.0'
|
||||
VERSION = '1.0.1'
|
||||
AUTHOR = _('InvenTree contributors')
|
||||
|
||||
DEFAULT_SUPPLIER_NAME = 'TME'
|
||||
@ -26,6 +26,7 @@ class TMEPlugin(SupplierBarcodeMixin, SettingsMixin, InvenTreePlugin):
|
||||
'name': _('Supplier'),
|
||||
'description': _("The Supplier which acts as 'TME'"),
|
||||
'model': 'company.company',
|
||||
'model_filters': {'is_supplier': True},
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user