Add supplier CRUD on entity with Lieferanten group and entityhistory

This commit is contained in:
seb
2026-08-06 03:56:32 +02:00
parent 561ba5bb99
commit 4f46967f28
17 changed files with 1853 additions and 1338 deletions

View File

@@ -0,0 +1,54 @@
import { CREATE } from '../../sql/entity.js';
import { INSERT as INSERT_HISTORY } from '../../sql/entityhistory.js';
import request from '../request.js';
import resolveCompanyAccess from '../companyuser/resolveCompanyAccess.js';
import ensureLieferantenGroup from './ensureLieferantenGroup.js';
export default function create(pool) {
const access = resolveCompanyAccess(pool);
return async (googleAuthId, companyId, { name } = {}) => {
const cleaned = name?.trim();
if (!cleaned) {
throw new Error('Name required');
}
const { companyuserId } = await access(googleAuthId, companyId);
const tx = pool.transaction();
await tx.begin();
try {
const customergroupId = await ensureLieferantenGroup(pool, companyId, tx);
const created = await request(pool, tx)
.input('customergroupId', customergroupId)
.input('name', cleaned)
.query(CREATE);
const row = created.recordset[0];
await request(pool, tx)
.input('entityId', row.id)
.input('companyuserId', companyuserId)
.input('text', 'Erstellt')
.query(INSERT_HISTORY);
await tx.commit();
return {
id: row.id,
name: row.name,
createdAt: row.createdAt,
updatedAt: row.updatedAt,
};
} catch (err) {
try {
await tx.rollback();
} catch {
// ignore
}
throw err;
}
};
}

View File

@@ -0,0 +1,25 @@
import { DELETE_BY_ID, SUPPLIER_GROUP_NAME } from '../../sql/entity.js';
import resolveCompanyAccess from '../companyuser/resolveCompanyAccess.js';
export default function del(pool) {
const access = resolveCompanyAccess(pool);
return async (googleAuthId, companyId, id) => {
if (!Number.isFinite(id)) {
throw new Error('Supplier not found');
}
await access(googleAuthId, companyId);
const result = await pool
.request()
.input('id', id)
.input('companyId', companyId)
.input('groupName', SUPPLIER_GROUP_NAME)
.query(DELETE_BY_ID);
if (!result.rowsAffected[0]) {
throw new Error('Supplier not found');
}
};
}

View File

@@ -0,0 +1,26 @@
import {
CREATE,
GET_BY_COMPANY_AND_NAME,
} from '../../sql/customergroup.js';
import { SUPPLIER_GROUP_NAME } from '../../sql/entity.js';
/** Ensure company has customergroup "Lieferanten"; return its id. */
export default async function ensureLieferantenGroup(pool, companyId, tx) {
const req = () => (tx ?? pool).request();
const existing = await req()
.input('companyId', companyId)
.input('name', SUPPLIER_GROUP_NAME)
.query(GET_BY_COMPANY_AND_NAME);
if (existing.recordset[0]) {
return existing.recordset[0].id;
}
const created = await req()
.input('companyId', companyId)
.input('name', SUPPLIER_GROUP_NAME)
.query(CREATE);
return created.recordset[0].id;
}

View File

@@ -0,0 +1,23 @@
import { LIST_SUPPLIERS_BY_COMPANY, SUPPLIER_GROUP_NAME } from '../../sql/entity.js';
import resolveCompanyAccess from '../companyuser/resolveCompanyAccess.js';
export default function list(pool) {
const access = resolveCompanyAccess(pool);
return async (googleAuthId, companyId) => {
await access(googleAuthId, companyId);
const result = await pool
.request()
.input('companyId', companyId)
.input('groupName', SUPPLIER_GROUP_NAME)
.query(LIST_SUPPLIERS_BY_COMPANY);
return result.recordset.map((row) => ({
id: row.id,
name: row.name,
createdAt: row.createdAt,
updatedAt: row.updatedAt,
}));
};
}

View File

@@ -0,0 +1,93 @@
import {
GET_GROUP_ID_FOR_SUPPLIER,
GET_SUPPLIER_BY_ID,
SUPPLIER_GROUP_NAME,
UPDATE_NAME,
} from '../../sql/entity.js';
import { INSERT as INSERT_HISTORY } from '../../sql/entityhistory.js';
import request from '../request.js';
import resolveCompanyAccess from '../companyuser/resolveCompanyAccess.js';
function shape(row) {
return {
id: row.id,
name: row.name,
createdAt: row.createdAt,
updatedAt: row.updatedAt,
};
}
export default function update(pool) {
const access = resolveCompanyAccess(pool);
return async (googleAuthId, companyId, id, { name } = {}) => {
if (!Number.isFinite(id)) {
throw new Error('Supplier not found');
}
const cleaned = name?.trim();
if (!cleaned) {
throw new Error('Name required');
}
const { companyuserId } = await access(googleAuthId, companyId);
const existing = await pool
.request()
.input('id', id)
.input('companyId', companyId)
.input('groupName', SUPPLIER_GROUP_NAME)
.query(GET_GROUP_ID_FOR_SUPPLIER);
const current = existing.recordset[0];
if (!current) {
throw new Error('Supplier not found');
}
if (current.name === cleaned) {
const same = await pool
.request()
.input('id', id)
.input('companyId', companyId)
.input('groupName', SUPPLIER_GROUP_NAME)
.query(GET_SUPPLIER_BY_ID);
return shape(same.recordset[0]);
}
const tx = pool.transaction();
await tx.begin();
try {
const updated = await request(pool, tx)
.input('id', id)
.input('customergroupId', current.customergroupId)
.input('name', cleaned)
.query(UPDATE_NAME);
const row = updated.recordset[0];
if (!row) {
throw new Error('Supplier not found');
}
await request(pool, tx)
.input('entityId', id)
.input('companyuserId', companyuserId)
.input(
'text',
`Name geändert von "${current.name}" auf "${cleaned}"`,
)
.query(INSERT_HISTORY);
await tx.commit();
return shape(row);
} catch (err) {
try {
await tx.rollback();
} catch {
// ignore
}
throw err;
}
};
}