Skip to content

Commit

Permalink
Sosynpl[premieroctet#150] added conversation with Admin logic
Browse files Browse the repository at this point in the history
  • Loading branch information
SeghirOumo committed Jul 23, 2024
1 parent 7daadb4 commit 996f6f5
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 30 deletions.
33 changes: 19 additions & 14 deletions backend/web/server/plugins/sosynpl/functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -562,27 +562,32 @@ const preProcessGet = async ({ model, fields, id, user, params }) => {
return Conversation.findById(id)
.then(async(conv) => {
if(!conv){
const model = await getModel(id, ['mission','application'])
let customerId, freelanceId, application
if(model == 'mission') {
const model = await getModel(id, ['mission','application','customerFreelance'])
let customerId, freelanceId, applicationId, partnerId
if(model == 'customerFreelance') {
partnerId = id
}
else if(model == 'mission') {
const mission = await Mission.findById(id)
customerId = mission.customer
freelanceId = mission.freelance
application = mission.application
applicationId = mission.application._id
partnerId = idEqual(user._id, customerId) ? freelanceId : customerId
}
else {
application = await Application.findById(id).populate('announce')
else if(model == 'application' ) {
const application = await Application.findById(id).populate('announce')
customerId = application.announce.user
freelanceId = application.freelance
partnerId = idEqual(user._id, customerId) ? freelanceId : customerId
applicationId = application._id
}
const partnerId = idEqual(user._id, customerId) ? freelanceId : customerId
if(!partnerId) {
throw new Error(`${id} is not a valid user`)
}
if (idEqual(partnerId, user._id)) {
throw new Error(`Vous ne pouvez avoir de conversation avec vous-même`)
}
conv = Conversation.getFromUsersApplication(user._id, partnerId, application._id)
if(!partnerId) {
throw new Error(`${id} is not a valid user`)
}
if (idEqual(partnerId, user._id)) {
throw new Error(`Vous ne pouvez avoir de conversation avec vous-même`)
}
conv = Conversation.getFromUsers({user1:user._id, user2:partnerId, applicationId})
}
return conv
})
Expand Down
32 changes: 26 additions & 6 deletions backend/web/server/plugins/sosynpl/schemas/ConversationSchema.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ const mongoose = require('mongoose')
const {schemaOptions} = require('../../../utils/schemas')
const { idEqual } = require('../../../utils/database')
const { CREATED_AT_ATTRIBUTE } = require('../../../../utils/consts')
const User = require('../../../models/User')
const { ROLE_ADMIN } = require('../consts')
const Schema = mongoose.Schema

const ConversationSchema = new Schema({
Expand All @@ -20,7 +22,7 @@ const ConversationSchema = new Schema({
application: {
type: mongoose.Schema.ObjectId,
ref: 'application',
required: [true, `L'application est obligatoire`]
required: false,
},
},
schemaOptions)
Expand Down Expand Up @@ -48,13 +50,13 @@ ConversationSchema.virtual('latest_messages', {
},
})

ConversationSchema.statics.getFromUsersApplication = async function(user1, user2, applicationId) {
if (!user1 || !user2 || !applicationId) {
throw new Error(`Expected all, got : \nuser1:${user1}\nuser2:${user2}\napplicationId:${applicationId}`)
ConversationSchema.statics.getFromUsers = async function({user1, user2, applicationId}) {
if (!user1 || !user2) {
throw new Error(`Expected all, got : \nuser1:${user1}\nuser2:${user2}`)
}
let conversation=await this.findOne({$and: [{users: user1},{users: user2}], application: applicationId})
let conversation=await this.findOne({$and: [{users: user1},{users: user2}], ...applicationId ? {application: applicationId} : {}})
if (!conversation) {
conversation=await this.create({users: [user1, user2], application: applicationId})
conversation=await this.create({users: [user1, user2], ...applicationId ? {application: applicationId} : {}})
}
return conversation
};
Expand All @@ -64,4 +66,22 @@ ConversationSchema.methods.getPartner = async function(me) {
return partner
}

ConversationSchema.pre('validate', function(next) {
if (!this.application) {
return User.exists({
_id: { $in: this.users },
role: ROLE_ADMIN
})
.then(isAdmin => {
if (!isAdmin) {
return next(new Error(`Vous ne pouvez converser qu'avec un ADMIN ou dans le cadre d'une candidature`))
}
next()
})
}
else {
return next()
}
})

module.exports=ConversationSchema
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,11 @@ const CustomerFreelanceSchema = new Schema({
validate: [v => !v || IBANValidator.isValid(v), v => `L'IBAN '${v.value}' est invalide`],
required: false,
},
dedicated_admin: {
type: Schema.Types.ObjectId,
ref: 'user',
required: false
},
}, {...schemaOptions, ...DISCRIMINATOR_KEY})

/* eslint-disable prefer-arrow-callback */
Expand Down
99 changes: 99 additions & 0 deletions backend/web/tests/sosynpl/conversation.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
const mongoose = require('mongoose')
const { MONGOOSE_OPTIONS, loadFromDb } = require('../../server/utils/database')
require('../../server/plugins/sosynpl/functions')
require('../../server/models/Conversation')
require('../../server/models/Job')
require('../../server/models/Sector')
require('../../server/models/JobFile')
const moment = require('moment')
const { CUSTOMER_DATA, JOB_FILE_DATA, JOB_DATA, SECTOR_DATA, CATEGORY_DATA, FREELANCE_DATA, ANNOUNCE_DATA } = require('./data/base_data')
const JobFile = require('../../server/models/JobFile')
const Job = require('../../server/models/Job')
const Sector = require('../../server/models/Sector')
const CustomerFreelance = require('../../server/models/CustomerFreelance')
const HardSkillCategory = require('../../server/models/HardSkillCategory')
const Expertise = require('../../server/models/Expertise')
const LanguageLevel = require('../../server/models/LanguageLevel')
const { LANGUAGE_LEVEL_ADVANCED } = require('../../utils/consts')
const Software = require('../../server/models/Software')
const lodash = require('lodash')
const HardSkill = require('../../server/models/HardSkill')
const Announce = require('../../server/models/Announce')
const Application = require('../../server/models/Application')
const Mission = require('../../server/models/Mission')
const { ROLE_ADMIN } = require('../../server/plugins/sosynpl/consts')

describe('Conversation', () => {
const DBNAME = `test${moment().unix()}`
let freelance, customer, application, announce, mission, admin
let expertise1, expertise2, expertise3, software, sector, language

beforeAll(async () => {
await mongoose.connect(`mongodb://localhost/${DBNAME}`, MONGOOSE_OPTIONS)

const jobFile = await JobFile.create({ ...JOB_FILE_DATA })
const job = await Job.create({ ...JOB_DATA, job_file: jobFile })
sector = await Sector.create({ ...SECTOR_DATA })
const category1 = await HardSkillCategory.create({ ...CATEGORY_DATA, name: 'Catégorie 1' })
const category2 = await HardSkillCategory.create({ ...CATEGORY_DATA, name: 'Catégorie 2' })
expertise1 = await Expertise.create({ name: 'JavaScript' })
expertise2 = await Expertise.create({ name: 'Java' })
expertise3 = await Expertise.create({ name: 'Python' })
await Promise.all(lodash.range(4).map(idx => HardSkill.create({ name: `Skill 1-${idx}`, code: '12', job_file: jobFile, category: category1 })))
await Promise.all(lodash.range(2).map(idx => HardSkill.create({ name: `Skill 2-${idx}`, code: '12', job_file: jobFile, category: category2 })))
language = await LanguageLevel.create({ language: 'fr', level: LANGUAGE_LEVEL_ADVANCED })
software = await Software.create({ name: 'VS Code' })

customer = await CustomerFreelance.create({ ...CUSTOMER_DATA })

freelance = await CustomerFreelance.create({ ...FREELANCE_DATA, main_job: job, work_sector: [sector] })

admin = await CustomerFreelance.create({ ...CUSTOMER_DATA, role: ROLE_ADMIN})

announce = await Announce.create({
...ANNOUNCE_DATA,
user: customer._id,
sectors: [sector._id],
expertises: [expertise1._id, expertise2._id, expertise3._id],
pinned_expertises: [expertise1._id, expertise2._id, expertise3._id],
softwares: [software._id],
languages: [language._id],
})

application = await Application.create({
announce: announce._id,
customer: customer._id,
freelance: freelance._id,
})

mission = await Mission.create({
application: application._id,
customer: customer._id,
freelance: freelance._id,
title: 'dev',
start_date: new Date(),
end_date: new Date('2025-06-06'),
})
})

afterAll(async () => {
await mongoose.connection.close()
})

it('must refuse creating a conversation with a non ADMIN user', async () => {
try {
await loadFromDb({ model: 'conversation', user: customer, id: freelance._id, fields: ['messages_count', 'users'] })
throw new Error('Expected method to reject.')
} catch (err) {
expect(err.message).toBe("Vous ne pouvez converser qu'avec un ADMIN ou dans le cadre d'une candidature")
}
})
it('must accept creating a conversation with an ADMIN', async () => {
const [conv] = await loadFromDb({ model: 'conversation', user: customer, id: admin._id, fields: ['messages_count', 'users'] })
expect(conv.users.length).toEqual(2)
})
it('must accept creating a conversation for an application', async () => {
const [conv] = await loadFromDb({ model: 'conversation', user: customer, id: application._id, fields: ['messages_count', 'users'] })
expect(conv.users.length).toEqual(2)
})
})
36 changes: 26 additions & 10 deletions backend/web/tests/sosynpl/data/base_data.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const { ROLE_CUSTOMER, SOURCE, EXPERIENCE, WORK_DURATION } = require("../../../server/plugins/sosynpl/consts");
const { ROLE_CUSTOMER, SOURCE, EXPERIENCE, WORK_DURATION, DURATION_MONTH, MOBILITY_NONE } = require("../../../server/plugins/sosynpl/consts");

const CUSTOMER_DATA={
const CUSTOMER_DATA = {
password: "tagada",
email: "test@test.com",
firstname: "firstname",
Expand All @@ -11,8 +11,9 @@ const CUSTOMER_DATA={
cgu_accepted: true,
phone: '0675774324',
position: 'Dev'
}
const FREELANCE_DATA= {
}

const FREELANCE_DATA = {
...CUSTOMER_DATA,
source: Object.keys(SOURCE)[0],
linkedin: 'lien',
Expand All @@ -24,26 +25,41 @@ const FREELANCE_DATA= {
address: {},
}

const JOB_FILE_DATA={
const JOB_FILE_DATA = {
code: 'A0000',
name: 'Informatique'
}

const JOB_DATA={
const JOB_DATA = {
name: 'dev',
}

const SECTOR_DATA={
const SECTOR_DATA = {
name: 'Aéronautique',
}

const CATEGORY_DATA={
const CATEGORY_DATA = {
name: 'catégorie',
}

const ANNOUNCE_DATA={
const ANNOUNCE_DATA = {
title: 'dev',
experience: Object.keys(EXPERIENCE)[0],
duration: 2,
duration_unit: DURATION_MONTH,
budget: '6969669',
mobility_days_per_month: 2,
mobility: MOBILITY_NONE,
city: {
address: 'Place du Vieux-Marché',
city: 'Rouen',
zip_code: '76000',
country: 'France',
latitude: 49.4431,
longitude: 1.0993,
}
}

module.exports={
module.exports = {
CUSTOMER_DATA, FREELANCE_DATA, JOB_DATA, JOB_FILE_DATA, SECTOR_DATA, CATEGORY_DATA, ANNOUNCE_DATA,
}

0 comments on commit 996f6f5

Please sign in to comment.