diff --git a/apps/OpenSign/public/locales/en/translation.json b/apps/OpenSign/public/locales/en/translation.json index 51507ea96..4b0b4122b 100644 --- a/apps/OpenSign/public/locales/en/translation.json +++ b/apps/OpenSign/public/locales/en/translation.json @@ -647,6 +647,7 @@ "copied-code":"COPIED", "Installation":"Installation", "Usage" :"Usage", - "unauthorized-modal":"You don't have permission to perform this action, please contact {{adminName}}<{{adminEmail}}>." - + "unauthorized-modal":"You don't have permission to perform this action, please contact {{adminName}}<{{adminEmail}}>.", + "insufficient-credits":"Insufficient Signing Credits", + "insufficient-credits-mssg":"The owner of this document currently lacks the necessary OpenSign credits for you to sign. Please reach out to the owner if you require further details." } diff --git a/apps/OpenSign/public/locales/fr/translation.json b/apps/OpenSign/public/locales/fr/translation.json index f9ff9669b..178d9ddea 100644 --- a/apps/OpenSign/public/locales/fr/translation.json +++ b/apps/OpenSign/public/locales/fr/translation.json @@ -647,6 +647,7 @@ "copied-code":"COPIÉ", "Installation":"Installation", "Usage" :"Usage", - "unauthorized-modal":"Vous n'êtes pas autorisé à effectuer cette action, veuillez contacter {{adminName}}<{{adminEmail}}>." - + "unauthorized-modal":"Vous n'êtes pas autorisé à effectuer cette action, veuillez contacter {{adminName}}<{{adminEmail}}>.", + "insufficient-credits":"Crédits de signature insuffisants", + "insufficient-credits-mssg" :"Le propriétaire de ce document ne dispose actuellement pas des crédits OpenSign nécessaires pour que vous puissiez le signer. Veuillez contacter le propriétaire si vous avez besoin de plus de détails." } diff --git a/apps/OpenSign/src/constant/Utils.js b/apps/OpenSign/src/constant/Utils.js index 4ec3c35d0..2f98f17b9 100644 --- a/apps/OpenSign/src/constant/Utils.js +++ b/apps/OpenSign/src/constant/Utils.js @@ -33,14 +33,15 @@ export const openInNewTab = (url, target) => { export async function fetchSubscription( extUserId, contactObjId, - isGuestSign = false + isGuestSign = false, + isPublic = false ) { try { const Extand_Class = localStorage.getItem("Extand_Class"); const extClass = Extand_Class && JSON.parse(Extand_Class); // console.log("extClass ", extClass); let extUser; - if (extClass && extClass.length > 0) { + if (extClass && extClass.length > 0 && !isPublic) { extUser = extClass[0].objectId; } else { extUser = extUserId; @@ -54,8 +55,10 @@ export async function fetchSubscription( }; const params = isGuestSign ? { contactId: contactObjId } - : { extUserId: extUser }; + : { extUserId: extUser, ispublic: isPublic }; + console.log("params", params); const tenatRes = await axios.post(url, params, { headers: headers }); + console.log("tenantRes", tenatRes); let plan, status, billingDate, adminId; if (isGuestSign) { plan = tenatRes.data?.result?.result?.plan; diff --git a/apps/OpenSign/src/pages/PdfRequestFiles.js b/apps/OpenSign/src/pages/PdfRequestFiles.js index 3f9d41a25..7d4aed259 100644 --- a/apps/OpenSign/src/pages/PdfRequestFiles.js +++ b/apps/OpenSign/src/pages/PdfRequestFiles.js @@ -243,7 +243,13 @@ function PdfRequestFiles(props) { }; async function checkIsSubscribed(extUserId, contactId) { const isGuestSign = isGuestSignFlow || false; - const res = await fetchSubscription(extUserId, contactId, isGuestSign); + const isPublic = props.templateId ? true : false; + const res = await fetchSubscription( + extUserId, + contactId, + isGuestSign, + isPublic + ); const plan = res.plan; const billingDate = res?.billingDate; const status = res?.status; @@ -296,14 +302,16 @@ function PdfRequestFiles(props) { ? [templateDeatils.data.result] : []; if (documentData && documentData[0]?.error) { - props?.setTemplateStatus({ - status: "Invalid" - }); + props?.setTemplateStatus && + props?.setTemplateStatus({ + status: "Invalid" + }); } else if (documentData && documentData.length > 0) { if (documentData[0]?.IsPublic) { - props?.setTemplateStatus({ - status: "Success" - }); + props?.setTemplateStatus && + props?.setTemplateStatus({ + status: "Success" + }); const url = documentData[0] && (documentData[0]?.SignedUrl || documentData[0]?.URL); @@ -347,14 +355,16 @@ function PdfRequestFiles(props) { isLoad: false }); } else { - props?.setTemplateStatus({ - status: "Private" - }); + props?.setTemplateStatus && + props?.setTemplateStatus({ + status: "Private" + }); } } else { - props?.setTemplateStatus({ - status: "Invalid" - }); + props?.setTemplateStatus && + props?.setTemplateStatus({ + status: "Invalid" + }); } } catch (err) { console.log("err in get template details ", err); @@ -1286,7 +1296,11 @@ function PdfRequestFiles(props) { .catch((err) => { console.log("error updating field is decline ", err); setIsUiLoading(false); - alert(t("something-went-wrong-mssg")); + setIsAlert({ + title: "Error", + isShow: true, + alertMessage: t("something-went-wrong-mssg") + }); }); }; //function to add default signature for all requested placeholder of sign @@ -1467,11 +1481,32 @@ function PdfRequestFiles(props) { await SendOtp(); } else { console.log("error in public-sign to create user details"); - alert(t("something-went-wrong-mssg")); + setIsAlert({ + title: "Error", + isShow: true, + alertMessage: t("something-went-wrong-mssg") + }); } } catch (e) { console.log("e", e); - // setIsLoader(false); + if ( + e?.response?.data?.error === "Insufficient Credit" || + e?.response?.data?.error === "Plan expired" + ) { + handleCloseOtp(); + setIsAlert({ + title: t("insufficient-credits"), + isShow: true, + alertMessage: t("insufficient-credits-mssg") + }); + } else { + handleCloseOtp(); + setIsAlert({ + title: "Error", + isShow: true, + alertMessage: t("something-went-wrong-mssg") + }); + } } }; @@ -1503,7 +1538,11 @@ function PdfRequestFiles(props) { } } catch (error) { console.log("error in verify otp in public-sign", error); - alert(t("something-went-wrong-mssg")); + setIsAlert({ + title: "Error", + isShow: true, + alertMessage: t("something-went-wrong-mssg") + }); } }; @@ -1602,6 +1641,7 @@ function PdfRequestFiles(props) { ); }; + console.log("templateId", props.templateId); return ( @@ -1656,27 +1696,6 @@ function PdfRequestFiles(props) { {!requestSignTour && signerObjectId && requestSignTourFunction()} - <ModalUi - isOpen={isAlert.isShow} - title={t("alert-message")} - handleClose={() => - setIsAlert({ isShow: false, alertMessage: "" }) - } - > - <div className="h-full p-[20px]"> - <p>{isAlert.alertMessage}</p> - <button - onClick={() => - setIsAlert({ isShow: false, alertMessage: "" }) - } - type="button" - className="op-btn op-btn-primary mt-3 px-4" - > - {t("ok")} - </button> - </div> - </ModalUi> - <Tour showNumber={false} showNavigation={false} @@ -2184,6 +2203,22 @@ function PdfRequestFiles(props) { </button> </div> </ModalUi> + <ModalUi + isOpen={isAlert.isShow} + title={isAlert?.title || t("alert-message")} + handleClose={() => setIsAlert({ isShow: false, alertMessage: "" })} + > + <div className="h-full p-[20px]"> + <p>{isAlert.alertMessage}</p> + <button + onClick={() => setIsAlert({ isShow: false, alertMessage: "" })} + type="button" + className="op-btn op-btn-primary mt-3 px-4" + > + {t("close")} + </button> + </div> + </ModalUi> </> )} </DndProvider> diff --git a/apps/OpenSign/src/script/locales/en/translation.json b/apps/OpenSign/src/script/locales/en/translation.json index f2a1fdf1c..6b116ed3d 100644 --- a/apps/OpenSign/src/script/locales/en/translation.json +++ b/apps/OpenSign/src/script/locales/en/translation.json @@ -41,7 +41,7 @@ "upgrade-now": "Upgrade now", "upgrade-to": "Upgrade to", "plan": "Plan", - "subscribe-card-teamplan":"Unlock the full power of collaboration! Create unlimited organizations, teams, and hierarchies. Share templates seamlessly across teams and assign custom user roles. Elevate your workflow today!", + "subscribe-card-teamplan": "Unlock the full power of collaboration! Create unlimited organizations, teams, and hierarchies. Share templates seamlessly across teams and assign custom user roles. Elevate your workflow today!", "subscribe-card-plan": "Unlock premium features starting at just {{premiumPrice}}/month. Enjoy enhanced performance and only {{addonPrice}} per additional credit after your included premium credits.", "user-name-limit-char": "To have a username less than 8 character please subscribe", "tour-content": "Don't show this again", @@ -614,24 +614,25 @@ "select-date-format": "Select a date format", "quantityofcredits": "Quantity of premium credits", "remainingcredits": "Premium credits available:", - "remainingcreditshelp":"Use premium credits for API document signing, bulk sending, or embedding OpenSign integration on your website. You have {{allowedcredits}} included credits and {{addoncredits}} additional purchased credits remaining.", + "remainingcreditshelp": "Use premium credits for API document signing, bulk sending, or embedding OpenSign integration on your website. You have {{allowedcredits}} included credits and {{addoncredits}} additional purchased credits remaining.", "additional-credits": "Please purchase premium credits", "quotaerrquicksend": "Quota Reached, You don't have enough credits.", "buycredits": "Buy Premium Credits", - "rotate-right":"Rotate right", - "rotate-left":"Rotate left", - "rotate-alert-mssg":"All widgets on this page will be lost. Are you sure you want to proceed?", - "templateid":"Template-Id", - "bulksendsubcriptionalert":"Please upgrade to Professional or Team plan to use bulk send.", - "generate-test-token":"Generate Test Token", - "regenerate-test-token":"Regenerate Test Token", - "help-test-token":"This token can be used to test the APIs at the https://sandbox.opensignlabs.com/api/v1 endpoint, allowing you to conduct unlimited document signatures. Please note that the sandbox API will sign your documents with self-signed certificates, which may not be recognized as valid by Adobe. Once you’ve completed your testing, you can upgrade to one of our paid plans to generate a production token.", - "help-api-token":"This token can be used to access the production APIs at the {{origin}}/api/v1 endpoint. It can only be generated on one of our paid plans.", - "Add-Webhook":"Add Webhook", + "rotate-right": "Rotate right", + "rotate-left": "Rotate left", + "rotate-alert-mssg": "All widgets on this page will be lost. Are you sure you want to proceed?", + "templateid": "Template-Id", + "bulksendsubcriptionalert": "Please upgrade to Professional or Team plan to use bulk send.", + "generate-test-token": "Generate Test Token", + "regenerate-test-token": "Regenerate Test Token", + "help-test-token": "This token can be used to test the APIs at the https://sandbox.opensignlabs.com/api/v1 endpoint, allowing you to conduct unlimited document signatures. Please note that the sandbox API will sign your documents with self-signed certificates, which may not be recognized as valid by Adobe. Once you’ve completed your testing, you can upgrade to one of our paid plans to generate a production token.", + "help-api-token": "This token can be used to access the production APIs at the {{origin}}/api/v1 endpoint. It can only be generated on one of our paid plans.", + "Add-Webhook": "Add Webhook", "quotamailinfo": "You can send upto 15 signature request emails every month. Upgrade now to send unlimited signing requests directly.", "quotamail": "You've reached your limit of 15 signature request emails for this month. Upgrade now to continue sending emails directly.", - "quotamailTip":"Tip: You can still sign unlimited documents by manually sharing the signing request links.", - "quotamailhead":"Quota Reached", - "unauthorized-modal":"You don't have permission to perform this action, please contact {{adminName}}<{{adminEmail}}>." - + "quotamailTip": "Tip: You can still sign unlimited documents by manually sharing the signing request links.", + "quotamailhead": "Quota Reached", + "unauthorized-modal": "You don't have permission to perform this action, please contact {{adminName}}<{{adminEmail}}>.", + "insufficient-credits": "Insufficient Signing Credits", + "insufficient-credits-mssg":"The owner of this document currently lacks the necessary OpenSign credits for you to sign. Please reach out to the owner if you require further details." } diff --git a/apps/OpenSign/src/script/locales/fr/translation.json b/apps/OpenSign/src/script/locales/fr/translation.json index 7e401e781..d1ee4e8c0 100644 --- a/apps/OpenSign/src/script/locales/fr/translation.json +++ b/apps/OpenSign/src/script/locales/fr/translation.json @@ -632,6 +632,7 @@ "quotamail": "Vous avez atteint votre limite de 15 e-mails de demande de signature pour ce mois. Mettez à niveau maintenant pour continuer à envoyer des e-mails directement.", "quotamailTip":"Astuce : Vous pouvez toujours signer un nombre illimité de documents en partageant manuellement les liens de demande de signature.", "quotamailhead":"Quota atteint", - "unauthorized-modal":"Vous n'êtes pas autorisé à effectuer cette action, veuillez contacter {{adminName}}<{{adminEmail}}>." - + "unauthorized-modal":"Vous n'êtes pas autorisé à effectuer cette action, veuillez contacter {{adminName}}<{{adminEmail}}>.", + "insufficient-credits":"Crédits de signature insuffisants", + "insufficient-credits-mssg" :"Le propriétaire de ce document ne dispose actuellement pas des crédits OpenSign nécessaires pour que vous puissiez le signer. Veuillez contacter le propriétaire si vous avez besoin de plus de détails." } diff --git a/apps/OpenSignServer/cloud/parsefunction/PublicUserLinkContactToDoc.js b/apps/OpenSignServer/cloud/parsefunction/PublicUserLinkContactToDoc.js index 5c2e16532..ba2cf0820 100644 --- a/apps/OpenSignServer/cloud/parsefunction/PublicUserLinkContactToDoc.js +++ b/apps/OpenSignServer/cloud/parsefunction/PublicUserLinkContactToDoc.js @@ -221,6 +221,25 @@ const sendMailToAllSigners = async docId => { } }; +const deductcount = async _resSub => { + try { + const subscriptionCls = new Parse.Object('contracts_Subscriptions'); + subscriptionCls.id = _resSub.objectId; + const allowedCredits = _resSub?.AllowedCredits || 0; + const addonCredits = _resSub?.AddonCredits || 0; + if (allowedCredits > 0) { + const updateAllowedcredits = allowedCredits - 1 || 0; + subscriptionCls.set('AllowedCredits', updateAllowedcredits); + } else { + const updateAddonCredits = addonCredits > 0 ? addonCredits - 1 : 0; + subscriptionCls.set('AddonCredits', updateAddonCredits); + } + await subscriptionCls.save(null, { useMasterKey: true }); + } catch (err) { + console.log('Err in deductcount in PublicUserLinkContacttoDoc cloud function', err); + } +}; + // `PublicUserLinkContactToDoc` cloud function is used to create contact, add this contact in contracts_Guest role and // create new document from template and save contact pointer in placeholder, signers and ACL of Document export default async function PublicUserLinkContactToDoc(req) { @@ -240,126 +259,163 @@ export default async function PublicUserLinkContactToDoc(req) { throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Template not found.'); } const _tempRes = JSON.parse(JSON.stringify(tempRes)); - const Placeholders = _tempRes?.Placeholders || []; - let index; - if (role) { - index = Placeholders?.findIndex(x => x.Role && x.Role === role); - } else { - throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, ''); - } - if (index !== -1) { - // Execute the query to check if a contact already exists in the 'contracts_Contactbook' class - const contactCls = new Parse.Query('contracts_Contactbook'); - contactCls.equalTo('Email', email); - contactCls.equalTo('CreatedBy', _tempRes.CreatedBy); - contactCls.notEqualTo('IsDeleted', true); - const existContact = await contactCls.first({ useMasterKey: true }); - if (existContact) { - const template_json = JSON.parse(JSON.stringify(tempRes)); - //update contact in placeholder, signers and update ACl in provide document - const docRes = await createDocumentFromTemplate(template_json, existContact, index); - if (docRes) { - //condition will execute only if sendInOrder will be false for send email to all signers at a time. - if (!template_json?.SendinOrder) { - await sendMailToAllSigners(docRes.id); - } - return { contactId: existContact.id, docId: docRes.id }; + const subscription = new Parse.Query('contracts_Subscriptions'); + subscription.equalTo('TenantId', { + __type: 'Pointer', + className: 'partners_Tenant', + objectId: _tempRes?.ExtUserPtr?.TenantId?.objectId, + }); + subscription.include('ExtUserPtr'); + const date = new Date(); + subscription.greaterThanOrEqualTo('Next_billing_date', date); + const resSub = await subscription.first({ useMasterKey: true }); + if (resSub) { + const _resSub = JSON.parse(JSON.stringify(resSub)); + const allowedCredits = _resSub?.AllowedCredits || 0; + const addonCredits = _resSub?.AddonCredits || 0; + const totalcredits = allowedCredits + addonCredits; + if (totalcredits > 0) { + const Placeholders = _tempRes?.Placeholders || []; + let index; + if (role) { + index = Placeholders?.findIndex(x => x.Role && x.Role === role); + } else { + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, ''); } - } else { - // Execute the query to check if a user already exists in the 'contracts_Users' class - const extUserQuery = new Parse.Query('contracts_Users'); - extUserQuery.equalTo('Email', email); - const extUser = await extUserQuery.first({ useMasterKey: true }); - if (extUser) { - const _extUser = JSON.parse(JSON.stringify(extUser)); - const contact = { - UserId: _extUser.UserId, - Name: _extUser.Name, - Email: email, - Phone: _extUser?.Phone ? _extUser.Phone : '', - CreatedBy: _tempRes.CreatedBy, - TenantId: _tempRes.ExtUserPtr.TenantId, - }; - const template_json = JSON.parse(JSON.stringify(tempRes)); - // if user present on platform create contact on the basis of extended user details - const contactRes = await saveRoleContact(contact); - const docRes = await createDocumentFromTemplate(template_json, contactRes, index); - if (docRes) { - //condition will execute only if sendInOrder will be false for send email to all signers at a time. - if (!template_json?.SendinOrder) { - await sendMailToAllSigners(docRes.id); + if (index !== -1) { + // Execute the query to check if a contact already exists in the 'contracts_Contactbook' class + const contactCls = new Parse.Query('contracts_Contactbook'); + contactCls.equalTo('Email', email); + contactCls.equalTo('CreatedBy', _tempRes.CreatedBy); + contactCls.notEqualTo('IsDeleted', true); + const existContact = await contactCls.first({ useMasterKey: true }); + if (existContact) { + const template_json = JSON.parse(JSON.stringify(tempRes)); + //update contact in placeholder, signers and update ACl in provide document + const docRes = await createDocumentFromTemplate(template_json, existContact, index); + if (docRes) { + await deductcount(_resSub); + //condition will execute only if sendInOrder will be false for send email to all signers at a time. + if (!template_json?.SendinOrder) { + await sendMailToAllSigners(docRes.id); + } + return { contactId: existContact.id, docId: docRes.id }; } - return { contactId: contactRes.id, docId: docRes.id }; - } - } else if (name) { - try { - // Execute the query to check if a user already exists in the '_User' class - const userQuery = new Parse.Query(Parse.User); - userQuery.equalTo('email', email); - const userRes = await userQuery.first({ useMasterKey: true }); - if (userRes) { + } else { + // Execute the query to check if a user already exists in the 'contracts_Users' class + const extUserQuery = new Parse.Query('contracts_Users'); + extUserQuery.equalTo('Email', email); + const extUser = await extUserQuery.first({ useMasterKey: true }); + if (extUser) { + const _extUser = JSON.parse(JSON.stringify(extUser)); const contact = { - UserId: { __type: 'Pointer', className: '_User', objectId: userRes.id }, - Name: name, + UserId: _extUser.UserId, + Name: _extUser.Name, Email: email, - Phone: phone, + Phone: _extUser?.Phone ? _extUser.Phone : '', CreatedBy: _tempRes.CreatedBy, TenantId: _tempRes.ExtUserPtr.TenantId, }; const template_json = JSON.parse(JSON.stringify(tempRes)); - // Create new contract on the basis provided contact details by user and userId from _User class + // if user present on platform create contact on the basis of extended user details const contactRes = await saveRoleContact(contact); - //update contact in placeholder, signers and update ACl in provide document const docRes = await createDocumentFromTemplate(template_json, contactRes, index); if (docRes) { + await deductcount(_resSub); //condition will execute only if sendInOrder will be false for send email to all signers at a time. if (!template_json?.SendinOrder) { await sendMailToAllSigners(docRes.id); } return { contactId: contactRes.id, docId: docRes.id }; } + } else if (name) { + try { + // Execute the query to check if a user already exists in the '_User' class + const userQuery = new Parse.Query(Parse.User); + userQuery.equalTo('email', email); + const userRes = await userQuery.first({ useMasterKey: true }); + if (userRes) { + const contact = { + UserId: { __type: 'Pointer', className: '_User', objectId: userRes.id }, + Name: name, + Email: email, + Phone: phone, + CreatedBy: _tempRes.CreatedBy, + TenantId: _tempRes.ExtUserPtr.TenantId, + }; + const template_json = JSON.parse(JSON.stringify(tempRes)); + // Create new contract on the basis provided contact details by user and userId from _User class + const contactRes = await saveRoleContact(contact); + //update contact in placeholder, signers and update ACl in provide document + const docRes = await createDocumentFromTemplate( + template_json, + contactRes, + index + ); + if (docRes) { + await deductcount(_resSub); + //condition will execute only if sendInOrder will be false for send email to all signers at a time. + if (!template_json?.SendinOrder) { + await sendMailToAllSigners(docRes.id); + } + return { contactId: contactRes.id, docId: docRes.id }; + } + } else { + // create new user in _User class on the basis of details provide by user + const _users = Parse.Object.extend('User'); + const _user = new _users(); + _user.set('name', name); + _user.set('username', email); + _user.set('email', email); + _user.set('password', email); + if (phone) { + _user.set('phone', phone); + } + const newUserRes = await _user.save(); + const contact = { + UserId: { __type: 'Pointer', className: '_User', objectId: newUserRes.id }, + Name: name, + Email: email, + Phone: phone, + CreatedBy: _tempRes.CreatedBy, + TenantId: _tempRes.ExtUserPtr.TenantId, + }; + const template_json = JSON.parse(JSON.stringify(tempRes)); + // Create new contract on the basis provided contact details by user and userId from _User class + const contactRes = await saveRoleContact(contact); + //update contact in placeholder, signers and update ACl in provide document + const docRes = await createDocumentFromTemplate( + template_json, + contactRes, + index + ); + if (docRes) { + await deductcount(_resSub); + //condition will execute only if sendInOrder will be false for send email to all signers at a time. + if (!template_json?.SendinOrder) { + await sendMailToAllSigners(docRes.id); + } + return { contactId: contactRes.id, docId: docRes.id }; + } + } + } catch (err) { + console.log('Err', err); + } } else { - // create new user in _User class on the basis of details provide by user - const _users = Parse.Object.extend('User'); - const _user = new _users(); - _user.set('name', name); - _user.set('username', email); - _user.set('email', email); - _user.set('password', email); - if (phone) { - _user.set('phone', phone); - } - const newUserRes = await _user.save(); - const contact = { - UserId: { __type: 'Pointer', className: '_User', objectId: newUserRes.id }, - Name: name, - Email: email, - Phone: phone, - CreatedBy: _tempRes.CreatedBy, - TenantId: _tempRes.ExtUserPtr.TenantId, - }; - const template_json = JSON.parse(JSON.stringify(tempRes)); - // Create new contract on the basis provided contact details by user and userId from _User class - const contactRes = await saveRoleContact(contact); - //update contact in placeholder, signers and update ACl in provide document - const docRes = await createDocumentFromTemplate(template_json, contactRes, index); - if (docRes) { - //condition will execute only if sendInOrder will be false for send email to all signers at a time. - if (!template_json?.SendinOrder) { - await sendMailToAllSigners(docRes.id); - } - return { contactId: contactRes.id, docId: docRes.id }; - } + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'User not found.'); } - } catch (err) { - console.log('Err', err); } } else { - throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'User not found.'); + throw new Parse.Error( + Parse.Error.OBJECT_NOT_FOUND, + 'Please provide required parameters!' + ); } + } else { + throw new Parse.Error(Parse.Error.REQUEST_LIMIT_EXCEEDED, 'Insufficient Credit'); } } else { - throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Please provide required parameters!'); + throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Plan expired'); } } else { throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Template not found.');