diff --git a/Binner/Binner.Web/ClientApp/src/pages/Inventory.js b/Binner/Binner.Web/ClientApp/src/pages/Inventory.js
index 4b0d302a..752106c2 100644
--- a/Binner/Binner.Web/ClientApp/src/pages/Inventory.js
+++ b/Binner/Binner.Web/ClientApp/src/pages/Inventory.js
@@ -193,6 +193,9 @@ export function Inventory({ partNumber = "", ...rest }) {
const [confirmReImport, setConfirmReImport] = useState(false);
const [confirmReImportAction, setConfirmReImportAction] = useState(null);
+ // check if we are on the add page
+ const onAddPage = location.pathname === "/inventory/add";
+
let blocker = useBlocker(
({ currentLocation, nextLocation }) =>
isDirty && currentLocation.pathname !== nextLocation.pathname
@@ -243,8 +246,8 @@ export function Inventory({ partNumber = "", ...rest }) {
setLoadingPartMetadata(false);
} else if (rest.params.partNumberToAdd) {
// a part number to add is specified in the URL path
- const { data } = await doFetchPartMetadata(rest.params.partNumberToAdd, partToSearch, false);
- processPartMetadataResponse(data, partToSearch.storedFiles, true, true);
+ const { data, responseCode } = await doFetchPartMetadata(rest.params.partNumberToAdd, partToSearch, false, onAddPage);
+ processPartMetadataResponse(data, partToSearch.storedFiles, true, true, responseCode);
setLoadingPartMetadata(false);
setIsDirty(true);
} else {
@@ -254,8 +257,8 @@ export function Inventory({ partNumber = "", ...rest }) {
} else {
// fetch part metadata, don't allow overwriting of fields that have already been entered
setLoadingPartMetadata(true);
- const { data } = await doFetchPartMetadata(targetPart.partNumber, partToSearch, false);
- processPartMetadataResponse(data, partToSearch.storedFiles, true, false); // false, don't overwrite entered fields
+ const { data, responseCode } = await doFetchPartMetadata(targetPart.partNumber, partToSearch, false, onAddPage);
+ processPartMetadataResponse(data, partToSearch.storedFiles, true, false, responseCode); // false, don't overwrite entered fields
setLoadingPartMetadata(false);
setIsDirty(true);
}
@@ -296,7 +299,7 @@ export function Inventory({ partNumber = "", ...rest }) {
setPartMetadataErrors([]);
try {
const includeInventorySearch = !pageHasParameters;
- const { data, existsInInventory, inventoryPart } = await doFetchPartMetadata(input, localPart, includeInventorySearch);
+ const { data, existsInInventory, inventoryPart, responseCode } = await doFetchPartMetadata(input, localPart, includeInventorySearch, onAddPage);
if (existsInInventory) {
setPartExistsInInventory(true);
setSuggestedPartNumber(inventoryPart);
@@ -305,7 +308,7 @@ export function Inventory({ partNumber = "", ...rest }) {
setSuggestedPartNumber(null);
}
- processPartMetadataResponse(data, localPart.storedFiles, !pageHasParameters, true);
+ processPartMetadataResponse(data, localPart.storedFiles, !pageHasParameters, true, responseCode);
setLoadingPartMetadata(false);
return { part: localPart, exists: existsInInventory };
} catch (ex) {
@@ -466,7 +469,7 @@ export function Inventory({ partNumber = "", ...rest }) {
return entity;
}, []);
- const processPartMetadataResponse = useCallback((data, storedFiles, allowSetFromMetadata, allowOverwrite) => {
+ const processPartMetadataResponse = useCallback((data, storedFiles, allowSetFromMetadata, allowOverwrite, responseCode) => {
// cancelled or auth required
if (!data) {
setLoadingPartMetadata(false);
@@ -488,7 +491,7 @@ export function Inventory({ partNumber = "", ...rest }) {
if (allowSetFromMetadata) {
updatedPart = setPartFromMetadata(metadataParts, { ...suggestedPart, quantity: -1 }, allowOverwrite);
}
- } else {
+ } else if (responseCode !== 204) {
// no part metadata available
setPartMetadataIsSubscribed(true);
}
@@ -509,13 +512,13 @@ export function Inventory({ partNumber = "", ...rest }) {
* @param {bool} includeInventorySearch true to also check local inventory for the part
* @returns part information
*/
- const doFetchPartMetadata = async (partNumber, part, includeInventorySearch = true) => {
+ const doFetchPartMetadata = async (partNumber, part, includeInventorySearch = true, newPart = true) => {
if (partTypesRef.current.length === 0)
console.error("There are no partTypes! This shouldn't happen and is a bug.");
Inventory.doFetchPartMetadataController?.abort();
Inventory.doFetchPartMetadataController = new AbortController();
try {
- const response = await fetchApi(`/api/part/info?partNumber=${encodeURIComponent(partNumber.trim())}&partTypeId=${part.partTypeId}&mountingTypeId=${part.mountingTypeId}&supplierPartNumbers=digikey:${part.digiKeyPartNumber || ""},mouser:${part.mouserPartNumber || ""},arrow:${part.arrowPartNumber},tme:${part.tmePartNumber},element14:${part.element14PartNumber}`, {
+ const response = await fetchApi(`/api/part/info?newPart=${newPart}&partNumber=${encodeURIComponent(partNumber.trim())}&partTypeId=${part.partTypeId}&mountingTypeId=${part.mountingTypeId}&supplierPartNumbers=digikey:${part.digiKeyPartNumber || ""},mouser:${part.mouserPartNumber || ""},arrow:${part.arrowPartNumber},tme:${part.tmePartNumber},element14:${part.element14PartNumber}`, {
signal: Inventory.doFetchPartMetadataController.signal
});
const data = response.data;
@@ -545,7 +548,7 @@ export function Inventory({ partNumber = "", ...rest }) {
}
// let caller handle errors
- return { data, existsInInventory, inventoryPart: existingInventoryPartNumber };
+ return { data, existsInInventory, inventoryPart: existingInventoryPartNumber, responseCode: response.responseObject.status };
} catch (ex) {
if (ex?.name === "AbortError") {
@@ -836,8 +839,8 @@ export function Inventory({ partNumber = "", ...rest }) {
// part is not in inventory, add it as new
setLoadingPartMetadata(true);
- const { data } = await doFetchPartMetadata(cleanPartNumber, part, false);
- const metaResult = processPartMetadataResponse(data, part.storedFiles, true, true);
+ const { data, responseCode} = await doFetchPartMetadata(cleanPartNumber, part, false, onAddPage);
+ const metaResult = processPartMetadataResponse(data, part.storedFiles, true, true, responseCode);
setLoadingPartMetadata(false);
setIsDirty(true);
@@ -1453,8 +1456,8 @@ export function Inventory({ partNumber = "", ...rest }) {
e.stopPropagation();
setLoadingPartMetadata(true);
setConfirmRefreshPartIsOpen(false);
- const { data } = await doFetchPartMetadata(inputPartNumber, part, false);
- processPartMetadataResponse(data, part.storedFiles, true, true);
+ const { data, responseCode } = await doFetchPartMetadata(inputPartNumber, part, false, true);
+ processPartMetadataResponse(data, part.storedFiles, true, true, responseCode);
setLoadingPartMetadata(false);
setIsDirty(true);
if (confirmRefreshPartDoNotAskAgain) {
diff --git a/Binner/Binner.Web/ClientApp/src/pages/Settings.js b/Binner/Binner.Web/ClientApp/src/pages/Settings.js
index 0239af70..6dd67e33 100644
--- a/Binner/Binner.Web/ClientApp/src/pages/Settings.js
+++ b/Binner/Binner.Web/ClientApp/src/pages/Settings.js
@@ -111,6 +111,7 @@ export const Settings = () => {
enableAutoPartSearch: true,
enableDarkMode: false,
enableCheckNewVersion: true,
+ enableAutomaticMetadataFetchingForExistingParts: true,
});
const [integrationSettings, setIntegrationSettings] = useState({
binner: {
@@ -200,10 +201,10 @@ export const Settings = () => {
const { data } = response;
setLoading(false);
// break out data into multiple state variables to optimize render performance
- const { licenseKey, maxCacheItems, cacheAbsoluteExpirationMinutes, cacheSlidingExpirationMinutes, enableAutoPartSearch, enableDarkMode, enableCheckNewVersion } = data;
+ const { licenseKey, maxCacheItems, cacheAbsoluteExpirationMinutes, cacheSlidingExpirationMinutes, enableAutoPartSearch, enableDarkMode, enableCheckNewVersion, enableAutomaticMetadataFetchingForExistingParts } = data;
const language = data.locale.language;
const currency = data.locale.currency;
- setGlobalSettings({ licenseKey, language, currency, maxCacheItems, cacheAbsoluteExpirationMinutes, cacheSlidingExpirationMinutes, enableAutoPartSearch, enableDarkMode, enableCheckNewVersion });
+ setGlobalSettings({ licenseKey, language, currency, maxCacheItems, cacheAbsoluteExpirationMinutes, cacheSlidingExpirationMinutes, enableAutoPartSearch, enableDarkMode, enableCheckNewVersion, enableAutomaticMetadataFetchingForExistingParts });
const { binner, digikey, mouser, arrow, octopart, tme, element14 } = data;
setIntegrationSettings({ binner, digikey, mouser, arrow, octopart, tme, element14 });
setPrinterSettings({ printer: data.printer });
@@ -895,6 +896,28 @@ export const Settings = () => {
}
/>
+
+
+
+
+ Select this option to enable automatic updating using the part search APIs to fetch metadata for existing parts in your inventory when opening them in the inventory.
+ }
+ trigger={
+ handleChange(e, control, 'global')}
+ />
+ }
+ />
+
);
diff --git a/Binner/Binner.Web/Controllers/PartController.cs b/Binner/Binner.Web/Controllers/PartController.cs
index 3b2b35a3..89c4b6c5 100644
--- a/Binner/Binner.Web/Controllers/PartController.cs
+++ b/Binner/Binner.Web/Controllers/PartController.cs
@@ -639,8 +639,18 @@ public async Task GetLowStockAsync([FromQuery] PaginatedRequest r
/// List of supplier part numbers if known, in the format: 'suppliername:partnumber,suppliername2:partnumber'
///
[HttpGet("info")]
- public async Task GetPartInfoAsync([FromQuery] string partNumber, [FromQuery] string partTypeId = "", [FromQuery] string mountingTypeId = "", [FromQuery] string supplierPartNumbers = "")
+ public async Task GetPartInfoAsync([FromQuery] string partNumber, [FromQuery] string partTypeId = "", [FromQuery] string mountingTypeId = "", [FromQuery] string supplierPartNumbers = "", [FromQuery] bool? newPart = true)
{
+ // get the organization configuration
+ var organisationConfig = await _userConfigurationService.GetOrganizationConfigurationAsync();
+
+ // check the settings if we need to skip non new part search requests
+ if (newPart != null && newPart == false && organisationConfig.enableAutomaticMetadataFetchingForExistingParts == false)
+ {
+ // check if we should skip this request
+ return StatusCode(StatusCodes.Status204NoContent);
+ }
+
try
{
var partType = partTypeId;
diff --git a/Binner/Binner.Web/Controllers/PartTypeController.cs b/Binner/Binner.Web/Controllers/PartTypeController.cs
index 008f670d..9a60e45b 100644
--- a/Binner/Binner.Web/Controllers/PartTypeController.cs
+++ b/Binner/Binner.Web/Controllers/PartTypeController.cs
@@ -14,6 +14,8 @@
using System.Linq;
using System.Net.Mime;
using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Authentication.JwtBearer;
namespace Binner.Web.Controllers
{
diff --git a/Binner/Data/Binner.Data.Migrations.MySql/Migrations/20250824132916_automaticMetadataFetch.Designer.cs b/Binner/Data/Binner.Data.Migrations.MySql/Migrations/20250824132916_automaticMetadataFetch.Designer.cs
new file mode 100644
index 00000000..0a18f16b
--- /dev/null
+++ b/Binner/Data/Binner.Data.Migrations.MySql/Migrations/20250824132916_automaticMetadataFetch.Designer.cs
@@ -0,0 +1,2607 @@
+//
+using System;
+using Binner.Data;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace Binner.Data.Migrations.MySql.Migrations
+{
+ [DbContext(typeof(BinnerContext))]
+ [Migration("20250824132916_automaticMetadataFetch")]
+ partial class automaticMetadataFetch
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasDefaultSchema("dbo")
+ .HasAnnotation("ProductVersion", "9.0.6")
+ .HasAnnotation("Relational:MaxIdentifierLength", 64);
+
+ MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
+
+ modelBuilder.Entity("Binner.Data.Model.CustomField", b =>
+ {
+ b.Property("CustomFieldId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("CustomFieldId"));
+
+ b.Property("CustomFieldTypeId")
+ .HasColumnType("int");
+
+ b.Property("DateCreatedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("DateModifiedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("Description")
+ .HasColumnType("longtext");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("OrganizationId")
+ .HasColumnType("int");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.HasKey("CustomFieldId");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("CustomFields", "dbo");
+ });
+
+ modelBuilder.Entity("Binner.Data.Model.CustomFieldValue", b =>
+ {
+ b.Property("CustomFieldValueId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("CustomFieldValueId"));
+
+ b.Property("CustomFieldId")
+ .HasColumnType("bigint");
+
+ b.Property("CustomFieldTypeId")
+ .HasColumnType("int");
+
+ b.Property("DateCreatedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("DateModifiedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("OrganizationId")
+ .HasColumnType("int");
+
+ b.Property("RecordId")
+ .HasColumnType("bigint");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.Property("Value")
+ .HasColumnType("longtext");
+
+ b.HasKey("CustomFieldValueId");
+
+ b.HasIndex("CustomFieldId");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("CustomFieldValues", "dbo");
+ });
+
+ modelBuilder.Entity("Binner.Data.Model.Label", b =>
+ {
+ b.Property("LabelId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("LabelId"));
+
+ b.Property("DateCreatedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("DateModifiedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("IsPartLabelTemplate")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("LabelTemplateId")
+ .HasColumnType("int");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("OrganizationId")
+ .HasColumnType("int");
+
+ b.Property("Template")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.HasKey("LabelId");
+
+ b.HasIndex("LabelTemplateId");
+
+ b.ToTable("Labels", "dbo");
+ });
+
+ modelBuilder.Entity("Binner.Data.Model.LabelTemplate", b =>
+ {
+ b.Property("LabelTemplateId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("LabelTemplateId"));
+
+ b.Property("DateCreatedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("DateModifiedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("Description")
+ .HasColumnType("longtext");
+
+ b.Property("Dpi")
+ .HasColumnType("int");
+
+ b.Property("DriverHeight")
+ .HasColumnType("int");
+
+ b.Property("DriverName")
+ .HasColumnType("longtext");
+
+ b.Property("DriverWidth")
+ .HasColumnType("int");
+
+ b.Property("ExtraData")
+ .HasColumnType("longtext");
+
+ b.Property("Height")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("LabelCount")
+ .HasColumnType("int");
+
+ b.Property("LabelPaperSource")
+ .HasColumnType("int");
+
+ b.Property("Margin")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("OrganizationId")
+ .HasColumnType("int");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.Property("Width")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.HasKey("LabelTemplateId");
+
+ b.ToTable("LabelTemplates", "dbo");
+ });
+
+ modelBuilder.Entity("Binner.Data.Model.MessageState", b =>
+ {
+ b.Property("MessageStateId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("MessageStateId"));
+
+ b.Property("DateCreatedUtc")
+ .HasColumnType("datetime(6)");
+
+ b.Property("MessageId")
+ .HasColumnType("char(36)");
+
+ b.Property("OrganizationId")
+ .HasColumnType("int");
+
+ b.Property("ReadDateUtc")
+ .HasColumnType("datetime(6)");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.HasKey("MessageStateId");
+
+ b.ToTable("MessageStates", "dbo");
+ });
+
+ modelBuilder.Entity("Binner.Data.Model.OAuthCredential", b =>
+ {
+ b.Property("OAuthCredentialId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("OAuthCredentialId"));
+
+ b.Property("AccessToken")
+ .HasColumnType("longtext");
+
+ b.Property("ApiSettings")
+ .HasColumnType("longtext");
+
+ b.Property("DateCreatedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("DateExpiresUtc")
+ .HasColumnType("datetime(6)");
+
+ b.Property("DateModifiedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("Ip")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasDefaultValue(0L);
+
+ b.Property("OrganizationId")
+ .HasColumnType("int");
+
+ b.Property("Provider")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("varchar(128)");
+
+ b.Property("RefreshToken")
+ .HasColumnType("longtext");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.HasKey("OAuthCredentialId");
+
+ b.HasIndex("UserId");
+
+ b.HasIndex("Provider", "UserId", "OrganizationId");
+
+ b.ToTable("OAuthCredentials", "dbo");
+ });
+
+ modelBuilder.Entity("Binner.Data.Model.OAuthRequest", b =>
+ {
+ b.Property("OAuthRequestId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("OAuthRequestId"));
+
+ b.Property("AuthorizationCode")
+ .HasColumnType("longtext");
+
+ b.Property("AuthorizationReceived")
+ .HasColumnType("tinyint(1)")
+ .HasDefaultValue(false);
+
+ b.Property("DateCreatedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("DateModifiedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("Error")
+ .HasColumnType("longtext");
+
+ b.Property("ErrorDescription")
+ .HasColumnType("longtext");
+
+ b.Property("Ip")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint")
+ .HasDefaultValue(0L);
+
+ b.Property("OrganizationId")
+ .HasColumnType("int");
+
+ b.Property("Provider")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("RequestId")
+ .HasColumnType("char(36)");
+
+ b.Property("ReturnToUrl")
+ .HasColumnType("longtext");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.HasKey("OAuthRequestId");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("OAuthRequests", "dbo");
+ });
+
+ modelBuilder.Entity("Binner.Data.Model.OrderImportHistory", b =>
+ {
+ b.Property("OrderImportHistoryId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("OrderImportHistoryId"));
+
+ b.Property("DateCreatedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("DateModifiedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("Invoice")
+ .HasColumnType("longtext");
+
+ b.Property("OrganizationId")
+ .HasColumnType("int");
+
+ b.Property("Packlist")
+ .HasColumnType("longtext");
+
+ b.Property("SalesOrder")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("Supplier")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.HasKey("OrderImportHistoryId");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("OrderImportHistories", "dbo");
+ });
+
+ modelBuilder.Entity("Binner.Data.Model.OrderImportHistoryLineItem", b =>
+ {
+ b.Property("OrderImportHistoryLineItemId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("OrderImportHistoryLineItemId"));
+
+ b.Property("Cost")
+ .HasColumnType("double");
+
+ b.Property("CustomerReference")
+ .HasColumnType("longtext");
+
+ b.Property("DateCreatedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("DateModifiedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("Description")
+ .HasColumnType("longtext");
+
+ b.Property("Manufacturer")
+ .HasColumnType("longtext");
+
+ b.Property("ManufacturerPartNumber")
+ .HasColumnType("longtext");
+
+ b.Property("OrderImportHistoryId")
+ .HasColumnType("bigint");
+
+ b.Property("OrganizationId")
+ .HasColumnType("int");
+
+ b.Property("PartId")
+ .HasColumnType("bigint");
+
+ b.Property("PartNumber")
+ .HasColumnType("longtext");
+
+ b.Property("Quantity")
+ .HasColumnType("bigint");
+
+ b.Property("Supplier")
+ .HasColumnType("longtext");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.HasKey("OrderImportHistoryLineItemId");
+
+ b.HasIndex("OrderImportHistoryId");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("OrderImportHistoryLineItems", "dbo");
+ });
+
+ modelBuilder.Entity("Binner.Data.Model.Organization", b =>
+ {
+ b.Property("OrganizationId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("OrganizationId"));
+
+ b.Property("DateCreatedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("DateLockedUtc")
+ .HasColumnType("datetime(6)");
+
+ b.Property("DateModifiedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("Description")
+ .HasColumnType("longtext");
+
+ b.Property("Name")
+ .HasColumnType("longtext");
+
+ b.HasKey("OrganizationId");
+
+ b.ToTable("Organizations", "dbo");
+ });
+
+ modelBuilder.Entity("Binner.Data.Model.OrganizationConfiguration", b =>
+ {
+ b.Property("OrganizationConfigurationId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("OrganizationConfigurationId"));
+
+ b.Property("CacheAbsoluteExpirationMinutes")
+ .HasColumnType("int");
+
+ b.Property("CacheSlidingExpirationMinutes")
+ .HasColumnType("int");
+
+ b.Property("DateCreatedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("DateModifiedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("KiCadSettingsJson")
+ .HasColumnType("longtext");
+
+ b.Property("LicenseKey")
+ .HasColumnType("longtext");
+
+ b.Property("MaxCacheItems")
+ .HasColumnType("int");
+
+ b.Property("OrganizationId")
+ .HasColumnType("int");
+
+ b.Property("UseModule")
+ .HasColumnType("int");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.Property("enableAutomaticMetadataFetchingForExistingParts")
+ .HasColumnType("tinyint(1)");
+
+ b.HasKey("OrganizationConfigurationId");
+
+ b.HasIndex("OrganizationId");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("OrganizationConfigurations", "dbo");
+ });
+
+ modelBuilder.Entity("Binner.Data.Model.OrganizationIntegrationConfiguration", b =>
+ {
+ b.Property("OrganizationIntegrationConfigurationId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("OrganizationIntegrationConfigurationId"));
+
+ b.Property("ArrowApiKey")
+ .HasColumnType("longtext");
+
+ b.Property("ArrowApiUrl")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("ArrowEnabled")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("ArrowUsername")
+ .HasColumnType("longtext");
+
+ b.Property("DateCreatedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("DateModifiedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("DigiKeyApiUrl")
+ .HasColumnType("longtext");
+
+ b.Property("DigiKeyClientId")
+ .HasColumnType("longtext");
+
+ b.Property("DigiKeyClientSecret")
+ .HasColumnType("longtext");
+
+ b.Property("DigiKeyEnabled")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("DigiKeyOAuthPostbackUrl")
+ .HasColumnType("longtext");
+
+ b.Property("DigiKeySite")
+ .HasColumnType("int");
+
+ b.Property("MouserApiUrl")
+ .HasColumnType("longtext");
+
+ b.Property("MouserCartApiKey")
+ .HasColumnType("longtext");
+
+ b.Property("MouserEnabled")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("MouserOrderApiKey")
+ .HasColumnType("longtext");
+
+ b.Property("MouserSearchApiKey")
+ .HasColumnType("longtext");
+
+ b.Property("NexarClientId")
+ .HasColumnType("longtext");
+
+ b.Property("NexarClientSecret")
+ .HasColumnType("longtext");
+
+ b.Property("NexarEnabled")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("OrganizationId")
+ .HasColumnType("int");
+
+ b.Property("SwarmApiKey")
+ .HasColumnType("longtext");
+
+ b.Property("SwarmApiUrl")
+ .HasColumnType("longtext");
+
+ b.Property("SwarmEnabled")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("SwarmTimeout")
+ .HasColumnType("time(6)");
+
+ b.Property("TmeApiKey")
+ .HasColumnType("longtext");
+
+ b.Property("TmeApiUrl")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("TmeApplicationSecret")
+ .HasColumnType("longtext");
+
+ b.Property("TmeCountry")
+ .HasColumnType("longtext");
+
+ b.Property("TmeEnabled")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("TmeResolveExternalLinks")
+ .HasColumnType("tinyint(1)");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.HasKey("OrganizationIntegrationConfigurationId");
+
+ b.HasIndex("OrganizationId");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("OrganizationIntegrationConfigurations", "dbo");
+ });
+
+ modelBuilder.Entity("Binner.Data.Model.Part", b =>
+ {
+ b.Property("PartId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("PartId"));
+
+ b.Property("ArrowPartNumber")
+ .HasColumnType("longtext");
+
+ b.Property("BaseProductNumber")
+ .HasColumnType("longtext");
+
+ b.Property("BinNumber")
+ .HasColumnType("varchar(255)");
+
+ b.Property("BinNumber2")
+ .HasColumnType("varchar(255)");
+
+ b.Property("Cost")
+ .HasColumnType("decimal(18,4)");
+
+ b.Property("Currency")
+ .HasColumnType("longtext");
+
+ b.Property("DataSource")
+ .HasColumnType("int");
+
+ b.Property("DataSourceId")
+ .HasColumnType("longtext");
+
+ b.Property("DatasheetUrl")
+ .HasColumnType("longtext");
+
+ b.Property("DateCreatedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("DateModifiedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("Description")
+ .HasColumnType("varchar(255)");
+
+ b.Property("DigiKeyPartNumber")
+ .HasColumnType("varchar(255)");
+
+ b.Property("ExportControlClassNumber")
+ .HasColumnType("longtext");
+
+ b.Property("ExtensionValue1")
+ .HasColumnType("longtext");
+
+ b.Property("ExtensionValue2")
+ .HasColumnType("longtext");
+
+ b.Property("FootprintName")
+ .HasColumnType("longtext");
+
+ b.Property("HtsusCode")
+ .HasColumnType("longtext");
+
+ b.Property("ImageUrl")
+ .HasColumnType("longtext");
+
+ b.Property("Keywords")
+ .HasColumnType("varchar(255)");
+
+ b.Property("LastSwarmSyncUtc")
+ .HasColumnType("datetime(6)");
+
+ b.Property("LeadTime")
+ .HasColumnType("longtext");
+
+ b.Property("Location")
+ .HasColumnType("varchar(255)");
+
+ b.Property("LowStockThreshold")
+ .HasColumnType("int");
+
+ b.Property("LowestCostSupplier")
+ .HasColumnType("longtext");
+
+ b.Property("LowestCostSupplierUrl")
+ .HasColumnType("longtext");
+
+ b.Property("Manufacturer")
+ .HasColumnType("varchar(255)");
+
+ b.Property("ManufacturerPartNumber")
+ .HasColumnType("varchar(255)");
+
+ b.Property("MetadataLastUpdatedUtc")
+ .HasColumnType("datetime(6)");
+
+ b.Property("MoistureSensitivityLevel")
+ .HasColumnType("longtext");
+
+ b.Property("MountingTypeId")
+ .HasColumnType("int");
+
+ b.Property("MouserPartNumber")
+ .HasColumnType("varchar(255)");
+
+ b.Property("OrganizationId")
+ .HasColumnType("int");
+
+ b.Property("OtherNames")
+ .HasColumnType("longtext");
+
+ b.Property("PackageType")
+ .HasColumnType("longtext");
+
+ b.Property("PartNumber")
+ .HasMaxLength(64)
+ .HasColumnType("varchar(64)");
+
+ b.Property("PartTypeId")
+ .HasColumnType("bigint");
+
+ b.Property("ProductStatus")
+ .HasColumnType("longtext");
+
+ b.Property("ProductUrl")
+ .HasColumnType("longtext");
+
+ b.Property("ProjectId")
+ .HasColumnType("bigint");
+
+ b.Property("Quantity")
+ .HasColumnType("bigint");
+
+ b.Property("ReachStatus")
+ .HasColumnType("longtext");
+
+ b.Property("RohsStatus")
+ .HasColumnType("longtext");
+
+ b.Property("Series")
+ .HasColumnType("longtext");
+
+ b.Property("ShortId")
+ .HasColumnType("longtext");
+
+ b.Property("SwarmPartNumberManufacturerId")
+ .HasColumnType("int");
+
+ b.Property("SymbolName")
+ .HasColumnType("longtext");
+
+ b.Property("TmePartNumber")
+ .HasColumnType("longtext");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.Property("Value")
+ .HasColumnType("longtext");
+
+ b.HasKey("PartId");
+
+ b.HasIndex("ProjectId");
+
+ b.HasIndex("UserId");
+
+ b.HasIndex("BinNumber", "UserId");
+
+ b.HasIndex("BinNumber2", "UserId");
+
+ b.HasIndex("Description", "UserId");
+
+ b.HasIndex("DigiKeyPartNumber", "UserId");
+
+ b.HasIndex("Keywords", "UserId");
+
+ b.HasIndex("Location", "UserId");
+
+ b.HasIndex("Manufacturer", "UserId");
+
+ b.HasIndex("ManufacturerPartNumber", "UserId");
+
+ b.HasIndex("MouserPartNumber", "UserId");
+
+ b.HasIndex("PartNumber", "UserId");
+
+ b.HasIndex("PartTypeId", "UserId");
+
+ b.ToTable("Parts", "dbo");
+ });
+
+ modelBuilder.Entity("Binner.Data.Model.PartModel", b =>
+ {
+ b.Property("PartModelId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("PartModelId"));
+
+ b.Property("DateCreatedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("DateModifiedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("Filename")
+ .HasColumnType("longtext");
+
+ b.Property("ModelType")
+ .HasColumnType("int");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("OrganizationId")
+ .HasColumnType("int");
+
+ b.Property("PartId")
+ .HasColumnType("bigint");
+
+ b.Property("Source")
+ .HasColumnType("int");
+
+ b.Property("Url")
+ .HasColumnType("longtext");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.HasKey("PartModelId");
+
+ b.HasIndex("UserId");
+
+ b.HasIndex("PartId", "OrganizationId");
+
+ b.ToTable("PartModels", "dbo");
+ });
+
+ modelBuilder.Entity("Binner.Data.Model.PartParametric", b =>
+ {
+ b.Property("PartParametricId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("PartParametricId"));
+
+ b.Property("DateCreatedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("DateModifiedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("DigiKeyParameterId")
+ .HasColumnType("int");
+
+ b.Property("DigiKeyParameterText")
+ .HasColumnType("longtext");
+
+ b.Property("DigiKeyParameterType")
+ .HasColumnType("longtext");
+
+ b.Property("DigiKeyValueId")
+ .HasColumnType("longtext");
+
+ b.Property("DigiKeyValueText")
+ .HasColumnType("longtext");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("OrganizationId")
+ .HasColumnType("int");
+
+ b.Property("PartId")
+ .HasColumnType("bigint");
+
+ b.Property("Units")
+ .HasColumnType("int");
+
+ b.Property("UserId")
+ .HasColumnType("int");
+
+ b.Property("Value")
+ .IsRequired()
+ .HasColumnType("longtext");
+
+ b.Property("ValueNumber")
+ .HasColumnType("decimal(18,4)");
+
+ b.HasKey("PartParametricId");
+
+ b.HasIndex("UserId");
+
+ b.HasIndex("PartId", "OrganizationId");
+
+ b.ToTable("PartParametrics", "dbo");
+ });
+
+ modelBuilder.Entity("Binner.Data.Model.PartScanHistory", b =>
+ {
+ b.Property("PartScanHistoryId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("bigint");
+
+ MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("PartScanHistoryId"));
+
+ b.Property("BarcodeType")
+ .HasColumnType("int");
+
+ b.Property("CountryOfOrigin")
+ .HasColumnType("longtext");
+
+ b.Property("Crc")
+ .HasColumnType("int");
+
+ b.Property("DateCreatedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("DateModifiedUtc")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("datetime(6)")
+ .HasDefaultValueSql("getutcdate()");
+
+ b.Property("Description")
+ .HasColumnType("longtext");
+
+ b.Property("Invoice")
+ .HasColumnType("longtext");
+
+ b.Property("LotCode")
+ .HasColumnType("longtext");
+
+ b.Property