mirror of
https://github.com/nowcommunity/nowdatabase.git
synced 2026-10-12 19:13:52 +03:00
DwC-A localities: include remaining now_loc fields
This commit is contained in:
@@ -130,6 +130,7 @@ type LocalityForExport = Pick<
|
||||
| 'dec_long'
|
||||
| 'dms_lat'
|
||||
| 'dms_long'
|
||||
| 'approx_coord'
|
||||
| 'altitude'
|
||||
| 'loc_detail'
|
||||
| 'chron'
|
||||
@@ -148,6 +149,8 @@ type LocalityForExport = Pick<
|
||||
| 'date_meth'
|
||||
| 'age_comm'
|
||||
| 'site_area'
|
||||
| 'gen_loc'
|
||||
| 'plate'
|
||||
| 'appr_num_spm'
|
||||
| 'num_spm'
|
||||
| 'true_quant'
|
||||
@@ -176,6 +179,12 @@ type LocalityForExport = Pick<
|
||||
| 'invert_pres'
|
||||
| 'time_rep'
|
||||
| 'taph_comm'
|
||||
| 'tax_comm'
|
||||
| 'datum_plane'
|
||||
| 'tos'
|
||||
| 'bos'
|
||||
| 'loc_status'
|
||||
| 'hominin_skeletal_remains'
|
||||
| 'climate_type'
|
||||
| 'biome'
|
||||
| 'v_ht'
|
||||
@@ -214,6 +223,29 @@ type LocalityForExport = Pick<
|
||||
now_syn_loc: ReadonlyArray<{ synonym: string | null }>
|
||||
now_ss: ReadonlyArray<{ sed_struct: string }>
|
||||
now_coll_meth: ReadonlyArray<{ coll_meth: string }>
|
||||
now_mus: ReadonlyArray<{
|
||||
museum: string
|
||||
com_mlist: {
|
||||
institution: string
|
||||
alt_int_name: string | null
|
||||
city: string | null
|
||||
state: string | null
|
||||
country: string | null
|
||||
}
|
||||
}>
|
||||
now_plr: ReadonlyArray<{
|
||||
now_proj: {
|
||||
proj_code: string | null
|
||||
proj_name: string | null
|
||||
proj_status: string | null
|
||||
}
|
||||
}>
|
||||
now_lau: ReadonlyArray<{
|
||||
lau_date: Date | null
|
||||
lau_comment: string | null
|
||||
com_people_now_lau_lau_coordinatorTocom_people: { full_name: string }
|
||||
com_people_now_lau_lau_authorizerTocom_people: { full_name: string }
|
||||
}>
|
||||
now_ls: ReadonlyArray<{
|
||||
com_species: {
|
||||
order_name: string
|
||||
@@ -263,7 +295,11 @@ export const mapLocalityToLocationRow = (locality: LocalityForExport): LocationC
|
||||
verbatimLatitude: toMaybeMeaningful(locality.dms_lat),
|
||||
verbatimLongitude: toMaybeMeaningful(locality.dms_long),
|
||||
verbatimElevation: locality.altitude === null || locality.altitude === undefined ? '' : String(locality.altitude),
|
||||
locationRemarks: [toMaybeMeaningful(locality.loc_detail), toMaybeMeaningful(locality.age_comm)]
|
||||
locationRemarks: [
|
||||
toMaybeMeaningful(locality.loc_detail),
|
||||
toMaybeMeaningful(locality.age_comm),
|
||||
toMaybeMeaningful(locality.tax_comm),
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' | '),
|
||||
}
|
||||
@@ -451,6 +487,27 @@ const LOCALITY_MEASUREMENT_MAPPINGS: Array<{
|
||||
// TODO(#1150): Add unit and definition for NOW locality site_area.
|
||||
measurementMethod: '',
|
||||
},
|
||||
{
|
||||
field: 'approx_coord',
|
||||
measurementType: 'approximate coordinates',
|
||||
measurementUnit: '',
|
||||
// TODO(#1150): Add definition (what qualifies as approximate).
|
||||
measurementMethod: '',
|
||||
},
|
||||
{
|
||||
field: 'gen_loc',
|
||||
measurementType: 'general locality',
|
||||
measurementUnit: '',
|
||||
// TODO(#1150): Add controlled vocabulary / definition.
|
||||
measurementMethod: '',
|
||||
},
|
||||
{
|
||||
field: 'plate',
|
||||
measurementType: 'tectonic plate',
|
||||
measurementUnit: '',
|
||||
// TODO(#1150): Add controlled vocabulary / definition.
|
||||
measurementMethod: '',
|
||||
},
|
||||
{
|
||||
field: 'appr_num_spm',
|
||||
measurementType: 'approximate number of specimens',
|
||||
@@ -584,6 +641,20 @@ const LOCALITY_MEASUREMENT_MAPPINGS: Array<{
|
||||
// TODO(#1150): Add field description.
|
||||
measurementMethod: '',
|
||||
},
|
||||
{
|
||||
field: 'loc_status',
|
||||
measurementType: 'locality status',
|
||||
measurementUnit: '',
|
||||
// TODO(#1150): Add definition.
|
||||
measurementMethod: '',
|
||||
},
|
||||
{
|
||||
field: 'hominin_skeletal_remains',
|
||||
measurementType: 'Hominin skeletal remains (field)',
|
||||
measurementUnit: '',
|
||||
// TODO(#1150): Add field description.
|
||||
measurementMethod: '',
|
||||
},
|
||||
{
|
||||
field: 'assem_fm',
|
||||
measurementType: 'Assemblage Formation',
|
||||
@@ -875,6 +946,13 @@ export const mapLocalityToMeasurementRows = (locality: LocalityForExport): Local
|
||||
const maxAgeId = buildLocalityMeasurementId(lid, 'max_age')
|
||||
const minAgeId = buildLocalityMeasurementId(lid, 'min_age')
|
||||
|
||||
const stratigraphyParentId = buildLocalityMeasurementId(lid, 'stratigraphy')
|
||||
const tosId = buildLocalityMeasurementId(lid, 'tos')
|
||||
const bosId = buildLocalityMeasurementId(lid, 'bos')
|
||||
const datumPlaneId = buildLocalityMeasurementId(lid, 'datum_plane')
|
||||
|
||||
const lastUpdateParentId = buildLocalityMeasurementId(lid, 'last_update')
|
||||
|
||||
const hasMaxAgeGroup =
|
||||
isMeaningfulMeasurementValue(locality.max_age) ||
|
||||
isMeaningfulMeasurementValue(locality.bfa_max) ||
|
||||
@@ -891,6 +969,135 @@ export const mapLocalityToMeasurementRows = (locality: LocalityForExport): Local
|
||||
|
||||
const rows: LocalityMeasurementCsvRow[] = []
|
||||
|
||||
const hasAnyStratigraphy =
|
||||
isMeaningfulMeasurementValue(locality.datum_plane) ||
|
||||
isMeaningfulMeasurementValue(locality.tos) ||
|
||||
isMeaningfulMeasurementValue(locality.bos)
|
||||
|
||||
if (hasAnyStratigraphy) {
|
||||
rows.push({
|
||||
taxonID,
|
||||
measurementID: stratigraphyParentId,
|
||||
parentMeasurementID: '',
|
||||
measurementType: 'stratigraphic section',
|
||||
verbatimMeasurementType: 'stratigraphy',
|
||||
measurementValue: '',
|
||||
measurementUnit: '',
|
||||
// TODO(#1150): Add field description.
|
||||
measurementMethod: '',
|
||||
})
|
||||
}
|
||||
|
||||
if (isMeaningfulMeasurementValue(locality.datum_plane)) {
|
||||
rows.push({
|
||||
taxonID,
|
||||
measurementID: datumPlaneId,
|
||||
parentMeasurementID: hasAnyStratigraphy ? stratigraphyParentId : '',
|
||||
measurementType: 'datum plane',
|
||||
verbatimMeasurementType: 'datum_plane',
|
||||
measurementValue: toMaybeMeaningful(locality.datum_plane),
|
||||
measurementUnit: '',
|
||||
// TODO(#1150): Add field description.
|
||||
measurementMethod: '',
|
||||
})
|
||||
}
|
||||
|
||||
if (typeof locality.tos === 'number') {
|
||||
const value = toMaybeMeaningfulNumberWithZeroOption(locality.tos, { allowZero: true })
|
||||
if (value) {
|
||||
rows.push({
|
||||
taxonID,
|
||||
measurementID: tosId,
|
||||
parentMeasurementID: hasAnyStratigraphy ? stratigraphyParentId : '',
|
||||
measurementType: 'top of section',
|
||||
verbatimMeasurementType: 'tos',
|
||||
measurementValue: value,
|
||||
measurementUnit: '',
|
||||
// TODO(#1150): Add unit and definition.
|
||||
measurementMethod: '',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof locality.bos === 'number') {
|
||||
const value = toMaybeMeaningfulNumberWithZeroOption(locality.bos, { allowZero: true })
|
||||
if (value) {
|
||||
rows.push({
|
||||
taxonID,
|
||||
measurementID: bosId,
|
||||
parentMeasurementID: hasAnyStratigraphy ? stratigraphyParentId : '',
|
||||
measurementType: 'bottom of section',
|
||||
verbatimMeasurementType: 'bos',
|
||||
measurementValue: value,
|
||||
measurementUnit: '',
|
||||
// TODO(#1150): Add unit and definition.
|
||||
measurementMethod: '',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const lastUpdate = locality.now_lau[0]
|
||||
if (lastUpdate) {
|
||||
rows.push({
|
||||
taxonID,
|
||||
measurementID: lastUpdateParentId,
|
||||
parentMeasurementID: '',
|
||||
measurementType: 'last update',
|
||||
verbatimMeasurementType: 'now_lau',
|
||||
measurementValue: '',
|
||||
measurementUnit: '',
|
||||
measurementMethod: '',
|
||||
})
|
||||
|
||||
if (lastUpdate.lau_date) {
|
||||
rows.push({
|
||||
taxonID,
|
||||
measurementID: buildLocalityMeasurementId(lid, 'last_update_date'),
|
||||
parentMeasurementID: lastUpdateParentId,
|
||||
measurementType: 'last update date',
|
||||
verbatimMeasurementType: 'now_lau.lau_date',
|
||||
measurementValue: lastUpdate.lau_date.toISOString().slice(0, 10),
|
||||
measurementUnit: '',
|
||||
measurementMethod: '',
|
||||
})
|
||||
}
|
||||
|
||||
rows.push({
|
||||
taxonID,
|
||||
measurementID: buildLocalityMeasurementId(lid, 'last_update_coordinator'),
|
||||
parentMeasurementID: lastUpdateParentId,
|
||||
measurementType: 'last update coordinator',
|
||||
verbatimMeasurementType: 'now_lau.lau_coordinator',
|
||||
measurementValue: toMaybeMeaningful(lastUpdate.com_people_now_lau_lau_coordinatorTocom_people.full_name),
|
||||
measurementUnit: '',
|
||||
measurementMethod: '',
|
||||
})
|
||||
|
||||
rows.push({
|
||||
taxonID,
|
||||
measurementID: buildLocalityMeasurementId(lid, 'last_update_authorizer'),
|
||||
parentMeasurementID: lastUpdateParentId,
|
||||
measurementType: 'last update authorizer',
|
||||
verbatimMeasurementType: 'now_lau.lau_authorizer',
|
||||
measurementValue: toMaybeMeaningful(lastUpdate.com_people_now_lau_lau_authorizerTocom_people.full_name),
|
||||
measurementUnit: '',
|
||||
measurementMethod: '',
|
||||
})
|
||||
|
||||
if (isMeaningfulString(lastUpdate.lau_comment)) {
|
||||
rows.push({
|
||||
taxonID,
|
||||
measurementID: buildLocalityMeasurementId(lid, 'last_update_comment'),
|
||||
parentMeasurementID: lastUpdateParentId,
|
||||
measurementType: 'last update comment',
|
||||
verbatimMeasurementType: 'now_lau.lau_comment',
|
||||
measurementValue: lastUpdate.lau_comment.trim(),
|
||||
measurementUnit: '',
|
||||
measurementMethod: '',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (hasAnyAgeBasis) {
|
||||
rows.push({
|
||||
taxonID,
|
||||
@@ -978,6 +1185,63 @@ export const mapLocalityToMeasurementRows = (locality: LocalityForExport): Local
|
||||
|
||||
rows.push(...coreRows)
|
||||
|
||||
const museums = locality.now_mus
|
||||
.map(row => {
|
||||
const institution = row.com_mlist.alt_int_name ?? row.com_mlist.institution
|
||||
const locationBits = [
|
||||
toMaybeMeaningful(row.com_mlist.city),
|
||||
toMaybeMeaningful(row.com_mlist.state),
|
||||
toMaybeMeaningful(row.com_mlist.country),
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(', ')
|
||||
return [row.museum, institution, locationBits ? `(${locationBits})` : ''].filter(Boolean).join(' ')
|
||||
})
|
||||
.filter(isMeaningfulString)
|
||||
.map(value => value.trim())
|
||||
|
||||
if (museums.length) {
|
||||
rows.push({
|
||||
taxonID,
|
||||
measurementID: buildLocalityMeasurementId(lid, 'museums'),
|
||||
parentMeasurementID: '',
|
||||
measurementType: 'Museums',
|
||||
verbatimMeasurementType: 'now_mus.museum',
|
||||
measurementValue: museums.join('|'),
|
||||
measurementUnit: '',
|
||||
// TODO(#1150): Add field description.
|
||||
measurementMethod: '',
|
||||
})
|
||||
}
|
||||
|
||||
const projects = locality.now_plr
|
||||
.map(row => row.now_proj)
|
||||
.map(project =>
|
||||
[
|
||||
toMaybeMeaningful(project.proj_code),
|
||||
toMaybeMeaningful(project.proj_name),
|
||||
toMaybeMeaningful(project.proj_status),
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' - ')
|
||||
)
|
||||
.filter(isMeaningfulString)
|
||||
.map(value => value.trim())
|
||||
|
||||
if (projects.length) {
|
||||
rows.push({
|
||||
taxonID,
|
||||
measurementID: buildLocalityMeasurementId(lid, 'projects'),
|
||||
parentMeasurementID: '',
|
||||
measurementType: 'Projects',
|
||||
verbatimMeasurementType: 'now_plr.pid',
|
||||
measurementValue: projects.join('|'),
|
||||
measurementUnit: '',
|
||||
// TODO(#1150): Add field description.
|
||||
measurementMethod: '',
|
||||
})
|
||||
}
|
||||
|
||||
const collectingMethods = locality.now_coll_meth
|
||||
.map(method => method.coll_meth)
|
||||
.filter(value => isMeaningfulString(value))
|
||||
@@ -1227,6 +1491,7 @@ export const buildDwcLocalityArchiveZipBuffer = async (): Promise<Buffer> => {
|
||||
dec_long: true,
|
||||
dms_lat: true,
|
||||
dms_long: true,
|
||||
approx_coord: true,
|
||||
altitude: true,
|
||||
loc_detail: true,
|
||||
chron: true,
|
||||
@@ -1245,6 +1510,8 @@ export const buildDwcLocalityArchiveZipBuffer = async (): Promise<Buffer> => {
|
||||
date_meth: true,
|
||||
age_comm: true,
|
||||
site_area: true,
|
||||
gen_loc: true,
|
||||
plate: true,
|
||||
appr_num_spm: true,
|
||||
num_spm: true,
|
||||
true_quant: true,
|
||||
@@ -1273,6 +1540,12 @@ export const buildDwcLocalityArchiveZipBuffer = async (): Promise<Buffer> => {
|
||||
invert_pres: true,
|
||||
time_rep: true,
|
||||
taph_comm: true,
|
||||
tax_comm: true,
|
||||
datum_plane: true,
|
||||
tos: true,
|
||||
bos: true,
|
||||
loc_status: true,
|
||||
hominin_skeletal_remains: true,
|
||||
climate_type: true,
|
||||
biome: true,
|
||||
v_ht: true,
|
||||
@@ -1320,6 +1593,27 @@ export const buildDwcLocalityArchiveZipBuffer = async (): Promise<Buffer> => {
|
||||
now_coll_meth: {
|
||||
select: { coll_meth: true },
|
||||
},
|
||||
now_mus: {
|
||||
select: {
|
||||
museum: true,
|
||||
com_mlist: { select: { institution: true, alt_int_name: true, city: true, state: true, country: true } },
|
||||
},
|
||||
},
|
||||
now_plr: {
|
||||
select: {
|
||||
now_proj: { select: { proj_code: true, proj_name: true, proj_status: true } },
|
||||
},
|
||||
},
|
||||
now_lau: {
|
||||
take: 1,
|
||||
orderBy: { lau_date: 'desc' },
|
||||
select: {
|
||||
lau_date: true,
|
||||
lau_comment: true,
|
||||
com_people_now_lau_lau_coordinatorTocom_people: { select: { full_name: true } },
|
||||
com_people_now_lau_lau_authorizerTocom_people: { select: { full_name: true } },
|
||||
},
|
||||
},
|
||||
now_ls: {
|
||||
select: {
|
||||
com_species: {
|
||||
|
||||
@@ -21,6 +21,7 @@ describe('DwC-A locality export mapping', () => {
|
||||
dec_long: 24.9384,
|
||||
dms_lat: null,
|
||||
dms_long: null,
|
||||
approx_coord: null,
|
||||
altitude: 123,
|
||||
loc_detail: 'Some notes',
|
||||
chron: 'Test chron',
|
||||
@@ -39,6 +40,8 @@ describe('DwC-A locality export mapping', () => {
|
||||
date_meth: 'radioisotope',
|
||||
age_comm: 'Age comment',
|
||||
site_area: null,
|
||||
gen_loc: null,
|
||||
plate: null,
|
||||
appr_num_spm: null,
|
||||
num_spm: null,
|
||||
true_quant: null,
|
||||
@@ -67,6 +70,12 @@ describe('DwC-A locality export mapping', () => {
|
||||
invert_pres: null,
|
||||
time_rep: null,
|
||||
taph_comm: null,
|
||||
tax_comm: null,
|
||||
datum_plane: null,
|
||||
tos: null,
|
||||
bos: null,
|
||||
loc_status: null,
|
||||
hominin_skeletal_remains: false,
|
||||
climate_type: null,
|
||||
biome: null,
|
||||
v_ht: null,
|
||||
@@ -102,6 +111,9 @@ describe('DwC-A locality export mapping', () => {
|
||||
now_syn_loc: [],
|
||||
now_ss: [],
|
||||
now_coll_meth: [],
|
||||
now_mus: [],
|
||||
now_plr: [],
|
||||
now_lau: [],
|
||||
now_ls: [],
|
||||
now_time_unit_now_loc_bfa_maxTonow_time_unit: null,
|
||||
now_time_unit_now_loc_bfa_minTonow_time_unit: null,
|
||||
@@ -155,6 +167,21 @@ describe('DwC-A locality export mapping', () => {
|
||||
expect(collectingMethodsRow?.measurementValue).toEqual('screenwash|quarry')
|
||||
})
|
||||
|
||||
it('uses parentMeasurementID for stratigraphy fields', () => {
|
||||
const rows = mapLocalityToMeasurementRows({
|
||||
...baseLocality,
|
||||
datum_plane: 'Datum',
|
||||
tos: 0,
|
||||
bos: 12.5,
|
||||
})
|
||||
const parent = rows.find(r => r.verbatimMeasurementType === 'stratigraphy')
|
||||
expect(parent).toBeTruthy()
|
||||
const tosRow = rows.find(r => r.verbatimMeasurementType === 'tos')
|
||||
const bosRow = rows.find(r => r.verbatimMeasurementType === 'bos')
|
||||
expect(tosRow?.parentMeasurementID).toEqual(parent?.measurementID)
|
||||
expect(bosRow?.parentMeasurementID).toEqual(parent?.measurementID)
|
||||
})
|
||||
|
||||
it('generates a ZIP archive with expected files', async () => {
|
||||
const zipBuffer = await buildDwcLocalityArchiveZipBufferFromLocalities([baseLocality])
|
||||
const zip = await JSZip.loadAsync(zipBuffer)
|
||||
|
||||
Reference in New Issue
Block a user