Skip to content

feat(PM-573): copilot opportunities implementation #777

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 104 additions & 1 deletion docs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ paths:
"200":
description: Created copilot request
schema:
$ref: "#/definitions/Copilot"
$ref: "#/definitions/CopilotRequest"
"401":
description: Unauthorized
schema:
Expand All @@ -276,6 +276,39 @@ paths:
required: true
schema:
$ref: "#/definitions/NewCopilotRequest"
"/projects/{projectId}/copilots/request/{copilotRequestId}/approve":
post:
tags:
- projects copilot opportunity approve
operationId: createCopilotOpportunity
security:
- Bearer: []
description: "create copilot opportunity"
responses:
"200":
description: Created copilot opportunity
schema:
$ref: "#/definitions/CopilotOpportunity"
"401":
description: Unauthorized
schema:
$ref: "#/definitions/ErrorModel"
"400":
description: Bad request
schema:
$ref: "#/definitions/ErrorModel"
"500":
description: Internal Server Error
schema:
$ref: "#/definitions/ErrorModel"
parameters:
- $ref: "#/parameters/projectIdParam"
- $ref: "#/parameters/copilotRequestIdParam"
- name: body
in: body
required: true
schema:
$ref: "#/definitions/NewCopilotOpportunity"
"/projects/{projectId}/attachments":
get:
tags:
Expand Down Expand Up @@ -5246,6 +5279,13 @@ parameters:
required: true
type: integer
format: int64
copilotRequestIdParam:
name: copilotRequestId
in: path
description: copilot request identifier
required: true
type: integer
format: int64
phaseIdParam:
name: phaseId
in: path
Expand Down Expand Up @@ -5571,6 +5611,24 @@ definitions:
numHoursPerWeek:
type: integer
description: Expected hours per week
NewCopilotOpportunity:
type: object
required:
- data
- type
- skills
properties:
data:
type: object
description: copilot opportunity data
type:
type: string
description: type of the copilot opportunity
skills:
type: array
items:
type: string
description: skills of the copilot opportunity
NewProject:
type: object
required:
Expand Down Expand Up @@ -5724,6 +5782,51 @@ definitions:
format: int64
description: READ-ONLY. User that last updated this task
readOnly: true
CopilotOpportunity:
type: object
properties:
id:
description: unique identifier
type: integer
format: int64
data:
description: copilot opportunity data
type: object
status:
description: status of the copilot opportunity
type: string
type:
description: type of the copilot opportunity
type: string
copilotRequestId:
description: copilot request id
type: integer
projectId:
description: project id
type: integer
skills:
type: array
items:
type: string
description: skills of the copilot opportunity
createdAt:
type: string
description: Datetime (GMT) when task was created
readOnly: true
createdBy:
type: integer
format: int64
description: READ-ONLY. User who created this task
readOnly: true
updatedAt:
type: string
description: READ-ONLY. Datetime (GMT) when task was updated
readOnly: true
updatedBy:
type: integer
format: int64
description: READ-ONLY. User that last updated this task
readOnly: true
Project:
type: object
properties:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
'use strict';

module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable("copilot_opportunities", {
id: {
type: Sequelize.BIGINT,
allowNull: false,
primaryKey: true,
autoIncrement: true,
},
data: {
type: Sequelize.JSON,
allowNull: false,
},
status: {
type: Sequelize.STRING(16),
allowNull: false,
},
projectId: {
type: Sequelize.BIGINT,
allowNull: false,
references: {
model: "projects",
key: "id",
},
onUpdate: "CASCADE",
onDelete: "SET NULL",
},
copilotRequestId: {
type: Sequelize.BIGINT,
allowNull: false,
references: {
model: "copilot_requests",
key: "id",
},
onUpdate: "CASCADE",
onDelete: "SET NULL",
},
type: {
type: Sequelize.STRING(16),
allowNull: false,
},
skills: {
type: DataTypes.ARRAY({ type: DataTypes.STRING(16), allowNull: true }),
allowNull: false,
defaultValue: [],
},
deletedAt: {
type: Sequelize.DATE,
allowNull: true,
},
createdAt: {
type: Sequelize.DATE,
allowNull: true,
},
updatedAt: {
type: Sequelize.DATE,
allowNull: true,
},
deletedBy: {
type: Sequelize.BIGINT,
allowNull: true,
},
createdBy: {
type: Sequelize.BIGINT,
allowNull: false,
},
updatedBy: {
type: Sequelize.BIGINT,
allowNull: false,
},
});
},

