@overture-stack/lyric
Version:
Data Submission system
203 lines (202 loc) • 9.28 kB
JavaScript
import { and, count, eq, or } from 'drizzle-orm/sql';
import { submissions } from '@overture-stack/lyric-data-model/models';
import { ServiceUnavailable } from '../utils/errors.js';
import { SUBMISSION_STATUS, } from '../utils/types.js';
const repository = (dependencies) => {
const LOG_MODULE = 'ACTIVE_SUBMISSION_REPOSITORY';
const { db, logger } = dependencies;
const getSubmissionColumns = {
id: true,
status: true,
organization: true,
data: true,
errors: true,
createdAt: true,
createdBy: true,
updatedAt: true,
updatedBy: true,
};
const getSubmissionRelations = {
dictionary: {
columns: {
name: true,
version: true,
},
},
dictionaryCategory: {
columns: {
id: true,
name: true,
},
},
};
const openSubmissionStatus = [SUBMISSION_STATUS.OPEN, SUBMISSION_STATUS.VALID, SUBMISSION_STATUS.INVALID];
const getActiveStatusesCondition = (onlyActive, activeStatuses) => {
return onlyActive ? or(...activeStatuses.map((status) => eq(submissions.status, status))) : undefined;
};
return {
/**
* Save a new Active Submission in Database
* @param data An Active Submission object to be saved
* @returns The created Active Submission
*/
save: async (data) => {
try {
const savedActiveSubmission = await db.insert(submissions).values(data).returning();
logger.info(LOG_MODULE, `New Active Submission saved successfully`);
return savedActiveSubmission[0];
}
catch (error) {
logger.error(LOG_MODULE, `Failed saving Active Submission`, error);
throw new ServiceUnavailable();
}
},
/**
* Finds the current Active Submission by parameters
* @param {Object} params
* @param {number} params.categoryId Category ID
* @param {string} params.username Name of the user
* @param {string} params.organization Organization name
* @returns
*/
getActiveSubmission: async ({ categoryId, username, organization, }) => {
try {
return await db.query.submissions.findFirst({
where: and(eq(submissions.dictionaryCategoryId, categoryId), eq(submissions.createdBy, username), eq(submissions.organization, organization), or(eq(submissions.status, 'OPEN'), eq(submissions.status, 'VALID'), eq(submissions.status, 'INVALID'))),
});
}
catch (error) {
logger.error(LOG_MODULE, `Failed getting active Submission`, error);
throw new ServiceUnavailable();
}
},
/**
* Finds a Submission by ID
* @param {number} submissionId Submission ID
* @returns The Submission found
*/
getSubmissionById: async (submissionId) => {
try {
return await db.query.submissions.findFirst({
where: and(eq(submissions.id, submissionId)),
});
}
catch (error) {
logger.error(LOG_MODULE, `Failed getting Submission with id '${submissionId}'`, error);
throw new ServiceUnavailable();
}
},
/**
* Update a Submission record in database
* @param {number} submissionId Submission ID to update
* @param {Partial<Submission>} newData Set fields to update
* @param tx The transaction to use for the operation, optional
* @returns An updated record
*/
update: async (submissionId, newData, tx) => {
try {
const resultUpdate = await (tx || db)
.update(submissions)
.set({ ...newData, updatedAt: new Date() })
.where(eq(submissions.id, submissionId))
.returning();
return resultUpdate[0];
}
catch (error) {
logger.error(LOG_MODULE, `Failed updating Active Submission`, error);
throw new ServiceUnavailable();
}
},
/**
* Get Submissions by category
* @param {number} categoryId - Category ID
* @param {Object} paginationOptions - Pagination properties
* @param {number} paginationOptions.page - Page number
* @param {number} paginationOptions.pageSize - Items per page
* @param {Object} filterOptions
* @param {boolean} filterOptions.onlyActive - Filter by Active status
* @param {string} filterOptions.username - Filter by creator's username
* @param {string} filterOptions.organization - Filter by Organization
* @returns One or many Active Submissions
*/
getSubmissionsWithRelationsByCategory: async (categoryId, paginationOptions, filterOptions) => {
const { page, pageSize } = paginationOptions;
try {
return await db.query.submissions.findMany({
where: and(eq(submissions.dictionaryCategoryId, categoryId), filterOptions.username ? eq(submissions.createdBy, filterOptions.username) : undefined, getActiveStatusesCondition(filterOptions.onlyActive, openSubmissionStatus), filterOptions.organization ? eq(submissions.organization, filterOptions.organization) : undefined),
columns: getSubmissionColumns,
with: getSubmissionRelations,
orderBy: (submissions, { desc }) => desc(submissions.createdAt),
limit: pageSize,
offset: (page - 1) * pageSize,
});
}
catch (error) {
logger.error(LOG_MODULE, `Failed querying Submissions by category with relations`, error);
throw new ServiceUnavailable();
}
},
/**
* Count Submissions by category ID
* @param {number} categoryId - Category ID
* @param {Object} filterOptions
* @param {boolean} filterOptions.onlyActive - Filter by Active status
* @param {string} filterOptions.username - Filter by creator's username
* @param {string} filterOptions.organization - Filter by Organization
* @returns One or many Active Submissions
*/
getTotalSubmissionsByCategory: async (categoryId, filterOptions) => {
try {
const resultCount = await db
.select({ total: count() })
.from(submissions)
.where(and(eq(submissions.dictionaryCategoryId, categoryId), filterOptions.username ? eq(submissions.createdBy, filterOptions.username) : undefined, getActiveStatusesCondition(filterOptions.onlyActive, openSubmissionStatus), filterOptions.organization ? eq(submissions.organization, filterOptions.organization) : undefined));
return resultCount[0].total;
}
catch (error) {
logger.error(LOG_MODULE, `Failed counting Submission with categoryId '${categoryId}'`, error);
throw new ServiceUnavailable();
}
},
/**
* Get Active Submission by Organization
* @param {Object} filterParams
* @param {number} filterParams.categoryId Category ID
* @param {string} filterParams.username User Name
* @param {string} filterParams.organization Organization name
* @returns One Active Submission
*/
getActiveSubmissionWithRelationsByOrganization: async ({ categoryId, username, organization, }) => {
try {
return await db.query.submissions.findFirst({
where: and(eq(submissions.dictionaryCategoryId, categoryId), eq(submissions.createdBy, username), eq(submissions.organization, organization), or(eq(submissions.status, 'OPEN'), eq(submissions.status, 'VALID'), eq(submissions.status, 'INVALID'))),
columns: getSubmissionColumns,
with: getSubmissionRelations,
});
}
catch (error) {
logger.error(LOG_MODULE, `Failed querying Active Submission with relations`, error);
throw new ServiceUnavailable();
}
},
/**
* Get Submission by ID
* @param {number} submissionId Submission ID
* @returns A Submission
*/
getSubmissionWithRelationsById: async (submissionId) => {
try {
return await db.query.submissions.findFirst({
where: and(eq(submissions.id, submissionId)),
columns: getSubmissionColumns,
with: getSubmissionRelations,
});
}
catch (error) {
logger.error(LOG_MODULE, `Failed querying Submission with relations`, error);
throw new ServiceUnavailable();
}
},
};
};
export default repository;