Files
dashlibstorage/src/store/entityaddress/create.js
2026-09-22 07:25:16 +02:00

115 lines
4.1 KiB
JavaScript

import {
CREATE as MSSQL_CREATE,
GET_NEXT_SORT as MSSQL_GET_NEXT_SORT,
} from '../../providers/mssql/queries/entityaddress.js';
import {
CREATE as SQLITE_CREATE,
GET_NEXT_SORT as SQLITE_GET_NEXT_SORT,
} from '../../providers/sqlite3/queries/entityaddress.js';
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
import resolveEntityAccess from '../entity/resolveEntityAccess.js';
import makeRunner from '../runner.js';
function shape(row) {
return {
id: row.id,
entityId: row.entityId,
firstName: row.firstName ?? null,
name: row.name ?? null,
street: row.street ?? null,
streetNumber: row.streetNumber ?? null,
zip: row.zip ?? null,
city: row.city ?? null,
county: row.county ?? null,
addressType: row.addressType,
sort: row.sort,
};
}
function optionalString(value) {
if (value == null || value === '') return null;
const s = String(value).trim();
return s || null;
}
export default function create(provider) {
const access = resolveSelectedCompanyAccess(provider);
const entityAccess = resolveEntityAccess(provider);
const isSqlite = provider?.dialect === 'sqlite3';
const getSortSql = isSqlite ? SQLITE_GET_NEXT_SORT : MSSQL_GET_NEXT_SORT;
const createSql = isSqlite ? SQLITE_CREATE : MSSQL_CREATE;
/**
* Creates a new address for an entity.
*
* @param {number} googleAuthId - The id of the Google auth user.
* @param {number} entityId - The id of the entity.
* @param {object} input - The address input.
* @param {string} input.addressType - The address type (e.g. `'billing'`).
* @param {string} [input.firstName] - The first name.
* @param {string} [input.name] - The name.
* @param {string} [input.street] - The street.
* @param {string} [input.streetNumber] - The street number.
* @param {string} [input.zip] - The zip code.
* @param {string} [input.city] - The city.
* @param {string} [input.county] - The county.
* @param {number} [input.sort] - Optional sort order.
* @param {object} [tx] - Optional transaction to run within.
* @returns {Promise<{id: number, entityId: number, firstName: string|null, name: string|null, street: string|null, streetNumber: string|null, zip: string|null, city: string|null, county: string|null, addressType: string, sort: number}>} The created address.
* @throws {Error} If the address type is missing.
*
* @example
* const address = await store.entityaddress.create(42, 5, { addressType: 'billing', street: 'Main St', city: 'Berlin' });
* // => { id, entityId, firstName, name, street, streetNumber, zip, city, county, addressType, sort }
*/
return async (googleAuthId, entityId, input = {}, tx) => {
const addressType = input.addressType?.trim?.()
? input.addressType.trim()
: null;
if (!addressType) {
throw new Error('Address type required');
}
const runner = makeRunner(provider, tx);
const { companyId } = await access(googleAuthId, tx);
await entityAccess(companyId, entityId, tx);
let sort = input.sort;
if (sort === undefined || sort === null) {
const next = await runner.query(getSortSql, { entityId });
sort = next.rows[0].sort;
} else if (!Number.isFinite(sort)) {
throw new Error('Invalid sort');
}
const result = await runner.query(createSql, {
entityId,
firstName: optionalString(input.firstName),
name: optionalString(input.name),
street: optionalString(input.street),
streetNumber: optionalString(input.streetNumber),
zip: optionalString(input.zip),
city: optionalString(input.city),
county: optionalString(input.county),
addressType,
sort,
});
const row = result.rows[0] ?? {
id: result.insertId,
entityId,
firstName: optionalString(input.firstName),
name: optionalString(input.name),
street: optionalString(input.street),
streetNumber: optionalString(input.streetNumber),
zip: optionalString(input.zip),
city: optionalString(input.city),
county: optionalString(input.county),
addressType,
sort,
};
return shape(row);
};
}