diff --git a/api/openapi.yaml b/api/openapi.yaml index 49aaf28a7888bb4a893c483ef154917cb1662603..475b87fb5cdf6abaae988c5b91c25aab166e78e8 100644 --- a/api/openapi.yaml +++ b/api/openapi.yaml @@ -62,16 +62,35 @@ paths: post: tags: - ad - summary: Add a new ad - description: Add a new ad to the list - operationId: addAd + summary: Add a new ad with photos + description: Add a new ad to the list with photo uploads + operationId: addAdWithPhotos requestBody: - description: Create a new ad in the required: true content: - application/json: + multipart/form-data: schema: - $ref: '#/components/schemas/Ad' + type: object + properties: + title: + type: string + propertyType: + type: string + publicationStatus: + type: string + propertyStatus: + type: string + description: + type: string + price: + type: number + availabilityDate: + type: string + photos: + type: array + items: + type: string + format: binary security: - bearerAuth: [ ] responses: @@ -85,6 +104,7 @@ paths: description: Invalid input x-swagger-router-controller: Ad + get: tags: - ad @@ -122,9 +142,9 @@ paths: description: Annonce à mettre à jour required: true content: - application/json: + multipart/form-data: schema: - $ref: '#/components/schemas/UpdateAd' + $ref: '#/components/schemas/UpdateAdWithPhotos' security: - bearerAuth: [ ] responses: @@ -262,6 +282,7 @@ paths: '500': description: Erreur serveur interne. Veuillez réessayer plus tard. x-swagger-router-controller: Ad + /announcements/{id}/question/{questionId}/answer: put: tags: @@ -388,6 +409,33 @@ paths: components: schemas: + UpdateAdWithPhotos: + type: object + properties: + title: + type: string + propertyType: + type: string + publicationStatus: + type: string + description: + type: string + price: + type: number + availabilityDate: + type: string + photos: + type: array + items: + type: string + format: binary + required: + - title + - propertyType + - publicationStatus + - description + - price + - availabilityDate Ad: type: object properties: diff --git a/controllers/Ad.js b/controllers/Ad.js index 1fc0ab56ac99d63f0a201374e0fcd93d2d16a4ed..16729a7b35d29db095ab33d3d15686d8556e3e06 100644 --- a/controllers/Ad.js +++ b/controllers/Ad.js @@ -17,18 +17,18 @@ const extractToken = (req, res, next) => { }; }; -router.post('/', extractToken, async (req, res) => { +router.post('/', extractToken, upload.array('photos'), async (req, res) => { try { - const response = await AdService.addAd(req.body, req.token); + const response = await AdService.addAdWithPhotos(req.body, req.files, req.token); utils.writeJson(res, response); } catch (error) { res.status(500).json({message: error.message}); } }); -router.put('/update/:id', extractToken, async (req, res) => { +router.put('/update/:id', extractToken, upload.array('photos'), async (req, res) => { try { - const response = await AdService.updateAd(req.params.id, req.body, req.token); + const response = await AdService.updateAd(req.params.id, req.body, req.files, req.token); utils.writeJson(res, response); } catch (error) { res.status(500).json({message: error.message}); diff --git a/service/AdService.js b/service/AdService.js index 155b4b7bcdcf40f736c86a4b5fd11f256564cec4..831a07618171159a88427c072aaf653376311284 100644 --- a/service/AdService.js +++ b/service/AdService.js @@ -7,21 +7,18 @@ const {extractUserFromToken} = require("./UserService"); const secretKey = process.env.SECRET_KEY; // Service for adding an ad -exports.addAd = async function (body, token) { +exports.addAdWithPhotos = async function (body, photos, token) { try { - const {title, propertyType, publicationStatus, propertyStatus, description, price, availabilityDate} = body; - const photos = []; - /* - req.files.forEach(file => { - photos.push(file.filename); - }); - */ - const decoded = await extractUserFromToken(token, secretKey); - const user = await User.findOne({username: decoded.username}); + const { title, propertyType, publicationStatus, propertyStatus, description, price, availabilityDate } = body; + const user = await extractUserFromToken(token, secretKey); - if (user.isAgent === false) { - throw new Error('User non autorisée.'); - } + const photoPaths = photos.map(file => { + // Process and store the file, return its path + const photoFileName = `${Date.now()}_${file.originalname}`; + const relativePath = path.join('uploads', photoFileName); + fs.writeFileSync(relativePath, file.buffer); + return relativePath; + }); const newAnnouncement = new Ad({ title, @@ -31,7 +28,7 @@ exports.addAd = async function (body, token) { description, price, availabilityDate, - //photos, + photos: photoPaths, userName: user.username }); @@ -39,16 +36,17 @@ exports.addAd = async function (body, token) { return newAnnouncement; } catch (error) { - console.error('Error adding ad:', error); - throw new Error('Failed to add ad. Check server logs for details.'); + console.error('Error adding ad with photos:', error); + throw new Error('Failed to add ad with photos. Check server logs for details.'); } }; + // Service for adding photos to an ad -exports.addPhotosToAd = async function (announcementId, photos) { +exports.addPhotosToAd = async function (announcementId, photos,token) { try { console.log(announcementId, ' ', photos); - + const user = await extractUserFromToken(token, secretKey); const photoPaths = photos.map(file => { const photoFileName = `${Date.now()}_${file.originalname}`; const relativePath = path.relative(process.cwd(), path.join(process.cwd(), 'uploads', photoFileName)); @@ -72,27 +70,33 @@ exports.addPhotosToAd = async function (announcementId, photos) { } }; -// Méthode pour mettre à jour une annonce -exports.updateAd = function (announcementId, reqBody, token) { - return new Promise(async (resolve, reject) => { - try { - const user = await extractUserFromToken(token, secretKey); - const Announcement = await Ad.findById(announcementId); - if (user.username !== Announcement.userName) { - return resolve({status: 403, message: 'User non autorisé'}); - } - const { +// Service for updating an ad with photos +exports.updateAd = async function (announcementId, reqBody, files, token) { + try { + const user = await extractUserFromToken(token, secretKey); + const { title, propertyType, publicationStatus, description, price, availabilityDate } = reqBody; + + const photoPaths = files.map(file => { + const photoFileName = `${Date.now()}_${file.originalname}`; + const relativePath = path.join('uploads', photoFileName); + fs.writeFileSync(relativePath, file.buffer); + return relativePath; + }); + + const updatedAnnouncement = await Ad.findByIdAndUpdate( + announcementId, + { title, propertyType, publicationStatus, propertyStatus, description, price, - availabilityDate - } = reqBody; - /* - let photos = []; - const oldPhotos = reqBody.oldPhotos || []; + availabilityDate, + $push: { photos: { $each: photoPaths } } + }, + { new: true } + ); reqFiles.forEach(file => { photos.push(file.filename); @@ -124,8 +128,13 @@ exports.updateAd = function (announcementId, reqBody, token) { } catch (error) { reject(error); } - }); -} + + return { status: 200, message: 'Annonce modifiée avec succès.', updatedAd: updatedAnnouncement }; + } catch (error) { + console.error('Error updating ad with photos:', error); + throw new Error('Failed to update ad with photos. Check server logs for details.'); + } +}; exports.deleteAd = function (announcementId, token) { return new Promise(async (resolve, reject) => { diff --git a/uploads/1700080075377_add_motes.png b/uploads/1700080075377_add_motes.png new file mode 100644 index 0000000000000000000000000000000000000000..e90919426510ea5ae154b6db7ad7ebf368b91a7b Binary files /dev/null and b/uploads/1700080075377_add_motes.png differ diff --git a/uploads/1700080075378_simu_2_types.png b/uploads/1700080075378_simu_2_types.png new file mode 100644 index 0000000000000000000000000000000000000000..a5fcbd3040aff7c53d4d361e716fb98c7beaaf30 Binary files /dev/null and b/uploads/1700080075378_simu_2_types.png differ