|
| 1 | +import axios from 'axios'; |
| 2 | +import { color, customAPIurl } from '../../../../Utils.js'; |
| 3 | + |
| 4 | +const randomId = () => Math.floor(1000 + Math.random() * 9000); |
| 5 | +export default async function createDocumentwithCoordinate(request, response) { |
| 6 | + const name = request.body.title; |
| 7 | + const note = request.body.note; |
| 8 | + const description = request.body.description; |
| 9 | + const signers = request.body.signers; |
| 10 | + const folderId = request.body.folderId; |
| 11 | + const base64File = request.body.file; |
| 12 | + const fileData = request.files?.[0] ? request.files[0].buffer : null; |
| 13 | + // console.log('fileData ', fileData); |
| 14 | + const protocol = customAPIurl(); |
| 15 | + const baseUrl = new URL(process.env.SERVER_URL); |
| 16 | + |
| 17 | + try { |
| 18 | + const reqToken = request.headers['x-api-token']; |
| 19 | + if (!reqToken) { |
| 20 | + return response.status(400).json({ error: 'Please Provide API Token' }); |
| 21 | + } |
| 22 | + const tokenQuery = new Parse.Query('appToken'); |
| 23 | + tokenQuery.equalTo('token', reqToken); |
| 24 | + const token = await tokenQuery.first({ useMasterKey: true }); |
| 25 | + if (token !== undefined) { |
| 26 | + // Valid Token then proceed request |
| 27 | + if (signers && signers.length > 0) { |
| 28 | + const userPtr = token.get('userId'); |
| 29 | + let fileUrl; |
| 30 | + if (request.files?.[0]) { |
| 31 | + const file = new Parse.File(request.files?.[0]?.originalname, { |
| 32 | + base64: fileData?.toString('base64'), |
| 33 | + }); |
| 34 | + await file.save({ useMasterKey: true }); |
| 35 | + fileUrl = file.url(); |
| 36 | + } else { |
| 37 | + const file = new Parse.File(`${name}.pdf`, { |
| 38 | + base64: base64File, |
| 39 | + }); |
| 40 | + await file.save({ useMasterKey: true }); |
| 41 | + fileUrl = file.url(); |
| 42 | + } |
| 43 | + const contractsUser = new Parse.Query('contracts_Users'); |
| 44 | + contractsUser.equalTo('UserId', userPtr); |
| 45 | + const extUser = await contractsUser.first({ useMasterKey: true }); |
| 46 | + const parseExtUser = JSON.parse(JSON.stringify(extUser)); |
| 47 | + |
| 48 | + const extUserPtr = { |
| 49 | + __type: 'Pointer', |
| 50 | + className: 'contracts_Users', |
| 51 | + objectId: extUser.id, |
| 52 | + }; |
| 53 | + |
| 54 | + const object = new Parse.Object('contracts_Document'); |
| 55 | + object.set('Name', name); |
| 56 | + |
| 57 | + if (note) { |
| 58 | + object.set('Note', note); |
| 59 | + } |
| 60 | + if (description) { |
| 61 | + object.set('Description', description); |
| 62 | + } |
| 63 | + object.set('URL', fileUrl); |
| 64 | + object.set('CreatedBy', userPtr); |
| 65 | + object.set('ExtUserPtr', extUserPtr); |
| 66 | + let contact = []; |
| 67 | + if (signers && signers.length > 0) { |
| 68 | + let parseSigners; |
| 69 | + if (base64File) { |
| 70 | + parseSigners = signers; |
| 71 | + } else { |
| 72 | + parseSigners = JSON.parse(signers); |
| 73 | + } |
| 74 | + let createContactUrl = protocol + '/v1/createcontact'; |
| 75 | + |
| 76 | + for (const [index, element] of parseSigners.entries()) { |
| 77 | + const body = { |
| 78 | + name: element?.name || '', |
| 79 | + email: element?.email || '', |
| 80 | + phone: element?.phone || '', |
| 81 | + }; |
| 82 | + try { |
| 83 | + const res = await axios.post(createContactUrl, body, { |
| 84 | + headers: { 'Content-Type': 'application/json', 'x-api-token': reqToken }, |
| 85 | + }); |
| 86 | + // console.log('res ', res.data); |
| 87 | + const contactPtr = { |
| 88 | + __type: 'Pointer', |
| 89 | + className: 'contracts_Contactbook', |
| 90 | + objectId: res.data?.objectId, |
| 91 | + }; |
| 92 | + const newObj = { ...element, contactPtr: contactPtr, index: index }; |
| 93 | + contact.push(newObj); |
| 94 | + } catch (err) { |
| 95 | + // console.log('err ', err.response); |
| 96 | + if (err?.response?.data?.objectId) { |
| 97 | + const contactPtr = { |
| 98 | + __type: 'Pointer', |
| 99 | + className: 'contracts_Contactbook', |
| 100 | + objectId: err.response.data?.objectId, |
| 101 | + }; |
| 102 | + const newObj = { ...element, contactPtr: contactPtr, index: index }; |
| 103 | + contact.push(newObj); |
| 104 | + } |
| 105 | + } |
| 106 | + } |
| 107 | + object.set( |
| 108 | + 'Signers', |
| 109 | + contact?.map(x => x.contactPtr) |
| 110 | + ); |
| 111 | + let updatePlaceholders = contact.map(x => { |
| 112 | + return { |
| 113 | + signerObjId: x?.contactPtr?.objectId, |
| 114 | + signerPtr: x?.contactPtr, |
| 115 | + Role: x.role, |
| 116 | + Id: randomId(), |
| 117 | + blockColor: color[x?.index], |
| 118 | + placeHolder: x.widgets.map((widget, i) => ({ |
| 119 | + pageNumber: widget.page, |
| 120 | + pos: [ |
| 121 | + { |
| 122 | + xPosition: widget.x, |
| 123 | + yPosition: widget.y, |
| 124 | + isStamp: widget.type === 'stamp' || widget.type === 'image' ? true : false, |
| 125 | + key: randomId(), |
| 126 | + isDrag: false, |
| 127 | + firstXPos: widget.x, |
| 128 | + firstYPos: widget.y, |
| 129 | + yBottom: 0, |
| 130 | + scale: 1, |
| 131 | + isMobile: false, |
| 132 | + zIndex: i + 1, |
| 133 | + type: widget.type, |
| 134 | + widgetValue: '', |
| 135 | + Width: widget.w, |
| 136 | + Height: widget.h, |
| 137 | + }, |
| 138 | + ], |
| 139 | + })), |
| 140 | + }; |
| 141 | + }); |
| 142 | + object.set('Placeholders', updatePlaceholders); |
| 143 | + } |
| 144 | + if (folderId) { |
| 145 | + object.set('Folder', { |
| 146 | + __type: 'Pointer', |
| 147 | + className: 'contracts_Document', |
| 148 | + objectId: folderId, |
| 149 | + }); |
| 150 | + } |
| 151 | + const newACL = new Parse.ACL(); |
| 152 | + newACL.setPublicReadAccess(false); |
| 153 | + newACL.setPublicWriteAccess(false); |
| 154 | + newACL.setReadAccess(userPtr.id, true); |
| 155 | + newACL.setWriteAccess(userPtr.id, true); |
| 156 | + object.setACL(newACL); |
| 157 | + const res = await object.save(null, { useMasterKey: true }); |
| 158 | + |
| 159 | + const newDate = new Date(); |
| 160 | + newDate.setDate(newDate.getDate() + 15); |
| 161 | + const localExpireDate = newDate.toLocaleDateString('en-US', { |
| 162 | + day: 'numeric', |
| 163 | + month: 'long', |
| 164 | + year: 'numeric', |
| 165 | + }); |
| 166 | + let sender = parseExtUser.Email; |
| 167 | + let sendMail; |
| 168 | + const serverUrl = process.env.SERVER_URL; |
| 169 | + const newServer = serverUrl.replaceAll('/', '%2F'); |
| 170 | + const serverParams = `${newServer}%2F&${process.env.APP_ID}&contracts`; |
| 171 | + |
| 172 | + for (let i = 0; i < contact.length; i++) { |
| 173 | + try { |
| 174 | + const imgPng = 'https://qikinnovation.ams3.digitaloceanspaces.com/logo.png'; |
| 175 | + let url = `${process.env.SERVER_URL}/functions/sendmailv3/`; |
| 176 | + const headers = { |
| 177 | + 'Content-Type': 'application/json', |
| 178 | + 'X-Parse-Application-Id': process.env.APP_ID, |
| 179 | + 'X-Parse-Master-Key': process.env.MASTER_KEY, |
| 180 | + }; |
| 181 | + |
| 182 | + const objectId = contact[i].contactPtr.objectId; |
| 183 | + |
| 184 | + const hostUrl = baseUrl.origin + '/loadmf/signmicroapp'; |
| 185 | + let signPdf = `${hostUrl}/login/${res.id}/${contact[i].email}/${objectId}/${serverParams}`; |
| 186 | + const openSignUrl = 'https://www.opensignlabs.com/contact-us'; |
| 187 | + const orgName = parseExtUser.Company ? parseExtUser.Company : ''; |
| 188 | + const themeBGcolor = '#47a3ad'; |
| 189 | + let params = { |
| 190 | + recipient: contact[i].email, |
| 191 | + subject: `${parseExtUser.Name} has requested you to sign ${parseExtUser.Name}`, |
| 192 | + from: sender, |
| 193 | + html: |
| 194 | + "<html><head><meta http-equiv='Content-Type' content='text/html; charset=UTF-8' /> </head> <body> <div style='background-color: #f5f5f5; padding: 20px'=> <div style=' box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;background: white;padding-bottom: 20px;'> <div style='padding:10px 10px 0 10px'><img src=" + |
| 195 | + imgPng + |
| 196 | + " height='50' style='padding: 20px,width:170px,height:40px' /></div> <div style=' padding: 2px;font-family: system-ui;background-color:" + |
| 197 | + themeBGcolor + |
| 198 | + ";'><p style='font-size: 20px;font-weight: 400;color: white;padding-left: 20px;' > Digital Signature Request</p></div><div><p style='padding: 20px;font-family: system-ui;font-size: 14px; margin-bottom: 10px;'> " + |
| 199 | + parseExtUser.Name + |
| 200 | + ' has requested you to review and sign <strong> ' + |
| 201 | + name + |
| 202 | + "</strong>.</p><div style='padding: 5px 0px 5px 25px;display: flex;flex-direction: row;justify-content: space-around;'><table> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Sender</td> <td> </td> <td style='color:#626363;font-weight:bold'>" + |
| 203 | + sender + |
| 204 | + "</td></tr><tr><td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Organization</td> <td> </td><td style='color:#626363;font-weight:bold'> " + |
| 205 | + orgName + |
| 206 | + "</td></tr> <tr> <td style='font-weight:bold;font-family:sans-serif;font-size:15px'>Expire on</td><td> </td> <td style='color:#626363;font-weight:bold'>" + |
| 207 | + localExpireDate + |
| 208 | + "</td></tr><tr> <td></td> <td> </td></tr></table> </div> <div style='margin-left:70px'><a href=" + |
| 209 | + signPdf + |
| 210 | + "> <button style='padding: 12px 12px 12px 12px;background-color: #d46b0f;color: white; border: 0px;box-shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;font-weight:bold;margin-top:30px'>Sign here</button></a> </div> <div style='display: flex; justify-content: center;margin-top: 10px;'> </div></div></div><div><p> This is an automated email from OpenSign™. For any queries regarding this email, please contact the sender " + |
| 211 | + sender + |
| 212 | + ' directly.If you think this email is inappropriate or spam, you may file a complaint with OpenSign™ <a href= ' + |
| 213 | + openSignUrl + |
| 214 | + ' target=_blank>here</a>.</p> </div></div></body> </html>', |
| 215 | + }; |
| 216 | + sendMail = await axios.post(url, params, { headers: headers }); |
| 217 | + } catch (error) { |
| 218 | + console.log('error', error); |
| 219 | + } |
| 220 | + } |
| 221 | + |
| 222 | + if (sendMail.data.result.status === 'success') { |
| 223 | + const user = contact.find(x => x.email === parseExtUser.Email); |
| 224 | + if (user && user.email) { |
| 225 | + return response.json({ |
| 226 | + objectId: res.id, |
| 227 | + url: `${baseUrl.origin}/loadmf/signmicroapp/login/${res.id}/${user.email}/${user.contactPtr.objectId}/${serverParams}`, |
| 228 | + message: 'Document sent successfully!', |
| 229 | + }); |
| 230 | + } else { |
| 231 | + return response.json({ |
| 232 | + objectId: res.id, |
| 233 | + message: 'Document sent successfully!', |
| 234 | + }); |
| 235 | + } |
| 236 | + } |
| 237 | + } else { |
| 238 | + return response.status(400).json({ error: 'Please provide signers!' }); |
| 239 | + } |
| 240 | + } else { |
| 241 | + return response.status(405).json({ error: 'Invalid API Token!' }); |
| 242 | + } |
| 243 | + } catch (err) { |
| 244 | + console.log('err ', err); |
| 245 | + return response.status(400).json({ error: 'Something went wrong!' }); |
| 246 | + } |
| 247 | +} |
0 commit comments