mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Merge branch 'inventree:master' into matmair/issue2501
This commit is contained in:
commit
b2676e3629
@ -311,6 +311,14 @@ if DEBUG and CONFIG.get('debug_toolbar', False): # pragma: no cover
|
||||
INSTALLED_APPS.append('debug_toolbar')
|
||||
MIDDLEWARE.append('debug_toolbar.middleware.DebugToolbarMiddleware')
|
||||
|
||||
# InvenTree URL configuration
|
||||
|
||||
# Base URL for admin pages (default="admin")
|
||||
INVENTREE_ADMIN_URL = get_setting(
|
||||
'INVENTREE_ADMIN_URL',
|
||||
CONFIG.get('admin_url', 'admin'),
|
||||
)
|
||||
|
||||
ROOT_URLCONF = 'InvenTree.urls'
|
||||
|
||||
TEMPLATES = [
|
||||
|
@ -4,7 +4,6 @@ Top-level URL lookup for InvenTree application.
|
||||
Passes URL lookup downstream to each app as required.
|
||||
"""
|
||||
|
||||
|
||||
from django.conf.urls import url, include
|
||||
from django.urls import path
|
||||
from django.contrib import admin
|
||||
@ -169,9 +168,9 @@ frontendpatterns = [
|
||||
url(r'^stats/', DatabaseStatsView.as_view(), name='stats'),
|
||||
|
||||
# admin sites
|
||||
url(r'^admin/error_log/', include('error_report.urls')),
|
||||
url(r'^admin/shell/', include('django_admin_shell.urls')),
|
||||
url(r'^admin/', admin.site.urls, name='inventree-admin'),
|
||||
url(f'^{settings.INVENTREE_ADMIN_URL}/error_log/', include('error_report.urls')),
|
||||
url(f'^{settings.INVENTREE_ADMIN_URL}/shell/', include('django_admin_shell.urls')),
|
||||
url(f'^{settings.INVENTREE_ADMIN_URL}/', admin.site.urls, name='inventree-admin'),
|
||||
|
||||
# DB user sessions
|
||||
url(r'^accounts/sessions/other/delete/$', view=CustomSessionDeleteOtherView.as_view(), name='session_delete_other', ),
|
||||
|
@ -12,11 +12,14 @@ import common.models
|
||||
INVENTREE_SW_VERSION = "0.7.0 dev"
|
||||
|
||||
# InvenTree API version
|
||||
INVENTREE_API_VERSION = 26
|
||||
INVENTREE_API_VERSION = 27
|
||||
|
||||
"""
|
||||
Increment this API version number whenever there is a significant change to the API that any clients need to know about
|
||||
|
||||
v27 -> 2022-02-28
|
||||
- Adds target_date field to individual line items for purchase orders and sales orders
|
||||
|
||||
v26 -> 2022-02-17
|
||||
- Adds API endpoint for uploading a BOM file and extracting data
|
||||
|
||||
|
@ -383,9 +383,7 @@ class Build(MPTTModel, ReferenceIndexingMixin):
|
||||
Returns the BOM items for the part referenced by this BuildOrder
|
||||
"""
|
||||
|
||||
return self.part.bom_items.all().prefetch_related(
|
||||
'sub_part'
|
||||
)
|
||||
return self.part.get_bom_items()
|
||||
|
||||
@property
|
||||
def tracked_bom_items(self):
|
||||
|
@ -151,7 +151,7 @@ src="{% static 'img/blank_image.png' %}"
|
||||
{% trans "Target Date" %}
|
||||
</td>
|
||||
<td>
|
||||
{{ build.target_date }}
|
||||
{% render_date build.target_date %}
|
||||
{% if build.is_overdue %}
|
||||
<span title='{% blocktrans with target=build.target_date %}This build was due on {{target}}{% endblocktrans %}' class='badge badge-right rounded-pill bg-danger'>{% trans "Overdue" %}</span>
|
||||
{% endif %}
|
||||
|
@ -18,7 +18,7 @@
|
||||
<div class='panel-content'>
|
||||
<div class='row'>
|
||||
<div class='col-sm-6'>
|
||||
<table class='table table-striped'>
|
||||
<table class='table table-striped table-condensed'>
|
||||
<col width='25'>
|
||||
<tr>
|
||||
<td><span class='fas fa-info'></span></td>
|
||||
@ -120,19 +120,19 @@
|
||||
</table>
|
||||
</div>
|
||||
<div class='col-sm-6'>
|
||||
<table class='table table-striped'>
|
||||
<table class='table table-striped table-condensed'>
|
||||
<col width='25'>
|
||||
<tr>
|
||||
<td><span class='fas fa-calendar-alt'></span></td>
|
||||
<td>{% trans "Created" %}</td>
|
||||
<td>{{ build.creation_date }}</td>
|
||||
<td>{% render_date build.creation_date %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class='fas fa-calendar-alt'></span></td>
|
||||
<td>{% trans "Target Date" %}</td>
|
||||
{% if build.target_date %}
|
||||
<td>
|
||||
{{ build.target_date }}{% if build.is_overdue %} <span class='fas fa-calendar-times icon-red'></span>{% endif %}
|
||||
{% render_date build.target_date %}{% if build.is_overdue %} <span class='fas fa-calendar-times icon-red'></span>{% endif %}
|
||||
</td>
|
||||
{% else %}
|
||||
<td><em>{% trans "No target date set" %}</em></td>
|
||||
@ -142,7 +142,7 @@
|
||||
<td><span class='fas fa-calendar-alt'></span></td>
|
||||
<td>{% trans "Completed" %}</td>
|
||||
{% if build.completion_date %}
|
||||
<td>{{ build.completion_date }}{% if build.completed_by %}<span class='badge badge-right rounded-pill bg-dark'>{{ build.completed_by }}</span>{% endif %}</td>
|
||||
<td>{% render_date build.completion_date %}{% if build.completed_by %}<span class='badge badge-right rounded-pill bg-dark'>{{ build.completed_by }}</span>{% endif %}</td>
|
||||
{% else %}
|
||||
<td><em>{% trans "Build not complete" %}</em></td>
|
||||
{% endif %}
|
||||
|
@ -443,12 +443,12 @@ class BaseInvenTreeSetting(models.Model):
|
||||
except self.DoesNotExist:
|
||||
pass
|
||||
|
||||
def choices(self):
|
||||
def choices(self, **kwargs):
|
||||
"""
|
||||
Return the available choices for this setting (or None if no choices are defined)
|
||||
"""
|
||||
|
||||
return self.__class__.get_setting_choices(self.key)
|
||||
return self.__class__.get_setting_choices(self.key, **kwargs)
|
||||
|
||||
def valid_options(self):
|
||||
"""
|
||||
@ -462,6 +462,33 @@ class BaseInvenTreeSetting(models.Model):
|
||||
|
||||
return [opt[0] for opt in choices]
|
||||
|
||||
def is_choice(self, **kwargs):
|
||||
"""
|
||||
Check if this setting is a "choice" field
|
||||
"""
|
||||
|
||||
return self.__class__.get_setting_choices(self.key, **kwargs) is not None
|
||||
|
||||
def as_choice(self, **kwargs):
|
||||
"""
|
||||
Render this setting as the "display" value of a choice field,
|
||||
e.g. if the choices are:
|
||||
[('A4', 'A4 paper'), ('A3', 'A3 paper')],
|
||||
and the value is 'A4',
|
||||
then display 'A4 paper'
|
||||
"""
|
||||
|
||||
choices = self.get_setting_choices(self.key, **kwargs)
|
||||
|
||||
if not choices:
|
||||
return self.value
|
||||
|
||||
for value, display in choices:
|
||||
if value == self.value:
|
||||
return display
|
||||
|
||||
return self.value
|
||||
|
||||
def is_bool(self, **kwargs):
|
||||
"""
|
||||
Check if this setting is required to be a boolean value
|
||||
@ -1212,6 +1239,21 @@ class InvenTreeUserSetting(BaseInvenTreeSetting):
|
||||
'default': False,
|
||||
'validator': bool,
|
||||
},
|
||||
|
||||
'DATE_DISPLAY_FORMAT': {
|
||||
'name': _('Date Format'),
|
||||
'description': _('Preferred format for displaying dates'),
|
||||
'default': 'YYYY-MM-DD',
|
||||
'choices': [
|
||||
('YYYY-MM-DD', '2022-02-22'),
|
||||
('YYYY/MM/DD', '2022/22/22'),
|
||||
('DD-MM-YYYY', '22-02-2022'),
|
||||
('DD/MM/YYYY', '22/02/2022'),
|
||||
('MM-DD-YYYY', '02-22-2022'),
|
||||
('MM/DD/YYYY', '02/22/2022'),
|
||||
('MMM DD YYYY', 'Feb 22 2022'),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
class Meta:
|
||||
|
@ -274,7 +274,7 @@ class POLineItemFilter(rest_filters.FilterSet):
|
||||
model = models.PurchaseOrderLineItem
|
||||
fields = [
|
||||
'order',
|
||||
'part'
|
||||
'part',
|
||||
]
|
||||
|
||||
pending = rest_filters.BooleanFilter(label='pending', method='filter_pending')
|
||||
@ -391,6 +391,7 @@ class POLineItemList(generics.ListCreateAPIView):
|
||||
'reference',
|
||||
'SKU',
|
||||
'total_price',
|
||||
'target_date',
|
||||
]
|
||||
|
||||
search_fields = [
|
||||
@ -401,11 +402,6 @@ class POLineItemList(generics.ListCreateAPIView):
|
||||
'reference',
|
||||
]
|
||||
|
||||
filter_fields = [
|
||||
'order',
|
||||
'part'
|
||||
]
|
||||
|
||||
|
||||
class POLineItemDetail(generics.RetrieveUpdateDestroyAPIView):
|
||||
"""
|
||||
@ -703,6 +699,7 @@ class SOLineItemList(generics.ListCreateAPIView):
|
||||
'part__name',
|
||||
'quantity',
|
||||
'reference',
|
||||
'target_date',
|
||||
]
|
||||
|
||||
search_fields = [
|
||||
|
23
InvenTree/order/migrations/0062_auto_20220228_0321.py
Normal file
23
InvenTree/order/migrations/0062_auto_20220228_0321.py
Normal file
@ -0,0 +1,23 @@
|
||||
# Generated by Django 3.2.10 on 2022-02-28 03:21
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('order', '0061_merge_0054_auto_20211201_2139_0060_auto_20211129_1339'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='purchaseorderlineitem',
|
||||
name='target_date',
|
||||
field=models.DateField(blank=True, help_text='Target shipping date for this line item', null=True, verbose_name='Target Date'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='salesorderlineitem',
|
||||
name='target_date',
|
||||
field=models.DateField(blank=True, help_text='Target shipping date for this line item', null=True, verbose_name='Target Date'),
|
||||
),
|
||||
]
|
@ -0,0 +1,17 @@
|
||||
# Generated by Django 3.2.10 on 2022-02-28 04:27
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('order', '0062_auto_20220228_0321'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterUniqueTogether(
|
||||
name='purchaseorderlineitem',
|
||||
unique_together=set(),
|
||||
),
|
||||
]
|
@ -816,9 +816,18 @@ class OrderLineItem(models.Model):
|
||||
|
||||
Attributes:
|
||||
quantity: Number of items
|
||||
reference: Reference text (e.g. customer reference) for this line item
|
||||
note: Annotation for the item
|
||||
target_date: An (optional) date for expected shipment of this line item.
|
||||
"""
|
||||
|
||||
"""
|
||||
Query filter for determining if an individual line item is "overdue":
|
||||
- Amount received is less than the required quantity
|
||||
- Target date is not None
|
||||
- Target date is in the past
|
||||
"""
|
||||
OVERDUE_FILTER = Q(received__lt=F('quantity')) & ~Q(target_date=None) & Q(target_date__lt=datetime.now().date())
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
@ -835,6 +844,12 @@ class OrderLineItem(models.Model):
|
||||
|
||||
notes = models.CharField(max_length=500, blank=True, verbose_name=_('Notes'), help_text=_('Line item notes'))
|
||||
|
||||
target_date = models.DateField(
|
||||
blank=True, null=True,
|
||||
verbose_name=_('Target Date'),
|
||||
help_text=_('Target shipping date for this line item'),
|
||||
)
|
||||
|
||||
|
||||
class PurchaseOrderLineItem(OrderLineItem):
|
||||
""" Model for a purchase order line item.
|
||||
@ -846,7 +861,6 @@ class PurchaseOrderLineItem(OrderLineItem):
|
||||
|
||||
class Meta:
|
||||
unique_together = (
|
||||
('order', 'part', 'quantity', 'purchase_price')
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
|
@ -12,7 +12,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||
from django.core.exceptions import ValidationError as DjangoValidationError
|
||||
from django.db import models, transaction
|
||||
from django.db.models import Case, When, Value
|
||||
from django.db.models import BooleanField, ExpressionWrapper, F
|
||||
from django.db.models import BooleanField, ExpressionWrapper, F, Q
|
||||
|
||||
from rest_framework import serializers
|
||||
from rest_framework.serializers import ValidationError
|
||||
@ -28,7 +28,7 @@ from InvenTree.serializers import InvenTreeModelSerializer
|
||||
from InvenTree.serializers import InvenTreeDecimalField
|
||||
from InvenTree.serializers import InvenTreeMoneySerializer
|
||||
from InvenTree.serializers import ReferenceIndexingSerializerMixin
|
||||
from InvenTree.status_codes import StockStatus
|
||||
from InvenTree.status_codes import StockStatus, PurchaseOrderStatus, SalesOrderStatus
|
||||
|
||||
import order.models
|
||||
|
||||
@ -128,6 +128,7 @@ class POLineItemSerializer(InvenTreeModelSerializer):
|
||||
Add some extra annotations to this queryset:
|
||||
|
||||
- Total price = purchase_price * quantity
|
||||
- "Overdue" status (boolean field)
|
||||
"""
|
||||
|
||||
queryset = queryset.annotate(
|
||||
@ -137,6 +138,15 @@ class POLineItemSerializer(InvenTreeModelSerializer):
|
||||
)
|
||||
)
|
||||
|
||||
queryset = queryset.annotate(
|
||||
overdue=Case(
|
||||
When(
|
||||
Q(order__status__in=PurchaseOrderStatus.OPEN) & order.models.OrderLineItem.OVERDUE_FILTER, then=Value(True, output_field=BooleanField())
|
||||
),
|
||||
default=Value(False, output_field=BooleanField()),
|
||||
)
|
||||
)
|
||||
|
||||
return queryset
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@ -157,6 +167,8 @@ class POLineItemSerializer(InvenTreeModelSerializer):
|
||||
quantity = serializers.FloatField(default=1)
|
||||
received = serializers.FloatField(default=0)
|
||||
|
||||
overdue = serializers.BooleanField(required=False, read_only=True)
|
||||
|
||||
total_price = serializers.FloatField(read_only=True)
|
||||
|
||||
part_detail = PartBriefSerializer(source='get_base_part', many=False, read_only=True)
|
||||
@ -187,6 +199,7 @@ class POLineItemSerializer(InvenTreeModelSerializer):
|
||||
'notes',
|
||||
'order',
|
||||
'order_detail',
|
||||
'overdue',
|
||||
'part',
|
||||
'part_detail',
|
||||
'supplier_part_detail',
|
||||
@ -196,6 +209,7 @@ class POLineItemSerializer(InvenTreeModelSerializer):
|
||||
'purchase_price_string',
|
||||
'destination',
|
||||
'destination_detail',
|
||||
'target_date',
|
||||
'total_price',
|
||||
]
|
||||
|
||||
@ -601,6 +615,23 @@ class SalesOrderAllocationSerializer(InvenTreeModelSerializer):
|
||||
class SOLineItemSerializer(InvenTreeModelSerializer):
|
||||
""" Serializer for a SalesOrderLineItem object """
|
||||
|
||||
@staticmethod
|
||||
def annotate_queryset(queryset):
|
||||
"""
|
||||
Add some extra annotations to this queryset:
|
||||
|
||||
- "Overdue" status (boolean field)
|
||||
"""
|
||||
|
||||
queryset = queryset.annotate(
|
||||
overdue=Case(
|
||||
When(
|
||||
Q(order__status__in=SalesOrderStatus.OPEN) & order.models.OrderLineItem.OVERDUE_FILTER, then=Value(True, output_field=BooleanField()),
|
||||
),
|
||||
default=Value(False, output_field=BooleanField()),
|
||||
)
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
||||
part_detail = kwargs.pop('part_detail', False)
|
||||
@ -622,6 +653,8 @@ class SOLineItemSerializer(InvenTreeModelSerializer):
|
||||
part_detail = PartBriefSerializer(source='part', many=False, read_only=True)
|
||||
allocations = SalesOrderAllocationSerializer(many=True, read_only=True, location_detail=True)
|
||||
|
||||
overdue = serializers.BooleanField(required=False, read_only=True)
|
||||
|
||||
quantity = InvenTreeDecimalField()
|
||||
|
||||
allocated = serializers.FloatField(source='allocated_quantity', read_only=True)
|
||||
@ -651,12 +684,14 @@ class SOLineItemSerializer(InvenTreeModelSerializer):
|
||||
'notes',
|
||||
'order',
|
||||
'order_detail',
|
||||
'overdue',
|
||||
'part',
|
||||
'part_detail',
|
||||
'sale_price',
|
||||
'sale_price_currency',
|
||||
'sale_price_string',
|
||||
'shipped',
|
||||
'target_date',
|
||||
]
|
||||
|
||||
|
||||
|
@ -141,27 +141,27 @@ src="{% static 'img/blank_image.png' %}"
|
||||
<tr>
|
||||
<td><span class='fas fa-calendar-alt'></span></td>
|
||||
<td>{% trans "Created" %}</td>
|
||||
<td>{{ order.creation_date }}<span class='badge badge-right rounded-pill bg-dark'>{{ order.created_by }}</span></td>
|
||||
<td>{% render_date order.creation_date %}<span class='badge badge-right rounded-pill bg-dark'>{{ order.created_by }}</span></td>
|
||||
</tr>
|
||||
{% if order.issue_date %}
|
||||
<tr>
|
||||
<td><span class='fas fa-calendar-alt'></span></td>
|
||||
<td>{% trans "Issued" %}</td>
|
||||
<td>{{ order.issue_date }}</td>
|
||||
<td>{% render_date order.issue_date %}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if order.target_date %}
|
||||
<tr>
|
||||
<td><span class='fas fa-calendar-alt'></span></td>
|
||||
<td>{% trans "Target Date" %}</td>
|
||||
<td>{{ order.target_date }}</td>
|
||||
<td>{% render_date order.target_date %}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if order.status == PurchaseOrderStatus.COMPLETE %}
|
||||
<tr>
|
||||
<td><span class='fas fa-calendar-alt'></span></td>
|
||||
<td>{% trans "Received" %}</td>
|
||||
<td>{{ order.complete_date }}<span class='badge badge-right rounded-pill bg-dark'>{{ order.received_by }}</span></td>
|
||||
<td>{% render_date order.complete_date %}<span class='badge badge-right rounded-pill bg-dark'>{{ order.received_by }}</span></td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if order.responsible %}
|
||||
|
@ -174,6 +174,7 @@ $('#new-po-line').click(function() {
|
||||
value: '{{ order.supplier.currency }}',
|
||||
{% endif %}
|
||||
},
|
||||
target_date: {},
|
||||
destination: {},
|
||||
notes: {},
|
||||
},
|
||||
@ -210,7 +211,7 @@ $('#new-po-line').click(function() {
|
||||
loadPurchaseOrderLineItemTable('#po-line-table', {
|
||||
order: {{ order.pk }},
|
||||
supplier: {{ order.supplier.pk }},
|
||||
{% if order.status == PurchaseOrderStatus.PENDING %}
|
||||
{% if roles.purchase_order.change %}
|
||||
allow_edit: true,
|
||||
{% else %}
|
||||
allow_edit: false,
|
||||
|
@ -155,13 +155,13 @@ src="{% static 'img/blank_image.png' %}"
|
||||
<tr>
|
||||
<td><span class='fas fa-calendar-alt'></span></td>
|
||||
<td>{% trans "Created" %}</td>
|
||||
<td>{{ order.creation_date }}<span class='badge badge-right rounded-pill bg-dark'>{{ order.created_by }}</span></td>
|
||||
<td>{% render_date order.creation_date %}<span class='badge badge-right rounded-pill bg-dark'>{{ order.created_by }}</span></td>
|
||||
</tr>
|
||||
{% if order.target_date %}
|
||||
<tr>
|
||||
<td><span class='fas fa-calendar-alt'></span></td>
|
||||
<td>{% trans "Target Date" %}</td>
|
||||
<td>{{ order.target_date }}</td>
|
||||
<td>{% render_date order.target_date %}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if order.shipment_date %}
|
||||
@ -169,7 +169,7 @@ src="{% static 'img/blank_image.png' %}"
|
||||
<td><span class='fas fa-truck'></span></td>
|
||||
<td>{% trans "Completed" %}</td>
|
||||
<td>
|
||||
{{ order.shipment_date }}
|
||||
{% render_date order.shipment_date %}
|
||||
{% if order.shipped_by %}
|
||||
<span class='badge badge-right rounded-pill bg-dark'>{{ order.shipped_by }}</span>
|
||||
{% endif %}
|
||||
|
@ -238,6 +238,7 @@
|
||||
reference: {},
|
||||
sale_price: {},
|
||||
sale_price_currency: {},
|
||||
target_date: {},
|
||||
notes: {},
|
||||
},
|
||||
method: 'POST',
|
||||
|
@ -1453,7 +1453,9 @@ class Part(MPTTModel):
|
||||
By default, will include inherited BOM items
|
||||
"""
|
||||
|
||||
return BomItem.objects.filter(self.get_bom_item_filter(include_inherited=include_inherited))
|
||||
queryset = BomItem.objects.filter(self.get_bom_item_filter(include_inherited=include_inherited))
|
||||
|
||||
return queryset.prefetch_related('sub_part')
|
||||
|
||||
def get_installed_part_options(self, include_inherited=True, include_variants=True):
|
||||
"""
|
||||
|
@ -122,7 +122,13 @@
|
||||
<h4>{% trans "Sales Order Allocations" %}</h4>
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<table class='table table-striped table-condensed' id='sales-order-allocation-table'></table>
|
||||
|
||||
<div id='sales-order-allocation-button-toolbar'>
|
||||
<div class='btn-group' role='group'>
|
||||
{% include "filter_list.html" with id="salesorderallocation" %}
|
||||
</div>
|
||||
</div>
|
||||
<table class='table table-striped table-condensed' id='sales-order-allocation-table' data-toolbar='#sales-order-allocation-button-toolbar'></table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -342,7 +348,12 @@
|
||||
<h4>{% trans "Build Order Allocations" %}</h4>
|
||||
</div>
|
||||
<div class='panel-content'>
|
||||
<table class='table table-striped table-condensed' id='build-order-allocation-table'></table>
|
||||
<div id='build-allocation-button-toolbar'>
|
||||
<div class='btn-group' role='group'>
|
||||
{% include "filter_list.html" with id="buildorderallocation" %}
|
||||
</div>
|
||||
</div>
|
||||
<table class='table table-striped table-condensed' id='build-order-allocation-table' data-toolbar='#build-allocation-button-toolbar'></table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -722,6 +733,7 @@
|
||||
});
|
||||
|
||||
// Load the BOM table data in the pricing view
|
||||
{% if part.has_bom and roles.sales_order.view %}
|
||||
loadBomTable($("#bom-pricing-table"), {
|
||||
editable: false,
|
||||
bom_url: "{% url 'api-bom-list' %}",
|
||||
@ -729,6 +741,7 @@
|
||||
parent_id: {{ part.id }} ,
|
||||
sub_part_detail: true,
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
onPanelLoad("purchase-orders", function() {
|
||||
loadPartPurchaseOrderTable(
|
||||
@ -952,7 +965,7 @@
|
||||
{% if price_history %}
|
||||
var purchasepricedata = {
|
||||
labels: [
|
||||
{% for line in price_history %}'{{ line.date }}',{% endfor %}
|
||||
{% for line in price_history %}'{% render_date line.date %}',{% endfor %}
|
||||
],
|
||||
datasets: [{
|
||||
label: '{% blocktrans %}Purchase Unit Price - {{currency}}{% endblocktrans %}',
|
||||
@ -1065,7 +1078,7 @@
|
||||
{% if sale_history %}
|
||||
var salepricedata = {
|
||||
labels: [
|
||||
{% for line in sale_history %}'{{ line.date }}',{% endfor %}
|
||||
{% for line in sale_history %}'{% render_date line.date %}',{% endfor %}
|
||||
],
|
||||
datasets: [{
|
||||
label: '{% blocktrans %}Unit Price - {{currency}}{% endblocktrans %}',
|
||||
|
@ -59,13 +59,13 @@
|
||||
<ul class='dropdown-menu'>
|
||||
<li>
|
||||
<a class='dropdown-item' href='#' id='part-count'>
|
||||
<span class='fas fa-clipboard-list'></span>
|
||||
<span class='fas fa-check-circle icon-green'></span>
|
||||
{% trans "Count part stock" %}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class='dropdown-item' href='#' id='part-move'>
|
||||
<span class='fas fa-exchange-alt'></span>
|
||||
<span class='fas fa-exchange-alt icon-blue'></span>
|
||||
{% trans "Transfer part stock" %}
|
||||
</a>
|
||||
</li>
|
||||
@ -312,7 +312,7 @@
|
||||
<td><span class='fas fa-calendar-alt'></span></td>
|
||||
<td>{% trans "Creation Date" %}</td>
|
||||
<td>
|
||||
{{ part.creation_date }}
|
||||
{% render_date part.creation_date %}
|
||||
{% if part.creation_user %}
|
||||
<span class='badge badge-right rounded-pill bg-dark'>{{ part.creation_user }}</span>
|
||||
{% endif %}
|
||||
|
@ -5,6 +5,7 @@ This module provides template tags for extra functionality,
|
||||
over and above the built-in Django tags.
|
||||
"""
|
||||
|
||||
from datetime import date
|
||||
import os
|
||||
import sys
|
||||
|
||||
@ -43,6 +44,52 @@ def define(value, *args, **kwargs):
|
||||
return value
|
||||
|
||||
|
||||
@register.simple_tag(takes_context=True)
|
||||
def render_date(context, date_object):
|
||||
"""
|
||||
Renders a date according to the preference of the provided user
|
||||
|
||||
Note that the user preference is stored using the formatting adopted by moment.js,
|
||||
which differs from the python formatting!
|
||||
"""
|
||||
|
||||
if date_object is None:
|
||||
return None
|
||||
|
||||
if type(date_object) == str:
|
||||
# If a string is passed, first convert it to a datetime
|
||||
date_object = date.fromisoformat(date_object)
|
||||
|
||||
# We may have already pre-cached the date format by calling this already!
|
||||
user_date_format = context.get('user_date_format', None)
|
||||
|
||||
if user_date_format is None:
|
||||
|
||||
user = context.get('user', None)
|
||||
|
||||
if user:
|
||||
# User is specified - look for their date display preference
|
||||
user_date_format = InvenTreeUserSetting.get_setting('DATE_DISPLAY_FORMAT', user=user)
|
||||
else:
|
||||
user_date_format = 'YYYY-MM-DD'
|
||||
|
||||
# Convert the format string to Pythonic equivalent
|
||||
replacements = [
|
||||
('YYYY', '%Y'),
|
||||
('MMM', '%b'),
|
||||
('MM', '%m'),
|
||||
('DD', '%d'),
|
||||
]
|
||||
|
||||
for o, n in replacements:
|
||||
user_date_format = user_date_format.replace(o, n)
|
||||
|
||||
# Update the context cache
|
||||
context['user_date_format'] = user_date_format
|
||||
|
||||
return date_object.strftime(user_date_format)
|
||||
|
||||
|
||||
@register.simple_tag()
|
||||
def decimal(x, *args, **kwargs):
|
||||
""" Simplified rendering of a decimal number """
|
||||
|
@ -120,13 +120,13 @@ content: "v{{report_revision}} - {{ date.isoformat }}";
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{% trans "Issued" %}</th>
|
||||
<td>{{ build.creation_date }}</td>
|
||||
<td>{% render_date build.creation_date %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{% trans "Target Date" %}</th>
|
||||
<td>
|
||||
{% if build.target_date %}
|
||||
{{ build.target_date }}
|
||||
{% render_date build.target_date %}
|
||||
{% else %}
|
||||
<em>Not specified</em>
|
||||
{% endif %}
|
||||
|
@ -909,7 +909,6 @@ class StockItem(MPTTModel):
|
||||
""" Can this stock item be deleted? It can NOT be deleted under the following circumstances:
|
||||
|
||||
- Has installed stock items
|
||||
- Has a serial number and is tracked
|
||||
- Is installed inside another StockItem
|
||||
- It has been assigned to a SalesOrder
|
||||
- It has been assigned to a BuildOrder
|
||||
@ -918,9 +917,6 @@ class StockItem(MPTTModel):
|
||||
if self.installed_item_count() > 0:
|
||||
return False
|
||||
|
||||
if self.part.trackable and self.serial is not None:
|
||||
return False
|
||||
|
||||
if self.sales_order is not None:
|
||||
return False
|
||||
|
||||
|
@ -66,7 +66,7 @@
|
||||
<ul class='dropdown-menu' role='menu'>
|
||||
{% if not item.serialized %}
|
||||
{% if item.in_stock %}
|
||||
<li><a class='dropdown-item' href='#' id='stock-count' title='{% trans "Count stock" %}'><span class='fas fa-clipboard-list'></span> {% trans "Count stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href='#' id='stock-count' title='{% trans "Count stock" %}'><span class='fas fa-check-circle icon-green'></span> {% trans "Count stock" %}</a></li>
|
||||
{% endif %}
|
||||
{% if not item.customer %}
|
||||
<li><a class='dropdown-item' href='#' id='stock-add' title='{% trans "Add stock" %}'><span class='fas fa-plus-circle icon-green'></span> {% trans "Add stock" %}</a></li>
|
||||
@ -187,7 +187,7 @@
|
||||
<td><span class='fas fa-calendar-alt{% if item.is_expired %} icon-red{% endif %}'></span></td>
|
||||
<td>{% trans "Expiry Date" %}</td>
|
||||
<td>
|
||||
{{ item.expiry_date }}
|
||||
{% render_date item.expiry_date %}
|
||||
{% if item.is_expired %}
|
||||
<span title='{% blocktrans %}This StockItem expired on {{ item.expiry_date }}{% endblocktrans %}' class='badge rounded-pill bg-danger badge-right'>{% trans "Expired" %}</span>
|
||||
{% elif item.is_stale %}
|
||||
@ -205,7 +205,7 @@
|
||||
<td><span class='fas fa-calendar-alt'></span></td>
|
||||
<td>{% trans "Last Stocktake" %}</td>
|
||||
{% if item.stocktake_date %}
|
||||
<td>{{ item.stocktake_date }} <span class='badge badge-right rounded-pill bg-dark'>{{ item.stocktake_user }}</span></td>
|
||||
<td>{% render_date item.stocktake_date %} <span class='badge badge-right rounded-pill bg-dark'>{{ item.stocktake_user }}</span></td>
|
||||
{% else %}
|
||||
<td><em>{% trans "No stocktake performed" %}</em></td>
|
||||
{% endif %}
|
||||
|
@ -81,7 +81,7 @@
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ plugin.author }}</td>
|
||||
<td>{{ plugin.pub_date }}</td>
|
||||
<td>{% render_date plugin.pub_date %}</td>
|
||||
<td>{% if plugin.version %}{{ plugin.version }}{% endif %}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
@ -36,7 +36,7 @@
|
||||
<tr>
|
||||
<td><span class='fas fa-calendar-alt'></span></td>
|
||||
<td>{% trans "Date" %}</td>
|
||||
<td>{{ plugin.pub_date }}{% include "clip.html" %}</td>
|
||||
<td>{% render_date plugin.pub_date %}{% include "clip.html" %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class='fas fa-hashtag'></span></td>
|
||||
@ -101,7 +101,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class='fas fa-calendar-alt'></span></td>
|
||||
<td>{% trans "Commit Date" %}</td><td>{{ plugin.package.date }}{% include "clip.html" %}</td>
|
||||
<td>{% trans "Commit Date" %}</td><td>{% render_date plugin.package.date %}{% include "clip.html" %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class='fas fa-code-branch'></span></td>
|
||||
|
@ -28,7 +28,11 @@
|
||||
<div id='setting-{{ setting.pk }}'>
|
||||
<span id='setting-value-{{ setting.key.upper }}' fieldname='{{ setting.key.upper }}'>
|
||||
{% if setting.value %}
|
||||
{% if setting.is_choice %}
|
||||
<strong>{{ setting.as_choice }}</strong>
|
||||
{% else %}
|
||||
<strong>{{ setting.value }}</strong>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<em style='color: #855;'>{% trans "No value set" %}</em>
|
||||
{% endif %}
|
||||
|
@ -15,6 +15,7 @@
|
||||
<table class='table table-striped table-condensed'>
|
||||
<tbody>
|
||||
{% include "InvenTree/settings/setting.html" with key="STICKY_HEADER" icon="fa-bars" user_setting=True %}
|
||||
{% include "InvenTree/settings/setting.html" with key="DATE_DISPLAY_FORMAT" icon="fa-calendar-alt" user_setting=True %}
|
||||
{% include "InvenTree/settings/setting.html" with key="FORMS_CLOSE_USING_ESCAPE" icon="fa-window-close" user_setting=True %}
|
||||
{% include "InvenTree/settings/setting.html" with key="PART_SHOW_QUANTITY_IN_FORMS" icon="fa-hashtag" user_setting=True %}
|
||||
</tbody>
|
||||
|
@ -44,7 +44,7 @@
|
||||
{% if commit_date %}
|
||||
<tr>
|
||||
<td><span class='fas fa-calendar-alt'></span></td>
|
||||
<td>{% trans "Commit Date" %}</td><td>{{ commit_date }}{% include "clip.html" %}</td>
|
||||
<td>{% trans "Commit Date" %}</td><td>{% render_date commit_date %}{% include "clip.html" %}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
@ -7,6 +7,7 @@
|
||||
clearEvents,
|
||||
endDate,
|
||||
startDate,
|
||||
renderDate,
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -32,3 +33,33 @@ function clearEvents(calendar) {
|
||||
event.remove();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Render the provided date in the user-specified format.
|
||||
*
|
||||
* The provided "date" variable is a string, nominally ISO format e.g. 2022-02-22
|
||||
* The user-configured setting DATE_DISPLAY_FORMAT determines how the date should be displayed.
|
||||
*/
|
||||
|
||||
function renderDate(date, options={}) {
|
||||
|
||||
if (!date) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var fmt = user_settings.DATE_DISPLAY_FORMAT || 'YYYY-MM-DD';
|
||||
|
||||
if (options.showTime) {
|
||||
fmt += ' HH:mm';
|
||||
}
|
||||
|
||||
var m = moment(date);
|
||||
|
||||
if (m.isValid()) {
|
||||
return m.format(fmt);
|
||||
} else {
|
||||
// Invalid input string, simply return provided value
|
||||
return date;
|
||||
}
|
||||
}
|
||||
|
@ -40,12 +40,15 @@ function editSetting(pk, options={}) {
|
||||
url = `/api/settings/user/${pk}/`;
|
||||
}
|
||||
|
||||
var reload_required = false;
|
||||
|
||||
// First, read the settings object from the server
|
||||
inventreeGet(url, {}, {
|
||||
success: function(response) {
|
||||
|
||||
if (response.choices && response.choices.length > 0) {
|
||||
response.type = 'choice';
|
||||
reload_required = true;
|
||||
}
|
||||
|
||||
// Construct the field
|
||||
@ -89,7 +92,9 @@ function editSetting(pk, options={}) {
|
||||
|
||||
var setting = response.key;
|
||||
|
||||
if (response.type == 'boolean') {
|
||||
if (reload_required) {
|
||||
location.reload();
|
||||
} else if (response.type == 'boolean') {
|
||||
var enabled = response.value.toString().toLowerCase() == 'true';
|
||||
$(`#setting-value-${setting}`).prop('checked', enabled);
|
||||
} else {
|
||||
|
@ -165,6 +165,9 @@ function loadAttachmentTable(url, options) {
|
||||
{
|
||||
field: 'upload_date',
|
||||
title: '{% trans "Upload Date" %}',
|
||||
formatter: function(value) {
|
||||
return renderDate(value);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'actions',
|
||||
|
@ -1961,6 +1961,9 @@ function loadBuildTable(table, options) {
|
||||
field: 'creation_date',
|
||||
title: '{% trans "Created" %}',
|
||||
sortable: true,
|
||||
formatter: function(value) {
|
||||
return renderDate(value);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'issued_by',
|
||||
@ -1990,11 +1993,17 @@ function loadBuildTable(table, options) {
|
||||
field: 'target_date',
|
||||
title: '{% trans "Target Date" %}',
|
||||
sortable: true,
|
||||
formatter: function(value) {
|
||||
return renderDate(value);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'completion_date',
|
||||
title: '{% trans "Completion Date" %}',
|
||||
sortable: true,
|
||||
formatter: function(value) {
|
||||
return renderDate(value);
|
||||
}
|
||||
},
|
||||
],
|
||||
});
|
||||
|
@ -923,11 +923,17 @@ function loadPurchaseOrderTable(table, options) {
|
||||
field: 'creation_date',
|
||||
title: '{% trans "Date" %}',
|
||||
sortable: true,
|
||||
formatter: function(value) {
|
||||
return renderDate(value);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'target_date',
|
||||
title: '{% trans "Target Date" %}',
|
||||
sortable: true,
|
||||
formatter: function(value) {
|
||||
return renderDate(value);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'line_items',
|
||||
@ -1005,6 +1011,7 @@ function loadPurchaseOrderLineItemTable(table, options={}) {
|
||||
reference: {},
|
||||
purchase_price: {},
|
||||
purchase_price_currency: {},
|
||||
target_date: {},
|
||||
destination: {},
|
||||
notes: {},
|
||||
},
|
||||
@ -1046,7 +1053,11 @@ function loadPurchaseOrderLineItemTable(table, options={}) {
|
||||
],
|
||||
{
|
||||
success: function() {
|
||||
// Reload the line item table
|
||||
$(table).bootstrapTable('refresh');
|
||||
|
||||
// Reload the "received stock" table
|
||||
$('#stock-table').bootstrapTable('refresh');
|
||||
}
|
||||
}
|
||||
);
|
||||
@ -1186,6 +1197,28 @@ function loadPurchaseOrderLineItemTable(table, options={}) {
|
||||
return formatter.format(total);
|
||||
}
|
||||
},
|
||||
{
|
||||
sortable: true,
|
||||
field: 'target_date',
|
||||
switchable: true,
|
||||
title: '{% trans "Target Date" %}',
|
||||
formatter: function(value, row) {
|
||||
if (row.target_date) {
|
||||
var html = renderDate(row.target_date);
|
||||
|
||||
if (row.overdue) {
|
||||
html += `<span class='fas fa-calendar-alt icon-red float-right' title='{% trans "This line item is overdue" %}'></span>`;
|
||||
}
|
||||
|
||||
return html;
|
||||
|
||||
} else if (row.order_detail && row.order_detail.target_date) {
|
||||
return `<em>${renderDate(row.order_detail.target_date)}</em>`;
|
||||
} else {
|
||||
return '-';
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
sortable: false,
|
||||
field: 'received',
|
||||
@ -1232,15 +1265,15 @@ function loadPurchaseOrderLineItemTable(table, options={}) {
|
||||
|
||||
var pk = row.pk;
|
||||
|
||||
if (options.allow_receive && row.received < row.quantity) {
|
||||
html += makeIconButton('fa-sign-in-alt icon-green', 'button-line-receive', pk, '{% trans "Receive line item" %}');
|
||||
}
|
||||
|
||||
if (options.allow_edit) {
|
||||
html += makeIconButton('fa-edit icon-blue', 'button-line-edit', pk, '{% trans "Edit line item" %}');
|
||||
html += makeIconButton('fa-trash-alt icon-red', 'button-line-delete', pk, '{% trans "Delete line item" %}');
|
||||
}
|
||||
|
||||
if (options.allow_receive && row.received < row.quantity) {
|
||||
html += makeIconButton('fa-sign-in-alt', 'button-line-receive', pk, '{% trans "Receive line item" %}');
|
||||
}
|
||||
|
||||
html += `</div>`;
|
||||
|
||||
return html;
|
||||
@ -1344,16 +1377,25 @@ function loadSalesOrderTable(table, options) {
|
||||
sortable: true,
|
||||
field: 'creation_date',
|
||||
title: '{% trans "Creation Date" %}',
|
||||
formatter: function(value) {
|
||||
return renderDate(value);
|
||||
}
|
||||
},
|
||||
{
|
||||
sortable: true,
|
||||
field: 'target_date',
|
||||
title: '{% trans "Target Date" %}',
|
||||
formatter: function(value) {
|
||||
return renderDate(value);
|
||||
}
|
||||
},
|
||||
{
|
||||
sortable: true,
|
||||
field: 'shipment_date',
|
||||
title: '{% trans "Shipment Date" %}',
|
||||
formatter: function(value) {
|
||||
return renderDate(value);
|
||||
}
|
||||
},
|
||||
{
|
||||
sortable: true,
|
||||
@ -1505,9 +1547,9 @@ function loadSalesOrderShipmentTable(table, options={}) {
|
||||
sortable: true,
|
||||
formatter: function(value, row) {
|
||||
if (value) {
|
||||
return value;
|
||||
return renderDate(value);
|
||||
} else {
|
||||
return '{% trans "Not shipped" %}';
|
||||
return '<em>{% trans "Not shipped" %}</em>';
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -2283,6 +2325,28 @@ function loadSalesOrderLineItemTable(table, options={}) {
|
||||
return formatter.format(total);
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'target_date',
|
||||
title: '{% trans "Target Date" %}',
|
||||
sortable: true,
|
||||
switchable: true,
|
||||
formatter: function(value, row) {
|
||||
if (row.target_date) {
|
||||
var html = renderDate(row.target_date);
|
||||
|
||||
if (row.overdue) {
|
||||
html += `<span class='fas fa-calendar-alt icon-red float-right' title='{% trans "This line item is overdue" %}'></span>`;
|
||||
}
|
||||
|
||||
return html;
|
||||
|
||||
} else if (row.order_detail && row.order_detail.target_date) {
|
||||
return `<em>${renderDate(row.order_detail.target_date)}</em>`;
|
||||
} else {
|
||||
return '-';
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
if (pending) {
|
||||
@ -2426,6 +2490,7 @@ function loadSalesOrderLineItemTable(table, options={}) {
|
||||
reference: {},
|
||||
sale_price: {},
|
||||
sale_price_currency: {},
|
||||
target_date: {},
|
||||
notes: {},
|
||||
},
|
||||
title: '{% trans "Edit Line Item" %}',
|
||||
|
@ -905,6 +905,28 @@ function loadPartPurchaseOrderTable(table, part_id, options={}) {
|
||||
field: 'quantity',
|
||||
title: '{% trans "Quantity" %}',
|
||||
},
|
||||
{
|
||||
field: 'target_date',
|
||||
title: '{% trans "Target Date" %}',
|
||||
switchable: true,
|
||||
sortable: true,
|
||||
formatter: function(value, row) {
|
||||
if (row.target_date) {
|
||||
var html = row.target_date;
|
||||
|
||||
if (row.overdue) {
|
||||
html += `<span class='fas fa-calendar-alt icon-red float-right' title='{% trans "This line item is overdue" %}'></span>`;
|
||||
}
|
||||
|
||||
return html;
|
||||
|
||||
} else if (row.order_detail && row.order_detail.target_date) {
|
||||
return `<em>${row.order_detail.target_date}</em>`;
|
||||
} else {
|
||||
return '-';
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'received',
|
||||
title: '{% trans "Received" %}',
|
||||
|
@ -25,7 +25,6 @@
|
||||
modalSetContent,
|
||||
modalSetTitle,
|
||||
modalSubmit,
|
||||
moment,
|
||||
openModal,
|
||||
printStockItemLabels,
|
||||
printTestReports,
|
||||
@ -1820,6 +1819,9 @@ function loadStockTable(table, options) {
|
||||
col = {
|
||||
field: 'stocktake_date',
|
||||
title: '{% trans "Stocktake" %}',
|
||||
formatter: function(value) {
|
||||
return renderDate(value);
|
||||
}
|
||||
};
|
||||
|
||||
if (!options.params.ordering) {
|
||||
@ -1833,6 +1835,9 @@ function loadStockTable(table, options) {
|
||||
title: '{% trans "Expiry Date" %}',
|
||||
visible: global_settings.STOCK_ENABLE_EXPIRY,
|
||||
switchable: global_settings.STOCK_ENABLE_EXPIRY,
|
||||
formatter: function(value) {
|
||||
return renderDate(value);
|
||||
}
|
||||
};
|
||||
|
||||
if (!options.params.ordering) {
|
||||
@ -1844,6 +1849,9 @@ function loadStockTable(table, options) {
|
||||
col = {
|
||||
field: 'updated',
|
||||
title: '{% trans "Last Updated" %}',
|
||||
formatter: function(value) {
|
||||
return renderDate(value);
|
||||
}
|
||||
};
|
||||
|
||||
if (!options.params.ordering) {
|
||||
@ -2649,14 +2657,7 @@ function loadStockTrackingTable(table, options) {
|
||||
title: '{% trans "Date" %}',
|
||||
sortable: true,
|
||||
formatter: function(value) {
|
||||
var m = moment(value);
|
||||
|
||||
if (m.isValid()) {
|
||||
var html = m.format('dddd MMMM Do YYYY'); // + '<br>' + m.format('h:mm a');
|
||||
return html;
|
||||
}
|
||||
|
||||
return '<i>{% trans "Invalid date" %}</i>';
|
||||
return renderDate(value, {showTime: true});
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -278,7 +278,7 @@ $.fn.inventreeTable = function(options) {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log(`Could not get list of visible columns for column '${tableName}'`);
|
||||
console.log(`Could not get list of visible columns for table '${tableName}'`);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@
|
||||
<ul class='dropdown-menu dropdown-menu-end inventree-navbar-menu'>
|
||||
{% if user.is_authenticated %}
|
||||
{% if user.is_staff and not demo %}
|
||||
<li><a class='dropdown-item' href="/admin/"><span class="fas fa-user-shield"></span> {% trans "Admin" %}</a></li>
|
||||
<li><a class='dropdown-item' href="{% url 'admin:index' %}"><span class="fas fa-user-shield"></span> {% trans "Admin" %}</a></li>
|
||||
{% endif %}
|
||||
<li><a class='dropdown-item' href="{% url 'settings' %}"><span class="fas fa-cog"></span> {% trans "Settings" %}</a></li>
|
||||
<li><a class='dropdown-item' href="{% url 'account_logout' %}"><span class="fas fa-sign-out-alt"></span> {% trans "Logout" %}</a></li>
|
||||
|
@ -46,16 +46,16 @@
|
||||
<ul class="dropdown-menu">
|
||||
{% if roles.stock.change %}
|
||||
<li><a class='dropdown-item' href="#" id='multi-item-add' title='{% trans "Add to selected stock items" %}'><span class='fas fa-plus-circle icon-green'></span> {% trans "Add stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href="#" id='multi-item-remove' title='{% trans "Remove from selected stock items" %}'><span class='fas fa-minus-circle'></span> {% trans "Remove stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href="#" id='multi-item-stocktake' title='{% trans "Stocktake selected stock items" %}'><span class='fas fa-check-circle'></span> {% trans "Count stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href='#' id='multi-item-move' title='{% trans "Move selected stock items" %}'><span class='fas fa-exchange-alt'></span> {% trans "Move stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href="#" id='multi-item-remove' title='{% trans "Remove from selected stock items" %}'><span class='fas fa-minus-circle icon-red'></span> {% trans "Remove stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href="#" id='multi-item-stocktake' title='{% trans "Stocktake selected stock items" %}'><span class='fas fa-check-circle icon-green'></span> {% trans "Count stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href='#' id='multi-item-move' title='{% trans "Move selected stock items" %}'><span class='fas fa-exchange-alt icon-blue'></span> {% trans "Transfer stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href='#' id='multi-item-merge' title='{% trans "Merge selected stock items" %}'><span class='fas fa-object-group'></span> {% trans "Merge stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href='#' id='multi-item-order' title='{% trans "Order selected items" %}'><span class='fas fa-shopping-cart'></span> {% trans "Order stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href='#' id='multi-item-assign' title='{% trans "Assign to customer" %}'><span class='fas fa-user-tie'></span> {% trans "Assign to customer" %}</a></li>
|
||||
<li><a class='dropdown-item' href='#' id='multi-item-set-status' title='{% trans "Change status" %}'><span class='fas fa-exclamation-circle'></span> {% trans "Change stock status" %}</a></li>
|
||||
{% endif %}
|
||||
{% if roles.stock.delete %}
|
||||
<li><a class='dropdown-item' href='#' id='multi-item-delete' title='{% trans "Delete selected items" %}'><span class='fas fa-trash-alt icon-red'></span> {% trans "Delete Stock" %}</a></li>
|
||||
<li><a class='dropdown-item' href='#' id='multi-item-delete' title='{% trans "Delete selected items" %}'><span class='fas fa-trash-alt icon-red'></span> {% trans "Delete stock" %}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -2,7 +2,7 @@
|
||||
InvenTree-Version: {% inventree_version %}
|
||||
Django Version: {% django_version %}
|
||||
{% inventree_commit_hash as hash %}{% if hash %}Commit Hash: {{ hash }}{% endif %}
|
||||
{% inventree_commit_date as commit_date %}{% if commit_date %}Commit Date: {{ commit_date }}{% endif %}
|
||||
{% inventree_commit_date as commit_date %}{% if commit_date %}Commit Date: {% render_date commit_date %}{% endif %}
|
||||
Database: {% inventree_db_engine %}
|
||||
Debug-Mode: {% inventree_in_debug_mode %}
|
||||
Deployed using Docker: {% inventree_docker_mode %}
|
Loading…
Reference in New Issue
Block a user