mirror of
https://github.com/inventree/InvenTree.git
synced 2025-10-29 20:30:39 +00:00
Delete locations fix (#10672)
* Cleaner handling of inputs * Fix for frontend form: - Fix typo in field - Better option defaults * Tweak part category delete form * Add frontend tests
This commit is contained in:
@@ -283,13 +283,11 @@ class CategoryDetail(CategoryMixin, OutputOptionsMixin, CustomRetrieveUpdateDest
|
|||||||
|
|
||||||
def destroy(self, request, *args, **kwargs):
|
def destroy(self, request, *args, **kwargs):
|
||||||
"""Delete a Part category instance via the API."""
|
"""Delete a Part category instance via the API."""
|
||||||
delete_parts = (
|
delete_parts = str2bool(request.data.get('delete_parts', False))
|
||||||
'delete_parts' in request.data and request.data['delete_parts'] == '1'
|
delete_child_categories = str2bool(
|
||||||
)
|
request.data.get('delete_child_categories', False)
|
||||||
delete_child_categories = (
|
|
||||||
'delete_child_categories' in request.data
|
|
||||||
and request.data['delete_child_categories'] == '1'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return super().destroy(
|
return super().destroy(
|
||||||
request,
|
request,
|
||||||
*args,
|
*args,
|
||||||
|
|||||||
@@ -431,8 +431,12 @@ class StockLocationDetail(
|
|||||||
|
|
||||||
def destroy(self, request, *args, **kwargs):
|
def destroy(self, request, *args, **kwargs):
|
||||||
"""Delete a Stock location instance via the API."""
|
"""Delete a Stock location instance via the API."""
|
||||||
delete_stock_items = str(request.data.get('delete_stock_items', 0)) == '1'
|
delete_stock_items = InvenTree.helpers.str2bool(
|
||||||
delete_sub_locations = str(request.data.get('delete_sub_locations', 0)) == '1'
|
request.data.get('delete_stock_items', False)
|
||||||
|
)
|
||||||
|
delete_sub_locations = InvenTree.helpers.str2bool(
|
||||||
|
request.data.get('delete_sub_locations', False)
|
||||||
|
)
|
||||||
|
|
||||||
return super().destroy(
|
return super().destroy(
|
||||||
request,
|
request,
|
||||||
|
|||||||
@@ -185,11 +185,11 @@ export default function CategoryDetail() {
|
|||||||
const deleteOptions = useMemo(() => {
|
const deleteOptions = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
value: 0,
|
value: 'false',
|
||||||
display_name: t`Move items to parent category`
|
display_name: t`Move items to parent category`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 1,
|
value: 'true',
|
||||||
display_name: t`Delete items`
|
display_name: t`Delete items`
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
@@ -204,12 +204,14 @@ export default function CategoryDetail() {
|
|||||||
label: t`Parts Action`,
|
label: t`Parts Action`,
|
||||||
description: t`Action for parts in this category`,
|
description: t`Action for parts in this category`,
|
||||||
choices: deleteOptions,
|
choices: deleteOptions,
|
||||||
|
required: true,
|
||||||
field_type: 'choice'
|
field_type: 'choice'
|
||||||
},
|
},
|
||||||
delete_child_categories: {
|
delete_child_categories: {
|
||||||
label: t`Child Categories Action`,
|
label: t`Child Categories Action`,
|
||||||
description: t`Action for child categories in this category`,
|
description: t`Action for child categories in this category`,
|
||||||
choices: deleteOptions,
|
choices: deleteOptions,
|
||||||
|
required: true,
|
||||||
field_type: 'choice'
|
field_type: 'choice'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -218,11 +218,11 @@ export default function Stock() {
|
|||||||
const deleteOptions = useMemo(() => {
|
const deleteOptions = useMemo(() => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
value: 0,
|
value: 'false',
|
||||||
display_name: t`Move items to parent location`
|
display_name: t`Move items to parent location`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 1,
|
value: 'true',
|
||||||
display_name: t`Delete items`
|
display_name: t`Delete items`
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
@@ -235,12 +235,14 @@ export default function Stock() {
|
|||||||
fields: {
|
fields: {
|
||||||
delete_stock_items: {
|
delete_stock_items: {
|
||||||
label: t`Items Action`,
|
label: t`Items Action`,
|
||||||
|
required: true,
|
||||||
description: t`Action for stock items in this location`,
|
description: t`Action for stock items in this location`,
|
||||||
field_type: 'choice',
|
field_type: 'choice',
|
||||||
choices: deleteOptions
|
choices: deleteOptions
|
||||||
},
|
},
|
||||||
delete_sub_location: {
|
delete_sub_locations: {
|
||||||
label: t`Child Locations Action`,
|
label: t`Locations Action`,
|
||||||
|
required: true,
|
||||||
description: t`Action for child locations in this location`,
|
description: t`Action for child locations in this location`,
|
||||||
field_type: 'choice',
|
field_type: 'choice',
|
||||||
choices: deleteOptions
|
choices: deleteOptions
|
||||||
|
|||||||
@@ -54,6 +54,67 @@ test('Stock - Location Tree', async ({ browser }) => {
|
|||||||
await page.getByRole('cell', { name: 'Factory' }).first().waitFor();
|
await page.getByRole('cell', { name: 'Factory' }).first().waitFor();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Stock - Location Delete', async ({ browser }) => {
|
||||||
|
const page = await doCachedLogin(browser, {
|
||||||
|
url: 'stock/location/38/sublocations'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create a sub-location
|
||||||
|
await page
|
||||||
|
.getByRole('button', { name: 'action-button-add-stock-location' })
|
||||||
|
.click();
|
||||||
|
await page
|
||||||
|
.getByRole('textbox', { name: 'text-field-name' })
|
||||||
|
.fill('my-location-1');
|
||||||
|
await page.getByRole('button', { name: 'Submit' }).click();
|
||||||
|
|
||||||
|
// Create a secondary sub-location
|
||||||
|
await loadTab(page, 'Sublocations');
|
||||||
|
await page
|
||||||
|
.getByRole('button', { name: 'action-button-add-stock-location' })
|
||||||
|
.click();
|
||||||
|
await page
|
||||||
|
.getByRole('textbox', { name: 'text-field-name' })
|
||||||
|
.fill('my-location-2');
|
||||||
|
await page.getByRole('button', { name: 'Submit' }).click();
|
||||||
|
|
||||||
|
// Navigate up to parent
|
||||||
|
await page.getByRole('link', { name: 'breadcrumb-2-my-location-1' }).click();
|
||||||
|
await loadTab(page, 'Sublocations');
|
||||||
|
await page
|
||||||
|
.getByRole('cell', { name: 'my-location-2', exact: true })
|
||||||
|
.waitFor();
|
||||||
|
|
||||||
|
// Delete this location, and all child locations
|
||||||
|
await page
|
||||||
|
.locator('div')
|
||||||
|
.filter({ hasText: /^Stock>PCB Assembler>my-location-1Stock Location$/ })
|
||||||
|
.getByLabel('action-menu-location-actions')
|
||||||
|
.click();
|
||||||
|
await page
|
||||||
|
.getByRole('menuitem', { name: 'action-menu-location-actions-delete' })
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByRole('textbox', { name: 'choice-field-delete_stock_items' })
|
||||||
|
.click();
|
||||||
|
await page
|
||||||
|
.getByRole('option', { name: 'Move items to parent location' })
|
||||||
|
.click();
|
||||||
|
|
||||||
|
await page
|
||||||
|
.getByRole('textbox', { name: 'choice-field-delete_sub_locations' })
|
||||||
|
.click();
|
||||||
|
await page.getByRole('option', { name: 'Delete items' }).click();
|
||||||
|
|
||||||
|
await page.getByRole('button', { name: 'Delete' }).click();
|
||||||
|
|
||||||
|
// Confirm we are on the right page
|
||||||
|
await page.getByText('External PCB assembler').waitFor();
|
||||||
|
await loadTab(page, 'Sublocations');
|
||||||
|
await page.getByText('No records found').first().waitFor();
|
||||||
|
});
|
||||||
|
|
||||||
test('Stock - Filters', async ({ browser }) => {
|
test('Stock - Filters', async ({ browser }) => {
|
||||||
const page = await doCachedLogin(browser, {
|
const page = await doCachedLogin(browser, {
|
||||||
username: 'steven',
|
username: 'steven',
|
||||||
|
|||||||
Reference in New Issue
Block a user