Reformatting everything with black
This commit is contained in:
1 parent
7bd07f084a
commit
8185f1f8b3
48 files changed
+1000
-348
No files matched your search
@@ -4,15 +4,15 @@ Revision ID: 0c3d1a5cff1f
|
|||||||
Revises: 5b6a7817b408
|
Revises: 5b6a7817b408
|
||||||
Create Date: 2026-07-02 12:22:24.106795
|
Create Date: 2026-07-02 12:22:24.106795
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Sequence, Union
|
from typing import Sequence, Union
|
||||||
|
|
||||||
from alembic import op
|
from alembic import op
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision: str = '0c3d1a5cff1f'
|
revision: str = "0c3d1a5cff1f"
|
||||||
down_revision: Union[str, None] = '5b6a7817b408'
|
down_revision: Union[str, None] = "5b6a7817b408"
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
branch_labels: Union[str, Sequence[str], None] = None
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
depends_on: Union[str, Sequence[str], None] = None
|
||||||
|
|
||||||
|
|||||||
@@ -4,15 +4,15 @@ Revision ID: 5b6a7817b408
|
|||||||
Revises: 7be5ef599d3f
|
Revises: 7be5ef599d3f
|
||||||
Create Date: 2026-07-02 11:57:13.095417
|
Create Date: 2026-07-02 11:57:13.095417
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Sequence, Union
|
from typing import Sequence, Union
|
||||||
|
|
||||||
from alembic import op
|
from alembic import op
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision: str = '5b6a7817b408'
|
revision: str = "5b6a7817b408"
|
||||||
down_revision: Union[str, None] = '7be5ef599d3f'
|
down_revision: Union[str, None] = "7be5ef599d3f"
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
branch_labels: Union[str, Sequence[str], None] = None
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
depends_on: Union[str, Sequence[str], None] = None
|
||||||
|
|
||||||
|
|||||||
@@ -4,15 +4,15 @@ Revision ID: 70e48bda8829
|
|||||||
Revises: c7882cedc9ae
|
Revises: c7882cedc9ae
|
||||||
Create Date: 2026-07-02 13:54:58.335394
|
Create Date: 2026-07-02 13:54:58.335394
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Sequence, Union
|
from typing import Sequence, Union
|
||||||
|
|
||||||
from alembic import op
|
from alembic import op
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision: str = '70e48bda8829'
|
revision: str = "70e48bda8829"
|
||||||
down_revision: Union[str, None] = 'c7882cedc9ae'
|
down_revision: Union[str, None] = "c7882cedc9ae"
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
branch_labels: Union[str, Sequence[str], None] = None
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
depends_on: Union[str, Sequence[str], None] = None
|
||||||
|
|
||||||
|
|||||||
@@ -4,15 +4,15 @@ Revision ID: 7be5ef599d3f
|
|||||||
Revises: b60d0aa3ceda
|
Revises: b60d0aa3ceda
|
||||||
Create Date: 2026-06-25 15:29:20.685050
|
Create Date: 2026-06-25 15:29:20.685050
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Sequence, Union
|
from typing import Sequence, Union
|
||||||
|
|
||||||
from alembic import op
|
from alembic import op
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision: str = '7be5ef599d3f'
|
revision: str = "7be5ef599d3f"
|
||||||
down_revision: Union[str, None] = 'b60d0aa3ceda'
|
down_revision: Union[str, None] = "b60d0aa3ceda"
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
branch_labels: Union[str, Sequence[str], None] = None
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
depends_on: Union[str, Sequence[str], None] = None
|
||||||
|
|
||||||
|
|||||||
@@ -4,15 +4,15 @@ Revision ID: 8bc411b5814e
|
|||||||
Revises: 0c3d1a5cff1f
|
Revises: 0c3d1a5cff1f
|
||||||
Create Date: 2026-07-02 12:37:59.457033
|
Create Date: 2026-07-02 12:37:59.457033
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Sequence, Union
|
from typing import Sequence, Union
|
||||||
|
|
||||||
from alembic import op
|
from alembic import op
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision: str = '8bc411b5814e'
|
revision: str = "8bc411b5814e"
|
||||||
down_revision: Union[str, None] = '0c3d1a5cff1f'
|
down_revision: Union[str, None] = "0c3d1a5cff1f"
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
branch_labels: Union[str, Sequence[str], None] = None
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
depends_on: Union[str, Sequence[str], None] = None
|
||||||
|
|
||||||
|
|||||||
@@ -4,44 +4,49 @@ Revision ID: a192abbf4091
|
|||||||
Revises: 627d4460a94f
|
Revises: 627d4460a94f
|
||||||
Create Date: 2026-06-25 10:32:11.398529
|
Create Date: 2026-06-25 10:32:11.398529
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Sequence, Union
|
from typing import Sequence, Union
|
||||||
|
|
||||||
from alembic import op
|
from alembic import op
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision: str = 'a192abbf4091'
|
revision: str = "a192abbf4091"
|
||||||
down_revision: Union[str, None] = '627d4460a94f'
|
down_revision: Union[str, None] = "627d4460a94f"
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
branch_labels: Union[str, Sequence[str], None] = None
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
depends_on: Union[str, Sequence[str], None] = None
|
||||||
|
|
||||||
|
|
||||||
def upgrade() -> None:
|
def upgrade() -> None:
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.create_table('manufacturers',
|
op.create_table(
|
||||||
sa.Column('id', sa.Integer(), nullable=False),
|
"manufacturers",
|
||||||
sa.Column('name', sa.String(), nullable=False),
|
sa.Column("id", sa.Integer(), nullable=False),
|
||||||
sa.Column('url', sa.String(), nullable=False),
|
sa.Column("name", sa.String(), nullable=False),
|
||||||
sa.Column('logo_url', sa.String(), nullable=True),
|
sa.Column("url", sa.String(), nullable=False),
|
||||||
sa.PrimaryKeyConstraint('id')
|
sa.Column("logo_url", sa.String(), nullable=True),
|
||||||
|
sa.PrimaryKeyConstraint("id"),
|
||||||
)
|
)
|
||||||
with op.batch_alter_table('unc_threads', schema=None) as batch_op:
|
with op.batch_alter_table("unc_threads", schema=None) as batch_op:
|
||||||
batch_op.alter_column('series',
|
batch_op.alter_column(
|
||||||
existing_type=sa.VARCHAR(length=8),
|
"series",
|
||||||
type_=sa.Enum('UNC', 'UNF', 'UNEF', 'UN', 'UNS', name='uncseries'),
|
existing_type=sa.VARCHAR(length=8),
|
||||||
existing_nullable=False)
|
type_=sa.Enum("UNC", "UNF", "UNEF", "UN", "UNS", name="uncseries"),
|
||||||
|
existing_nullable=False,
|
||||||
|
)
|
||||||
|
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
def downgrade() -> None:
|
def downgrade() -> None:
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
with op.batch_alter_table('unc_threads', schema=None) as batch_op:
|
with op.batch_alter_table("unc_threads", schema=None) as batch_op:
|
||||||
batch_op.alter_column('series',
|
batch_op.alter_column(
|
||||||
existing_type=sa.Enum('UNC', 'UNF', 'UNEF', 'UN', 'UNS', name='uncseries'),
|
"series",
|
||||||
type_=sa.VARCHAR(length=8),
|
existing_type=sa.Enum("UNC", "UNF", "UNEF", "UN", "UNS", name="uncseries"),
|
||||||
existing_nullable=False)
|
type_=sa.VARCHAR(length=8),
|
||||||
|
existing_nullable=False,
|
||||||
|
)
|
||||||
|
|
||||||
op.drop_table('manufacturers')
|
op.drop_table("manufacturers")
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
@@ -4,33 +4,36 @@ Revision ID: a52e7ca7a925
|
|||||||
Revises: a192abbf4091
|
Revises: a192abbf4091
|
||||||
Create Date: 2026-06-25 10:35:40.227253
|
Create Date: 2026-06-25 10:35:40.227253
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Sequence, Union
|
from typing import Sequence, Union
|
||||||
|
|
||||||
from alembic import op
|
from alembic import op
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision: str = 'a52e7ca7a925'
|
revision: str = "a52e7ca7a925"
|
||||||
down_revision: Union[str, None] = 'a192abbf4091'
|
down_revision: Union[str, None] = "a192abbf4091"
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
branch_labels: Union[str, Sequence[str], None] = None
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
depends_on: Union[str, Sequence[str], None] = None
|
||||||
|
|
||||||
|
|
||||||
def upgrade() -> None:
|
def upgrade() -> None:
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.create_table('scope_models',
|
op.create_table(
|
||||||
sa.Column('id', sa.Integer(), nullable=False),
|
"scope_models",
|
||||||
sa.Column('name', sa.String(), nullable=False),
|
sa.Column("id", sa.Integer(), nullable=False),
|
||||||
sa.Column('manufacturer_id', sa.Integer(), nullable=False),
|
sa.Column("name", sa.String(), nullable=False),
|
||||||
sa.Column('url', sa.String(), nullable=True),
|
sa.Column("manufacturer_id", sa.Integer(), nullable=False),
|
||||||
sa.ForeignKeyConstraint(['manufacturer_id'], ['manufacturers.id'], ondelete='RESTRICT'),
|
sa.Column("url", sa.String(), nullable=True),
|
||||||
sa.PrimaryKeyConstraint('id')
|
sa.ForeignKeyConstraint(
|
||||||
|
["manufacturer_id"], ["manufacturers.id"], ondelete="RESTRICT"
|
||||||
|
),
|
||||||
|
sa.PrimaryKeyConstraint("id"),
|
||||||
)
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
def downgrade() -> None:
|
def downgrade() -> None:
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_table('scope_models')
|
op.drop_table("scope_models")
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
@@ -4,15 +4,15 @@ Revision ID: adf4a5b9493e
|
|||||||
Revises: 70e48bda8829
|
Revises: 70e48bda8829
|
||||||
Create Date: 2026-07-02 14:03:23.561253
|
Create Date: 2026-07-02 14:03:23.561253
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Sequence, Union
|
from typing import Sequence, Union
|
||||||
|
|
||||||
from alembic import op
|
from alembic import op
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision: str = 'adf4a5b9493e'
|
revision: str = "adf4a5b9493e"
|
||||||
down_revision: Union[str, None] = '70e48bda8829'
|
down_revision: Union[str, None] = "70e48bda8829"
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
branch_labels: Union[str, Sequence[str], None] = None
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
depends_on: Union[str, Sequence[str], None] = None
|
||||||
|
|
||||||
|
|||||||
@@ -4,15 +4,15 @@ Revision ID: b60d0aa3ceda
|
|||||||
Revises: fd5379986da4
|
Revises: fd5379986da4
|
||||||
Create Date: 2026-06-25 11:29:20.420056
|
Create Date: 2026-06-25 11:29:20.420056
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Sequence, Union
|
from typing import Sequence, Union
|
||||||
|
|
||||||
from alembic import op
|
from alembic import op
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision: str = 'b60d0aa3ceda'
|
revision: str = "b60d0aa3ceda"
|
||||||
down_revision: Union[str, None] = 'fd5379986da4'
|
down_revision: Union[str, None] = "fd5379986da4"
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
branch_labels: Union[str, Sequence[str], None] = None
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
depends_on: Union[str, Sequence[str], None] = None
|
||||||
|
|
||||||
|
|||||||
@@ -4,15 +4,15 @@ Revision ID: bfbce324cd5f
|
|||||||
Revises: 8bc411b5814e
|
Revises: 8bc411b5814e
|
||||||
Create Date: 2026-07-02 12:46:27.493942
|
Create Date: 2026-07-02 12:46:27.493942
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Sequence, Union
|
from typing import Sequence, Union
|
||||||
|
|
||||||
from alembic import op
|
from alembic import op
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision: str = 'bfbce324cd5f'
|
revision: str = "bfbce324cd5f"
|
||||||
down_revision: Union[str, None] = '8bc411b5814e'
|
down_revision: Union[str, None] = "8bc411b5814e"
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
branch_labels: Union[str, Sequence[str], None] = None
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
depends_on: Union[str, Sequence[str], None] = None
|
||||||
|
|
||||||
|
|||||||
@@ -4,15 +4,15 @@ Revision ID: c7882cedc9ae
|
|||||||
Revises: bfbce324cd5f
|
Revises: bfbce324cd5f
|
||||||
Create Date: 2026-07-02 13:31:57.064381
|
Create Date: 2026-07-02 13:31:57.064381
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Sequence, Union
|
from typing import Sequence, Union
|
||||||
|
|
||||||
from alembic import op
|
from alembic import op
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision: str = 'c7882cedc9ae'
|
revision: str = "c7882cedc9ae"
|
||||||
down_revision: Union[str, None] = 'bfbce324cd5f'
|
down_revision: Union[str, None] = "bfbce324cd5f"
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
branch_labels: Union[str, Sequence[str], None] = None
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
depends_on: Union[str, Sequence[str], None] = None
|
||||||
|
|
||||||
|
|||||||
@@ -4,31 +4,32 @@ Revision ID: e23aa8dd2536
|
|||||||
Revises: a52e7ca7a925
|
Revises: a52e7ca7a925
|
||||||
Create Date: 2026-06-25 10:49:56.463466
|
Create Date: 2026-06-25 10:49:56.463466
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Sequence, Union
|
from typing import Sequence, Union
|
||||||
|
|
||||||
from alembic import op
|
from alembic import op
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision: str = 'e23aa8dd2536'
|
revision: str = "e23aa8dd2536"
|
||||||
down_revision: Union[str, None] = 'a52e7ca7a925'
|
down_revision: Union[str, None] = "a52e7ca7a925"
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
branch_labels: Union[str, Sequence[str], None] = None
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
depends_on: Union[str, Sequence[str], None] = None
|
||||||
|
|
||||||
|
|
||||||
def upgrade() -> None:
|
def upgrade() -> None:
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.create_table('part_types',
|
op.create_table(
|
||||||
sa.Column('id', sa.Integer(), nullable=False),
|
"part_types",
|
||||||
sa.Column('name', sa.String(), nullable=False),
|
sa.Column("id", sa.Integer(), nullable=False),
|
||||||
sa.PrimaryKeyConstraint('id'),
|
sa.Column("name", sa.String(), nullable=False),
|
||||||
sa.UniqueConstraint('name')
|
sa.PrimaryKeyConstraint("id"),
|
||||||
|
sa.UniqueConstraint("name"),
|
||||||
)
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
def downgrade() -> None:
|
def downgrade() -> None:
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_table('part_types')
|
op.drop_table("part_types")
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
@@ -4,15 +4,15 @@ Revision ID: fd5379986da4
|
|||||||
Revises: e23aa8dd2536
|
Revises: e23aa8dd2536
|
||||||
Create Date: 2026-06-25 11:06:13.028067
|
Create Date: 2026-06-25 11:06:13.028067
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Sequence, Union
|
from typing import Sequence, Union
|
||||||
|
|
||||||
from alembic import op
|
from alembic import op
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision: str = 'fd5379986da4'
|
revision: str = "fd5379986da4"
|
||||||
down_revision: Union[str, None] = 'e23aa8dd2536'
|
down_revision: Union[str, None] = "e23aa8dd2536"
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
branch_labels: Union[str, Sequence[str], None] = None
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
depends_on: Union[str, Sequence[str], None] = None
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,10 @@ async def create_attachment_point_name(
|
|||||||
):
|
):
|
||||||
apn = await apn_crud.create(db, name=payload.name)
|
apn = await apn_crud.create(db, name=payload.name)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="create", resource_type="AttachmentPointName",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="create",
|
||||||
|
resource_type="AttachmentPointName",
|
||||||
resource_id=apn.id,
|
resource_id=apn.id,
|
||||||
description=audit_crud.describe_create("AttachmentPointName", apn.id, apn.name),
|
description=audit_crud.describe_create("AttachmentPointName", apn.id, apn.name),
|
||||||
)
|
)
|
||||||
@@ -67,7 +70,10 @@ async def update_attachment_point_name(
|
|||||||
changes = payload.model_dump(exclude_unset=True)
|
changes = payload.model_dump(exclude_unset=True)
|
||||||
apn = await apn_crud.update(db, apn, changes)
|
apn = await apn_crud.update(db, apn, changes)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="update", resource_type="AttachmentPointName",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="update",
|
||||||
|
resource_type="AttachmentPointName",
|
||||||
resource_id=apn.id,
|
resource_id=apn.id,
|
||||||
description=audit_crud.describe_update("AttachmentPointName", apn.id, changes),
|
description=audit_crud.describe_update("AttachmentPointName", apn.id, changes),
|
||||||
)
|
)
|
||||||
@@ -86,7 +92,10 @@ async def delete_attachment_point_name(
|
|||||||
name = apn.name
|
name = apn.name
|
||||||
await apn_crud.delete(db, apn)
|
await apn_crud.delete(db, apn)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="delete", resource_type="AttachmentPointName",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="delete",
|
||||||
|
resource_type="AttachmentPointName",
|
||||||
resource_id=apn_id,
|
resource_id=apn_id,
|
||||||
description=audit_crud.describe_delete("AttachmentPointName", apn_id, name),
|
description=audit_crud.describe_delete("AttachmentPointName", apn_id, name),
|
||||||
)
|
)
|
||||||
@@ -40,7 +40,9 @@ async def list_attachment_points(
|
|||||||
return await attachment_point_crud.list_all(db, skip=skip, limit=limit)
|
return await attachment_point_crud.list_all(db, skip=skip, limit=limit)
|
||||||
|
|
||||||
|
|
||||||
@router.post("", response_model=AttachmentPointRead, status_code=status.HTTP_201_CREATED)
|
@router.post(
|
||||||
|
"", response_model=AttachmentPointRead, status_code=status.HTTP_201_CREATED
|
||||||
|
)
|
||||||
async def create_attachment_point(
|
async def create_attachment_point(
|
||||||
payload: AttachmentPointCreate,
|
payload: AttachmentPointCreate,
|
||||||
db: AsyncSession = Depends(get_db),
|
db: AsyncSession = Depends(get_db),
|
||||||
@@ -59,7 +61,10 @@ async def create_attachment_point(
|
|||||||
)
|
)
|
||||||
ap = await attachment_point_crud.create(db, **payload.model_dump())
|
ap = await attachment_point_crud.create(db, **payload.model_dump())
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="create", resource_type="AttachmentPoint",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="create",
|
||||||
|
resource_type="AttachmentPoint",
|
||||||
resource_id=ap.id,
|
resource_id=ap.id,
|
||||||
description=audit_crud.describe_create(
|
description=audit_crud.describe_create(
|
||||||
"AttachmentPoint", ap.id, _connection_label(ap)
|
"AttachmentPoint", ap.id, _connection_label(ap)
|
||||||
@@ -93,7 +98,10 @@ async def update_attachment_point(
|
|||||||
changes = payload.model_dump(exclude_unset=True)
|
changes = payload.model_dump(exclude_unset=True)
|
||||||
ap = await attachment_point_crud.update(db, ap, changes)
|
ap = await attachment_point_crud.update(db, ap, changes)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="update", resource_type="AttachmentPoint",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="update",
|
||||||
|
resource_type="AttachmentPoint",
|
||||||
resource_id=ap.id,
|
resource_id=ap.id,
|
||||||
description=audit_crud.describe_update("AttachmentPoint", ap.id, changes),
|
description=audit_crud.describe_update("AttachmentPoint", ap.id, changes),
|
||||||
)
|
)
|
||||||
@@ -112,7 +120,12 @@ async def delete_attachment_point(
|
|||||||
label = _connection_label(ap)
|
label = _connection_label(ap)
|
||||||
await attachment_point_crud.delete(db, ap)
|
await attachment_point_crud.delete(db, ap)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="delete", resource_type="AttachmentPoint",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="delete",
|
||||||
|
resource_type="AttachmentPoint",
|
||||||
resource_id=attachment_point_id,
|
resource_id=attachment_point_id,
|
||||||
description=audit_crud.describe_delete("AttachmentPoint", attachment_point_id, label),
|
description=audit_crud.describe_delete(
|
||||||
|
"AttachmentPoint", attachment_point_id, label
|
||||||
|
),
|
||||||
)
|
)
|
||||||
@@ -44,9 +44,14 @@ async def create_augmented_part(
|
|||||||
sub_part_type_id=payload.sub_part_type_id,
|
sub_part_type_id=payload.sub_part_type_id,
|
||||||
)
|
)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="create", resource_type="AugmentedPart",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="create",
|
||||||
|
resource_type="AugmentedPart",
|
||||||
resource_id=ap.id,
|
resource_id=ap.id,
|
||||||
description=audit_crud.describe_create("AugmentedPart", ap.id, ap.sku or ap.description),
|
description=audit_crud.describe_create(
|
||||||
|
"AugmentedPart", ap.id, ap.sku or ap.description
|
||||||
|
),
|
||||||
)
|
)
|
||||||
return ap
|
return ap
|
||||||
|
|
||||||
@@ -58,7 +63,10 @@ async def sync_augmented_parts(
|
|||||||
):
|
):
|
||||||
result = await augmented_part_sync.sync(db)
|
result = await augmented_part_sync.sync(db)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="update", resource_type="AugmentedPart",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="update",
|
||||||
|
resource_type="AugmentedPart",
|
||||||
resource_id=None,
|
resource_id=None,
|
||||||
description=(
|
description=(
|
||||||
f"Sync: {result.created} created, {result.deleted} deleted, "
|
f"Sync: {result.created} created, {result.deleted} deleted, "
|
||||||
@@ -93,7 +101,10 @@ async def update_augmented_part(
|
|||||||
changes = payload.model_dump(exclude_unset=True)
|
changes = payload.model_dump(exclude_unset=True)
|
||||||
ap = await augmented_part_crud.update(db, ap, changes)
|
ap = await augmented_part_crud.update(db, ap, changes)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="update", resource_type="AugmentedPart",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="update",
|
||||||
|
resource_type="AugmentedPart",
|
||||||
resource_id=ap.id,
|
resource_id=ap.id,
|
||||||
description=audit_crud.describe_update("AugmentedPart", ap.id, changes),
|
description=audit_crud.describe_update("AugmentedPart", ap.id, changes),
|
||||||
)
|
)
|
||||||
@@ -112,7 +123,12 @@ async def delete_augmented_part(
|
|||||||
label = ap.sku or ap.description
|
label = ap.sku or ap.description
|
||||||
await augmented_part_crud.delete(db, ap)
|
await augmented_part_crud.delete(db, ap)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="delete", resource_type="AugmentedPart",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="delete",
|
||||||
|
resource_type="AugmentedPart",
|
||||||
resource_id=augmented_part_id,
|
resource_id=augmented_part_id,
|
||||||
description=audit_crud.describe_delete("AugmentedPart", augmented_part_id, label),
|
description=audit_crud.describe_delete(
|
||||||
|
"AugmentedPart", augmented_part_id, label
|
||||||
|
),
|
||||||
)
|
)
|
||||||
@@ -25,7 +25,9 @@ async def list_clamp_connections(
|
|||||||
return await clamp_connection_crud.list_all(db, skip=skip, limit=limit)
|
return await clamp_connection_crud.list_all(db, skip=skip, limit=limit)
|
||||||
|
|
||||||
|
|
||||||
@router.post("", response_model=ClampConnectionRead, status_code=status.HTTP_201_CREATED)
|
@router.post(
|
||||||
|
"", response_model=ClampConnectionRead, status_code=status.HTTP_201_CREATED
|
||||||
|
)
|
||||||
async def create_clamp_connection(
|
async def create_clamp_connection(
|
||||||
payload: ClampConnectionCreate,
|
payload: ClampConnectionCreate,
|
||||||
db: AsyncSession = Depends(get_db),
|
db: AsyncSession = Depends(get_db),
|
||||||
@@ -39,11 +41,19 @@ async def create_clamp_connection(
|
|||||||
max_in=payload.max_in,
|
max_in=payload.max_in,
|
||||||
)
|
)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="create", resource_type="ClampConnection",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="create",
|
||||||
|
resource_type="ClampConnection",
|
||||||
resource_id=cc.id,
|
resource_id=cc.id,
|
||||||
description=audit_crud.describe_create(
|
description=audit_crud.describe_create(
|
||||||
"ClampConnection", cc.id,
|
"ClampConnection",
|
||||||
f"{cc.min_mm}–{cc.max_mm} mm" if cc.min_mm is not None else f"{cc.min_in}–{cc.max_in} in",
|
cc.id,
|
||||||
|
(
|
||||||
|
f"{cc.min_mm}–{cc.max_mm} mm"
|
||||||
|
if cc.min_mm is not None
|
||||||
|
else f"{cc.min_in}–{cc.max_in} in"
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
return cc
|
return cc
|
||||||
@@ -74,7 +84,10 @@ async def update_clamp_connection(
|
|||||||
changes = payload.model_dump(exclude_unset=True)
|
changes = payload.model_dump(exclude_unset=True)
|
||||||
cc = await clamp_connection_crud.update(db, cc, changes)
|
cc = await clamp_connection_crud.update(db, cc, changes)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="update", resource_type="ClampConnection",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="update",
|
||||||
|
resource_type="ClampConnection",
|
||||||
resource_id=cc.id,
|
resource_id=cc.id,
|
||||||
description=audit_crud.describe_update("ClampConnection", cc.id, changes),
|
description=audit_crud.describe_update("ClampConnection", cc.id, changes),
|
||||||
)
|
)
|
||||||
@@ -91,12 +104,18 @@ async def delete_clamp_connection(
|
|||||||
if cc is None:
|
if cc is None:
|
||||||
raise HTTPException(status_code=404, detail="Clamp connection not found")
|
raise HTTPException(status_code=404, detail="Clamp connection not found")
|
||||||
label = (
|
label = (
|
||||||
f"{cc.min_mm}–{cc.max_mm} mm" if cc.min_mm is not None
|
f"{cc.min_mm}–{cc.max_mm} mm"
|
||||||
|
if cc.min_mm is not None
|
||||||
else f"{cc.min_in}–{cc.max_in} in"
|
else f"{cc.min_in}–{cc.max_in} in"
|
||||||
)
|
)
|
||||||
await clamp_connection_crud.delete(db, cc)
|
await clamp_connection_crud.delete(db, cc)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="delete", resource_type="ClampConnection",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="delete",
|
||||||
|
resource_type="ClampConnection",
|
||||||
resource_id=clamp_connection_id,
|
resource_id=clamp_connection_id,
|
||||||
description=audit_crud.describe_delete("ClampConnection", clamp_connection_id, label),
|
description=audit_crud.describe_delete(
|
||||||
|
"ClampConnection", clamp_connection_id, label
|
||||||
|
),
|
||||||
)
|
)
|
||||||
@@ -51,7 +51,11 @@ async def update_config(
|
|||||||
):
|
):
|
||||||
current = await config_crud.get(db)
|
current = await config_crud.get(db)
|
||||||
# Keep existing password if not provided in the update
|
# Keep existing password if not provided in the update
|
||||||
new_password = payload.password if payload.password is not None else (current.password if current else None)
|
new_password = (
|
||||||
|
payload.password
|
||||||
|
if payload.password is not None
|
||||||
|
else (current.password if current else None)
|
||||||
|
)
|
||||||
config = await config_crud.upsert(
|
config = await config_crud.upsert(
|
||||||
db,
|
db,
|
||||||
odata_url=payload.odata_url,
|
odata_url=payload.odata_url,
|
||||||
@@ -59,7 +63,10 @@ async def update_config(
|
|||||||
password=new_password,
|
password=new_password,
|
||||||
)
|
)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="update", resource_type="ImportedPartConfig",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="update",
|
||||||
|
resource_type="ImportedPartConfig",
|
||||||
resource_id=1,
|
resource_id=1,
|
||||||
description="Updated ImportedPart OData configuration",
|
description="Updated ImportedPart OData configuration",
|
||||||
)
|
)
|
||||||
@@ -81,10 +88,15 @@ async def refresh_imported_parts(
|
|||||||
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||||
detail="OData URL is not configured.",
|
detail="OData URL is not configured.",
|
||||||
)
|
)
|
||||||
records = await odata_service.fetch(config.odata_url, config.username, config.password)
|
records = await odata_service.fetch(
|
||||||
|
config.odata_url, config.username, config.password
|
||||||
|
)
|
||||||
created, updated = await imported_part_crud.upsert_bulk(db, records)
|
created, updated = await imported_part_crud.upsert_bulk(db, records)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="update", resource_type="ImportedPart",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="update",
|
||||||
|
resource_type="ImportedPart",
|
||||||
resource_id=None,
|
resource_id=None,
|
||||||
description=f"OData sync: {created} created, {updated} updated ({len(records)} total records)",
|
description=f"OData sync: {created} created, {updated} updated ({len(records)} total records)",
|
||||||
)
|
)
|
||||||
@@ -99,7 +111,9 @@ async def get_imported_part(
|
|||||||
):
|
):
|
||||||
part = await imported_part_crud.get(db, inventory_id)
|
part = await imported_part_crud.get(db, inventory_id)
|
||||||
if part is None:
|
if part is None:
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Imported part not found")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="Imported part not found"
|
||||||
|
)
|
||||||
return part
|
return part
|
||||||
|
|
||||||
|
|
||||||
@@ -111,10 +125,15 @@ async def delete_imported_part(
|
|||||||
):
|
):
|
||||||
part = await imported_part_crud.get(db, inventory_id)
|
part = await imported_part_crud.get(db, inventory_id)
|
||||||
if part is None:
|
if part is None:
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Imported part not found")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="Imported part not found"
|
||||||
|
)
|
||||||
await imported_part_crud.delete(db, part)
|
await imported_part_crud.delete(db, part)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="delete", resource_type="ImportedPart",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="delete",
|
||||||
|
resource_type="ImportedPart",
|
||||||
resource_id=None,
|
resource_id=None,
|
||||||
description=audit_crud.describe_delete("ImportedPart", 0, inventory_id),
|
description=audit_crud.describe_delete("ImportedPart", 0, inventory_id),
|
||||||
)
|
)
|
||||||
+24
-7
@@ -34,9 +34,14 @@ async def create_iso_thread(
|
|||||||
depth_mm=payload.depth_mm,
|
depth_mm=payload.depth_mm,
|
||||||
)
|
)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="create", resource_type="IsoThread",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="create",
|
||||||
|
resource_type="IsoThread",
|
||||||
resource_id=thread.id,
|
resource_id=thread.id,
|
||||||
description=audit_crud.describe_create("IsoThread", thread.id, f"M{thread.diameter_mm}×{thread.pitch_mm}"),
|
description=audit_crud.describe_create(
|
||||||
|
"IsoThread", thread.id, f"M{thread.diameter_mm}×{thread.pitch_mm}"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
return thread
|
return thread
|
||||||
|
|
||||||
@@ -49,7 +54,9 @@ async def get_iso_thread(
|
|||||||
):
|
):
|
||||||
thread = await iso_thread_crud.get(db, iso_thread_id)
|
thread = await iso_thread_crud.get(db, iso_thread_id)
|
||||||
if thread is None:
|
if thread is None:
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="ISO thread not found")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="ISO thread not found"
|
||||||
|
)
|
||||||
return thread
|
return thread
|
||||||
|
|
||||||
|
|
||||||
@@ -62,11 +69,16 @@ async def update_iso_thread(
|
|||||||
):
|
):
|
||||||
thread = await iso_thread_crud.get(db, iso_thread_id)
|
thread = await iso_thread_crud.get(db, iso_thread_id)
|
||||||
if thread is None:
|
if thread is None:
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="ISO thread not found")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="ISO thread not found"
|
||||||
|
)
|
||||||
changes = payload.model_dump(exclude_unset=True)
|
changes = payload.model_dump(exclude_unset=True)
|
||||||
thread = await iso_thread_crud.update(db, thread, changes)
|
thread = await iso_thread_crud.update(db, thread, changes)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="update", resource_type="IsoThread",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="update",
|
||||||
|
resource_type="IsoThread",
|
||||||
resource_id=thread.id,
|
resource_id=thread.id,
|
||||||
description=audit_crud.describe_update("IsoThread", thread.id, changes),
|
description=audit_crud.describe_update("IsoThread", thread.id, changes),
|
||||||
)
|
)
|
||||||
@@ -81,11 +93,16 @@ async def delete_iso_thread(
|
|||||||
):
|
):
|
||||||
thread = await iso_thread_crud.get(db, iso_thread_id)
|
thread = await iso_thread_crud.get(db, iso_thread_id)
|
||||||
if thread is None:
|
if thread is None:
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="ISO thread not found")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="ISO thread not found"
|
||||||
|
)
|
||||||
name = f"M{thread.diameter_mm}×{thread.pitch_mm}"
|
name = f"M{thread.diameter_mm}×{thread.pitch_mm}"
|
||||||
await iso_thread_crud.delete(db, thread)
|
await iso_thread_crud.delete(db, thread)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="delete", resource_type="IsoThread",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="delete",
|
||||||
|
resource_type="IsoThread",
|
||||||
resource_id=iso_thread_id,
|
resource_id=iso_thread_id,
|
||||||
description=audit_crud.describe_delete("IsoThread", iso_thread_id, name),
|
description=audit_crud.describe_delete("IsoThread", iso_thread_id, name),
|
||||||
)
|
)
|
||||||
@@ -6,7 +6,11 @@ from app.crud import audit as audit_crud
|
|||||||
from app.crud import manufacturer as manufacturer_crud
|
from app.crud import manufacturer as manufacturer_crud
|
||||||
from app.deps import require_permission
|
from app.deps import require_permission
|
||||||
from app.models.user import User
|
from app.models.user import User
|
||||||
from app.schemas.manufacturer import ManufacturerCreate, ManufacturerRead, ManufacturerUpdate
|
from app.schemas.manufacturer import (
|
||||||
|
ManufacturerCreate,
|
||||||
|
ManufacturerRead,
|
||||||
|
ManufacturerUpdate,
|
||||||
|
)
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
@@ -34,7 +38,10 @@ async def create_manufacturer(
|
|||||||
logo_url=str(payload.logo_url) if payload.logo_url else None,
|
logo_url=str(payload.logo_url) if payload.logo_url else None,
|
||||||
)
|
)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="create", resource_type="Manufacturer",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="create",
|
||||||
|
resource_type="Manufacturer",
|
||||||
resource_id=m.id,
|
resource_id=m.id,
|
||||||
description=audit_crud.describe_create("Manufacturer", m.id, m.name),
|
description=audit_crud.describe_create("Manufacturer", m.id, m.name),
|
||||||
)
|
)
|
||||||
@@ -49,7 +56,9 @@ async def get_manufacturer(
|
|||||||
):
|
):
|
||||||
m = await manufacturer_crud.get(db, manufacturer_id)
|
m = await manufacturer_crud.get(db, manufacturer_id)
|
||||||
if m is None:
|
if m is None:
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Manufacturer not found")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="Manufacturer not found"
|
||||||
|
)
|
||||||
return m
|
return m
|
||||||
|
|
||||||
|
|
||||||
@@ -62,7 +71,9 @@ async def update_manufacturer(
|
|||||||
):
|
):
|
||||||
m = await manufacturer_crud.get(db, manufacturer_id)
|
m = await manufacturer_crud.get(db, manufacturer_id)
|
||||||
if m is None:
|
if m is None:
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Manufacturer not found")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="Manufacturer not found"
|
||||||
|
)
|
||||||
data = payload.model_dump(exclude_unset=True)
|
data = payload.model_dump(exclude_unset=True)
|
||||||
if "url" in data and data["url"] is not None:
|
if "url" in data and data["url"] is not None:
|
||||||
data["url"] = str(data["url"])
|
data["url"] = str(data["url"])
|
||||||
@@ -70,7 +81,10 @@ async def update_manufacturer(
|
|||||||
data["logo_url"] = str(data["logo_url"])
|
data["logo_url"] = str(data["logo_url"])
|
||||||
m = await manufacturer_crud.update(db, m, data)
|
m = await manufacturer_crud.update(db, m, data)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="update", resource_type="Manufacturer",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="update",
|
||||||
|
resource_type="Manufacturer",
|
||||||
resource_id=m.id,
|
resource_id=m.id,
|
||||||
description=audit_crud.describe_update("Manufacturer", m.id, data),
|
description=audit_crud.describe_update("Manufacturer", m.id, data),
|
||||||
)
|
)
|
||||||
@@ -85,11 +99,16 @@ async def delete_manufacturer(
|
|||||||
):
|
):
|
||||||
m = await manufacturer_crud.get(db, manufacturer_id)
|
m = await manufacturer_crud.get(db, manufacturer_id)
|
||||||
if m is None:
|
if m is None:
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Manufacturer not found")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="Manufacturer not found"
|
||||||
|
)
|
||||||
name = m.name
|
name = m.name
|
||||||
await manufacturer_crud.delete(db, m)
|
await manufacturer_crud.delete(db, m)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="delete", resource_type="Manufacturer",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="delete",
|
||||||
|
resource_type="Manufacturer",
|
||||||
resource_id=manufacturer_id,
|
resource_id=manufacturer_id,
|
||||||
description=audit_crud.describe_delete("Manufacturer", manufacturer_id, name),
|
description=audit_crud.describe_delete("Manufacturer", manufacturer_id, name),
|
||||||
)
|
)
|
||||||
+12
-3
@@ -29,7 +29,10 @@ async def create_part_colour(
|
|||||||
):
|
):
|
||||||
pc = await part_colour_crud.create(db, name=payload.name)
|
pc = await part_colour_crud.create(db, name=payload.name)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="create", resource_type="PartColour",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="create",
|
||||||
|
resource_type="PartColour",
|
||||||
resource_id=pc.id,
|
resource_id=pc.id,
|
||||||
description=audit_crud.describe_create("PartColour", pc.id, pc.name),
|
description=audit_crud.describe_create("PartColour", pc.id, pc.name),
|
||||||
)
|
)
|
||||||
@@ -61,7 +64,10 @@ async def update_part_colour(
|
|||||||
changes = payload.model_dump(exclude_unset=True)
|
changes = payload.model_dump(exclude_unset=True)
|
||||||
pc = await part_colour_crud.update(db, pc, changes)
|
pc = await part_colour_crud.update(db, pc, changes)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="update", resource_type="PartColour",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="update",
|
||||||
|
resource_type="PartColour",
|
||||||
resource_id=pc.id,
|
resource_id=pc.id,
|
||||||
description=audit_crud.describe_update("PartColour", pc.id, changes),
|
description=audit_crud.describe_update("PartColour", pc.id, changes),
|
||||||
)
|
)
|
||||||
@@ -80,7 +86,10 @@ async def delete_part_colour(
|
|||||||
name = pc.name
|
name = pc.name
|
||||||
await part_colour_crud.delete(db, pc)
|
await part_colour_crud.delete(db, pc)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="delete", resource_type="PartColour",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="delete",
|
||||||
|
resource_type="PartColour",
|
||||||
resource_id=part_colour_id,
|
resource_id=part_colour_id,
|
||||||
description=audit_crud.describe_delete("PartColour", part_colour_id, name),
|
description=audit_crud.describe_delete("PartColour", part_colour_id, name),
|
||||||
)
|
)
|
||||||
+21
-6
@@ -29,7 +29,10 @@ async def create_part_type(
|
|||||||
):
|
):
|
||||||
pt = await part_type_crud.create(db, name=payload.name)
|
pt = await part_type_crud.create(db, name=payload.name)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="create", resource_type="PartType",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="create",
|
||||||
|
resource_type="PartType",
|
||||||
resource_id=pt.id,
|
resource_id=pt.id,
|
||||||
description=audit_crud.describe_create("PartType", pt.id, pt.name),
|
description=audit_crud.describe_create("PartType", pt.id, pt.name),
|
||||||
)
|
)
|
||||||
@@ -44,7 +47,9 @@ async def get_part_type(
|
|||||||
):
|
):
|
||||||
pt = await part_type_crud.get(db, part_type_id)
|
pt = await part_type_crud.get(db, part_type_id)
|
||||||
if pt is None:
|
if pt is None:
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Part type not found")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="Part type not found"
|
||||||
|
)
|
||||||
return pt
|
return pt
|
||||||
|
|
||||||
|
|
||||||
@@ -57,11 +62,16 @@ async def update_part_type(
|
|||||||
):
|
):
|
||||||
pt = await part_type_crud.get(db, part_type_id)
|
pt = await part_type_crud.get(db, part_type_id)
|
||||||
if pt is None:
|
if pt is None:
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Part type not found")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="Part type not found"
|
||||||
|
)
|
||||||
changes = payload.model_dump(exclude_unset=True)
|
changes = payload.model_dump(exclude_unset=True)
|
||||||
pt = await part_type_crud.update(db, pt, changes)
|
pt = await part_type_crud.update(db, pt, changes)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="update", resource_type="PartType",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="update",
|
||||||
|
resource_type="PartType",
|
||||||
resource_id=pt.id,
|
resource_id=pt.id,
|
||||||
description=audit_crud.describe_update("PartType", pt.id, changes),
|
description=audit_crud.describe_update("PartType", pt.id, changes),
|
||||||
)
|
)
|
||||||
@@ -76,11 +86,16 @@ async def delete_part_type(
|
|||||||
):
|
):
|
||||||
pt = await part_type_crud.get(db, part_type_id)
|
pt = await part_type_crud.get(db, part_type_id)
|
||||||
if pt is None:
|
if pt is None:
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Part type not found")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="Part type not found"
|
||||||
|
)
|
||||||
name = pt.name
|
name = pt.name
|
||||||
await part_type_crud.delete(db, pt)
|
await part_type_crud.delete(db, pt)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="delete", resource_type="PartType",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="delete",
|
||||||
|
resource_type="PartType",
|
||||||
resource_id=part_type_id,
|
resource_id=part_type_id,
|
||||||
description=audit_crud.describe_delete("PartType", part_type_id, name),
|
description=audit_crud.describe_delete("PartType", part_type_id, name),
|
||||||
)
|
)
|
||||||
+12
-3
@@ -36,7 +36,10 @@ async def create_role(
|
|||||||
permission_ids=payload.permission_ids,
|
permission_ids=payload.permission_ids,
|
||||||
)
|
)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="create", resource_type="Role",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="create",
|
||||||
|
resource_type="Role",
|
||||||
resource_id=role.id,
|
resource_id=role.id,
|
||||||
description=audit_crud.describe_create("Role", role.id, role.name),
|
description=audit_crud.describe_create("Role", role.id, role.name),
|
||||||
)
|
)
|
||||||
@@ -80,7 +83,10 @@ async def update_role(
|
|||||||
changes = payload.model_dump(exclude_unset=True)
|
changes = payload.model_dump(exclude_unset=True)
|
||||||
role = await role_crud.update(db, role, changes)
|
role = await role_crud.update(db, role, changes)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="update", resource_type="Role",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="update",
|
||||||
|
resource_type="Role",
|
||||||
resource_id=role.id,
|
resource_id=role.id,
|
||||||
description=audit_crud.describe_update("Role", role.id, changes),
|
description=audit_crud.describe_update("Role", role.id, changes),
|
||||||
)
|
)
|
||||||
@@ -101,7 +107,10 @@ async def delete_role(
|
|||||||
name = role.name
|
name = role.name
|
||||||
await role_crud.delete(db, role)
|
await role_crud.delete(db, role)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="delete", resource_type="Role",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="delete",
|
||||||
|
resource_type="Role",
|
||||||
resource_id=role_id,
|
resource_id=role_id,
|
||||||
description=audit_crud.describe_delete("Role", role_id, name),
|
description=audit_crud.describe_delete("Role", role_id, name),
|
||||||
)
|
)
|
||||||
+57
-13
@@ -1,22 +1,66 @@
|
|||||||
from fastapi import APIRouter
|
from fastapi import APIRouter
|
||||||
|
|
||||||
from app.api import attachment_point_names, attachment_points, audit_log, augmented_parts, auth, clamp_connections, imported_parts, iso_threads, manufacturers, part_colours, part_types, roles, scope_models, static_connections, sub_part_types, unc_threads, users
|
from app.api import (
|
||||||
|
attachment_point_names,
|
||||||
|
attachment_points,
|
||||||
|
audit_log,
|
||||||
|
augmented_parts,
|
||||||
|
auth,
|
||||||
|
clamp_connections,
|
||||||
|
imported_parts,
|
||||||
|
iso_threads,
|
||||||
|
manufacturers,
|
||||||
|
part_colours,
|
||||||
|
part_types,
|
||||||
|
roles,
|
||||||
|
scope_models,
|
||||||
|
static_connections,
|
||||||
|
sub_part_types,
|
||||||
|
unc_threads,
|
||||||
|
users,
|
||||||
|
)
|
||||||
|
|
||||||
api_router = APIRouter()
|
api_router = APIRouter()
|
||||||
api_router.include_router(auth.router, prefix="/auth", tags=["auth"])
|
api_router.include_router(auth.router, prefix="/auth", tags=["auth"])
|
||||||
api_router.include_router(users.router, prefix="/users", tags=["users"])
|
api_router.include_router(users.router, prefix="/users", tags=["users"])
|
||||||
api_router.include_router(roles.router, prefix="/roles", tags=["roles"])
|
api_router.include_router(roles.router, prefix="/roles", tags=["roles"])
|
||||||
api_router.include_router(iso_threads.router, prefix="/iso-threads", tags=["iso-threads"])
|
api_router.include_router(
|
||||||
api_router.include_router(unc_threads.router, prefix="/unc-threads", tags=["unc-threads"])
|
iso_threads.router, prefix="/iso-threads", tags=["iso-threads"]
|
||||||
api_router.include_router(manufacturers.router, prefix="/manufacturers", tags=["manufacturers"])
|
)
|
||||||
api_router.include_router(scope_models.router, prefix="/scope-models", tags=["scope-models"])
|
api_router.include_router(
|
||||||
api_router.include_router(part_colours.router, prefix="/part-colours", tags=["part-colours"])
|
unc_threads.router, prefix="/unc-threads", tags=["unc-threads"]
|
||||||
|
)
|
||||||
|
api_router.include_router(
|
||||||
|
manufacturers.router, prefix="/manufacturers", tags=["manufacturers"]
|
||||||
|
)
|
||||||
|
api_router.include_router(
|
||||||
|
scope_models.router, prefix="/scope-models", tags=["scope-models"]
|
||||||
|
)
|
||||||
|
api_router.include_router(
|
||||||
|
part_colours.router, prefix="/part-colours", tags=["part-colours"]
|
||||||
|
)
|
||||||
api_router.include_router(part_types.router, prefix="/part-types", tags=["part-types"])
|
api_router.include_router(part_types.router, prefix="/part-types", tags=["part-types"])
|
||||||
api_router.include_router(sub_part_types.router, prefix="/sub-part-types", tags=["sub-part-types"])
|
api_router.include_router(
|
||||||
api_router.include_router(static_connections.router, prefix="/static-connections", tags=["static-connections"])
|
sub_part_types.router, prefix="/sub-part-types", tags=["sub-part-types"]
|
||||||
api_router.include_router(clamp_connections.router, prefix="/clamp-connections", tags=["clamp-connections"])
|
)
|
||||||
api_router.include_router(attachment_point_names.router, prefix="/attachment-point-names", tags=["attachment-point-names"])
|
api_router.include_router(
|
||||||
api_router.include_router(attachment_points.router, prefix="/attachment-points", tags=["attachment-points"])
|
static_connections.router, prefix="/static-connections", tags=["static-connections"]
|
||||||
api_router.include_router(imported_parts.router, prefix="/imported-parts", tags=["imported-parts"])
|
)
|
||||||
api_router.include_router(augmented_parts.router, prefix="/augmented-parts", tags=["augmented-parts"])
|
api_router.include_router(
|
||||||
|
clamp_connections.router, prefix="/clamp-connections", tags=["clamp-connections"]
|
||||||
|
)
|
||||||
|
api_router.include_router(
|
||||||
|
attachment_point_names.router,
|
||||||
|
prefix="/attachment-point-names",
|
||||||
|
tags=["attachment-point-names"],
|
||||||
|
)
|
||||||
|
api_router.include_router(
|
||||||
|
attachment_points.router, prefix="/attachment-points", tags=["attachment-points"]
|
||||||
|
)
|
||||||
|
api_router.include_router(
|
||||||
|
imported_parts.router, prefix="/imported-parts", tags=["imported-parts"]
|
||||||
|
)
|
||||||
|
api_router.include_router(
|
||||||
|
augmented_parts.router, prefix="/augmented-parts", tags=["augmented-parts"]
|
||||||
|
)
|
||||||
api_router.include_router(audit_log.router, prefix="/audit-log", tags=["audit-log"])
|
api_router.include_router(audit_log.router, prefix="/audit-log", tags=["audit-log"])
|
||||||
+21
-6
@@ -34,7 +34,10 @@ async def create_scope_model(
|
|||||||
url=str(payload.url) if payload.url else None,
|
url=str(payload.url) if payload.url else None,
|
||||||
)
|
)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="create", resource_type="ScopeModel",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="create",
|
||||||
|
resource_type="ScopeModel",
|
||||||
resource_id=sm.id,
|
resource_id=sm.id,
|
||||||
description=audit_crud.describe_create("ScopeModel", sm.id, sm.name),
|
description=audit_crud.describe_create("ScopeModel", sm.id, sm.name),
|
||||||
)
|
)
|
||||||
@@ -49,7 +52,9 @@ async def get_scope_model(
|
|||||||
):
|
):
|
||||||
sm = await scope_model_crud.get(db, scope_model_id)
|
sm = await scope_model_crud.get(db, scope_model_id)
|
||||||
if sm is None:
|
if sm is None:
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Scope model not found")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="Scope model not found"
|
||||||
|
)
|
||||||
return sm
|
return sm
|
||||||
|
|
||||||
|
|
||||||
@@ -62,13 +67,18 @@ async def update_scope_model(
|
|||||||
):
|
):
|
||||||
sm = await scope_model_crud.get(db, scope_model_id)
|
sm = await scope_model_crud.get(db, scope_model_id)
|
||||||
if sm is None:
|
if sm is None:
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Scope model not found")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="Scope model not found"
|
||||||
|
)
|
||||||
data = payload.model_dump(exclude_unset=True)
|
data = payload.model_dump(exclude_unset=True)
|
||||||
if "url" in data and data["url"] is not None:
|
if "url" in data and data["url"] is not None:
|
||||||
data["url"] = str(data["url"])
|
data["url"] = str(data["url"])
|
||||||
sm = await scope_model_crud.update(db, sm, data)
|
sm = await scope_model_crud.update(db, sm, data)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="update", resource_type="ScopeModel",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="update",
|
||||||
|
resource_type="ScopeModel",
|
||||||
resource_id=sm.id,
|
resource_id=sm.id,
|
||||||
description=audit_crud.describe_update("ScopeModel", sm.id, data),
|
description=audit_crud.describe_update("ScopeModel", sm.id, data),
|
||||||
)
|
)
|
||||||
@@ -83,11 +93,16 @@ async def delete_scope_model(
|
|||||||
):
|
):
|
||||||
sm = await scope_model_crud.get(db, scope_model_id)
|
sm = await scope_model_crud.get(db, scope_model_id)
|
||||||
if sm is None:
|
if sm is None:
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Scope model not found")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="Scope model not found"
|
||||||
|
)
|
||||||
name = sm.name
|
name = sm.name
|
||||||
await scope_model_crud.delete(db, sm)
|
await scope_model_crud.delete(db, sm)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="delete", resource_type="ScopeModel",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="delete",
|
||||||
|
resource_type="ScopeModel",
|
||||||
resource_id=scope_model_id,
|
resource_id=scope_model_id,
|
||||||
description=audit_crud.describe_delete("ScopeModel", scope_model_id, name),
|
description=audit_crud.describe_delete("ScopeModel", scope_model_id, name),
|
||||||
)
|
)
|
||||||
@@ -25,17 +25,26 @@ async def list_static_connections(
|
|||||||
return await static_connection_crud.list_all(db, skip=skip, limit=limit)
|
return await static_connection_crud.list_all(db, skip=skip, limit=limit)
|
||||||
|
|
||||||
|
|
||||||
@router.post("", response_model=StaticConnectionRead, status_code=status.HTTP_201_CREATED)
|
@router.post(
|
||||||
|
"", response_model=StaticConnectionRead, status_code=status.HTTP_201_CREATED
|
||||||
|
)
|
||||||
async def create_static_connection(
|
async def create_static_connection(
|
||||||
payload: StaticConnectionCreate,
|
payload: StaticConnectionCreate,
|
||||||
db: AsyncSession = Depends(get_db),
|
db: AsyncSession = Depends(get_db),
|
||||||
actor: User = Depends(require_permission("static_connections:write")),
|
actor: User = Depends(require_permission("static_connections:write")),
|
||||||
):
|
):
|
||||||
sc = await static_connection_crud.create(db, od_mm=payload.od_mm, od_in=payload.od_in)
|
sc = await static_connection_crud.create(
|
||||||
|
db, od_mm=payload.od_mm, od_in=payload.od_in
|
||||||
|
)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="create", resource_type="StaticConnection",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="create",
|
||||||
|
resource_type="StaticConnection",
|
||||||
resource_id=sc.id,
|
resource_id=sc.id,
|
||||||
description=audit_crud.describe_create("StaticConnection", sc.id, f"{sc.od_mm} mm"),
|
description=audit_crud.describe_create(
|
||||||
|
"StaticConnection", sc.id, f"{sc.od_mm} mm"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
return sc
|
return sc
|
||||||
|
|
||||||
@@ -65,7 +74,10 @@ async def update_static_connection(
|
|||||||
changes = payload.model_dump(exclude_unset=True)
|
changes = payload.model_dump(exclude_unset=True)
|
||||||
sc = await static_connection_crud.update(db, sc, changes)
|
sc = await static_connection_crud.update(db, sc, changes)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="update", resource_type="StaticConnection",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="update",
|
||||||
|
resource_type="StaticConnection",
|
||||||
resource_id=sc.id,
|
resource_id=sc.id,
|
||||||
description=audit_crud.describe_update("StaticConnection", sc.id, changes),
|
description=audit_crud.describe_update("StaticConnection", sc.id, changes),
|
||||||
)
|
)
|
||||||
@@ -84,7 +96,10 @@ async def delete_static_connection(
|
|||||||
od_mm = sc.od_mm
|
od_mm = sc.od_mm
|
||||||
await static_connection_crud.delete(db, sc)
|
await static_connection_crud.delete(db, sc)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="delete", resource_type="StaticConnection",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="delete",
|
||||||
|
resource_type="StaticConnection",
|
||||||
resource_id=static_connection_id,
|
resource_id=static_connection_id,
|
||||||
description=audit_crud.describe_delete(
|
description=audit_crud.describe_delete(
|
||||||
"StaticConnection", static_connection_id, f"{od_mm} mm"
|
"StaticConnection", static_connection_id, f"{od_mm} mm"
|
||||||
|
|||||||
@@ -6,7 +6,11 @@ from app.crud import audit as audit_crud
|
|||||||
from app.crud import sub_part_type as sub_part_type_crud
|
from app.crud import sub_part_type as sub_part_type_crud
|
||||||
from app.deps import require_permission
|
from app.deps import require_permission
|
||||||
from app.models.user import User
|
from app.models.user import User
|
||||||
from app.schemas.sub_part_type import SubPartTypeCreate, SubPartTypeRead, SubPartTypeUpdate
|
from app.schemas.sub_part_type import (
|
||||||
|
SubPartTypeCreate,
|
||||||
|
SubPartTypeRead,
|
||||||
|
SubPartTypeUpdate,
|
||||||
|
)
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
@@ -31,7 +35,10 @@ async def create_sub_part_type(
|
|||||||
db, name=payload.name, part_type_id=payload.part_type_id
|
db, name=payload.name, part_type_id=payload.part_type_id
|
||||||
)
|
)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="create", resource_type="SubPartType",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="create",
|
||||||
|
resource_type="SubPartType",
|
||||||
resource_id=spt.id,
|
resource_id=spt.id,
|
||||||
description=audit_crud.describe_create("SubPartType", spt.id, spt.name),
|
description=audit_crud.describe_create("SubPartType", spt.id, spt.name),
|
||||||
)
|
)
|
||||||
@@ -46,7 +53,9 @@ async def get_sub_part_type(
|
|||||||
):
|
):
|
||||||
spt = await sub_part_type_crud.get(db, sub_part_type_id)
|
spt = await sub_part_type_crud.get(db, sub_part_type_id)
|
||||||
if spt is None:
|
if spt is None:
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Sub part type not found")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="Sub part type not found"
|
||||||
|
)
|
||||||
return spt
|
return spt
|
||||||
|
|
||||||
|
|
||||||
@@ -59,11 +68,16 @@ async def update_sub_part_type(
|
|||||||
):
|
):
|
||||||
spt = await sub_part_type_crud.get(db, sub_part_type_id)
|
spt = await sub_part_type_crud.get(db, sub_part_type_id)
|
||||||
if spt is None:
|
if spt is None:
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Sub part type not found")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="Sub part type not found"
|
||||||
|
)
|
||||||
changes = payload.model_dump(exclude_unset=True)
|
changes = payload.model_dump(exclude_unset=True)
|
||||||
spt = await sub_part_type_crud.update(db, spt, changes)
|
spt = await sub_part_type_crud.update(db, spt, changes)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="update", resource_type="SubPartType",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="update",
|
||||||
|
resource_type="SubPartType",
|
||||||
resource_id=spt.id,
|
resource_id=spt.id,
|
||||||
description=audit_crud.describe_update("SubPartType", spt.id, changes),
|
description=audit_crud.describe_update("SubPartType", spt.id, changes),
|
||||||
)
|
)
|
||||||
@@ -78,11 +92,16 @@ async def delete_sub_part_type(
|
|||||||
):
|
):
|
||||||
spt = await sub_part_type_crud.get(db, sub_part_type_id)
|
spt = await sub_part_type_crud.get(db, sub_part_type_id)
|
||||||
if spt is None:
|
if spt is None:
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Sub part type not found")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="Sub part type not found"
|
||||||
|
)
|
||||||
name = spt.name
|
name = spt.name
|
||||||
await sub_part_type_crud.delete(db, spt)
|
await sub_part_type_crud.delete(db, spt)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="delete", resource_type="SubPartType",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="delete",
|
||||||
|
resource_type="SubPartType",
|
||||||
resource_id=sub_part_type_id,
|
resource_id=sub_part_type_id,
|
||||||
description=audit_crud.describe_delete("SubPartType", sub_part_type_id, name),
|
description=audit_crud.describe_delete("SubPartType", sub_part_type_id, name),
|
||||||
)
|
)
|
||||||
+26
-7
@@ -35,9 +35,16 @@ async def create_unc_thread(
|
|||||||
depth_in=payload.depth_in,
|
depth_in=payload.depth_in,
|
||||||
)
|
)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="create", resource_type="UncThread",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="create",
|
||||||
|
resource_type="UncThread",
|
||||||
resource_id=thread.id,
|
resource_id=thread.id,
|
||||||
description=audit_crud.describe_create("UncThread", thread.id, f"{thread.diameter_fraction}-{thread.tpi} {thread.series.value}"),
|
description=audit_crud.describe_create(
|
||||||
|
"UncThread",
|
||||||
|
thread.id,
|
||||||
|
f"{thread.diameter_fraction}-{thread.tpi} {thread.series.value}",
|
||||||
|
),
|
||||||
)
|
)
|
||||||
return thread
|
return thread
|
||||||
|
|
||||||
@@ -50,7 +57,9 @@ async def get_unc_thread(
|
|||||||
):
|
):
|
||||||
thread = await unc_thread_crud.get(db, unc_thread_id)
|
thread = await unc_thread_crud.get(db, unc_thread_id)
|
||||||
if thread is None:
|
if thread is None:
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="UNC thread not found")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="UNC thread not found"
|
||||||
|
)
|
||||||
return thread
|
return thread
|
||||||
|
|
||||||
|
|
||||||
@@ -63,11 +72,16 @@ async def update_unc_thread(
|
|||||||
):
|
):
|
||||||
thread = await unc_thread_crud.get(db, unc_thread_id)
|
thread = await unc_thread_crud.get(db, unc_thread_id)
|
||||||
if thread is None:
|
if thread is None:
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="UNC thread not found")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="UNC thread not found"
|
||||||
|
)
|
||||||
changes = payload.model_dump(exclude_unset=True)
|
changes = payload.model_dump(exclude_unset=True)
|
||||||
thread = await unc_thread_crud.update(db, thread, changes)
|
thread = await unc_thread_crud.update(db, thread, changes)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="update", resource_type="UncThread",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="update",
|
||||||
|
resource_type="UncThread",
|
||||||
resource_id=thread.id,
|
resource_id=thread.id,
|
||||||
description=audit_crud.describe_update("UncThread", thread.id, changes),
|
description=audit_crud.describe_update("UncThread", thread.id, changes),
|
||||||
)
|
)
|
||||||
@@ -82,11 +96,16 @@ async def delete_unc_thread(
|
|||||||
):
|
):
|
||||||
thread = await unc_thread_crud.get(db, unc_thread_id)
|
thread = await unc_thread_crud.get(db, unc_thread_id)
|
||||||
if thread is None:
|
if thread is None:
|
||||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="UNC thread not found")
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="UNC thread not found"
|
||||||
|
)
|
||||||
name = f"{thread.diameter_fraction}-{thread.tpi} {thread.series.value}"
|
name = f"{thread.diameter_fraction}-{thread.tpi} {thread.series.value}"
|
||||||
await unc_thread_crud.delete(db, thread)
|
await unc_thread_crud.delete(db, thread)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="delete", resource_type="UncThread",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="delete",
|
||||||
|
resource_type="UncThread",
|
||||||
resource_id=unc_thread_id,
|
resource_id=unc_thread_id,
|
||||||
description=audit_crud.describe_delete("UncThread", unc_thread_id, name),
|
description=audit_crud.describe_delete("UncThread", unc_thread_id, name),
|
||||||
)
|
)
|
||||||
+12
-3
@@ -45,7 +45,10 @@ async def create_user(
|
|||||||
role_ids=payload.role_ids,
|
role_ids=payload.role_ids,
|
||||||
)
|
)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="create", resource_type="User",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="create",
|
||||||
|
resource_type="User",
|
||||||
resource_id=created.id,
|
resource_id=created.id,
|
||||||
description=audit_crud.describe_create("User", created.id, created.email),
|
description=audit_crud.describe_create("User", created.id, created.email),
|
||||||
)
|
)
|
||||||
@@ -81,7 +84,10 @@ async def update_user(
|
|||||||
changes = payload.model_dump(exclude_unset=True)
|
changes = payload.model_dump(exclude_unset=True)
|
||||||
target = await user_crud.update(db, target, changes)
|
target = await user_crud.update(db, target, changes)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="update", resource_type="User",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="update",
|
||||||
|
resource_type="User",
|
||||||
resource_id=user_id,
|
resource_id=user_id,
|
||||||
description=audit_crud.describe_update("User", user_id, changes),
|
description=audit_crud.describe_update("User", user_id, changes),
|
||||||
)
|
)
|
||||||
@@ -102,7 +108,10 @@ async def delete_user(
|
|||||||
email = target.email
|
email = target.email
|
||||||
await user_crud.delete(db, target)
|
await user_crud.delete(db, target)
|
||||||
await audit_crud.log(
|
await audit_crud.log(
|
||||||
db, actor=actor, action="delete", resource_type="User",
|
db,
|
||||||
|
actor=actor,
|
||||||
|
action="delete",
|
||||||
|
resource_type="User",
|
||||||
resource_id=user_id,
|
resource_id=user_id,
|
||||||
description=audit_crud.describe_delete("User", user_id, email),
|
description=audit_crud.describe_delete("User", user_id, email),
|
||||||
)
|
)
|
||||||
@@ -63,9 +63,7 @@ async def create(
|
|||||||
return ap
|
return ap
|
||||||
|
|
||||||
|
|
||||||
async def update(
|
async def update(db: AsyncSession, ap: AttachmentPoint, data: dict) -> AttachmentPoint:
|
||||||
db: AsyncSession, ap: AttachmentPoint, data: dict
|
|
||||||
) -> AttachmentPoint:
|
|
||||||
for field, value in data.items():
|
for field, value in data.items():
|
||||||
setattr(ap, field, value)
|
setattr(ap, field, value)
|
||||||
await db.commit()
|
await db.commit()
|
||||||
|
|||||||
+12
-11
@@ -48,7 +48,9 @@ async def list_filtered(
|
|||||||
q = q.where(AugmentedPart.part_type_id == part_type_id)
|
q = q.where(AugmentedPart.part_type_id == part_type_id)
|
||||||
if sub_part_type_id is not None:
|
if sub_part_type_id is not None:
|
||||||
q = q.where(AugmentedPart.sub_part_type_id == sub_part_type_id)
|
q = q.where(AugmentedPart.sub_part_type_id == sub_part_type_id)
|
||||||
result = await db.execute(q.order_by(AugmentedPart.description).offset(skip).limit(limit))
|
result = await db.execute(
|
||||||
|
q.order_by(AugmentedPart.description).offset(skip).limit(limit)
|
||||||
|
)
|
||||||
return list(result.scalars().all())
|
return list(result.scalars().all())
|
||||||
|
|
||||||
|
|
||||||
@@ -62,6 +64,7 @@ async def count_filtered(
|
|||||||
sub_part_type_id: int | None = None,
|
sub_part_type_id: int | None = None,
|
||||||
) -> int:
|
) -> int:
|
||||||
from sqlalchemy import func
|
from sqlalchemy import func
|
||||||
|
|
||||||
q = select(func.count()).select_from(AugmentedPart)
|
q = select(func.count()).select_from(AugmentedPart)
|
||||||
if description.strip():
|
if description.strip():
|
||||||
q = q.where(AugmentedPart.description.ilike(f"%{description.strip()}%"))
|
q = q.where(AugmentedPart.description.ilike(f"%{description.strip()}%"))
|
||||||
@@ -86,19 +89,18 @@ async def get_unlinked_imported_parts_filtered(
|
|||||||
skip: int = 0,
|
skip: int = 0,
|
||||||
limit: int = 50,
|
limit: int = 50,
|
||||||
) -> list[ImportedPart]:
|
) -> list[ImportedPart]:
|
||||||
q = (
|
q = select(ImportedPart).where(
|
||||||
select(ImportedPart)
|
ImportedPart.InventoryID.not_in(
|
||||||
.where(
|
select(augmented_part_imported_parts.c.imported_part_id)
|
||||||
ImportedPart.InventoryID.not_in(
|
|
||||||
select(augmented_part_imported_parts.c.imported_part_id)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if description.strip():
|
if description.strip():
|
||||||
q = q.where(ImportedPart.Description.ilike(f"%{description.strip()}%"))
|
q = q.where(ImportedPart.Description.ilike(f"%{description.strip()}%"))
|
||||||
if colour.strip():
|
if colour.strip():
|
||||||
q = q.where(ImportedPart.TBXColour.ilike(f"%{colour.strip()}%"))
|
q = q.where(ImportedPart.TBXColour.ilike(f"%{colour.strip()}%"))
|
||||||
result = await db.execute(q.order_by(ImportedPart.InventoryID).offset(skip).limit(limit))
|
result = await db.execute(
|
||||||
|
q.order_by(ImportedPart.InventoryID).offset(skip).limit(limit)
|
||||||
|
)
|
||||||
return list(result.scalars().all())
|
return list(result.scalars().all())
|
||||||
|
|
||||||
|
|
||||||
@@ -108,6 +110,7 @@ async def count_unlinked_filtered(
|
|||||||
colour: str = "",
|
colour: str = "",
|
||||||
) -> int:
|
) -> int:
|
||||||
from sqlalchemy import func
|
from sqlalchemy import func
|
||||||
|
|
||||||
q = (
|
q = (
|
||||||
select(func.count())
|
select(func.count())
|
||||||
.select_from(ImportedPart)
|
.select_from(ImportedPart)
|
||||||
@@ -166,9 +169,7 @@ async def create(
|
|||||||
return ap
|
return ap
|
||||||
|
|
||||||
|
|
||||||
async def update(
|
async def update(db: AsyncSession, ap: AugmentedPart, data: dict) -> AugmentedPart:
|
||||||
db: AsyncSession, ap: AugmentedPart, data: dict
|
|
||||||
) -> AugmentedPart:
|
|
||||||
for field, value in data.items():
|
for field, value in data.items():
|
||||||
setattr(ap, field, value)
|
setattr(ap, field, value)
|
||||||
await db.commit()
|
await db.commit()
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ async def list_all(
|
|||||||
) -> list[ClampConnection]:
|
) -> list[ClampConnection]:
|
||||||
result = await db.execute(
|
result = await db.execute(
|
||||||
select(ClampConnection)
|
select(ClampConnection)
|
||||||
.order_by(ClampConnection.min_mm.nulls_last(), ClampConnection.min_in.nulls_last())
|
.order_by(
|
||||||
|
ClampConnection.min_mm.nulls_last(), ClampConnection.min_in.nulls_last()
|
||||||
|
)
|
||||||
.offset(skip)
|
.offset(skip)
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
)
|
)
|
||||||
@@ -35,9 +37,7 @@ async def create(
|
|||||||
return cc
|
return cc
|
||||||
|
|
||||||
|
|
||||||
async def update(
|
async def update(db: AsyncSession, cc: ClampConnection, data: dict) -> ClampConnection:
|
||||||
db: AsyncSession, cc: ClampConnection, data: dict
|
|
||||||
) -> ClampConnection:
|
|
||||||
for field, value in data.items():
|
for field, value in data.items():
|
||||||
setattr(cc, field, value)
|
setattr(cc, field, value)
|
||||||
await db.commit()
|
await db.commit()
|
||||||
|
|||||||
@@ -3,11 +3,18 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
|||||||
|
|
||||||
from app.models.imported_part import ImportedPart
|
from app.models.imported_part import ImportedPart
|
||||||
|
|
||||||
_FIELDS = frozenset({
|
_FIELDS = frozenset(
|
||||||
"InventoryID", "Description", "TBXColour",
|
{
|
||||||
"ProductMaxThreadDepthmm", "ProductMaxThreadDepthin",
|
"InventoryID",
|
||||||
"ProductODmm", "ProductODin", "TBXThreadAttribute",
|
"Description",
|
||||||
})
|
"TBXColour",
|
||||||
|
"ProductMaxThreadDepthmm",
|
||||||
|
"ProductMaxThreadDepthin",
|
||||||
|
"ProductODmm",
|
||||||
|
"ProductODin",
|
||||||
|
"TBXThreadAttribute",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def get(db: AsyncSession, inventory_id: str) -> ImportedPart | None:
|
async def get(db: AsyncSession, inventory_id: str) -> ImportedPart | None:
|
||||||
@@ -18,7 +25,10 @@ async def list_all(
|
|||||||
db: AsyncSession, skip: int = 0, limit: int = 500
|
db: AsyncSession, skip: int = 0, limit: int = 500
|
||||||
) -> list[ImportedPart]:
|
) -> list[ImportedPart]:
|
||||||
result = await db.execute(
|
result = await db.execute(
|
||||||
select(ImportedPart).order_by(ImportedPart.InventoryID).offset(skip).limit(limit)
|
select(ImportedPart)
|
||||||
|
.order_by(ImportedPart.InventoryID)
|
||||||
|
.offset(skip)
|
||||||
|
.limit(limit)
|
||||||
)
|
)
|
||||||
return list(result.scalars().all())
|
return list(result.scalars().all())
|
||||||
|
|
||||||
@@ -32,7 +42,9 @@ async def list_filtered(
|
|||||||
q = select(ImportedPart)
|
q = select(ImportedPart)
|
||||||
if description.strip():
|
if description.strip():
|
||||||
q = q.where(ImportedPart.Description.ilike(f"%{description.strip()}%"))
|
q = q.where(ImportedPart.Description.ilike(f"%{description.strip()}%"))
|
||||||
result = await db.execute(q.order_by(ImportedPart.InventoryID).offset(skip).limit(limit))
|
result = await db.execute(
|
||||||
|
q.order_by(ImportedPart.InventoryID).offset(skip).limit(limit)
|
||||||
|
)
|
||||||
return list(result.scalars().all())
|
return list(result.scalars().all())
|
||||||
|
|
||||||
|
|
||||||
@@ -47,12 +59,14 @@ async def distinct_colours(db: AsyncSession) -> list[str]:
|
|||||||
|
|
||||||
async def count(db: AsyncSession) -> int:
|
async def count(db: AsyncSession) -> int:
|
||||||
from sqlalchemy import func
|
from sqlalchemy import func
|
||||||
|
|
||||||
result = await db.execute(select(func.count()).select_from(ImportedPart))
|
result = await db.execute(select(func.count()).select_from(ImportedPart))
|
||||||
return result.scalar_one()
|
return result.scalar_one()
|
||||||
|
|
||||||
|
|
||||||
async def count_filtered(db: AsyncSession, description: str = "") -> int:
|
async def count_filtered(db: AsyncSession, description: str = "") -> int:
|
||||||
from sqlalchemy import func
|
from sqlalchemy import func
|
||||||
|
|
||||||
q = select(func.count()).select_from(ImportedPart)
|
q = select(func.count()).select_from(ImportedPart)
|
||||||
if description.strip():
|
if description.strip():
|
||||||
q = q.where(ImportedPart.Description.ilike(f"%{description.strip()}%"))
|
q = q.where(ImportedPart.Description.ilike(f"%{description.strip()}%"))
|
||||||
@@ -81,7 +95,9 @@ async def upsert_bulk(db: AsyncSession, records: list[dict]) -> tuple[int, int]:
|
|||||||
incoming_ids = {r["InventoryID"] for r in clean}
|
incoming_ids = {r["InventoryID"] for r in clean}
|
||||||
|
|
||||||
result = await db.execute(
|
result = await db.execute(
|
||||||
select(ImportedPart.InventoryID).where(ImportedPart.InventoryID.in_(incoming_ids))
|
select(ImportedPart.InventoryID).where(
|
||||||
|
ImportedPart.InventoryID.in_(incoming_ids)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
existing_ids = {row[0] for row in result.all()}
|
existing_ids = {row[0] for row in result.all()}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ async def get_by_values(
|
|||||||
depth_mm: float | None,
|
depth_mm: float | None,
|
||||||
) -> IsoThread | None:
|
) -> IsoThread | None:
|
||||||
depth_clause = (
|
depth_clause = (
|
||||||
IsoThread.depth_mm.is_(None) if depth_mm is None else IsoThread.depth_mm == depth_mm
|
IsoThread.depth_mm.is_(None)
|
||||||
|
if depth_mm is None
|
||||||
|
else IsoThread.depth_mm == depth_mm
|
||||||
)
|
)
|
||||||
result = await db.execute(
|
result = await db.execute(
|
||||||
select(IsoThread).where(
|
select(IsoThread).where(
|
||||||
@@ -28,7 +30,9 @@ async def get_by_values(
|
|||||||
return result.scalar_one_or_none()
|
return result.scalar_one_or_none()
|
||||||
|
|
||||||
|
|
||||||
async def list_all(db: AsyncSession, skip: int = 0, limit: int = 100) -> list[IsoThread]:
|
async def list_all(
|
||||||
|
db: AsyncSession, skip: int = 0, limit: int = 100
|
||||||
|
) -> list[IsoThread]:
|
||||||
result = await db.execute(
|
result = await db.execute(
|
||||||
select(IsoThread).order_by(IsoThread.id).offset(skip).limit(limit)
|
select(IsoThread).order_by(IsoThread.id).offset(skip).limit(limit)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -9,9 +9,7 @@ async def get(db: AsyncSession, manufacturer_id: int) -> Manufacturer | None:
|
|||||||
|
|
||||||
|
|
||||||
async def get_by_name(db: AsyncSession, name: str) -> Manufacturer | None:
|
async def get_by_name(db: AsyncSession, name: str) -> Manufacturer | None:
|
||||||
result = await db.execute(
|
result = await db.execute(select(Manufacturer).where(Manufacturer.name == name))
|
||||||
select(Manufacturer).where(Manufacturer.name == name)
|
|
||||||
)
|
|
||||||
return result.scalar_one_or_none()
|
return result.scalar_one_or_none()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,7 @@ async def get(db: AsyncSession, part_colour_id: int) -> PartColour | None:
|
|||||||
|
|
||||||
|
|
||||||
async def get_by_name(db: AsyncSession, name: str) -> PartColour | None:
|
async def get_by_name(db: AsyncSession, name: str) -> PartColour | None:
|
||||||
result = await db.execute(
|
result = await db.execute(select(PartColour).where(PartColour.name == name))
|
||||||
select(PartColour).where(PartColour.name == name)
|
|
||||||
)
|
|
||||||
return result.scalar_one_or_none()
|
return result.scalar_one_or_none()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -13,9 +13,7 @@ async def get_by_name(db: AsyncSession, name: str) -> PartType | None:
|
|||||||
return result.scalar_one_or_none()
|
return result.scalar_one_or_none()
|
||||||
|
|
||||||
|
|
||||||
async def list_all(
|
async def list_all(db: AsyncSession, skip: int = 0, limit: int = 100) -> list[PartType]:
|
||||||
db: AsyncSession, skip: int = 0, limit: int = 100
|
|
||||||
) -> list[PartType]:
|
|
||||||
result = await db.execute(
|
result = await db.execute(
|
||||||
select(PartType).order_by(PartType.name).offset(skip).limit(limit)
|
select(PartType).order_by(PartType.name).offset(skip).limit(limit)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -19,7 +19,10 @@ async def list_all(
|
|||||||
db: AsyncSession, skip: int = 0, limit: int = 100
|
db: AsyncSession, skip: int = 0, limit: int = 100
|
||||||
) -> list[StaticConnection]:
|
) -> list[StaticConnection]:
|
||||||
result = await db.execute(
|
result = await db.execute(
|
||||||
select(StaticConnection).order_by(StaticConnection.od_mm).offset(skip).limit(limit)
|
select(StaticConnection)
|
||||||
|
.order_by(StaticConnection.od_mm)
|
||||||
|
.offset(skip)
|
||||||
|
.limit(limit)
|
||||||
)
|
)
|
||||||
return list(result.scalars().all())
|
return list(result.scalars().all())
|
||||||
|
|
||||||
|
|||||||
@@ -28,9 +28,7 @@ async def list_all(
|
|||||||
return list(result.scalars().all())
|
return list(result.scalars().all())
|
||||||
|
|
||||||
|
|
||||||
async def create(
|
async def create(db: AsyncSession, *, name: str, part_type_id: int) -> SubPartType:
|
||||||
db: AsyncSession, *, name: str, part_type_id: int
|
|
||||||
) -> SubPartType:
|
|
||||||
spt = SubPartType(name=name, part_type_id=part_type_id)
|
spt = SubPartType(name=name, part_type_id=part_type_id)
|
||||||
db.add(spt)
|
db.add(spt)
|
||||||
await db.commit()
|
await db.commit()
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ async def get_by_values(
|
|||||||
depth_in: float | None,
|
depth_in: float | None,
|
||||||
) -> UncThread | None:
|
) -> UncThread | None:
|
||||||
depth_clause = (
|
depth_clause = (
|
||||||
UncThread.depth_in.is_(None) if depth_in is None else UncThread.depth_in == depth_in
|
UncThread.depth_in.is_(None)
|
||||||
|
if depth_in is None
|
||||||
|
else UncThread.depth_in == depth_in
|
||||||
)
|
)
|
||||||
result = await db.execute(
|
result = await db.execute(
|
||||||
select(UncThread).where(
|
select(UncThread).where(
|
||||||
@@ -30,7 +32,9 @@ async def get_by_values(
|
|||||||
return result.scalar_one_or_none()
|
return result.scalar_one_or_none()
|
||||||
|
|
||||||
|
|
||||||
async def list_all(db: AsyncSession, skip: int = 0, limit: int = 100) -> list[UncThread]:
|
async def list_all(
|
||||||
|
db: AsyncSession, skip: int = 0, limit: int = 100
|
||||||
|
) -> list[UncThread]:
|
||||||
result = await db.execute(
|
result = await db.execute(
|
||||||
select(UncThread).order_by(UncThread.id).offset(skip).limit(limit)
|
select(UncThread).order_by(UncThread.id).offset(skip).limit(limit)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
"""Import all models so they register with ``Base.metadata``."""
|
"""Import all models so they register with ``Base.metadata``."""
|
||||||
|
|
||||||
from app.models.associations import augmented_part_imported_parts, role_permissions, user_roles
|
from app.models.associations import (
|
||||||
|
augmented_part_imported_parts,
|
||||||
|
role_permissions,
|
||||||
|
user_roles,
|
||||||
|
)
|
||||||
from app.models.attachment_point import AttachmentPoint
|
from app.models.attachment_point import AttachmentPoint
|
||||||
from app.models.attachment_point_name import AttachmentPointName
|
from app.models.attachment_point_name import AttachmentPointName
|
||||||
from app.models.audit_log import AuditLog
|
from app.models.audit_log import AuditLog
|
||||||
|
|||||||
@@ -29,10 +29,14 @@ class AttachmentPoint(Base):
|
|||||||
ForeignKey("unc_threads.id", ondelete="RESTRICT"), nullable=True, default=None
|
ForeignKey("unc_threads.id", ondelete="RESTRICT"), nullable=True, default=None
|
||||||
)
|
)
|
||||||
clamp_connection_id: Mapped[int | None] = mapped_column(
|
clamp_connection_id: Mapped[int | None] = mapped_column(
|
||||||
ForeignKey("clamp_connections.id", ondelete="RESTRICT"), nullable=True, default=None
|
ForeignKey("clamp_connections.id", ondelete="RESTRICT"),
|
||||||
|
nullable=True,
|
||||||
|
default=None,
|
||||||
)
|
)
|
||||||
static_connection_id: Mapped[int | None] = mapped_column(
|
static_connection_id: Mapped[int | None] = mapped_column(
|
||||||
ForeignKey("static_connections.id", ondelete="RESTRICT"), nullable=True, default=None
|
ForeignKey("static_connections.id", ondelete="RESTRICT"),
|
||||||
|
nullable=True,
|
||||||
|
default=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
attachment_point_name: Mapped[AttachmentPointName] = relationship(lazy="selectin")
|
attachment_point_name: Mapped[AttachmentPointName] = relationship(lazy="selectin")
|
||||||
|
|||||||
@@ -30,7 +30,9 @@ class AugmentedPart(Base):
|
|||||||
ForeignKey("part_types.id", ondelete="RESTRICT"), nullable=False
|
ForeignKey("part_types.id", ondelete="RESTRICT"), nullable=False
|
||||||
)
|
)
|
||||||
sub_part_type_id: Mapped[int | None] = mapped_column(
|
sub_part_type_id: Mapped[int | None] = mapped_column(
|
||||||
ForeignKey("sub_part_types.id", ondelete="SET NULL"), nullable=True, default=None
|
ForeignKey("sub_part_types.id", ondelete="SET NULL"),
|
||||||
|
nullable=True,
|
||||||
|
default=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
# linked imported parts — not eagerly loaded; used by sync service only
|
# linked imported parts — not eagerly loaded; used by sync service only
|
||||||
|
|||||||
@@ -10,8 +10,12 @@ class ImportedPart(Base):
|
|||||||
InventoryID: Mapped[str] = mapped_column(String, primary_key=True)
|
InventoryID: Mapped[str] = mapped_column(String, primary_key=True)
|
||||||
Description: Mapped[str | None] = mapped_column(nullable=True, default=None)
|
Description: Mapped[str | None] = mapped_column(nullable=True, default=None)
|
||||||
TBXColour: Mapped[str | None] = mapped_column(nullable=True, default=None)
|
TBXColour: Mapped[str | None] = mapped_column(nullable=True, default=None)
|
||||||
ProductMaxThreadDepthmm: Mapped[str | None] = mapped_column(nullable=True, default=None)
|
ProductMaxThreadDepthmm: Mapped[str | None] = mapped_column(
|
||||||
ProductMaxThreadDepthin: Mapped[str | None] = mapped_column(nullable=True, default=None)
|
nullable=True, default=None
|
||||||
|
)
|
||||||
|
ProductMaxThreadDepthin: Mapped[str | None] = mapped_column(
|
||||||
|
nullable=True, default=None
|
||||||
|
)
|
||||||
ProductODmm: Mapped[str | None] = mapped_column(nullable=True, default=None)
|
ProductODmm: Mapped[str | None] = mapped_column(nullable=True, default=None)
|
||||||
ProductODin: Mapped[str | None] = mapped_column(nullable=True, default=None)
|
ProductODin: Mapped[str | None] = mapped_column(nullable=True, default=None)
|
||||||
TBXThreadAttribute: Mapped[str | None] = mapped_column(nullable=True, default=None)
|
TBXThreadAttribute: Mapped[str | None] = mapped_column(nullable=True, default=None)
|
||||||
@@ -87,7 +87,6 @@ def _parse_thread_attribute(value: str) -> tuple[str, dict] | None:
|
|||||||
return "iso", {
|
return "iso", {
|
||||||
"diameter_mm": float(m.group("diameter")),
|
"diameter_mm": float(m.group("diameter")),
|
||||||
"pitch_mm": float(m.group("pitch")),
|
"pitch_mm": float(m.group("pitch")),
|
||||||
"extra": float(m.group("extra")),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if m := _UNC_THREAD_RE.match(value):
|
if m := _UNC_THREAD_RE.match(value):
|
||||||
@@ -110,7 +109,9 @@ async def _get_or_create_attachment_point_name(db: AsyncSession, name: str):
|
|||||||
return apn
|
return apn
|
||||||
|
|
||||||
|
|
||||||
async def _add_attachment_point(db: AsyncSession, ap: AugmentedPart, ip: ImportedPart) -> None:
|
async def _add_attachment_point(
|
||||||
|
db: AsyncSession, ap: AugmentedPart, ip: ImportedPart
|
||||||
|
) -> None:
|
||||||
"""Infer and create an attachment point for a newly-synced AugmentedPart.
|
"""Infer and create an attachment point for a newly-synced AugmentedPart.
|
||||||
|
|
||||||
Preference order: TBXThreadAttribute (ISO/UNC thread) then ProductODmm/in
|
Preference order: TBXThreadAttribute (ISO/UNC thread) then ProductODmm/in
|
||||||
@@ -126,7 +127,9 @@ async def _add_attachment_point(db: AsyncSession, ap: AugmentedPart, ip: Importe
|
|||||||
|
|
||||||
if kind == "iso":
|
if kind == "iso":
|
||||||
depth_mm = _parse_float(ip.ProductMaxThreadDepthmm)
|
depth_mm = _parse_float(ip.ProductMaxThreadDepthmm)
|
||||||
thread = await iso_thread_crud.get_by_values(db, depth_mm=depth_mm, **fields)
|
thread = await iso_thread_crud.get_by_values(
|
||||||
|
db, depth_mm=depth_mm, **fields
|
||||||
|
)
|
||||||
if thread is None:
|
if thread is None:
|
||||||
thread = await iso_thread_crud.create(db, depth_mm=depth_mm, **fields)
|
thread = await iso_thread_crud.create(db, depth_mm=depth_mm, **fields)
|
||||||
await attachment_point_crud.create(
|
await attachment_point_crud.create(
|
||||||
@@ -137,7 +140,9 @@ async def _add_attachment_point(db: AsyncSession, ap: AugmentedPart, ip: Importe
|
|||||||
)
|
)
|
||||||
elif kind == "unc":
|
elif kind == "unc":
|
||||||
depth_in = _parse_float(ip.ProductMaxThreadDepthin)
|
depth_in = _parse_float(ip.ProductMaxThreadDepthin)
|
||||||
thread = await unc_thread_crud.get_by_values(db, depth_in=depth_in, **fields)
|
thread = await unc_thread_crud.get_by_values(
|
||||||
|
db, depth_in=depth_in, **fields
|
||||||
|
)
|
||||||
if thread is None:
|
if thread is None:
|
||||||
thread = await unc_thread_crud.create(db, depth_in=depth_in, **fields)
|
thread = await unc_thread_crud.create(db, depth_in=depth_in, **fields)
|
||||||
await attachment_point_crud.create(
|
await attachment_point_crud.create(
|
||||||
@@ -146,6 +151,8 @@ async def _add_attachment_point(db: AsyncSession, ap: AugmentedPart, ip: Importe
|
|||||||
attachment_point_name_id=apn.id,
|
attachment_point_name_id=apn.id,
|
||||||
unc_thread_id=thread.id,
|
unc_thread_id=thread.id,
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
pass
|
||||||
return
|
return
|
||||||
|
|
||||||
od_mm = _parse_float(ip.ProductODmm)
|
od_mm = _parse_float(ip.ProductODmm)
|
||||||
@@ -233,7 +240,9 @@ async def sync(db: AsyncSession) -> AugmentedPartSyncResult:
|
|||||||
# ------------------------------------------------------------------ phase 1
|
# ------------------------------------------------------------------ phase 1
|
||||||
|
|
||||||
# IDs referenced in existing associations
|
# IDs referenced in existing associations
|
||||||
result = await db.execute(select(augmented_part_imported_parts.c.imported_part_id).distinct())
|
result = await db.execute(
|
||||||
|
select(augmented_part_imported_parts.c.imported_part_id).distinct()
|
||||||
|
)
|
||||||
all_linked_ids: set[str] = {row[0] for row in result.all()}
|
all_linked_ids: set[str] = {row[0] for row in result.all()}
|
||||||
|
|
||||||
# IDs that still exist in imported_parts
|
# IDs that still exist in imported_parts
|
||||||
@@ -247,7 +256,9 @@ async def sync(db: AsyncSession) -> AugmentedPartSyncResult:
|
|||||||
# Which AugmentedParts are affected?
|
# Which AugmentedParts are affected?
|
||||||
result = await db.execute(
|
result = await db.execute(
|
||||||
select(augmented_part_imported_parts.c.augmented_part_id).where(
|
select(augmented_part_imported_parts.c.augmented_part_id).where(
|
||||||
augmented_part_imported_parts.c.imported_part_id.in_(orphaned_import_ids)
|
augmented_part_imported_parts.c.imported_part_id.in_(
|
||||||
|
orphaned_import_ids
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
orphaned_ap_ids: set[int] = {row[0] for row in result.all()}
|
orphaned_ap_ids: set[int] = {row[0] for row in result.all()}
|
||||||
@@ -255,7 +266,9 @@ async def sync(db: AsyncSession) -> AugmentedPartSyncResult:
|
|||||||
# Remove the stale association rows
|
# Remove the stale association rows
|
||||||
await db.execute(
|
await db.execute(
|
||||||
augmented_part_imported_parts.delete().where(
|
augmented_part_imported_parts.delete().where(
|
||||||
augmented_part_imported_parts.c.imported_part_id.in_(orphaned_import_ids)
|
augmented_part_imported_parts.c.imported_part_id.in_(
|
||||||
|
orphaned_import_ids
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
await db.flush()
|
await db.flush()
|
||||||
@@ -278,7 +291,9 @@ async def sync(db: AsyncSession) -> AugmentedPartSyncResult:
|
|||||||
# ------------------------------------------------------------------ phase 2
|
# ------------------------------------------------------------------ phase 2
|
||||||
|
|
||||||
# Re-query linked IDs after phase 1 cleanup
|
# Re-query linked IDs after phase 1 cleanup
|
||||||
result = await db.execute(select(augmented_part_imported_parts.c.imported_part_id).distinct())
|
result = await db.execute(
|
||||||
|
select(augmented_part_imported_parts.c.imported_part_id).distinct()
|
||||||
|
)
|
||||||
now_linked_ids: set[str] = {row[0] for row in result.all()}
|
now_linked_ids: set[str] = {row[0] for row in result.all()}
|
||||||
unlinked_ids = current_ids - now_linked_ids
|
unlinked_ids = current_ids - now_linked_ids
|
||||||
|
|
||||||
@@ -286,7 +301,9 @@ async def sync(db: AsyncSession) -> AugmentedPartSyncResult:
|
|||||||
skipped = 0
|
skipped = 0
|
||||||
|
|
||||||
if not unlinked_ids:
|
if not unlinked_ids:
|
||||||
return AugmentedPartSyncResult(created=created, deleted=deleted, skipped=skipped)
|
return AugmentedPartSyncResult(
|
||||||
|
created=created, deleted=deleted, skipped=skipped
|
||||||
|
)
|
||||||
|
|
||||||
result = await db.execute(
|
result = await db.execute(
|
||||||
select(ImportedPart).where(ImportedPart.InventoryID.in_(unlinked_ids))
|
select(ImportedPart).where(ImportedPart.InventoryID.in_(unlinked_ids))
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ async def fetch(
|
|||||||
records: list[dict] = []
|
records: list[dict] = []
|
||||||
next_url: str | None = url
|
next_url: str | None = url
|
||||||
|
|
||||||
headers= {"Accept": "application/json" }
|
headers = {"Accept": "application/json"}
|
||||||
async with httpx.AsyncClient(timeout=30.0) as client:
|
async with httpx.AsyncClient(timeout=30.0) as client:
|
||||||
while next_url:
|
while next_url:
|
||||||
response = await client.get(next_url, auth=auth, headers=headers)
|
response = await client.get(next_url, auth=auth, headers=headers)
|
||||||
|
|||||||
+425
-119
File diff suppressed because it is too large.
Load diff
+25
-3
@@ -77,7 +77,22 @@ PERMISSIONS = [
|
|||||||
# Default roles -> permission names. "admin" gets everything.
|
# Default roles -> permission names. "admin" gets everything.
|
||||||
ROLES = {
|
ROLES = {
|
||||||
"admin": [name for name, _ in PERMISSIONS], # includes audit_log:read
|
"admin": [name for name, _ in PERMISSIONS], # includes audit_log:read
|
||||||
"user": ["users:read", "iso_threads:read", "unc_threads:read", "manufacturers:read", "scope_models:read", "part_colours:read", "part_types:read", "sub_part_types:read", "imported_parts:read", "static_connections:read", "clamp_connections:read", "attachment_point_names:read", "attachment_points:read", "augmented_parts:read"],
|
"user": [
|
||||||
|
"users:read",
|
||||||
|
"iso_threads:read",
|
||||||
|
"unc_threads:read",
|
||||||
|
"manufacturers:read",
|
||||||
|
"scope_models:read",
|
||||||
|
"part_colours:read",
|
||||||
|
"part_types:read",
|
||||||
|
"sub_part_types:read",
|
||||||
|
"imported_parts:read",
|
||||||
|
"static_connections:read",
|
||||||
|
"clamp_connections:read",
|
||||||
|
"attachment_point_names:read",
|
||||||
|
"attachment_points:read",
|
||||||
|
"augmented_parts:read",
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -123,8 +138,15 @@ async def seed() -> None:
|
|||||||
pt = await part_type_crud.get_by_name(db, pt_name)
|
pt = await part_type_crud.get_by_name(db, pt_name)
|
||||||
if pt is not None:
|
if pt is not None:
|
||||||
for spt_name in spt_names:
|
for spt_name in spt_names:
|
||||||
if await sub_part_type_crud.get_by_name_and_part_type(db, spt_name, pt.id) is None:
|
if (
|
||||||
await sub_part_type_crud.create(db, name=spt_name, part_type_id=pt.id)
|
await sub_part_type_crud.get_by_name_and_part_type(
|
||||||
|
db, spt_name, pt.id
|
||||||
|
)
|
||||||
|
is None
|
||||||
|
):
|
||||||
|
await sub_part_type_crud.create(
|
||||||
|
db, name=spt_name, part_type_id=pt.id
|
||||||
|
)
|
||||||
|
|
||||||
# Superuser
|
# Superuser
|
||||||
existing = await user_crud.get_by_email(db, settings.first_superuser_email)
|
existing = await user_crud.get_by_email(db, settings.first_superuser_email)
|
||||||
|
|||||||
Reference in new issue
Block a user