Merge pull request #33 from BarkProductions/32-barcode-generation

32 barcode generation
This commit is contained in:
Drew Rautenberg
2026-06-10 20:20:50 -05:00
committed by GitHub
9 changed files with 307 additions and 17 deletions
@@ -0,0 +1,113 @@
// <auto-generated />
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using barkmanapi;
#nullable disable
namespace barkmanapi.Migrations
{
[DbContext(typeof(BarkContext))]
[Migration("20260611002716_barcodestring")]
partial class barcodestring
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.1")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("barkmanapi.InventoryItems", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Barcode")
.IsRequired()
.HasColumnType("text")
.HasColumnName("barcode");
b.Property<string>("Brand")
.IsRequired()
.HasColumnType("text")
.HasColumnName("brand");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text")
.HasColumnName("name");
b.Property<string>("Notes")
.HasColumnType("text")
.HasColumnName("notes");
b.Property<float?>("RentalPrice")
.HasColumnType("real")
.HasColumnName("rental_price");
b.Property<float?>("ReplacementCost")
.HasColumnType("real")
.HasColumnName("replacement_cost");
b.Property<string>("SerialNumber")
.HasColumnType("text")
.HasColumnName("serial_number");
b.Property<string>("StatusId")
.HasColumnType("text")
.HasColumnName("status_id");
b.Property<float?>("Weight")
.HasColumnType("real")
.HasColumnName("weight");
b.HasKey("Id")
.HasName("pk_inventory");
b.HasIndex("StatusId")
.HasDatabaseName("ix_inventory_status_id");
b.ToTable("inventory", (string)null);
});
modelBuilder.Entity("barkmanapi.ItemStatus", b =>
{
b.Property<string>("Id")
.HasColumnType("text")
.HasColumnName("id");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text")
.HasColumnName("name");
b.HasKey("Id")
.HasName("pk_item_status");
b.ToTable("item_status", (string)null);
});
modelBuilder.Entity("barkmanapi.InventoryItems", b =>
{
b.HasOne("barkmanapi.ItemStatus", "Status")
.WithMany()
.HasForeignKey("StatusId")
.HasConstraintName("fk_inventory_item_status_status_id");
b.Navigation("Status");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,34 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace barkmanapi.Migrations
{
/// <inheritdoc />
public partial class barcodestring : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "barcode",
table: "inventory",
type: "text",
nullable: false,
oldClrType: typeof(int),
oldType: "integer");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<int>(
name: "barcode",
table: "inventory",
type: "integer",
nullable: false,
oldClrType: typeof(string),
oldType: "text");
}
}
}
@@ -0,0 +1,117 @@
// <auto-generated />
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using barkmanapi;
#nullable disable
namespace barkmanapi.Migrations
{
[DbContext(typeof(BarkContext))]
[Migration("20260611005912_barcodeisunique")]
partial class barcodeisunique
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.1")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("barkmanapi.InventoryItems", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasColumnName("id");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Barcode")
.IsRequired()
.HasColumnType("text")
.HasColumnName("barcode");
b.Property<string>("Brand")
.IsRequired()
.HasColumnType("text")
.HasColumnName("brand");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text")
.HasColumnName("name");
b.Property<string>("Notes")
.HasColumnType("text")
.HasColumnName("notes");
b.Property<float?>("RentalPrice")
.HasColumnType("real")
.HasColumnName("rental_price");
b.Property<float?>("ReplacementCost")
.HasColumnType("real")
.HasColumnName("replacement_cost");
b.Property<string>("SerialNumber")
.HasColumnType("text")
.HasColumnName("serial_number");
b.Property<string>("StatusId")
.HasColumnType("text")
.HasColumnName("status_id");
b.Property<float?>("Weight")
.HasColumnType("real")
.HasColumnName("weight");
b.HasKey("Id")
.HasName("pk_inventory");
b.HasIndex("Barcode")
.IsUnique()
.HasDatabaseName("ix_inventory_barcode");
b.HasIndex("StatusId")
.HasDatabaseName("ix_inventory_status_id");
b.ToTable("inventory", (string)null);
});
modelBuilder.Entity("barkmanapi.ItemStatus", b =>
{
b.Property<string>("Id")
.HasColumnType("text")
.HasColumnName("id");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text")
.HasColumnName("name");
b.HasKey("Id")
.HasName("pk_item_status");
b.ToTable("item_status", (string)null);
});
modelBuilder.Entity("barkmanapi.InventoryItems", b =>
{
b.HasOne("barkmanapi.ItemStatus", "Status")
.WithMany()
.HasForeignKey("StatusId")
.HasConstraintName("fk_inventory_item_status_status_id");
b.Navigation("Status");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,28 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace barkmanapi.Migrations
{
/// <inheritdoc />
public partial class barcodeisunique : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateIndex(
name: "ix_inventory_barcode",
table: "inventory",
column: "barcode",
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "ix_inventory_barcode",
table: "inventory");
}
}
}
@@ -30,8 +30,9 @@ namespace barkmanapi.Migrations
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id")); NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int>("Barcode") b.Property<string>("Barcode")
.HasColumnType("integer") .IsRequired()
.HasColumnType("text")
.HasColumnName("barcode"); .HasColumnName("barcode");
b.Property<string>("Brand") b.Property<string>("Brand")
@@ -71,6 +72,10 @@ namespace barkmanapi.Migrations
b.HasKey("Id") b.HasKey("Id")
.HasName("pk_inventory"); .HasName("pk_inventory");
b.HasIndex("Barcode")
.IsUnique()
.HasDatabaseName("ix_inventory_barcode");
b.HasIndex("StatusId") b.HasIndex("StatusId")
.HasDatabaseName("ix_inventory_status_id"); .HasDatabaseName("ix_inventory_status_id");
+2 -1
View File
@@ -8,10 +8,11 @@ public class BarkContext(DbContextOptions<BarkContext> options) : DbContext(opti
public DbSet<ItemStatus> ItemStatus { get; set; } public DbSet<ItemStatus> ItemStatus { get; set; }
} }
[Index(nameof(Barcode), IsUnique = true)]
public class InventoryItems public class InventoryItems
{ {
public int Id {get; set;} public int Id {get; set;}
public int Barcode {get; set;} public string Barcode {get; set;}
public string Name { get; set; } public string Name { get; set; }
public string Brand { get; set; } public string Brand { get; set; }
public string? SerialNumber { get; set; } public string? SerialNumber { get; set; }
+2 -10
View File
@@ -6,7 +6,6 @@ import {useNavigate} from "react-router";
import {IconX, IconCheck} from '@tabler/icons-react'; import {IconX, IconCheck} from '@tabler/icons-react';
import {notifications} from '@mantine/notifications'; import {notifications} from '@mantine/notifications';
import useInventoryList from "./hooks/useInventoryList.tsx"; import useInventoryList from "./hooks/useInventoryList.tsx";
import {useEffect} from "react";
function AddItem() { function AddItem() {
@@ -18,7 +17,7 @@ function AddItem() {
const newItemForm = useForm<NewItem>({ const newItemForm = useForm<NewItem>({
mode: 'uncontrolled', mode: 'uncontrolled',
initialValues: { initialValues: {
barcode: 0, barcode: "",
name: "", name: "",
brand: "", brand: "",
serialNumber: "", serialNumber: "",
@@ -68,13 +67,6 @@ function AddItem() {
}) })
useEffect(() => {
if (inventoryQuery.data) {
const nextBarcode = inventoryQuery.data[inventoryQuery.data.length - 1].barcode + 1;
newItemForm.setValues({barcode: nextBarcode});
}
},[inventoryQuery.data]);
if (inventoryQuery.isPending) return 'Loading...' if (inventoryQuery.isPending) return 'Loading...'
if (inventoryQuery.error) return 'An error has occurred: ' + inventoryQuery.error.message if (inventoryQuery.error) return 'An error has occurred: ' + inventoryQuery.error.message
@@ -94,7 +86,7 @@ function AddItem() {
wrap="wrap"> wrap="wrap">
<Title order={1}>Add Item</Title> <Title order={1}>Add Item</Title>
<NumberInput withAsterisk size="md" key={newItemForm.key('barcode')} label="Barcode" <TextInput withAsterisk size="md" key={newItemForm.key('barcode')} label="Barcode"
placeholder="Barcode" {...newItemForm.getInputProps('barcode')}/> placeholder="Barcode" {...newItemForm.getInputProps('barcode')}/>
<TextInput withAsterisk key={newItemForm.key('brand')} size="md" label="Brand" <TextInput withAsterisk key={newItemForm.key('brand')} size="md" label="Brand"
placeholder="Brand" {...newItemForm.getInputProps('brand')}/> placeholder="Brand" {...newItemForm.getInputProps('brand')}/>
@@ -16,7 +16,7 @@ function EditItem() {
const editItemForm = useForm<EditableInventoryItem>({ const editItemForm = useForm<EditableInventoryItem>({
mode: 'uncontrolled', mode: 'uncontrolled',
initialValues: { initialValues: {
barcode: 0, barcode: "",
name: "", name: "",
brand: "", brand: "",
statusId: "", statusId: "",
@@ -113,7 +113,7 @@ function EditItem() {
<div>{isFetching ? 'Updating...' : ''}</div> <div>{isFetching ? 'Updating...' : ''}</div>
<Title order={1}>Edit Item</Title> <Title order={1}>Edit Item</Title>
<NumberInput withAsterisk size="md" key={editItemForm.key('barcode')} label="Barcode" <TextInput withAsterisk size="md" key={editItemForm.key('barcode')} label="Barcode"
placeholder="Barcode" {...editItemForm.getInputProps('barcode')}/> placeholder="Barcode" {...editItemForm.getInputProps('barcode')}/>
<TextInput withAsterisk key={editItemForm.key('brand')} size="md" label="Brand" <TextInput withAsterisk key={editItemForm.key('brand')} size="md" label="Brand"
placeholder="Brand" {...editItemForm.getInputProps('brand')}/> placeholder="Brand" {...editItemForm.getInputProps('brand')}/>
+2 -2
View File
@@ -1,6 +1,6 @@
export interface InventoryItem { export interface InventoryItem {
id: number, id: number,
barcode: number, barcode: string,
brand: string, brand: string,
name: string, name: string,
status: {id: string; name: string}, status: {id: string; name: string},
@@ -12,7 +12,7 @@ export interface InventoryItem {
} }
export interface NewItem { export interface NewItem {
barcode: number, barcode: string,
brand: string, brand: string,
name: string, name: string,
serialNumber: string, serialNumber: string,