mirror of
https://github.com/inventree/InvenTree.git
synced 2025-07-20 03:36:30 +00:00
Merge branch 'master' of https://github.com/inventree/InvenTree into matmair/issue6281
This commit is contained in:
src
backend
InvenTree
InvenTree
locale
ar
LC_MESSAGES
bg
LC_MESSAGES
cs
LC_MESSAGES
da
LC_MESSAGES
de
LC_MESSAGES
el
LC_MESSAGES
en
LC_MESSAGES
es
LC_MESSAGES
es_MX
LC_MESSAGES
et
LC_MESSAGES
fa
LC_MESSAGES
fi
LC_MESSAGES
fr
LC_MESSAGES
he
LC_MESSAGES
hi
LC_MESSAGES
hu
LC_MESSAGES
id
LC_MESSAGES
it
LC_MESSAGES
ja
LC_MESSAGES
ko
LC_MESSAGES
lt
LC_MESSAGES
lv
LC_MESSAGES
nl
LC_MESSAGES
no
LC_MESSAGES
pl
LC_MESSAGES
pt
LC_MESSAGES
pt_BR
LC_MESSAGES
ro
LC_MESSAGES
ru
LC_MESSAGES
sk
LC_MESSAGES
sl
LC_MESSAGES
sr
LC_MESSAGES
sv
LC_MESSAGES
th
LC_MESSAGES
tr
LC_MESSAGES
uk
LC_MESSAGES
vi
LC_MESSAGES
zh_Hans
LC_MESSAGES
zh_Hant
LC_MESSAGES
order
part
frontend
src
contexts
forms
locales
ar
bg
cs
da
de
el
en
es
es_MX
et
fa
fi
fr
he
hi
hu
id
it
ja
ko
lt
lv
nl
no
pl
pt
pt_BR
ro
ru
sk
sl
sr
sv
th
tr
uk
vi
zh_Hans
zh_Hant
@@ -11,6 +11,10 @@ v299 - 2025-01-10 : https://github.com/inventree/InvenTree/pull/6293
|
|||||||
- Removes a considerable amount of old auth endpoints
|
- Removes a considerable amount of old auth endpoints
|
||||||
- Introduces allauth based REST API
|
- Introduces allauth based REST API
|
||||||
|
|
||||||
|
v299 - 2025-01-10 - https://github.com/inventree/InvenTree/pull/8867
|
||||||
|
- Adds 'expiry_date' field to the PurchaseOrderReceive API endpoint
|
||||||
|
- Adds 'default_expiry` field to the PartBriefSerializer, affecting API endpoints which use it
|
||||||
|
|
||||||
v298 - 2025-01-07 - https://github.com/inventree/InvenTree/pull/8848
|
v298 - 2025-01-07 - https://github.com/inventree/InvenTree/pull/8848
|
||||||
- Adds 'created_by' field to PurchaseOrder API endpoints
|
- Adds 'created_by' field to PurchaseOrder API endpoints
|
||||||
- Adds 'created_by' field to SalesOrder API endpoints
|
- Adds 'created_by' field to SalesOrder API endpoints
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -410,6 +410,7 @@ class PurchaseOrderReceive(PurchaseOrderContextMixin, CreateAPI):
|
|||||||
- supplier_part: pk value of the supplier part
|
- supplier_part: pk value of the supplier part
|
||||||
- quantity: quantity to receive
|
- quantity: quantity to receive
|
||||||
- status: stock item status
|
- status: stock item status
|
||||||
|
- expiry_date: stock item expiry date (optional)
|
||||||
- location: destination for stock item (optional)
|
- location: destination for stock item (optional)
|
||||||
- batch_code: the batch code for this stock item
|
- batch_code: the batch code for this stock item
|
||||||
- serial_numbers: serial numbers for this stock item
|
- serial_numbers: serial numbers for this stock item
|
||||||
|
@@ -796,10 +796,32 @@ class PurchaseOrder(TotalPriceMixin, Order):
|
|||||||
def receive_line_item(
|
def receive_line_item(
|
||||||
self, line, location, quantity, user, status=StockStatus.OK.value, **kwargs
|
self, line, location, quantity, user, status=StockStatus.OK.value, **kwargs
|
||||||
):
|
):
|
||||||
"""Receive a line item (or partial line item) against this PurchaseOrder."""
|
"""Receive a line item (or partial line item) against this PurchaseOrder.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
line: The PurchaseOrderLineItem to receive against
|
||||||
|
location: The StockLocation to receive the item into
|
||||||
|
quantity: The quantity to receive
|
||||||
|
user: The User performing the action
|
||||||
|
status: The StockStatus to assign to the item (default: StockStatus.OK)
|
||||||
|
|
||||||
|
Keyword Arguments:
|
||||||
|
barch_code: Optional batch code for the new StockItem
|
||||||
|
serials: Optional list of serial numbers to assign to the new StockItem(s)
|
||||||
|
notes: Optional notes field for the StockItem
|
||||||
|
packaging: Optional packaging field for the StockItem
|
||||||
|
barcode: Optional barcode field for the StockItem
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValidationError: If the quantity is negative or otherwise invalid
|
||||||
|
ValidationError: If the order is not in the 'PLACED' state
|
||||||
|
"""
|
||||||
# Extract optional batch code for the new stock item
|
# Extract optional batch code for the new stock item
|
||||||
batch_code = kwargs.get('batch_code', '')
|
batch_code = kwargs.get('batch_code', '')
|
||||||
|
|
||||||
|
# Extract optional expiry date for the new stock item
|
||||||
|
expiry_date = kwargs.get('expiry_date')
|
||||||
|
|
||||||
# Extract optional list of serial numbers
|
# Extract optional list of serial numbers
|
||||||
serials = kwargs.get('serials')
|
serials = kwargs.get('serials')
|
||||||
|
|
||||||
@@ -863,6 +885,7 @@ class PurchaseOrder(TotalPriceMixin, Order):
|
|||||||
purchase_order=self,
|
purchase_order=self,
|
||||||
status=status,
|
status=status,
|
||||||
batch=batch_code,
|
batch=batch_code,
|
||||||
|
expiry_date=expiry_date,
|
||||||
packaging=packaging,
|
packaging=packaging,
|
||||||
serial=sn,
|
serial=sn,
|
||||||
purchase_price=unit_purchase_price,
|
purchase_price=unit_purchase_price,
|
||||||
|
@@ -717,6 +717,7 @@ class PurchaseOrderLineItemReceiveSerializer(serializers.Serializer):
|
|||||||
'quantity',
|
'quantity',
|
||||||
'status',
|
'status',
|
||||||
'batch_code',
|
'batch_code',
|
||||||
|
'expiry_date',
|
||||||
'serial_numbers',
|
'serial_numbers',
|
||||||
'packaging',
|
'packaging',
|
||||||
'note',
|
'note',
|
||||||
@@ -765,6 +766,13 @@ class PurchaseOrderLineItemReceiveSerializer(serializers.Serializer):
|
|||||||
allow_blank=True,
|
allow_blank=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
expiry_date = serializers.DateField(
|
||||||
|
label=_('Expiry Date'),
|
||||||
|
help_text=_('Enter expiry date for incoming stock items'),
|
||||||
|
required=False,
|
||||||
|
default=None,
|
||||||
|
)
|
||||||
|
|
||||||
serial_numbers = serializers.CharField(
|
serial_numbers = serializers.CharField(
|
||||||
label=_('Serial Numbers'),
|
label=_('Serial Numbers'),
|
||||||
help_text=_('Enter serial numbers for incoming stock items'),
|
help_text=_('Enter serial numbers for incoming stock items'),
|
||||||
@@ -967,6 +975,7 @@ class PurchaseOrderReceiveSerializer(serializers.Serializer):
|
|||||||
status=item['status'],
|
status=item['status'],
|
||||||
barcode=item.get('barcode', ''),
|
barcode=item.get('barcode', ''),
|
||||||
batch_code=item.get('batch_code', ''),
|
batch_code=item.get('batch_code', ''),
|
||||||
|
expiry_date=item.get('expiry_date', None),
|
||||||
packaging=item.get('packaging', ''),
|
packaging=item.get('packaging', ''),
|
||||||
serials=item.get('serials', None),
|
serials=item.get('serials', None),
|
||||||
notes=item.get('note', None),
|
notes=item.get('note', None),
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
import base64
|
import base64
|
||||||
import io
|
import io
|
||||||
import json
|
import json
|
||||||
from datetime import datetime, timedelta
|
from datetime import date, datetime, timedelta
|
||||||
|
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import connection
|
from django.db import connection
|
||||||
@@ -1061,12 +1061,20 @@ class PurchaseOrderReceiveTest(OrderTest):
|
|||||||
self.assertEqual(line_1.received, 0)
|
self.assertEqual(line_1.received, 0)
|
||||||
self.assertEqual(line_2.received, 50)
|
self.assertEqual(line_2.received, 50)
|
||||||
|
|
||||||
|
one_week_from_today = date.today() + timedelta(days=7)
|
||||||
|
|
||||||
valid_data = {
|
valid_data = {
|
||||||
'items': [
|
'items': [
|
||||||
{'line_item': 1, 'quantity': 50, 'barcode': 'MY-UNIQUE-BARCODE-123'},
|
{
|
||||||
|
'line_item': 1,
|
||||||
|
'quantity': 50,
|
||||||
|
'expiry_date': one_week_from_today.strftime(r'%Y-%m-%d'),
|
||||||
|
'barcode': 'MY-UNIQUE-BARCODE-123',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
'line_item': 2,
|
'line_item': 2,
|
||||||
'quantity': 200,
|
'quantity': 200,
|
||||||
|
'expiry_date': one_week_from_today.strftime(r'%Y-%m-%d'),
|
||||||
'location': 2, # Explicit location
|
'location': 2, # Explicit location
|
||||||
'barcode': 'MY-UNIQUE-BARCODE-456',
|
'barcode': 'MY-UNIQUE-BARCODE-456',
|
||||||
},
|
},
|
||||||
@@ -1111,6 +1119,10 @@ class PurchaseOrderReceiveTest(OrderTest):
|
|||||||
self.assertEqual(stock_1.last().location.pk, 1)
|
self.assertEqual(stock_1.last().location.pk, 1)
|
||||||
self.assertEqual(stock_2.last().location.pk, 2)
|
self.assertEqual(stock_2.last().location.pk, 2)
|
||||||
|
|
||||||
|
# Expiry dates should be set
|
||||||
|
self.assertEqual(stock_1.last().expiry_date, one_week_from_today)
|
||||||
|
self.assertEqual(stock_2.last().expiry_date, one_week_from_today)
|
||||||
|
|
||||||
# Barcodes should have been assigned to the stock items
|
# Barcodes should have been assigned to the stock items
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
StockItem.objects.filter(barcode_data='MY-UNIQUE-BARCODE-123').exists()
|
StockItem.objects.filter(barcode_data='MY-UNIQUE-BARCODE-123').exists()
|
||||||
|
@@ -352,6 +352,7 @@ class PartBriefSerializer(InvenTree.serializers.InvenTreeModelSerializer):
|
|||||||
'barcode_hash',
|
'barcode_hash',
|
||||||
'category_default_location',
|
'category_default_location',
|
||||||
'default_location',
|
'default_location',
|
||||||
|
'default_expiry',
|
||||||
'name',
|
'name',
|
||||||
'revision',
|
'revision',
|
||||||
'full_name',
|
'full_name',
|
||||||
|
@@ -47,6 +47,7 @@ export const getSupportedLanguages = (): Record<string, string> => {
|
|||||||
ru: t`Russian`,
|
ru: t`Russian`,
|
||||||
sk: t`Slovak`,
|
sk: t`Slovak`,
|
||||||
sl: t`Slovenian`,
|
sl: t`Slovenian`,
|
||||||
|
sr: t`Serbian`,
|
||||||
sv: t`Swedish`,
|
sv: t`Swedish`,
|
||||||
th: t`Thai`,
|
th: t`Thai`,
|
||||||
tr: t`Turkish`,
|
tr: t`Turkish`,
|
||||||
|
@@ -25,6 +25,8 @@ import {
|
|||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { useEffect, useMemo, useState } from 'react';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
|
import { IconCalendarExclamation } from '@tabler/icons-react';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
import { api } from '../App';
|
import { api } from '../App';
|
||||||
import { ActionButton } from '../components/buttons/ActionButton';
|
import { ActionButton } from '../components/buttons/ActionButton';
|
||||||
import RemoveRowButton from '../components/buttons/RemoveRowButton';
|
import RemoveRowButton from '../components/buttons/RemoveRowButton';
|
||||||
@@ -49,7 +51,7 @@ import {
|
|||||||
useSerialNumberGenerator
|
useSerialNumberGenerator
|
||||||
} from '../hooks/UseGenerator';
|
} from '../hooks/UseGenerator';
|
||||||
import { apiUrl } from '../states/ApiState';
|
import { apiUrl } from '../states/ApiState';
|
||||||
|
import { useGlobalSettingsState } from '../states/SettingsState';
|
||||||
/*
|
/*
|
||||||
* Construct a set of fields for creating / editing a PurchaseOrderLineItem instance
|
* Construct a set of fields for creating / editing a PurchaseOrderLineItem instance
|
||||||
*/
|
*/
|
||||||
@@ -246,6 +248,8 @@ function LineItemFormRow({
|
|||||||
[record]
|
[record]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const settings = useGlobalSettingsState();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!!record.destination) {
|
if (!!record.destination) {
|
||||||
props.changeFn(props.idx, 'location', record.destination);
|
props.changeFn(props.idx, 'location', record.destination);
|
||||||
@@ -298,6 +302,23 @@ function LineItemFormRow({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [expiryDateOpen, expiryDateHandlers] = useDisclosure(false, {
|
||||||
|
onOpen: () => {
|
||||||
|
// check the default part expiry. Assume expiry is relative to today
|
||||||
|
const defaultExpiry = record.part_detail?.default_expiry;
|
||||||
|
if (defaultExpiry !== undefined && defaultExpiry > 0) {
|
||||||
|
props.changeFn(
|
||||||
|
props.idx,
|
||||||
|
'expiry_date',
|
||||||
|
dayjs().add(defaultExpiry, 'day').format('YYYY-MM-DD')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onClose: () => {
|
||||||
|
props.changeFn(props.idx, 'expiry_date', undefined);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Status value
|
// Status value
|
||||||
const [statusOpen, statusHandlers] = useDisclosure(false, {
|
const [statusOpen, statusHandlers] = useDisclosure(false, {
|
||||||
onClose: () => props.changeFn(props.idx, 'status', undefined)
|
onClose: () => props.changeFn(props.idx, 'status', undefined)
|
||||||
@@ -440,6 +461,16 @@ function LineItemFormRow({
|
|||||||
tooltipAlignment='top'
|
tooltipAlignment='top'
|
||||||
variant={batchOpen ? 'filled' : 'transparent'}
|
variant={batchOpen ? 'filled' : 'transparent'}
|
||||||
/>
|
/>
|
||||||
|
{settings.isSet('STOCK_ENABLE_EXPIRY') && (
|
||||||
|
<ActionButton
|
||||||
|
size='sm'
|
||||||
|
onClick={() => expiryDateHandlers.toggle()}
|
||||||
|
icon={<IconCalendarExclamation />}
|
||||||
|
tooltip={t`Set Expiry Date`}
|
||||||
|
tooltipAlignment='top'
|
||||||
|
variant={expiryDateOpen ? 'filled' : 'transparent'}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<ActionButton
|
<ActionButton
|
||||||
size='sm'
|
size='sm'
|
||||||
icon={<InvenTreeIcon icon='packaging' />}
|
icon={<InvenTreeIcon icon='packaging' />}
|
||||||
@@ -586,6 +617,21 @@ function LineItemFormRow({
|
|||||||
}}
|
}}
|
||||||
error={props.rowErrors?.serial_numbers?.message}
|
error={props.rowErrors?.serial_numbers?.message}
|
||||||
/>
|
/>
|
||||||
|
{settings.isSet('STOCK_ENABLE_EXPIRY') && (
|
||||||
|
<TableFieldExtraRow
|
||||||
|
visible={expiryDateOpen}
|
||||||
|
onValueChange={(value) =>
|
||||||
|
props.changeFn(props.idx, 'expiry_date', value)
|
||||||
|
}
|
||||||
|
fieldDefinition={{
|
||||||
|
field_type: 'date',
|
||||||
|
label: t`Expiry Date`,
|
||||||
|
description: t`Enter an expiry date for received items`,
|
||||||
|
value: props.item.expiry_date
|
||||||
|
}}
|
||||||
|
error={props.rowErrors?.expiry_date?.message}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<TableFieldExtraRow
|
<TableFieldExtraRow
|
||||||
visible={packagingOpen}
|
visible={packagingOpen}
|
||||||
onValueChange={(value) => props.changeFn(props.idx, 'packaging', value)}
|
onValueChange={(value) => props.changeFn(props.idx, 'packaging', value)}
|
||||||
@@ -672,6 +718,7 @@ export function useReceiveLineItems(props: LineItemsForm) {
|
|||||||
line_item: elem.pk,
|
line_item: elem.pk,
|
||||||
location: elem.destination ?? elem.destination_detail?.pk ?? null,
|
location: elem.destination ?? elem.destination_detail?.pk ?? null,
|
||||||
quantity: elem.quantity - elem.received,
|
quantity: elem.quantity - elem.received,
|
||||||
|
expiry_date: null,
|
||||||
batch_code: '',
|
batch_code: '',
|
||||||
serial_numbers: '',
|
serial_numbers: '',
|
||||||
status: 10,
|
status: 10,
|
||||||
|
@@ -13,6 +13,7 @@ import {
|
|||||||
import { useQuery, useSuspenseQuery } from '@tanstack/react-query';
|
import { useQuery, useSuspenseQuery } from '@tanstack/react-query';
|
||||||
import { Suspense, useEffect, useMemo, useState } from 'react';
|
import { Suspense, useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
|
import dayjs from 'dayjs';
|
||||||
import { api } from '../App';
|
import { api } from '../App';
|
||||||
import { ActionButton } from '../components/buttons/ActionButton';
|
import { ActionButton } from '../components/buttons/ActionButton';
|
||||||
import RemoveRowButton from '../components/buttons/RemoveRowButton';
|
import RemoveRowButton from '../components/buttons/RemoveRowButton';
|
||||||
@@ -68,6 +69,8 @@ export function useStockFields({
|
|||||||
const [nextBatchCode, setNextBatchCode] = useState<string>('');
|
const [nextBatchCode, setNextBatchCode] = useState<string>('');
|
||||||
const [nextSerialNumber, setNextSerialNumber] = useState<string>('');
|
const [nextSerialNumber, setNextSerialNumber] = useState<string>('');
|
||||||
|
|
||||||
|
const [expiryDate, setExpiryDate] = useState<string | null>(null);
|
||||||
|
|
||||||
const batchGenerator = useBatchCodeGenerator((value: any) => {
|
const batchGenerator = useBatchCodeGenerator((value: any) => {
|
||||||
if (value) {
|
if (value) {
|
||||||
setNextBatchCode(`${t`Next batch code`}: ${value}`);
|
setNextBatchCode(`${t`Next batch code`}: ${value}`);
|
||||||
@@ -106,6 +109,14 @@ export function useStockFields({
|
|||||||
|
|
||||||
// Clear the 'supplier_part' field if the part is changed
|
// Clear the 'supplier_part' field if the part is changed
|
||||||
setSupplierPart(null);
|
setSupplierPart(null);
|
||||||
|
|
||||||
|
// Adjust the 'expiry date' for the stock item
|
||||||
|
const expiry_days = record?.default_expiry ?? 0;
|
||||||
|
|
||||||
|
if (expiry_days && expiry_days > 0) {
|
||||||
|
// Adjust the expiry date based on the part default expiry
|
||||||
|
setExpiryDate(dayjs().add(expiry_days, 'days').toISOString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
supplier_part: {
|
supplier_part: {
|
||||||
@@ -171,7 +182,11 @@ export function useStockFields({
|
|||||||
},
|
},
|
||||||
expiry_date: {
|
expiry_date: {
|
||||||
icon: <IconCalendarExclamation />,
|
icon: <IconCalendarExclamation />,
|
||||||
hidden: !globalSettings.isSet('STOCK_ENABLE_EXPIRY')
|
hidden: !globalSettings.isSet('STOCK_ENABLE_EXPIRY'),
|
||||||
|
value: expiryDate,
|
||||||
|
onValueChange: (value) => {
|
||||||
|
setExpiryDate(value);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
purchase_price: {
|
purchase_price: {
|
||||||
icon: <IconCurrencyDollar />
|
icon: <IconCurrencyDollar />
|
||||||
@@ -194,9 +209,15 @@ export function useStockFields({
|
|||||||
// TODO: Handle custom field management based on provided options
|
// TODO: Handle custom field management based on provided options
|
||||||
// TODO: refer to stock.py in original codebase
|
// TODO: refer to stock.py in original codebase
|
||||||
|
|
||||||
|
// Remove the expiry date field if it is not enabled
|
||||||
|
if (!globalSettings.isSet('STOCK_ENABLE_EXPIRY')) {
|
||||||
|
delete fields.expiry_date;
|
||||||
|
}
|
||||||
|
|
||||||
return fields;
|
return fields;
|
||||||
}, [
|
}, [
|
||||||
stockItem,
|
stockItem,
|
||||||
|
expiryDate,
|
||||||
partInstance,
|
partInstance,
|
||||||
partId,
|
partId,
|
||||||
globalSettings,
|
globalSettings,
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user