inventree-manufacturing-costs 0.1.1__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {inventree_manufacturing_costs-0.1.1/inventree_manufacturing_costs.egg-info → inventree_manufacturing_costs-0.2.1}/PKG-INFO +1 -1
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1/inventree_manufacturing_costs.egg-info}/PKG-INFO +1 -1
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/manufacturing_costs/__init__.py +1 -1
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/manufacturing_costs/static/PartPanel.js +49 -20
- inventree_manufacturing_costs-0.2.1/manufacturing_costs/static/PartPanel.js.map +1 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/manufacturing_costs/views.py +21 -4
- inventree_manufacturing_costs-0.1.1/manufacturing_costs/static/PartPanel.js.map +0 -1
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/LICENSE +0 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/MANIFEST.in +0 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/README.md +0 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/inventree_manufacturing_costs.egg-info/SOURCES.txt +0 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/inventree_manufacturing_costs.egg-info/dependency_links.txt +0 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/inventree_manufacturing_costs.egg-info/entry_points.txt +0 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/inventree_manufacturing_costs.egg-info/top_level.txt +0 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/manufacturing_costs/admin.py +0 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/manufacturing_costs/apps.py +0 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/manufacturing_costs/core.py +0 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/manufacturing_costs/migrations/0001_initial.py +0 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/manufacturing_costs/migrations/0002_remove_manufacturingcost_amortization_and_more.py +0 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/manufacturing_costs/migrations/0003_manufacturingcost_description.py +0 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/manufacturing_costs/migrations/0004_manufacturingcost_active_manufacturingcost_inherited.py +0 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/manufacturing_costs/migrations/__init__.py +0 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/manufacturing_costs/models.py +0 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/manufacturing_costs/serializers.py +0 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/manufacturing_costs/static/.vite/manifest.json +0 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/manufacturing_costs/static/AdminPanel.js +0 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/manufacturing_costs/static/AdminPanel.js.map +0 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/manufacturing_costs/static/assets/index-BjwOiYns.js +0 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/manufacturing_costs/static/assets/index-BjwOiYns.js.map +0 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/pyproject.toml +0 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/setup.cfg +0 -0
- {inventree_manufacturing_costs-0.1.1 → inventree_manufacturing_costs-0.2.1}/setup.py +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as createReactComponent, h as checkPluginVersion,
|
|
1
|
+
import { i as createReactComponent, h as checkPluginVersion, u as useQuery, a as apiUrl, R as RowEditAction, b as RowDuplicateAction, c as RowDeleteAction, j as formatDecimal, f as formatCurrencyValue, I as IconInfoCircle, d as RowActions, e as IconExclamationCircle, A as AddItemButton, S as SearchInput, g as IconRefresh, q as qr } from "./assets/index-BjwOiYns.js";
|
|
2
2
|
var ModelType = /* @__PURE__ */ ((ModelType2) => {
|
|
3
3
|
ModelType2["part"] = "part";
|
|
4
4
|
ModelType2["supplierpart"] = "supplierpart";
|
|
@@ -56,7 +56,6 @@ const Alert = window["MantineCore"].Alert;
|
|
|
56
56
|
const Button = window["MantineCore"].Button;
|
|
57
57
|
const Group = window["MantineCore"].Group;
|
|
58
58
|
const HoverCard = window["MantineCore"].HoverCard;
|
|
59
|
-
const Menu = window["MantineCore"].Menu;
|
|
60
59
|
const Stack = window["MantineCore"].Stack;
|
|
61
60
|
const Text = window["MantineCore"].Text;
|
|
62
61
|
const Tooltip = window["MantineCore"].Tooltip;
|
|
@@ -76,21 +75,6 @@ function ManufacturingCostsPanel({
|
|
|
76
75
|
const RATE_URL = "/plugin/manufacturing-costs/rate/";
|
|
77
76
|
const COST_URL = "/plugin/manufacturing-costs/cost/";
|
|
78
77
|
const EXPORT_URL = "/plugin/manufacturing-costs/cost/export/";
|
|
79
|
-
const downloadData = useCallback(
|
|
80
|
-
(exportFormat) => {
|
|
81
|
-
if (!partId) {
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
let url = `${apiUrl(EXPORT_URL)}?part=${partId}&export_format=${exportFormat}`;
|
|
85
|
-
if (context.host) {
|
|
86
|
-
url = `${context.host}${url}`;
|
|
87
|
-
} else {
|
|
88
|
-
url = `${window.location.origin}${url}`;
|
|
89
|
-
}
|
|
90
|
-
window.open(url, "_blank");
|
|
91
|
-
},
|
|
92
|
-
[partId, context.host, window.location]
|
|
93
|
-
);
|
|
94
78
|
const dataQuery = useQuery(
|
|
95
79
|
{
|
|
96
80
|
queryKey: ["manufacturing-cost", partId, searchTerm],
|
|
@@ -165,6 +149,43 @@ function ManufacturingCostsPanel({
|
|
|
165
149
|
dataQuery.refetch();
|
|
166
150
|
}
|
|
167
151
|
});
|
|
152
|
+
const exportDataForm = context.forms.create({
|
|
153
|
+
url: apiUrl(EXPORT_URL),
|
|
154
|
+
method: "GET",
|
|
155
|
+
title: "Export Manufacturing Costs",
|
|
156
|
+
fetchInitialData: false,
|
|
157
|
+
ignorePermissionCheck: true,
|
|
158
|
+
submitText: "Export",
|
|
159
|
+
fields: {
|
|
160
|
+
part: {
|
|
161
|
+
field_type: "integer",
|
|
162
|
+
value: partId,
|
|
163
|
+
hidden: true
|
|
164
|
+
},
|
|
165
|
+
export_format: {
|
|
166
|
+
label: "Export Format",
|
|
167
|
+
description: "Select the format for data export",
|
|
168
|
+
field_type: "choice",
|
|
169
|
+
choices: [
|
|
170
|
+
{ display_name: "CSV", value: "csv" },
|
|
171
|
+
{ display_name: "XLS", value: "xls" },
|
|
172
|
+
{ display_name: "XLSX", value: "xlsx" }
|
|
173
|
+
],
|
|
174
|
+
default: "csv"
|
|
175
|
+
},
|
|
176
|
+
include_subassemblies: {
|
|
177
|
+
field_type: "boolean",
|
|
178
|
+
label: "Include Sub-assemblies",
|
|
179
|
+
description: "Include manufacturing costs from sub-assemblies for this part",
|
|
180
|
+
default: true
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
onFormSuccess: (data) => {
|
|
184
|
+
if (data.complete && data.output) {
|
|
185
|
+
window.open(data.output, "_blank");
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
});
|
|
168
189
|
const rowActions = useCallback(
|
|
169
190
|
(record) => {
|
|
170
191
|
const partPk = context.instance.pk;
|
|
@@ -268,7 +289,7 @@ function ManufacturingCostsPanel({
|
|
|
268
289
|
}
|
|
269
290
|
];
|
|
270
291
|
}, []);
|
|
271
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, createCostForm.modal, duplicateCostForm.modal, editCostForm.modal, deleteCostForm.modal, /* @__PURE__ */ React.createElement(Stack, { gap: "xs" }, /* @__PURE__ */ React.createElement(
|
|
292
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, createCostForm.modal, duplicateCostForm.modal, editCostForm.modal, deleteCostForm.modal, exportDataForm.modal, /* @__PURE__ */ React.createElement(Stack, { gap: "xs" }, /* @__PURE__ */ React.createElement(
|
|
272
293
|
Alert,
|
|
273
294
|
{
|
|
274
295
|
color: "blue",
|
|
@@ -287,7 +308,8 @@ function ManufacturingCostsPanel({
|
|
|
287
308
|
), /* @__PURE__ */ React.createElement(Group, { justify: "space-between" }, /* @__PURE__ */ React.createElement(Group, { gap: "xs" }, /* @__PURE__ */ React.createElement(
|
|
288
309
|
AddItemButton,
|
|
289
310
|
{
|
|
290
|
-
tooltip: "Add new
|
|
311
|
+
tooltip: "Add new cost",
|
|
312
|
+
tooltipAlignment: "top-start",
|
|
291
313
|
onClick: () => {
|
|
292
314
|
createCostForm.open();
|
|
293
315
|
}
|
|
@@ -308,7 +330,14 @@ function ManufacturingCostsPanel({
|
|
|
308
330
|
}
|
|
309
331
|
},
|
|
310
332
|
/* @__PURE__ */ React.createElement(IconRefresh, null)
|
|
311
|
-
)), /* @__PURE__ */ React.createElement(
|
|
333
|
+
)), /* @__PURE__ */ React.createElement(
|
|
334
|
+
Button,
|
|
335
|
+
{
|
|
336
|
+
leftSection: /* @__PURE__ */ React.createElement(IconFileDownload, null),
|
|
337
|
+
onClick: () => exportDataForm.open()
|
|
338
|
+
},
|
|
339
|
+
"Export"
|
|
340
|
+
))), /* @__PURE__ */ React.createElement(
|
|
312
341
|
qr,
|
|
313
342
|
{
|
|
314
343
|
minHeight: 250,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PartPanel.js","sources":["../../frontend/node_modules/@inventreedb/ui/dist/enums/ModelType.js","../../frontend/node_modules/@tabler/icons-react/dist/esm/icons/IconFileDownload.mjs","../../frontend/node_modules/@tabler/icons-react/dist/esm/icons/IconUser.mjs","../../frontend/src/PartPanel.tsx"],"sourcesContent":["var ModelType = /* @__PURE__ */ ((ModelType2) => {\n ModelType2[\"part\"] = \"part\";\n ModelType2[\"supplierpart\"] = \"supplierpart\";\n ModelType2[\"manufacturerpart\"] = \"manufacturerpart\";\n ModelType2[\"partcategory\"] = \"partcategory\";\n ModelType2[\"partparametertemplate\"] = \"partparametertemplate\";\n ModelType2[\"parttesttemplate\"] = \"parttesttemplate\";\n ModelType2[\"projectcode\"] = \"projectcode\";\n ModelType2[\"stockitem\"] = \"stockitem\";\n ModelType2[\"stocklocation\"] = \"stocklocation\";\n ModelType2[\"stocklocationtype\"] = \"stocklocationtype\";\n ModelType2[\"stockhistory\"] = \"stockhistory\";\n ModelType2[\"build\"] = \"build\";\n ModelType2[\"buildline\"] = \"buildline\";\n ModelType2[\"builditem\"] = \"builditem\";\n ModelType2[\"company\"] = \"company\";\n ModelType2[\"purchaseorder\"] = \"purchaseorder\";\n ModelType2[\"purchaseorderlineitem\"] = \"purchaseorderlineitem\";\n ModelType2[\"salesorder\"] = \"salesorder\";\n ModelType2[\"salesordershipment\"] = \"salesordershipment\";\n ModelType2[\"returnorder\"] = \"returnorder\";\n ModelType2[\"returnorderlineitem\"] = \"returnorderlineitem\";\n ModelType2[\"importsession\"] = \"importsession\";\n ModelType2[\"address\"] = \"address\";\n ModelType2[\"contact\"] = \"contact\";\n ModelType2[\"owner\"] = \"owner\";\n ModelType2[\"user\"] = \"user\";\n ModelType2[\"group\"] = \"group\";\n ModelType2[\"reporttemplate\"] = \"reporttemplate\";\n ModelType2[\"labeltemplate\"] = \"labeltemplate\";\n ModelType2[\"pluginconfig\"] = \"pluginconfig\";\n ModelType2[\"contenttype\"] = \"contenttype\";\n ModelType2[\"selectionlist\"] = \"selectionlist\";\n ModelType2[\"error\"] = \"error\";\n return ModelType2;\n})(ModelType || {});\nexport {\n ModelType\n};\n//# sourceMappingURL=ModelType.js.map\n","/**\n * @license @tabler/icons-react v3.34.1 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M14 3v4a1 1 0 0 0 1 1h4\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2z\", \"key\": \"svg-1\" }], [\"path\", { \"d\": \"M12 17v-6\", \"key\": \"svg-2\" }], [\"path\", { \"d\": \"M9.5 14.5l2.5 2.5l2.5 -2.5\", \"key\": \"svg-3\" }]];\nconst IconFileDownload = createReactComponent(\"outline\", \"file-download\", \"FileDownload\", __iconNode);\n\nexport { __iconNode, IconFileDownload as default };\n//# sourceMappingURL=IconFileDownload.mjs.map\n","/**\n * @license @tabler/icons-react v3.34.1 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M8 7a4 4 0 1 0 8 0a4 4 0 0 0 -8 0\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M6 21v-2a4 4 0 0 1 4 -4h4a4 4 0 0 1 4 4v2\", \"key\": \"svg-1\" }]];\nconst IconUser = createReactComponent(\"outline\", \"user\", \"User\", __iconNode);\n\nexport { __iconNode, IconUser as default };\n//# sourceMappingURL=IconUser.mjs.map\n","// Import for type checking\nimport {\n AddItemButton,\n type ApiFormFieldSet,\n apiUrl,\n checkPluginVersion,\n formatCurrencyValue,\n formatDecimal,\n type InvenTreePluginContext,\n ModelType,\n RowActions,\n RowDeleteAction,\n RowDuplicateAction,\n RowEditAction,\n SearchInput\n} from '@inventreedb/ui';\nimport {\n ActionIcon,\n Alert,\n Button,\n Group,\n HoverCard,\n Stack,\n Text,\n Tooltip\n} from '@mantine/core';\nimport {\n IconExclamationCircle,\n IconFileDownload,\n IconInfoCircle,\n IconRefresh,\n IconUser\n} from '@tabler/icons-react';\nimport { useQuery } from '@tanstack/react-query';\nimport { DataTable } from 'mantine-datatable';\nimport { useCallback, useMemo, useState } from 'react';\n\nfunction RenderRate({ instance }: { instance: any }) {\n return (\n <Group gap='xs' justify='space-between'>\n <Text>{instance.name}</Text>\n <Group gap='xs' justify='right'>\n <Text size='xs'>{instance.description}</Text>\n {instance.units && <Text size='xs'>[{instance.units}]</Text>}\n </Group>\n </Group>\n );\n}\n\n/**\n * Render a custom panel with the provided context.\n * Refer to the InvenTree documentation for the context interface\n * https://docs.inventree.org/en/latest/plugins/mixins/ui/#plugin-context\n */\nfunction ManufacturingCostsPanel({\n context\n}: {\n context: InvenTreePluginContext;\n}) {\n const partId = useMemo(() => {\n return context.model == ModelType.part ? context.id || null : null;\n }, [context.model, context.id]);\n\n const [searchTerm, setSearchTerm] = useState<string>('');\n\n const RATE_URL: string = '/plugin/manufacturing-costs/rate/';\n const COST_URL: string = '/plugin/manufacturing-costs/cost/';\n const EXPORT_URL: string = '/plugin/manufacturing-costs/cost/export/';\n\n const dataQuery = useQuery(\n {\n queryKey: ['manufacturing-cost', partId, searchTerm],\n queryFn: async () => {\n const url = `${COST_URL}`;\n\n return (\n context.api\n ?.get(url, {\n params: {\n part: partId,\n search: searchTerm\n }\n })\n .then((response) => response.data)\n .catch(() => []) ?? []\n );\n }\n },\n context.queryClient\n );\n\n // Record which is selected in the table\n const [selectedRecord, setSelectedRecord] = useState<any>(null);\n\n const costFields: ApiFormFieldSet = useMemo(() => {\n return {\n part: {\n value: partId,\n disabled: true\n },\n description: {},\n quantity: {},\n // TODO: Add a \"pre-field\" element here\n rate: {\n api_url: apiUrl(RATE_URL),\n modelRenderer: RenderRate\n },\n // TODO: Mark unit_cost and unit_cost currency as \"disabled\" if a rate is selected\n unit_cost: {},\n unit_cost_currency: {},\n notes: {},\n inherited: {},\n active: {}\n };\n }, []);\n\n const createCostForm = context.forms.create({\n url: apiUrl(COST_URL),\n title: 'Add Manufacturing Cost',\n fields: costFields,\n successMessage: 'Cost created',\n onFormSuccess: () => {\n dataQuery.refetch();\n }\n });\n\n const duplicateCostForm = context.forms.create({\n url: apiUrl(COST_URL),\n title: 'Add Manufacturing Cost',\n fields: costFields,\n successMessage: 'Cost created',\n initialData: selectedRecord,\n onFormSuccess: () => {\n dataQuery.refetch();\n }\n });\n\n const editCostForm = context.forms.edit({\n url: apiUrl(COST_URL, selectedRecord?.pk),\n title: 'Edit Manufacturing Cost',\n fields: costFields,\n successMessage: 'Cost updated',\n onFormSuccess: () => {\n dataQuery.refetch();\n }\n });\n\n const deleteCostForm = context.forms.delete({\n url: apiUrl(COST_URL, selectedRecord?.pk),\n title: 'Delete Manufacturing Cost',\n successMessage: 'Cost deleted',\n onFormSuccess: () => {\n dataQuery.refetch();\n }\n });\n\n const exportDataForm = context.forms.create({\n url: apiUrl(EXPORT_URL),\n method: 'GET',\n title: 'Export Manufacturing Costs',\n fetchInitialData: false,\n ignorePermissionCheck: true,\n submitText: 'Export',\n fields: {\n part: {\n field_type: 'integer',\n value: partId,\n hidden: true\n },\n export_format: {\n label: 'Export Format',\n description: 'Select the format for data export',\n field_type: 'choice',\n choices: [\n { display_name: 'CSV', value: 'csv' },\n { display_name: 'XLS', value: 'xls' },\n { display_name: 'XLSX', value: 'xlsx' }\n ],\n default: 'csv'\n },\n include_subassemblies: {\n field_type: 'boolean',\n label: 'Include Sub-assemblies',\n description:\n 'Include manufacturing costs from sub-assemblies for this part',\n default: true\n }\n },\n onFormSuccess: (data: any) => {\n if (data.complete && data.output) {\n window.open(data.output, '_blank');\n }\n }\n });\n\n // Render the actions available for a given row in the table\n const rowActions = useCallback(\n (record: any) => {\n const partPk = context.instance.pk;\n\n return [\n RowEditAction({\n onClick: () => {\n setSelectedRecord(record);\n editCostForm?.open();\n },\n hidden: record.part != partPk\n }),\n RowDuplicateAction({\n onClick: () => {\n setSelectedRecord(record);\n duplicateCostForm?.open();\n }\n }),\n RowDeleteAction({\n onClick: () => {\n setSelectedRecord(record);\n deleteCostForm?.open();\n },\n hidden: record.part != partPk\n })\n ];\n },\n [context.instance]\n );\n\n const tableColums: any[] = useMemo(() => {\n return [\n {\n accessor: 'part',\n title: 'Part',\n render: (record: any) => record.part_detail?.full_name\n },\n {\n accessor: 'part_detail.IPN',\n title: 'IPN'\n },\n {\n accessor: 'description',\n title: 'Description'\n },\n {\n accessor: 'quantity',\n title: 'Quantity',\n format: (value: any) => formatDecimal(value)\n },\n {\n accessor: 'rate',\n title: 'Rate',\n render: (record: any) => {\n const rate = record.rate_detail;\n\n let unit_cost: string | number | null = '';\n\n if (rate) {\n unit_cost = formatCurrencyValue(rate.price, {\n currency: rate.price_currency\n });\n } else {\n unit_cost = formatCurrencyValue(record.unit_cost, {\n currency: record.unit_cost_currency\n });\n }\n\n return (\n <Group justify='space-between' gap='sm'>\n <Text>{unit_cost}</Text>\n {rate && (\n <HoverCard>\n <HoverCard.Target>\n <ActionIcon variant='transparent' size='sm'>\n <IconInfoCircle />\n </ActionIcon>\n </HoverCard.Target>\n <HoverCard.Dropdown>\n <RenderRate instance={rate} />\n </HoverCard.Dropdown>\n </HoverCard>\n )}\n </Group>\n );\n }\n },\n {\n accessor: 'notes',\n title: 'Notes'\n },\n {\n accessor: 'inherited',\n title: 'Inherited',\n render: (record: any) => (record.inherited ? 'Yes' : 'No')\n },\n {\n accessor: 'active',\n title: 'Active',\n render: (record: any) => (record.active ? 'Yes' : 'No')\n },\n {\n accessor: 'updated',\n title: 'Updated',\n render: (record: any) => {\n return (\n <Group justify='space-between'>\n <Text>{record.updated}</Text>\n {record.updated_by_detail && (\n <HoverCard position='bottom-end'>\n <HoverCard.Target>\n <ActionIcon variant='transparent' size='sm'>\n <IconUser />\n </ActionIcon>\n </HoverCard.Target>\n <HoverCard.Dropdown>\n {context.renderInstance({\n model: ModelType.user,\n instance: record.updated_by_detail\n })}\n </HoverCard.Dropdown>\n </HoverCard>\n )}\n </Group>\n );\n }\n },\n {\n accessor: '---',\n title: ' ',\n width: 50,\n resizable: false,\n sortable: false,\n render: (record: any, index: number) => (\n <RowActions actions={rowActions(record)} index={index} />\n )\n }\n ];\n }, []);\n\n return (\n <>\n {createCostForm.modal}\n {duplicateCostForm.modal}\n {editCostForm.modal}\n {deleteCostForm.modal}\n {exportDataForm.modal}\n <Stack gap='xs'>\n <Alert\n color='blue'\n icon={<IconInfoCircle />}\n title={'Manufacturing Costs'}\n >\n Additional manufacturing costs associated with this assembly.\n </Alert>\n {dataQuery.isError && (\n <Alert\n color='red'\n title='Error Fetching Data'\n icon={<IconExclamationCircle />}\n >\n {dataQuery.error instanceof Error\n ? dataQuery.error.message\n : 'An error occurred while fetching data from the server.'}\n </Alert>\n )}\n <Group justify='space-between'>\n <Group gap='xs'>\n <AddItemButton\n tooltip='Add new cost'\n tooltipAlignment='top-start'\n onClick={() => {\n createCostForm.open();\n }}\n />\n </Group>\n <Group gap='xs'>\n <SearchInput\n searchCallback={(value: string) => {\n setSearchTerm(value);\n }}\n />\n <Tooltip label='Refresh data' position='top-end'>\n <ActionIcon\n variant='transparent'\n onClick={() => {\n dataQuery.refetch();\n }}\n >\n <IconRefresh />\n </ActionIcon>\n </Tooltip>\n <Button\n leftSection={<IconFileDownload />}\n onClick={() => exportDataForm.open()}\n >\n Export\n </Button>\n </Group>\n </Group>\n <DataTable\n minHeight={250}\n withTableBorder\n withColumnBorders\n idAccessor={'pk'}\n noRecordsText='No manufacturing costs found'\n fetching={dataQuery.isFetching || dataQuery.isLoading}\n columns={tableColums}\n records={dataQuery.data || []}\n pinLastColumn\n />\n </Stack>\n </>\n );\n}\n\n// This is the function which is called by InvenTree to render the actual panel component\n// export function renderPartPanel(component: HTMLDivElement, context: InvenTreePluginContext) {\nexport function renderPartPanel(context: InvenTreePluginContext) {\n checkPluginVersion(context);\n return <ManufacturingCostsPanel context={context} />;\n}\n"],"names":["__iconNode","DataTable"],"mappings":"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","x_google_ignoreList":[0,1,2]}
|
|
@@ -5,12 +5,13 @@ from typing import cast
|
|
|
5
5
|
|
|
6
6
|
import tablib
|
|
7
7
|
|
|
8
|
+
from django.core.files.base import ContentFile
|
|
8
9
|
from django.db.models import Q
|
|
9
10
|
from django_filters import rest_framework as rest_filters
|
|
10
11
|
from rest_framework import filters, permissions
|
|
11
12
|
from rest_framework.views import APIView
|
|
13
|
+
from rest_framework.response import Response
|
|
12
14
|
|
|
13
|
-
from InvenTree.helpers import DownloadFile
|
|
14
15
|
from InvenTree.mixins import ListCreateAPI, RetrieveUpdateDestroyAPI
|
|
15
16
|
import part.models
|
|
16
17
|
|
|
@@ -152,11 +153,27 @@ class AssemblyCostExport(APIView):
|
|
|
152
153
|
|
|
153
154
|
data = self.dataset.export(self.export_format)
|
|
154
155
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
156
|
+
# Excel formats expect binary data
|
|
157
|
+
if self.export_format not in ["xls", "xlsx"]:
|
|
158
|
+
data = data.encode("utf-8")
|
|
159
|
+
|
|
160
|
+
# Create a new DataOutput object associated with this export session
|
|
161
|
+
from common.models import DataOutput
|
|
162
|
+
from common.serializers import DataOutputSerializer
|
|
163
|
+
|
|
164
|
+
filename = f"assembly_costs_{self.part.full_name}.{self.export_format}"
|
|
165
|
+
|
|
166
|
+
output = DataOutput.objects.create(
|
|
167
|
+
user=self.request.user,
|
|
168
|
+
output_type="manufacturing_costs",
|
|
169
|
+
plugin="manufacturing-costs",
|
|
170
|
+
progress=1,
|
|
171
|
+
complete=True,
|
|
172
|
+
output=ContentFile(data, filename),
|
|
158
173
|
)
|
|
159
174
|
|
|
175
|
+
return Response(DataOutputSerializer(output).data)
|
|
176
|
+
|
|
160
177
|
def file_headers(self):
|
|
161
178
|
"""Return the headers for the exported dataset."""
|
|
162
179
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PartPanel.js","sources":["../../frontend/node_modules/@inventreedb/ui/dist/enums/ModelType.js","../../frontend/node_modules/@tabler/icons-react/dist/esm/icons/IconFileDownload.mjs","../../frontend/node_modules/@tabler/icons-react/dist/esm/icons/IconUser.mjs","../../frontend/src/PartPanel.tsx"],"sourcesContent":["var ModelType = /* @__PURE__ */ ((ModelType2) => {\n ModelType2[\"part\"] = \"part\";\n ModelType2[\"supplierpart\"] = \"supplierpart\";\n ModelType2[\"manufacturerpart\"] = \"manufacturerpart\";\n ModelType2[\"partcategory\"] = \"partcategory\";\n ModelType2[\"partparametertemplate\"] = \"partparametertemplate\";\n ModelType2[\"parttesttemplate\"] = \"parttesttemplate\";\n ModelType2[\"projectcode\"] = \"projectcode\";\n ModelType2[\"stockitem\"] = \"stockitem\";\n ModelType2[\"stocklocation\"] = \"stocklocation\";\n ModelType2[\"stocklocationtype\"] = \"stocklocationtype\";\n ModelType2[\"stockhistory\"] = \"stockhistory\";\n ModelType2[\"build\"] = \"build\";\n ModelType2[\"buildline\"] = \"buildline\";\n ModelType2[\"builditem\"] = \"builditem\";\n ModelType2[\"company\"] = \"company\";\n ModelType2[\"purchaseorder\"] = \"purchaseorder\";\n ModelType2[\"purchaseorderlineitem\"] = \"purchaseorderlineitem\";\n ModelType2[\"salesorder\"] = \"salesorder\";\n ModelType2[\"salesordershipment\"] = \"salesordershipment\";\n ModelType2[\"returnorder\"] = \"returnorder\";\n ModelType2[\"returnorderlineitem\"] = \"returnorderlineitem\";\n ModelType2[\"importsession\"] = \"importsession\";\n ModelType2[\"address\"] = \"address\";\n ModelType2[\"contact\"] = \"contact\";\n ModelType2[\"owner\"] = \"owner\";\n ModelType2[\"user\"] = \"user\";\n ModelType2[\"group\"] = \"group\";\n ModelType2[\"reporttemplate\"] = \"reporttemplate\";\n ModelType2[\"labeltemplate\"] = \"labeltemplate\";\n ModelType2[\"pluginconfig\"] = \"pluginconfig\";\n ModelType2[\"contenttype\"] = \"contenttype\";\n ModelType2[\"selectionlist\"] = \"selectionlist\";\n ModelType2[\"error\"] = \"error\";\n return ModelType2;\n})(ModelType || {});\nexport {\n ModelType\n};\n//# sourceMappingURL=ModelType.js.map\n","/**\n * @license @tabler/icons-react v3.34.1 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M14 3v4a1 1 0 0 0 1 1h4\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2z\", \"key\": \"svg-1\" }], [\"path\", { \"d\": \"M12 17v-6\", \"key\": \"svg-2\" }], [\"path\", { \"d\": \"M9.5 14.5l2.5 2.5l2.5 -2.5\", \"key\": \"svg-3\" }]];\nconst IconFileDownload = createReactComponent(\"outline\", \"file-download\", \"FileDownload\", __iconNode);\n\nexport { __iconNode, IconFileDownload as default };\n//# sourceMappingURL=IconFileDownload.mjs.map\n","/**\n * @license @tabler/icons-react v3.34.1 - MIT\n *\n * This source code is licensed under the MIT license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createReactComponent from '../createReactComponent.mjs';\n\nconst __iconNode = [[\"path\", { \"d\": \"M8 7a4 4 0 1 0 8 0a4 4 0 0 0 -8 0\", \"key\": \"svg-0\" }], [\"path\", { \"d\": \"M6 21v-2a4 4 0 0 1 4 -4h4a4 4 0 0 1 4 4v2\", \"key\": \"svg-1\" }]];\nconst IconUser = createReactComponent(\"outline\", \"user\", \"User\", __iconNode);\n\nexport { __iconNode, IconUser as default };\n//# sourceMappingURL=IconUser.mjs.map\n","// Import for type checking\nimport {\n AddItemButton,\n type ApiFormFieldSet,\n apiUrl,\n checkPluginVersion,\n formatCurrencyValue,\n formatDecimal,\n type InvenTreePluginContext,\n ModelType,\n RowActions,\n RowDeleteAction,\n RowDuplicateAction,\n RowEditAction,\n SearchInput\n} from '@inventreedb/ui';\nimport {\n ActionIcon,\n Alert,\n Button,\n Group,\n HoverCard,\n Menu,\n Stack,\n Text,\n Tooltip\n} from '@mantine/core';\nimport {\n IconExclamationCircle,\n IconFileDownload,\n IconInfoCircle,\n IconRefresh,\n IconUser\n} from '@tabler/icons-react';\nimport { useQuery } from '@tanstack/react-query';\nimport { DataTable } from 'mantine-datatable';\nimport { useCallback, useMemo, useState } from 'react';\n\nfunction RenderRate({ instance }: { instance: any }) {\n return (\n <Group gap='xs' justify='space-between'>\n <Text>{instance.name}</Text>\n <Group gap='xs' justify='right'>\n <Text size='xs'>{instance.description}</Text>\n {instance.units && <Text size='xs'>[{instance.units}]</Text>}\n </Group>\n </Group>\n );\n}\n\n/**\n * Render a custom panel with the provided context.\n * Refer to the InvenTree documentation for the context interface\n * https://docs.inventree.org/en/latest/plugins/mixins/ui/#plugin-context\n */\nfunction ManufacturingCostsPanel({\n context\n}: {\n context: InvenTreePluginContext;\n}) {\n const partId = useMemo(() => {\n return context.model == ModelType.part ? context.id || null : null;\n }, [context.model, context.id]);\n\n const [searchTerm, setSearchTerm] = useState<string>('');\n\n const RATE_URL: string = '/plugin/manufacturing-costs/rate/';\n const COST_URL: string = '/plugin/manufacturing-costs/cost/';\n const EXPORT_URL: string = '/plugin/manufacturing-costs/cost/export/';\n\n // Callback to download the manufacturing cost data\n const downloadData = useCallback(\n (exportFormat: string) => {\n if (!partId) {\n return;\n }\n\n let url = `${apiUrl(EXPORT_URL)}?part=${partId}&export_format=${exportFormat}`;\n\n if (context.host) {\n url = `${context.host}${url}`;\n } else {\n url = `${window.location.origin}${url}`;\n }\n\n // TODO: Support other export options, besides data format\n\n window.open(url, '_blank');\n },\n [partId, context.host, window.location]\n );\n\n const dataQuery = useQuery(\n {\n queryKey: ['manufacturing-cost', partId, searchTerm],\n queryFn: async () => {\n const url = `${COST_URL}`;\n\n return (\n context.api\n ?.get(url, {\n params: {\n part: partId,\n search: searchTerm\n }\n })\n .then((response) => response.data)\n .catch(() => []) ?? []\n );\n }\n },\n context.queryClient\n );\n\n // Record which is selected in the table\n const [selectedRecord, setSelectedRecord] = useState<any>(null);\n\n const costFields: ApiFormFieldSet = useMemo(() => {\n return {\n part: {\n value: partId,\n disabled: true\n },\n description: {},\n quantity: {},\n // TODO: Add a \"pre-field\" element here\n rate: {\n api_url: apiUrl(RATE_URL),\n modelRenderer: RenderRate\n },\n // TODO: Mark unit_cost and unit_cost currency as \"disabled\" if a rate is selected\n unit_cost: {},\n unit_cost_currency: {},\n notes: {},\n inherited: {},\n active: {}\n };\n }, []);\n\n const createCostForm = context.forms.create({\n url: apiUrl(COST_URL),\n title: 'Add Manufacturing Cost',\n fields: costFields,\n successMessage: 'Cost created',\n onFormSuccess: () => {\n dataQuery.refetch();\n }\n });\n\n const duplicateCostForm = context.forms.create({\n url: apiUrl(COST_URL),\n title: 'Add Manufacturing Cost',\n fields: costFields,\n successMessage: 'Cost created',\n initialData: selectedRecord,\n onFormSuccess: () => {\n dataQuery.refetch();\n }\n });\n\n const editCostForm = context.forms.edit({\n url: apiUrl(COST_URL, selectedRecord?.pk),\n title: 'Edit Manufacturing Cost',\n fields: costFields,\n successMessage: 'Cost updated',\n onFormSuccess: () => {\n dataQuery.refetch();\n }\n });\n\n const deleteCostForm = context.forms.delete({\n url: apiUrl(COST_URL, selectedRecord?.pk),\n title: 'Delete Manufacturing Cost',\n successMessage: 'Cost deleted',\n onFormSuccess: () => {\n dataQuery.refetch();\n }\n });\n\n // Render the actions available for a given row in the table\n const rowActions = useCallback(\n (record: any) => {\n const partPk = context.instance.pk;\n\n return [\n RowEditAction({\n onClick: () => {\n setSelectedRecord(record);\n editCostForm?.open();\n },\n hidden: record.part != partPk\n }),\n RowDuplicateAction({\n onClick: () => {\n setSelectedRecord(record);\n duplicateCostForm?.open();\n }\n }),\n RowDeleteAction({\n onClick: () => {\n setSelectedRecord(record);\n deleteCostForm?.open();\n },\n hidden: record.part != partPk\n })\n ];\n },\n [context.instance]\n );\n\n const tableColums: any[] = useMemo(() => {\n return [\n {\n accessor: 'part',\n title: 'Part',\n render: (record: any) => record.part_detail?.full_name\n },\n {\n accessor: 'part_detail.IPN',\n title: 'IPN'\n },\n {\n accessor: 'description',\n title: 'Description'\n },\n {\n accessor: 'quantity',\n title: 'Quantity',\n format: (value: any) => formatDecimal(value)\n },\n {\n accessor: 'rate',\n title: 'Rate',\n render: (record: any) => {\n const rate = record.rate_detail;\n\n let unit_cost: string | number | null = '';\n\n if (rate) {\n unit_cost = formatCurrencyValue(rate.price, {\n currency: rate.price_currency\n });\n } else {\n unit_cost = formatCurrencyValue(record.unit_cost, {\n currency: record.unit_cost_currency\n });\n }\n\n return (\n <Group justify='space-between' gap='sm'>\n <Text>{unit_cost}</Text>\n {rate && (\n <HoverCard>\n <HoverCard.Target>\n <ActionIcon variant='transparent' size='sm'>\n <IconInfoCircle />\n </ActionIcon>\n </HoverCard.Target>\n <HoverCard.Dropdown>\n <RenderRate instance={rate} />\n </HoverCard.Dropdown>\n </HoverCard>\n )}\n </Group>\n );\n }\n },\n {\n accessor: 'notes',\n title: 'Notes'\n },\n {\n accessor: 'inherited',\n title: 'Inherited',\n render: (record: any) => (record.inherited ? 'Yes' : 'No')\n },\n {\n accessor: 'active',\n title: 'Active',\n render: (record: any) => (record.active ? 'Yes' : 'No')\n },\n {\n accessor: 'updated',\n title: 'Updated',\n render: (record: any) => {\n return (\n <Group justify='space-between'>\n <Text>{record.updated}</Text>\n {record.updated_by_detail && (\n <HoverCard position='bottom-end'>\n <HoverCard.Target>\n <ActionIcon variant='transparent' size='sm'>\n <IconUser />\n </ActionIcon>\n </HoverCard.Target>\n <HoverCard.Dropdown>\n {context.renderInstance({\n model: ModelType.user,\n instance: record.updated_by_detail\n })}\n </HoverCard.Dropdown>\n </HoverCard>\n )}\n </Group>\n );\n }\n },\n {\n accessor: '---',\n title: ' ',\n width: 50,\n resizable: false,\n sortable: false,\n render: (record: any, index: number) => (\n <RowActions actions={rowActions(record)} index={index} />\n )\n }\n ];\n }, []);\n\n return (\n <>\n {createCostForm.modal}\n {duplicateCostForm.modal}\n {editCostForm.modal}\n {deleteCostForm.modal}\n <Stack gap='xs'>\n <Alert\n color='blue'\n icon={<IconInfoCircle />}\n title={'Manufacturing Costs'}\n >\n Additional manufacturing costs associated with this assembly.\n </Alert>\n {dataQuery.isError && (\n <Alert\n color='red'\n title='Error Fetching Data'\n icon={<IconExclamationCircle />}\n >\n {dataQuery.error instanceof Error\n ? dataQuery.error.message\n : 'An error occurred while fetching data from the server.'}\n </Alert>\n )}\n <Group justify='space-between'>\n <Group gap='xs'>\n <AddItemButton\n tooltip='Add new rate'\n onClick={() => {\n createCostForm.open();\n }}\n />\n </Group>\n <Group gap='xs'>\n <SearchInput\n searchCallback={(value: string) => {\n setSearchTerm(value);\n }}\n />\n <Tooltip label='Refresh data' position='top-end'>\n <ActionIcon\n variant='transparent'\n onClick={() => {\n dataQuery.refetch();\n }}\n >\n <IconRefresh />\n </ActionIcon>\n </Tooltip>\n <Menu>\n <Menu.Target>\n <Button leftSection={<IconFileDownload />}>Export</Button>\n </Menu.Target>\n <Menu.Dropdown>\n <Menu.Item onClick={() => downloadData('csv')}>CSV</Menu.Item>\n <Menu.Item onClick={() => downloadData('xls')}>XLS</Menu.Item>\n <Menu.Item onClick={() => downloadData('xlsx')}>XLSX</Menu.Item>\n </Menu.Dropdown>\n </Menu>\n </Group>\n </Group>\n <DataTable\n minHeight={250}\n withTableBorder\n withColumnBorders\n idAccessor={'pk'}\n noRecordsText='No manufacturing costs found'\n fetching={dataQuery.isFetching || dataQuery.isLoading}\n columns={tableColums}\n records={dataQuery.data || []}\n pinLastColumn\n />\n </Stack>\n </>\n );\n}\n\n// This is the function which is called by InvenTree to render the actual panel component\n// export function renderPartPanel(component: HTMLDivElement, context: InvenTreePluginContext) {\nexport function renderPartPanel(context: InvenTreePluginContext) {\n checkPluginVersion(context);\n return <ManufacturingCostsPanel context={context} />;\n}\n"],"names":["__iconNode","DataTable"],"mappings":"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","x_google_ignoreList":[0,1,2]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|