mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-30 20:55:42 +00:00 
			
		
		
		
	Replace "addTrasactionNote" function with "add_tracking_entry"
- Does not add translated strings to the database
This commit is contained in:
		| @@ -22,7 +22,7 @@ from markdownx.models import MarkdownxField | ||||
|  | ||||
| from mptt.models import MPTTModel, TreeForeignKey | ||||
|  | ||||
| from InvenTree.status_codes import BuildStatus, StockStatus | ||||
| from InvenTree.status_codes import BuildStatus, StockStatus, StockHistoryCode | ||||
| from InvenTree.helpers import increment, getSetting, normalize, MakeBarcode | ||||
| from InvenTree.validators import validate_build_order_reference | ||||
| from InvenTree.models import InvenTreeAttachment | ||||
| @@ -811,6 +811,7 @@ class Build(MPTTModel): | ||||
|         # Select the location for the build output | ||||
|         location = kwargs.get('location', self.destination) | ||||
|         status = kwargs.get('status', StockStatus.OK) | ||||
|         notes = kwargs.get('notes', '') | ||||
|  | ||||
|         # List the allocated BuildItem objects for the given output | ||||
|         allocated_items = output.items_to_install.all() | ||||
| @@ -834,10 +835,13 @@ class Build(MPTTModel): | ||||
|  | ||||
|         output.save() | ||||
|  | ||||
|         output.addTransactionNote( | ||||
|             _('Completed build output'), | ||||
|         output.add_tracking_entry( | ||||
|             StockHistoryCode.BUILD_OUTPUT_COMPLETED, | ||||
|             user, | ||||
|             system=True | ||||
|             notes=notes, | ||||
|             deltas={ | ||||
|                 'status': status, | ||||
|             } | ||||
|         ) | ||||
|  | ||||
|         # Increase the completed quantity for this build | ||||
|   | ||||
| @@ -28,7 +28,7 @@ from company.models import Company, SupplierPart | ||||
|  | ||||
| from InvenTree.fields import RoundingDecimalField | ||||
| from InvenTree.helpers import decimal2string, increment, getSetting | ||||
| from InvenTree.status_codes import PurchaseOrderStatus, SalesOrderStatus, StockStatus | ||||
| from InvenTree.status_codes import PurchaseOrderStatus, SalesOrderStatus, StockStatus, StockHistoryCode | ||||
| from InvenTree.models import InvenTreeAttachment | ||||
|  | ||||
|  | ||||
| @@ -336,10 +336,12 @@ class PurchaseOrder(Order): | ||||
|         return self.pending_line_items().count() == 0 | ||||
|  | ||||
|     @transaction.atomic | ||||
|     def receive_line_item(self, line, location, quantity, user, status=StockStatus.OK, purchase_price=None): | ||||
|     def receive_line_item(self, line, location, quantity, user, status=StockStatus.OK, purchase_price=None, **kwargs): | ||||
|         """ Receive a line item (or partial line item) against this PO | ||||
|         """ | ||||
|  | ||||
|         notes = kwargs.get('notes', '') | ||||
|  | ||||
|         if not self.status == PurchaseOrderStatus.PLACED: | ||||
|             raise ValidationError({"status": _("Lines can only be received against an order marked as 'Placed'")}) | ||||
|  | ||||
| @@ -369,8 +371,22 @@ class PurchaseOrder(Order): | ||||
|             text = _("Received items") | ||||
|             note = _('Received {n} items against order {name}').format(n=quantity, name=str(self)) | ||||
|  | ||||
|             # Add a new transaction note to the newly created stock item | ||||
|             stock.addTransactionNote(text, user, note) | ||||
|             tracking_info = { | ||||
|                 'status': status, | ||||
|                 'purchaseorder': self.pk, | ||||
|                 'quantity': quantity, | ||||
|             } | ||||
|  | ||||
|             if location: | ||||
|                 tracking_info['location'] = location.pk | ||||
|  | ||||
|             stock.add_tracking_entry( | ||||
|                 StockHistoryCode.RECEIVED_AGAINST_PURCHASE_ORDER, | ||||
|                 user, | ||||
|                 notes=notes, | ||||
|                 url=self.get_absolute_url(), | ||||
|                 deltas=tracking_info | ||||
|             ) | ||||
|  | ||||
|         # Update the number of parts received against the particular line item | ||||
|         line.received += quantity | ||||
|   | ||||
							
								
								
									
										28
									
								
								InvenTree/stock/migrations/0060_auto_20210511_1713.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								InvenTree/stock/migrations/0060_auto_20210511_1713.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| # Generated by Django 3.2 on 2021-05-11 07:13 | ||||
|  | ||||
| from django.db import migrations, models | ||||
|  | ||||
|  | ||||
| class Migration(migrations.Migration): | ||||
|  | ||||
|     dependencies = [ | ||||
|         ('stock', '0059_auto_20210404_2016'), | ||||
|     ] | ||||
|  | ||||
|     operations = [ | ||||
|         migrations.AddField( | ||||
|             model_name='stockitemtracking', | ||||
|             name='deltas', | ||||
|             field=models.JSONField(blank=True, null=True), | ||||
|         ), | ||||
|         migrations.AddField( | ||||
|             model_name='stockitemtracking', | ||||
|             name='tracking_type', | ||||
|             field=models.IntegerField(default=0), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='stockitemtracking', | ||||
|             name='title', | ||||
|             field=models.CharField(blank=True, help_text='Tracking entry title', max_length=250, verbose_name='Title'), | ||||
|         ), | ||||
|     ] | ||||
							
								
								
									
										59
									
								
								InvenTree/stock/migrations/0061_auto_20210511_0911.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								InvenTree/stock/migrations/0061_auto_20210511_0911.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| # Generated by Django 3.2 on 2021-05-10 23:11 | ||||
|  | ||||
| from django.db import migrations | ||||
|  | ||||
|  | ||||
| def update_history(apps, schema_editor): | ||||
|     """ | ||||
|     Update each existing StockItemTracking object, | ||||
|     convert the recorded "quantity" to a delta | ||||
|     """ | ||||
|  | ||||
|     StockItem = apps.get_model('stock', 'stockitem') | ||||
|     StockItemTracking = apps.get_model('stock', 'stockitemtracking') | ||||
|  | ||||
|     update_count = 0 | ||||
|  | ||||
|     for item in StockItem.objects.all(): | ||||
|  | ||||
|         history = StockItemTracking.objects.filter(item=item).order_by('date') | ||||
|  | ||||
|         if history.count() == 0: | ||||
|             continue | ||||
|  | ||||
|         quantity = history[0].quantity | ||||
|  | ||||
|         for entry in history: | ||||
|              | ||||
|             q = entry.quantity | ||||
|  | ||||
|             if not q == quantity: | ||||
|  | ||||
|                 entry.deltas = { | ||||
|                     'quantity': float(q), | ||||
|                 } | ||||
|  | ||||
|                 entry.save() | ||||
|  | ||||
|                 update_count += 1 | ||||
|  | ||||
|                 quantity = q | ||||
|  | ||||
|     print(f"Updated {update_count} StockItemHistory entries") | ||||
|  | ||||
|  | ||||
| def reverse_update(apps, schema_editor): | ||||
|     """ | ||||
|     """ | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class Migration(migrations.Migration): | ||||
|  | ||||
|     dependencies = [ | ||||
|         ('stock', '0060_auto_20210511_1713'), | ||||
|     ] | ||||
|  | ||||
|     operations = [ | ||||
|         migrations.RunPython(update_history, reverse_code=reverse_update) | ||||
|     ] | ||||
| @@ -34,7 +34,7 @@ import common.models | ||||
| import report.models | ||||
| import label.models | ||||
|  | ||||
| from InvenTree.status_codes import StockStatus | ||||
| from InvenTree.status_codes import StockStatus, StockHistoryCode | ||||
| from InvenTree.models import InvenTreeTree, InvenTreeAttachment | ||||
| from InvenTree.fields import InvenTreeURLField | ||||
|  | ||||
| @@ -198,14 +198,18 @@ class StockItem(MPTTModel): | ||||
|  | ||||
|         if add_note: | ||||
|  | ||||
|             note = _('Created new stock item for {part}').format(part=str(self.part)) | ||||
|             tracking_info = { | ||||
|                 'quantity': self.quantity, | ||||
|                 'status': self.status, | ||||
|             } | ||||
|  | ||||
|             # This StockItem is being saved for the first time | ||||
|             self.addTransactionNote( | ||||
|                 _('Created stock item'), | ||||
|             if self.location: | ||||
|                 tracking_info['location'] = self.location.pk | ||||
|  | ||||
|             self.add_tracking_entry( | ||||
|                 StockHistoryCode.CREATED, | ||||
|                 user, | ||||
|                 note, | ||||
|                 system=True | ||||
|                 deltas=tracking_info | ||||
|             ) | ||||
|  | ||||
|     @property | ||||
| @@ -610,31 +614,45 @@ class StockItem(MPTTModel): | ||||
|  | ||||
|         # TODO - Remove any stock item allocations from this stock item | ||||
|  | ||||
|         item.addTransactionNote( | ||||
|             _("Assigned to Customer"), | ||||
|         item.add_tracking_entry( | ||||
|             StockHistoryCode.SENT_TO_CUSTOMER, | ||||
|             user, | ||||
|             notes=_("Manually assigned to customer {name}").format(name=customer.name), | ||||
|             system=True | ||||
|             { | ||||
|                 'customer': customer.id, | ||||
|                 'customer_name': customer.name, | ||||
|             }, | ||||
|             notes=notes, | ||||
|         ) | ||||
|  | ||||
|         # Return the reference to the stock item | ||||
|         return item | ||||
|  | ||||
|     def returnFromCustomer(self, location, user=None): | ||||
|     def returnFromCustomer(self, location, user=None, **kwargs): | ||||
|         """ | ||||
|         Return stock item from customer, back into the specified location. | ||||
|         """ | ||||
|  | ||||
|         self.addTransactionNote( | ||||
|             _("Returned from customer {name}").format(name=self.customer.name), | ||||
|         notes = kwargs.get('notes', '') | ||||
|  | ||||
|         tracking_info = {} | ||||
|  | ||||
|         if location: | ||||
|             tracking_info['location'] = location.id | ||||
|             tracking_info['location_name'] = location.name | ||||
|  | ||||
|         if self.customer: | ||||
|             tracking_info['customer'] = customer.id | ||||
|             tracking_info['customer_name'] = customer.name | ||||
|  | ||||
|         self.add_tracking_entry( | ||||
|             StockHistoryCode.RETURNED_FROM_CUSTOMER, | ||||
|             user, | ||||
|             notes=_("Returned to location {loc}").format(loc=location.name), | ||||
|             system=True | ||||
|             notes=notes, | ||||
|             deltas=tracking_info | ||||
|         ) | ||||
|  | ||||
|         self.customer = None | ||||
|         self.location = location | ||||
|         self.sales_order = None | ||||
|  | ||||
|         self.save() | ||||
|  | ||||
| @@ -788,18 +806,25 @@ class StockItem(MPTTModel): | ||||
|         stock_item.save() | ||||
|  | ||||
|         # Add a transaction note to the other item | ||||
|         stock_item.addTransactionNote( | ||||
|             _('Installed into stock item {pk}').format(str(self.pk)), | ||||
|         stock_item.add_tracking_entry( | ||||
|             StockHistoryCode.INSTALLED_INTO_ASSEMBLY, | ||||
|             user, | ||||
|             notes=notes, | ||||
|             url=self.get_absolute_url() | ||||
|             url=self.get_absolute_url(), | ||||
|             deltas={ | ||||
|                 'assembly': self.pk, | ||||
|             } | ||||
|         ) | ||||
|  | ||||
|         # Add a transaction note to this item | ||||
|         self.addTransactionNote( | ||||
|             _('Installed stock item {pk}').format(str(stock_item.pk)), | ||||
|             user, notes=notes, | ||||
|             url=stock_item.get_absolute_url() | ||||
|         # Add a transaction note to this item (the assembly) | ||||
|         self.add_tracking_entry( | ||||
|             StockHistoryCode.INSTALLED_CHILD_ITEM, | ||||
|             user, | ||||
|             notes=notes, | ||||
|             url=stock_item.get_absolute_url(), | ||||
|             deltas={ | ||||
|                 'stockitem': stock_item.pk, | ||||
|             } | ||||
|         ) | ||||
|  | ||||
|     @transaction.atomic | ||||
| @@ -820,32 +845,41 @@ class StockItem(MPTTModel): | ||||
|         # TODO - Are there any other checks that need to be performed at this stage? | ||||
|  | ||||
|         # Add a transaction note to the parent item | ||||
|         self.belongs_to.addTransactionNote( | ||||
|             _("Uninstalled stock item {pk}").format(pk=str(self.pk)), | ||||
|         self.belongs_to.add_tracking_entry( | ||||
|             StockHistoryCode.REMOVED_CHILD_ITEM, | ||||
|             user, | ||||
|             deltas={ | ||||
|                 'stockitem': self.pk,  | ||||
|             }, | ||||
|             notes=notes, | ||||
|             url=self.get_absolute_url(), | ||||
|         ) | ||||
|  | ||||
|         tracking_info = { | ||||
|             'assembly': self.belongs_to.pk | ||||
|         } | ||||
|  | ||||
|         if location: | ||||
|             tracking_info['location'] = location.pk | ||||
|             tracking_info['location_name'] = location.name | ||||
|             url = location.get_absolute_url() | ||||
|         else: | ||||
|             url = '' | ||||
|  | ||||
|         self.add_tracking_entry( | ||||
|             StockHistoryCode.REMOVED_FROM_ASSEMBLY, | ||||
|             user, | ||||
|             notes=notes, | ||||
|             url=url, | ||||
|             deltas=tracking_info | ||||
|         ) | ||||
|  | ||||
|         # Mark this stock item as *not* belonging to anyone | ||||
|         self.belongs_to = None | ||||
|         self.location = location | ||||
|  | ||||
|         self.save() | ||||
|  | ||||
|         if location: | ||||
|             url = location.get_absolute_url() | ||||
|         else: | ||||
|             url = '' | ||||
|  | ||||
|         # Add a transaction note! | ||||
|         self.addTransactionNote( | ||||
|             _('Uninstalled into location {loc}').formaT(loc=str(location)), | ||||
|             user, | ||||
|             notes=notes, | ||||
|             url=url | ||||
|         ) | ||||
|  | ||||
|     @property | ||||
|     def children(self): | ||||
|         """ Return a list of the child items which have been split from this stock item """ | ||||
| @@ -901,24 +935,30 @@ class StockItem(MPTTModel): | ||||
|     def has_tracking_info(self): | ||||
|         return self.tracking_info_count > 0 | ||||
|  | ||||
|     def addTransactionNote(self, title, user, notes='', url='', system=True): | ||||
|         """ Generation a stock transaction note for this item. | ||||
|     def add_tracking_entry(self, entry_type, user, deltas={}, notes='', url=''): | ||||
|         """ | ||||
|         Add a history tracking entry for this StockItem | ||||
|  | ||||
|         Brief automated note detailing a movement or quantity change. | ||||
|         Args: | ||||
|             entry_type - Integer code describing the "type" of historical action (see StockHistoryCode) | ||||
|             user - The user performing this action | ||||
|             deltas - A map of the changes made to the model | ||||
|             notes - User notes associated with this tracking entry | ||||
|             url - Optional URL associated with this tracking entry | ||||
|         """ | ||||
|  | ||||
|         track = StockItemTracking.objects.create( | ||||
|         entry = StockItemTracking.objects.create( | ||||
|             item=self, | ||||
|             title=title, | ||||
|             tracking_type=entry_type, | ||||
|             user=user, | ||||
|             quantity=self.quantity, | ||||
|             date=datetime.now().date(), | ||||
|             date=datetime.now(), | ||||
|             notes=notes, | ||||
|             deltas=deltas, | ||||
|             link=url, | ||||
|             system=system | ||||
|             system=True | ||||
|         ) | ||||
|  | ||||
|         track.save() | ||||
|         entry.save() | ||||
|  | ||||
|     @transaction.atomic | ||||
|     def serializeStock(self, quantity, serials, user, notes='', location=None): | ||||
| @@ -991,10 +1031,17 @@ class StockItem(MPTTModel): | ||||
|             new_item.copyTestResultsFrom(self) | ||||
|  | ||||
|             # Create a new stock tracking item | ||||
|             new_item.addTransactionNote(_('Add serial number'), user, notes=notes) | ||||
|             new_item.add_tracking_entry( | ||||
|                 StockHistoryCode.ASSIGNED_SERIAL, | ||||
|                 user, | ||||
|                 notes=notes, | ||||
|                 deltas={ | ||||
|                     'serial': serial, | ||||
|                 } | ||||
|             ) | ||||
|  | ||||
|         # Remove the equivalent number of items | ||||
|         self.take_stock(quantity, user, notes=_('Serialized {n} items').format(n=quantity)) | ||||
|         self.take_stock(quantity, user, notes=notes) | ||||
|  | ||||
|     @transaction.atomic | ||||
|     def copyHistoryFrom(self, other): | ||||
| @@ -1018,7 +1065,7 @@ class StockItem(MPTTModel): | ||||
|             result.save() | ||||
|  | ||||
|     @transaction.atomic | ||||
|     def splitStock(self, quantity, location, user): | ||||
|     def splitStock(self, quantity, location, user, **kwargs): | ||||
|         """ Split this stock item into two items, in the same location. | ||||
|         Stock tracking notes for this StockItem will be duplicated, | ||||
|         and added to the new StockItem. | ||||
| @@ -1032,6 +1079,8 @@ class StockItem(MPTTModel): | ||||
|             The new item will have a different StockItem ID, while this will remain the same. | ||||
|         """ | ||||
|  | ||||
|         notes = kwargs.get('notes', '') | ||||
|  | ||||
|         # Do not split a serialized part | ||||
|         if self.serialized: | ||||
|             return self | ||||
| @@ -1071,17 +1120,20 @@ class StockItem(MPTTModel): | ||||
|         new_stock.copyTestResultsFrom(self) | ||||
|  | ||||
|         # Add a new tracking item for the new stock item | ||||
|         new_stock.addTransactionNote( | ||||
|             _("Split from existing stock"), | ||||
|         new_stock.add_tracking_entry( | ||||
|             StockHistoryCode.SPLIT_FROM_PARENT, | ||||
|             user, | ||||
|             _('Split {n} items').format(n=helpers.normalize(quantity)) | ||||
|             notes=notes, | ||||
|             deltas={ | ||||
|                 'stockitem': self.pk, | ||||
|             } | ||||
|         ) | ||||
|  | ||||
|         # Remove the specified quantity from THIS stock item | ||||
|         self.take_stock( | ||||
|             quantity, | ||||
|             user, | ||||
|             f"{_('Split')} {quantity} {_('items into new stock item')}" | ||||
|             notes=notes | ||||
|         ) | ||||
|  | ||||
|         # Return a copy of the "new" stock item | ||||
| @@ -1138,11 +1190,21 @@ class StockItem(MPTTModel): | ||||
|  | ||||
|         self.location = location | ||||
|  | ||||
|         self.addTransactionNote( | ||||
|             msg, | ||||
|         tracking_info = {} | ||||
|  | ||||
|         if location: | ||||
|             tracking_info['location'] = location.pk | ||||
|             url = location.get_absolute_url() | ||||
|         else: | ||||
|             url = '' | ||||
|  | ||||
|         self.add_tracking_entry( | ||||
|             StockHistoryCode.STOCK_MOVE, | ||||
|             user, | ||||
|             notes=notes, | ||||
|             system=True) | ||||
|             deltas=tracking_info, | ||||
|             url=url, | ||||
|         ) | ||||
|  | ||||
|         self.save() | ||||
|  | ||||
| @@ -1202,13 +1264,13 @@ class StockItem(MPTTModel): | ||||
|  | ||||
|         if self.updateQuantity(count): | ||||
|  | ||||
|             text = _('Counted {n} items').format(n=helpers.normalize(count)) | ||||
|  | ||||
|             self.addTransactionNote( | ||||
|                 text, | ||||
|             self.add_tracking_entry( | ||||
|                 StockHistoryCode.STOCK_COUNT, | ||||
|                 user, | ||||
|                 notes=notes, | ||||
|                 system=True | ||||
|                 deltas={ | ||||
|                     'quantity': self.quantity, | ||||
|                 } | ||||
|             ) | ||||
|  | ||||
|         return True | ||||
| @@ -1234,13 +1296,15 @@ class StockItem(MPTTModel): | ||||
|             return False | ||||
|  | ||||
|         if self.updateQuantity(self.quantity + quantity): | ||||
|             text = _('Added {n} items').format(n=helpers.normalize(quantity)) | ||||
|  | ||||
|             self.addTransactionNote( | ||||
|                 text, | ||||
|             self.add_tracking_entry( | ||||
|                 StockHistoryCode.STOCK_ADD, | ||||
|                 user, | ||||
|                 notes=notes, | ||||
|                 system=True | ||||
|                 deltas={ | ||||
|                     'added': quantity, | ||||
|                     'quantity': self.quantity | ||||
|                 } | ||||
|             ) | ||||
|  | ||||
|         return True | ||||
| @@ -1264,12 +1328,15 @@ class StockItem(MPTTModel): | ||||
|  | ||||
|         if self.updateQuantity(self.quantity - quantity): | ||||
|  | ||||
|             text = _('Removed {n1} items').format(n1=helpers.normalize(quantity)) | ||||
|  | ||||
|             self.addTransactionNote(text, | ||||
|                                     user, | ||||
|                                     notes=notes, | ||||
|                                     system=True) | ||||
|             self.add_tracking_entry( | ||||
|                 StockHistoryCode.STOCK_REMOVE, | ||||
|                 user, | ||||
|                 notes=notes, | ||||
|                 deltas={ | ||||
|                     'removed': quantity, | ||||
|                     'quantity': self.quantity, | ||||
|                 } | ||||
|             ) | ||||
|  | ||||
|         return True | ||||
|  | ||||
| @@ -1527,30 +1594,57 @@ class StockItemAttachment(InvenTreeAttachment): | ||||
|  | ||||
|  | ||||
| class StockItemTracking(models.Model): | ||||
|     """ Stock tracking entry - breacrumb for keeping track of automated stock transactions | ||||
|     """ | ||||
|     Stock tracking entry - used for tracking history of a particular StockItem | ||||
|  | ||||
|     Note: 2021-05-11 | ||||
|     The legacy StockTrackingItem model contained very litle information about the "history" of the item. | ||||
|     In fact, only the "quantity" of the item was recorded at each interaction. | ||||
|     Also, the "title" was translated at time of generation, and thus was not really translateable. | ||||
|     The "new" system tracks all 'delta' changes to the model, | ||||
|     and tracks change "type" which can then later be translated | ||||
|  | ||||
|  | ||||
|     Attributes: | ||||
|         item: Link to StockItem | ||||
|         item: ForeignKey reference to a particular StockItem | ||||
|         date: Date that this tracking info was created | ||||
|         title: Title of this tracking info (generated by system) | ||||
|         title: Title of this tracking info (legacy, no longer used!) | ||||
|         tracking_type: The type of tracking information | ||||
|         notes: Associated notes (input by user) | ||||
|         link: Optional URL to external page | ||||
|         user: The user associated with this tracking info | ||||
|         deltas: The changes associated with this history item | ||||
|         quantity: The StockItem quantity at this point in time | ||||
|     """ | ||||
|  | ||||
|     def get_absolute_url(self): | ||||
|         return '/stock/track/{pk}'.format(pk=self.id) | ||||
|         # return reverse('stock-tracking-detail', kwargs={'pk': self.id}) | ||||
|  | ||||
|     item = models.ForeignKey(StockItem, on_delete=models.CASCADE, | ||||
|                              related_name='tracking_info') | ||||
|     tracking_type = models.IntegerField( | ||||
|         default=StockHistoryCode.LEGACY, | ||||
|     ) | ||||
|  | ||||
|     item = models.ForeignKey( | ||||
|         StockItem, | ||||
|         on_delete=models.CASCADE, | ||||
|         related_name='tracking_info' | ||||
|     ) | ||||
|  | ||||
|     date = models.DateTimeField(auto_now_add=True, editable=False) | ||||
|  | ||||
|     title = models.CharField(blank=False, max_length=250, verbose_name=_('Title'), help_text=_('Tracking entry title')) | ||||
|     title = models.CharField( | ||||
|         blank=True, | ||||
|         max_length=250, | ||||
|         verbose_name=_('Title'), | ||||
|         help_text=_('Tracking entry title') | ||||
|     ) | ||||
|  | ||||
|     notes = models.CharField(blank=True, max_length=512, verbose_name=_('Notes'), help_text=_('Entry notes')) | ||||
|     notes = models.CharField( | ||||
|         blank=True, | ||||
|         max_length=512, | ||||
|         verbose_name=_('Notes'), | ||||
|         help_text=_('Entry notes') | ||||
|     ) | ||||
|  | ||||
|     link = InvenTreeURLField(blank=True, verbose_name=_('Link'), help_text=_('Link to external page for further information')) | ||||
|  | ||||
| @@ -1558,13 +1652,15 @@ class StockItemTracking(models.Model): | ||||
|  | ||||
|     system = models.BooleanField(default=False) | ||||
|  | ||||
|     quantity = models.DecimalField(max_digits=15, decimal_places=5, validators=[MinValueValidator(0)], default=1, verbose_name=_('Quantity')) | ||||
|     deltas = models.JSONField(null=True, blank=True) | ||||
|  | ||||
|     # TODO | ||||
|     # image = models.ImageField(upload_to=func, max_length=255, null=True, blank=True) | ||||
|  | ||||
|     # TODO | ||||
|     # file = models.FileField() | ||||
|     quantity = models.DecimalField( | ||||
|         max_digits=15, | ||||
|         decimal_places=5, | ||||
|         validators=[MinValueValidator(0)], | ||||
|         default=1, | ||||
|         verbose_name=_('Quantity') | ||||
|     ) | ||||
|  | ||||
|  | ||||
| def rename_stock_item_test_result_attachment(instance, filename): | ||||
|   | ||||
		Reference in New Issue
	
	Block a user