{% load i18n %} {% load inventree_extras %} /* globals baseCurrency, Chart, constructForm, constructFormBody, constructInput, convertCurrency, formatCurrency, formatDecimal, formatPriceRange, getCurrencyConversionRates, getFormFieldValue, getTableData, global_settings, guessFieldType, handleFormErrors, handleFormSuccess, imageHoverIcon, inventreeGet, inventreeLoad, inventreePut, inventreeSave, loadTableFilters, makeDeleteButton, makeEditButton, makeIconBadge, makeIconButton, moment, orderParts, purchaseOrderStatusDisplay, receivePurchaseOrderItems, renderClipboard, renderDate, renderLink, setFormGroupVisibility, setupFilterList, shortenString, showAlertDialog, showApiError, showMessage, showModalSpinner, thumbnailImage, trueFalseLabel, updateFieldValue, withTitle, wrapButtons, yesNoLabel, */ /* exported createPart, createPartCategory, deletePart, deletePartCategory, duplicateBom, duplicatePart, editCategory, editPart, generateStocktakeReport, loadParametricPartTable, loadPartCategoryTable, loadPartParameterTable, loadPartParameterTemplateTable, loadPartPurchaseOrderTable, loadPartTable, loadPartTestTemplateTable, loadPartSchedulingChart, loadPartStocktakeTable, loadPartVariantTable, loadRelatedPartsTable, loadSimplePartTable, partDetail, partStockLabel, partTestTemplateFields, toggleStar, validateBom, */ /* Part API functions * Requires api.js to be loaded first */ function partGroups() { return { attributes: { title: '{% trans "Part Attributes" %}', collapsible: true, }, create: { title: '{% trans "Part Creation Options" %}', collapsible: true, }, duplicate: { title: '{% trans "Part Duplication Options" %}', collapsible: true, }, initial_stock: { title: '{% trans "Initial Stock" %}', collapsible: true, hidden: !global_settings.PART_CREATE_INITIAL, }, initial_supplier: { title: '{% trans "Initial Supplier Data" %}', collapsible: true, hidden: !global_settings.PART_CREATE_SUPPLIER, }, }; } // Construct fieldset for part forms function partFields(options={}) { var fields = { category: { secondary: { title: '{% trans "Add Part Category" %}', fields: function() { var fields = categoryFields(); return fields; } }, filters: { structural: false, }, }, name: {}, IPN: {}, revision: { icon: 'fa-code-branch', }, description: {}, variant_of: {}, keywords: { icon: 'fa-key', }, units: {}, link: { icon: 'fa-link', }, default_location: { icon: 'fa-sitemap', filters: { structural: false, } }, default_supplier: { icon: 'fa-building', filters: { part_detail: true, supplier_detail: true, } }, default_expiry: { icon: 'fa-calendar-alt', }, minimum_stock: { icon: 'fa-boxes', }, responsible: { icon: 'fa-user', }, component: { default: global_settings.PART_COMPONENT, group: 'attributes', }, assembly: { default: global_settings.PART_ASSEMBLY, group: 'attributes', }, is_template: { default: global_settings.PART_TEMPLATE, group: 'attributes', }, trackable: { default: global_settings.PART_TRACKABLE, group: 'attributes', }, purchaseable: { default: global_settings.PART_PURCHASEABLE, group: 'attributes', onEdit: function(value, name, field, options) { setFormGroupVisibility('supplier', value, options); } }, salable: { default: global_settings.PART_SALABLE, group: 'attributes', }, virtual: { default: global_settings.PART_VIRTUAL, group: 'attributes', }, }; if (options.category) { fields.category.value = options.category; } // If editing a part, we can set the "active" status if (options.edit) { fields.active = { group: 'attributes' }; } // Pop 'expiry' field if (!global_settings.STOCK_ENABLE_EXPIRY) { delete fields['default_expiry']; } // Pop 'revision' field if (!global_settings.PART_ENABLE_REVISION) { delete fields['revision']; } if (options.create || options.duplicate) { // Add fields for creating initial supplier data // Add fields for creating initial stock if (global_settings.PART_CREATE_INITIAL) { fields.initial_stock__quantity = { value: 0, }; fields.initial_stock__location = {}; } // Add fields for creating initial supplier data if (global_settings.PART_CREATE_SUPPLIER) { fields.initial_supplier__supplier = { filters: { is_supplier: true, } }; fields.initial_supplier__sku = {}; fields.initial_supplier__manufacturer = { filters: { is_manufacturer: true, } }; fields.initial_supplier__mpn = {}; } // No supplier parts available yet delete fields['default_supplier']; fields.copy_category_parameters = { value: global_settings.PART_CATEGORY_PARAMETERS, group: 'create', }; } // Additional fields when "duplicating" a part if (options.duplicate) { // The following fields exist under the child serializer named 'duplicate' fields.duplicate__part = { value: options.duplicate, hidden: true, }; fields.duplicate__copy_image = { value: true, }; fields.duplicate__copy_bom = { value: global_settings.PART_COPY_BOM, }; fields.duplicate__copy_parameters = { value: global_settings.PART_COPY_PARAMETERS, }; } return fields; } /* * Construct a set of fields for a PartCategory instance */ function categoryFields(options={}) { let fields = { parent: { help_text: '{% trans "Parent part category" %}', required: false, }, name: {}, description: {}, default_location: { icon: 'fa-sitemap', filters: { structural: false, } }, default_keywords: { icon: 'fa-key', }, structural: {}, icon: { help_text: `{% trans "Icon (optional) - Explore all available icons on" %} Font Awesome.`, placeholder: 'fas fa-tag', }, }; if (options.parent) { fields.parent.value = options.parent; } return fields; } // Create a PartCategory via the API function createPartCategory(options={}) { let fields = categoryFields(options); constructForm('{% url "api-part-category-list" %}', { fields: fields, method: 'POST', title: '{% trans "Create Part Category" %}', follow: true, persist: true, persistMessage: '{% trans "Create new category after this one" %}', successMessage: '{% trans "Part category created" %}' }); } // Edit a PartCategory via the API function editCategory(pk) { var url = `/api/part/category/${pk}/`; var fields = categoryFields(); constructForm(url, { fields: fields, title: '{% trans "Edit Part Category" %}', reload: true, }); } /* * Delete a PartCategory via the API */ function deletePartCategory(pk, options={}) { var url = `/api/part/category/${pk}/`; var html = `
${thumb} ${part.full_name} - ${part.description}
{% trans "Deleting this part cannot be reversed" %}