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); }; }