down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable("copilot_opportunities");
}
};
14 changes: 14 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,20 @@ export const COPILOT_REQUEST_STATUS = {
FULFILLED: 'fulfiled',
};

export const COPILOT_OPPORTUNITY_STATUS = {
ACTIVE: 'active',
COMPLETED: 'completed',
CANCELED: 'canceled',
};

export const COPILOT_OPPORTUNITY_TYPE = {
DEV: 'dev',
QA: 'qa',
DESIGN: 'design',
AI: 'ai'
};


export const WORKSTREAM_STATUS = {
DRAFT: 'draft',
REVIEWED: 'reviewed',
Expand Down
42 changes: 42 additions & 0 deletions src/models/copilotOpportunity.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import _ from 'lodash';
import { COPILOT_OPPORTUNITY_STATUS, COPILOT_OPPORTUNITY_TYPE } from '../constants';

module.exports = function defineCopilotOpportunity(sequelize, DataTypes) {
const CopilotOpportunity = sequelize.define('CopilotOpportunity', {
id: { type: DataTypes.BIGINT, primaryKey: true, autoIncrement: true },
status: {
type: DataTypes.STRING(16),
defaultValue: 'active',
allowNull: false,
validate: {
isIn: [_.values(COPILOT_OPPORTUNITY_STATUS)],
}
},
data: { type: DataTypes.JSON, defaultValue: {}, allowNull: false },
skills: { type: DataTypes.ARRAY({ type: DataTypes.STRING(16), allowNull: true }), defaultValue: [], allowNull: false },
type: {
type: DataTypes.STRING(16),
allowNull: false,
validate: {
isIn: [_.values(COPILOT_OPPORTUNITY_TYPE)],
}
},

deletedAt: { type: DataTypes.DATE, allowNull: true },
createdAt: { type: DataTypes.DATE, defaultValue: DataTypes.NOW },
updatedAt: { type: DataTypes.DATE, defaultValue: DataTypes.NOW },
deletedBy: { type: DataTypes.INTEGER, allowNull: true },
createdBy: { type: DataTypes.INTEGER, allowNull: false },
updatedBy: { type: DataTypes.INTEGER, allowNull: false },
}, {
tableName: 'copilot_opportunities',
paranoid: true,
timestamps: true,
updatedAt: 'updatedAt',
createdAt: 'createdAt',
deletedAt: 'deletedAt',
indexes: [],
});

return CopilotOpportunity;
};
4 changes: 4 additions & 0 deletions src/models/copilotRequest.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ module.exports = function defineCopilotRequest(sequelize, DataTypes) {
deletedAt: 'deletedAt',
indexes: [],
});

CopliotRequest.associate = (models) => {
CopliotRequest.hasMany(models.CopilotOpportunity, { as: 'copilotOpportunity', foreignKey: 'copilotRequestId' });
};

return CopliotRequest;
};
1 change: 1 addition & 0 deletions src/models/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ module.exports = function defineProject(sequelize, DataTypes) {
Project.hasMany(models.ScopeChangeRequest, { as: 'scopeChangeRequests', foreignKey: 'projectId' });
Project.hasMany(models.WorkStream, { as: 'workStreams', foreignKey: 'projectId' });
Project.hasMany(models.CopilotRequest, { as: 'copilotRequests', foreignKey: 'projectId' });
Project.hasMany(models.CopilotOpportunity, { as: 'copilotOpportunity', foreignKey: 'projectId' });
};

/**
Expand Down
Loading