2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-07-09 15:10:54 +00:00

[feature] Disable pricing task (#9730)

* Add setting to control pricing auto-update

* Auto pricing updates depend on global setting

* Tweak menu layout

* Fix typo

* Skip pricing task

* Tweak serializer

* Updated docs

* Update logic around automatic pricing updates

* Logic fix

* Remove daily holdoff
This commit is contained in:
Oliver
2025-07-05 11:16:42 +10:00
committed by GitHub
parent 925807e06b
commit 82dfe561ee
8 changed files with 65 additions and 15 deletions

View File

@ -588,12 +588,20 @@ SYSTEM_SETTINGS: dict[str, InvenTreeSettingsKeyType] = {
'default': False,
'validator': bool,
},
'PRICING_AUTO_UPDATE': {
'name': _('Auto Update Pricing'),
'description': _(
'Automatically update part pricing when internal data changes'
),
'default': True,
'validator': bool,
},
'PRICING_UPDATE_DAYS': {
'name': _('Pricing Rebuild Interval'),
'description': _('Number of days before part pricing is automatically updated'),
'units': _('days'),
'default': 30,
'validator': [int, MinValueValidator(10)],
'validator': [int, MinValueValidator(0)],
},
'PART_INTERNAL_PRICE': {
'name': _('Internal Prices'),

View File

@ -2033,7 +2033,7 @@ class Part(
return pricing
def schedule_pricing_update(self, create: bool = False):
def schedule_pricing_update(self, create: bool = False, force: bool = False):
"""Helper function to schedule a pricing update.
Importantly, catches any errors which may occur during deletion of related objects,
@ -2043,7 +2043,13 @@ class Part(
Arguments:
create: Whether or not a new PartPricing object should be created if it does not already exist
force: If True, force the pricing to be updated even auto pricing is disabled
"""
if not force and not get_global_setting(
'PRICING_AUTO_UPDATE', backup_value=True
):
return
try:
self.refresh_from_db()
except Part.DoesNotExist:
@ -2705,7 +2711,11 @@ class PartPricing(common.models.MetaMixin):
return result
def schedule_for_update(self, counter: int = 0):
"""Schedule this pricing to be updated."""
"""Schedule this pricing to be updated.
Arguments:
counter: Recursion counter (used to prevent infinite recursion)
"""
import InvenTree.ready
# If importing data, skip pricing update

View File

@ -1593,9 +1593,12 @@ class PartPricingSerializer(InvenTree.serializers.InvenTreeModelSerializer):
"""Called when the serializer is saved."""
super().save()
# Update part pricing
pricing = self.instance
pricing.update_pricing()
data = self.validated_data
if data.get('update', False):
# Update part pricing
pricing = self.instance
pricing.update_pricing()
class PartRelationSerializer(InvenTree.serializers.InvenTreeModelSerializer):

View File

@ -251,6 +251,13 @@ def check_missing_pricing(limit=250):
Arguments:
limit: Maximum number of parts to process at once
"""
# Find any parts which have 'old' pricing information
days = int(get_global_setting('PRICING_UPDATE_DAYS', 30))
if days <= 0:
# Task does not run if the interval is zero
return
# Find parts for which pricing information has never been updated
results = part_models.PartPricing.objects.filter(updated=None)[:limit]
@ -260,8 +267,6 @@ def check_missing_pricing(limit=250):
for pp in results:
pp.schedule_for_update()
# Find any parts which have 'old' pricing information
days = int(get_global_setting('PRICING_UPDATE_DAYS', 30))
stale_date = datetime.now().date() - timedelta(days=days)
results = part_models.PartPricing.objects.filter(updated__lte=stale_date)[:limit]

View File

@ -104,7 +104,11 @@ export default function CurrencyManagementPanel() {
<CurrencyTable setInfo={setInfo} />
<Divider />
<GlobalSettingList
keys={['CURRENCY_UPDATE_PLUGIN', 'CURRENCY_UPDATE_INTERVAL']}
keys={[
'INVENTREE_DEFAULT_CURRENCY',
'CURRENCY_UPDATE_PLUGIN',
'CURRENCY_UPDATE_INTERVAL'
]}
/>
</Stack>
);

View File

@ -138,6 +138,7 @@ export default function SystemSettings() {
'PART_BOM_USE_INTERNAL_PRICE',
'PRICING_DECIMAL_PLACES_MIN',
'PRICING_DECIMAL_PLACES',
'PRICING_AUTO_UPDATE',
'PRICING_UPDATE_DAYS'
]}
/>