u
This commit is contained in:
59
src/store/warehouse/create.js
Normal file
59
src/store/warehouse/create.js
Normal file
@@ -0,0 +1,59 @@
|
||||
import { CREATE as MSSQL_CREATE } from '../../providers/mssql/queries/warehouse.js';
|
||||
import { CREATE as SQLITE_CREATE } from '../../providers/sqlite3/queries/warehouse.js';
|
||||
import { isUniqueConstraintError } from '../../providers/provider.js';
|
||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||
import makeRunner from '../runner.js';
|
||||
|
||||
function shape(row) {
|
||||
return { id: row.id, name: row.name };
|
||||
}
|
||||
|
||||
export default function create(provider) {
|
||||
const access = resolveSelectedCompanyAccess(provider);
|
||||
const sql =
|
||||
provider?.dialect === 'sqlite3' ? SQLITE_CREATE : MSSQL_CREATE;
|
||||
|
||||
/**
|
||||
* Creates a new warehouse for the user's selected company.
|
||||
*
|
||||
* @param {number} googleAuthId - The id of the Google auth user.
|
||||
* @param {object} input - Warehouse input.
|
||||
* @param {string} input.name - The warehouse name.
|
||||
* @param {object} [tx] - Optional transaction to run within.
|
||||
* @returns {Promise<{id: number, name: string}>} The created warehouse.
|
||||
* @throws {Error} If name is missing or already exists.
|
||||
*
|
||||
* @example
|
||||
* const wh = await store.warehouse.create(googleAuthId, { name: 'Hauptlager' });
|
||||
* // => { id: 1, name: 'Hauptlager' }
|
||||
*/
|
||||
return async (googleAuthId, { name } = {}, tx) => {
|
||||
const cleaned = typeof name === 'string' ? name.trim() : '';
|
||||
if (!cleaned) {
|
||||
throw new Error('Name required');
|
||||
}
|
||||
|
||||
const runner = makeRunner(provider, tx);
|
||||
const { companyId } = await access(googleAuthId, runner);
|
||||
|
||||
try {
|
||||
const result = await runner.query(sql, {
|
||||
companyId,
|
||||
name: cleaned,
|
||||
});
|
||||
|
||||
const row = result.rows[0] ?? { id: result.insertId, name: cleaned };
|
||||
return shape(row);
|
||||
} catch (err) {
|
||||
if (
|
||||
isUniqueConstraintError(err) ||
|
||||
err?.number === 2627 ||
|
||||
err?.number === 2601 ||
|
||||
err?.code === 'SQLITE_CONSTRAINT_UNIQUE'
|
||||
) {
|
||||
throw new Error('Warehouse already exists');
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
}
|
||||
62
src/store/warehouse/delete.js
Normal file
62
src/store/warehouse/delete.js
Normal file
@@ -0,0 +1,62 @@
|
||||
import {
|
||||
DELETE_BY_COMPANY_AND_ID as MSSQL_DELETE,
|
||||
CHECK_LEDGER_USAGE as MSSQL_CHECK_USAGE,
|
||||
} from '../../providers/mssql/queries/warehouse.js';
|
||||
import {
|
||||
DELETE_BY_COMPANY_AND_ID as SQLITE_DELETE,
|
||||
CHECK_LEDGER_USAGE as SQLITE_CHECK_USAGE,
|
||||
} from '../../providers/sqlite3/queries/warehouse.js';
|
||||
import { isForeignKeyConstraintError } from '../../providers/provider.js';
|
||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||
import makeRunner from '../runner.js';
|
||||
|
||||
export default function del(provider) {
|
||||
const access = resolveSelectedCompanyAccess(provider);
|
||||
const isSqlite = provider?.dialect === 'sqlite3';
|
||||
const deleteSql = isSqlite ? SQLITE_DELETE : MSSQL_DELETE;
|
||||
const checkUsageSql = isSqlite ? SQLITE_CHECK_USAGE : MSSQL_CHECK_USAGE;
|
||||
|
||||
/**
|
||||
* Deletes a warehouse for the user's selected company, unless referenced in the ledger.
|
||||
*
|
||||
* @param {number} googleAuthId - The id of the Google auth user.
|
||||
* @param {number} id - The warehouse ID to delete.
|
||||
* @param {object} [tx] - Optional transaction to run within.
|
||||
* @returns {Promise<void>}
|
||||
* @throws {Error} If warehouse not found or is in use in the ledger.
|
||||
*
|
||||
* @example
|
||||
* await store.warehouse.delete(googleAuthId, 1);
|
||||
*/
|
||||
return async (googleAuthId, id, tx) => {
|
||||
const numericId = Number(id);
|
||||
if (!Number.isInteger(numericId) || numericId <= 0) {
|
||||
throw new Error('Warehouse not found');
|
||||
}
|
||||
|
||||
const runner = makeRunner(provider, tx);
|
||||
const { companyId } = await access(googleAuthId, runner);
|
||||
|
||||
// Pre-check if warehouse is referenced in the ledger
|
||||
const usage = await runner.query(checkUsageSql, { warehouseId: numericId });
|
||||
if (usage.rows && usage.rows.length > 0) {
|
||||
throw new Error('Warehouse in use in ledger');
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await runner.query(deleteSql, {
|
||||
id: numericId,
|
||||
companyId,
|
||||
});
|
||||
|
||||
if (!result.rowsAffected) {
|
||||
throw new Error('Warehouse not found');
|
||||
}
|
||||
} catch (err) {
|
||||
if (isForeignKeyConstraintError(err)) {
|
||||
throw new Error('Warehouse in use in ledger');
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
}
|
||||
44
src/store/warehouse/getById.js
Normal file
44
src/store/warehouse/getById.js
Normal file
@@ -0,0 +1,44 @@
|
||||
import { GET_BY_COMPANY_AND_ID as MSSQL_GET_BY_ID } from '../../providers/mssql/queries/warehouse.js';
|
||||
import { GET_BY_COMPANY_AND_ID as SQLITE_GET_BY_ID } from '../../providers/sqlite3/queries/warehouse.js';
|
||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||
import makeRunner from '../runner.js';
|
||||
|
||||
function shape(row) {
|
||||
return { id: row.id, name: row.name };
|
||||
}
|
||||
|
||||
export default function getById(provider) {
|
||||
const access = resolveSelectedCompanyAccess(provider);
|
||||
const sql =
|
||||
provider?.dialect === 'sqlite3' ? SQLITE_GET_BY_ID : MSSQL_GET_BY_ID;
|
||||
|
||||
/**
|
||||
* Retrieves a warehouse by its ID for the user's selected company.
|
||||
*
|
||||
* @param {number} googleAuthId - The id of the Google auth user.
|
||||
* @param {number} id - The warehouse ID.
|
||||
* @param {object} [tx] - Optional transaction to run within.
|
||||
* @returns {Promise<{id: number, name: string}|undefined>} The warehouse or undefined.
|
||||
*
|
||||
* @example
|
||||
* const wh = await store.warehouse.getById(googleAuthId, 1);
|
||||
* // => { id: 1, name: 'Hauptlager' }
|
||||
*/
|
||||
return async (googleAuthId, id, tx) => {
|
||||
const numericId = Number(id);
|
||||
if (!Number.isInteger(numericId) || numericId <= 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const runner = makeRunner(provider, tx);
|
||||
const { companyId } = await access(googleAuthId, runner);
|
||||
|
||||
const result = await runner.query(sql, {
|
||||
id: numericId,
|
||||
companyId,
|
||||
});
|
||||
|
||||
const row = result.rows[0];
|
||||
return row ? shape(row) : undefined;
|
||||
};
|
||||
}
|
||||
33
src/store/warehouse/list.js
Normal file
33
src/store/warehouse/list.js
Normal file
@@ -0,0 +1,33 @@
|
||||
import { LIST_BY_COMPANY as MSSQL_LIST } from '../../providers/mssql/queries/warehouse.js';
|
||||
import { LIST_BY_COMPANY as SQLITE_LIST } from '../../providers/sqlite3/queries/warehouse.js';
|
||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||
import makeRunner from '../runner.js';
|
||||
|
||||
function shape(row) {
|
||||
return { id: row.id, name: row.name };
|
||||
}
|
||||
|
||||
export default function list(provider) {
|
||||
const access = resolveSelectedCompanyAccess(provider);
|
||||
const sql =
|
||||
provider?.dialect === 'sqlite3' ? SQLITE_LIST : MSSQL_LIST;
|
||||
|
||||
/**
|
||||
* Lists all warehouses for the user's selected company.
|
||||
*
|
||||
* @param {number} googleAuthId - The id of the Google auth user.
|
||||
* @param {object} [tx] - Optional transaction to run within.
|
||||
* @returns {Promise<Array<{id: number, name: string}>>} List of warehouses.
|
||||
*
|
||||
* @example
|
||||
* const warehouses = await store.warehouse.list(googleAuthId);
|
||||
* // => [{ id: 1, name: 'Hauptlager' }]
|
||||
*/
|
||||
return async (googleAuthId, tx) => {
|
||||
const runner = makeRunner(provider, tx);
|
||||
const { companyId } = await access(googleAuthId, runner);
|
||||
|
||||
const result = await runner.query(sql, { companyId });
|
||||
return result.rows.map(shape);
|
||||
};
|
||||
}
|
||||
77
src/store/warehouse/update.js
Normal file
77
src/store/warehouse/update.js
Normal file
@@ -0,0 +1,77 @@
|
||||
import {
|
||||
GET_BY_COMPANY_AND_ID as MSSQL_GET_BY_ID,
|
||||
UPDATE_BY_ID as MSSQL_UPDATE,
|
||||
} from '../../providers/mssql/queries/warehouse.js';
|
||||
import {
|
||||
GET_BY_COMPANY_AND_ID as SQLITE_GET_BY_ID,
|
||||
UPDATE_BY_ID as SQLITE_UPDATE,
|
||||
} from '../../providers/sqlite3/queries/warehouse.js';
|
||||
import { isUniqueConstraintError } from '../../providers/provider.js';
|
||||
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||
import makeRunner from '../runner.js';
|
||||
|
||||
function shape(row) {
|
||||
return { id: row.id, name: row.name };
|
||||
}
|
||||
|
||||
export default function update(provider) {
|
||||
const access = resolveSelectedCompanyAccess(provider);
|
||||
const isSqlite = provider?.dialect === 'sqlite3';
|
||||
const getSql = isSqlite ? SQLITE_GET_BY_ID : MSSQL_GET_BY_ID;
|
||||
const updateSql = isSqlite ? SQLITE_UPDATE : MSSQL_UPDATE;
|
||||
|
||||
/**
|
||||
* Updates a warehouse name for the user's selected company.
|
||||
*
|
||||
* @param {number} googleAuthId - The id of the Google auth user.
|
||||
* @param {number} id - The warehouse ID to update.
|
||||
* @param {object} input - Update payload.
|
||||
* @param {string} input.name - The new warehouse name.
|
||||
* @param {object} [tx] - Optional transaction to run within.
|
||||
* @returns {Promise<{id: number, name: string}>} The updated warehouse.
|
||||
* @throws {Error} If warehouse not found, name is missing, or name already exists.
|
||||
*
|
||||
* @example
|
||||
* const updated = await store.warehouse.update(googleAuthId, 1, { name: 'Zentrallager' });
|
||||
* // => { id: 1, name: 'Zentrallager' }
|
||||
*/
|
||||
return async (googleAuthId, id, { name } = {}, tx) => {
|
||||
const numericId = Number(id);
|
||||
if (!Number.isInteger(numericId) || numericId <= 0) {
|
||||
throw new Error('Warehouse not found');
|
||||
}
|
||||
|
||||
const cleaned = typeof name === 'string' ? name.trim() : '';
|
||||
if (!cleaned) {
|
||||
throw new Error('Name required');
|
||||
}
|
||||
|
||||
const runner = makeRunner(provider, tx);
|
||||
const { companyId } = await access(googleAuthId, runner);
|
||||
|
||||
const existing = await runner.query(getSql, { id: numericId, companyId });
|
||||
if (!existing.rows[0]) {
|
||||
throw new Error('Warehouse not found');
|
||||
}
|
||||
|
||||
try {
|
||||
await runner.query(updateSql, {
|
||||
id: numericId,
|
||||
companyId,
|
||||
name: cleaned,
|
||||
});
|
||||
|
||||
return shape({ id: numericId, name: cleaned });
|
||||
} catch (err) {
|
||||
if (
|
||||
isUniqueConstraintError(err) ||
|
||||
err?.number === 2627 ||
|
||||
err?.number === 2601 ||
|
||||
err?.code === 'SQLITE_CONSTRAINT_UNIQUE'
|
||||
) {
|
||||
throw new Error('Warehouse already exists');
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user