Merge branch 'staging' of https://github.com/OpenSignLabs/OpenSign into raktima-patch-2

This commit is contained in:
RaktimaNXG
2024-09-02 20:03:47 +05:30
16 changed files with 316 additions and 148 deletions
@@ -623,5 +623,11 @@
"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 youve 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."
"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",
"quotamailselfsign": "You've reached your limit of 20 emails for this month. Upgrade now to continue sending emails directly.",
"quotamail": "You've reached your limit of 20 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 below.",
"quotamailhead":"Quota Reached"
}
@@ -624,5 +624,11 @@
"generate-test-token": "Générer jeton de test",
"regenerate-test-token":"Régénérer le jeton de test",
"help-test-token":"Ce jeton peut être utilisé pour tester les API au niveau du point de terminaison https://sandbox.opensignlabs.com/api/v1, vous permettant ainsi d'effectuer un nombre illimité de signatures de documents. Veuillez noter que l'API sandbox signera vos documents avec des certificats auto-signés, qui peuvent ne pas être reconnus comme valides par Adobe. Une fois vos tests terminés, vous pouvez passer à lun de nos forfaits payants pour générer un jeton de production.",
"help-api-token":"Ce jeton peut être utilisé pour accéder aux API de production au point de terminaison {{origin}}/api/v1. Il ne peut être généré que sur l'un de nos forfaits payants."
"help-api-token":"Ce jeton peut être utilisé pour accéder aux API de production au point de terminaison {{origin}}/api/v1. Il ne peut être généré que sur l'un de nos forfaits payants.",
"Add-Webhook":"Ajouter Webhook",
"quotamailselfsign": "Vous avez atteint votre limite de 20 e-mails pour ce mois. Mettez à niveau maintenant pour continuer à envoyer des e-mails directement.",
"quotamail": "Vous avez atteint votre limite de 20 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 ci-dessous.",
"quotamailhead":"Quota atteint"
}
+1 -1
View File
@@ -262,7 +262,7 @@ const BulkSendUi = (props) => {
quantity: 500,
priceperbulksend: 0.15,
price: (75.0).toFixed(2),
totalcredits: _resAddon.addon
totalcredits: obj?.totalcredits + _resAddon.addon
}));
}
}
@@ -15,7 +15,8 @@ function EmailComponent({
sender,
setIsAlert,
extUserId,
activeMailAdapter
activeMailAdapter,
planCode
}) {
const { t } = useTranslation();
const [emailList, setEmailList] = useState([]);
@@ -34,7 +35,7 @@ function EmailComponent({
const imgPng =
"https://qikinnovation.ams3.digitaloceanspaces.com/logo.png";
let url = `${localStorage.getItem("baseUrl")}functions/sendmailv3/`;
let url = `${localStorage.getItem("baseUrl")}functions/sendmailv3`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
@@ -50,6 +51,7 @@ function EmailComponent({
recipient: emailList[i],
subject: `${sender.name} has signed the doc - ${pdfName}`,
from: sender.email,
plan: planCode,
html:
"<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-color:white;'> <div><img src=" +
imgPng +
@@ -74,24 +76,19 @@ function EmailComponent({
});
}
}
if (sendMail && sendMail.data.result.status === "success") {
if (sendMail?.data?.result?.status === "success") {
setSuccessEmail(true);
setIsEmail(false);
setTimeout(() => {
setSuccessEmail(false);
setIsEmail(false);
setEmailValue("");
setEmailList([]);
}, 1500);
setIsLoading(false);
} else if (sendMail && sendMail.data.result.status === "error") {
} else if (sendMail?.data?.result?.status === "quota-reached") {
setIsLoading(false);
setIsEmail(false);
setIsAlert({
isShow: true,
alertMessage: t("something-went-wrong-mssg")
});
setIsAlert({ isShow: true, alertMessage: "quotareached" });
setEmailValue("");
setEmailList([]);
} else {
@@ -133,6 +133,7 @@ function PdfRequestFiles(props) {
const [documentId, setDocumentId] = useState("");
const [isPublicContact, setIsPublicContact] = useState(false);
const [pdfArrayBuffer, setPdfArrayBuffer] = useState("");
const [plancode, setPlanCode] = useState("");
const isHeader = useSelector((state) => state.showHeader);
const divRef = useRef(null);
@@ -246,6 +247,7 @@ function PdfRequestFiles(props) {
const plan = res.plan;
const billingDate = res?.billingDate;
const status = res?.status;
setPlanCode(plan);
if (plan === "freeplan") {
return true;
} else if (billingDate) {
@@ -986,6 +988,7 @@ function PdfRequestFiles(props) {
? replaceVar?.subject
: `${pdfDetails?.[0].ExtUserPtr.Name} has requested you to sign "${pdfDetails?.[0].Name}"`,
from: senderEmail,
plan: plancode,
html: requestBody
? replaceVar?.body
: "<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=" +
+64 -45
View File
@@ -61,6 +61,7 @@ import PdfZoom from "../components/pdf/PdfZoom";
import LottieWithLoader from "../primitives/DotLottieReact";
import { useTranslation } from "react-i18next";
import RotateAlert from "../components/RotateAlert";
import QuotaCard from "../primitives/QuotaCard";
function PlaceHolderSign() {
const { t } = useTranslation();
@@ -150,8 +151,8 @@ function PlaceHolderSign() {
const [isCustomize, setIsCustomize] = useState(false);
const [zoomPercent, setZoomPercent] = useState(0);
const [scale, setScale] = useState(1);
const [pdfRotateBase64, setPdfRotatese64] = useState("");
const [planCode, setPlanCode] = useState("");
const isMobile = window.innerWidth < 767;
const [, drop] = useDrop({
accept: "BOX",
@@ -240,6 +241,7 @@ function PlaceHolderSign() {
const res = await fetchSubscription();
const plan = res.plan;
const billingDate = res.billingDate;
setPlanCode(plan);
if (plan === "freeplan") {
return true;
} else if (billingDate) {
@@ -1079,7 +1081,7 @@ function PlaceHolderSign() {
try {
const imgPng =
"https://qikinnovation.ams3.digitaloceanspaces.com/logo.png";
let url = `${localStorage.getItem("baseUrl")}functions/sendmailv3/`;
let url = `${localStorage.getItem("baseUrl")}functions/sendmailv3`;
const headers = {
"Content-Type": "application/json",
"X-Parse-Application-Id": localStorage.getItem("parseAppId"),
@@ -1134,6 +1136,7 @@ function PlaceHolderSign() {
? replaceVar?.subject
: `${senderName} has requested you to sign "${documentName}"`,
from: senderEmail,
plan: planCode,
html: isCustomize
? replaceVar?.body
: "<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=" +
@@ -1164,7 +1167,7 @@ function PlaceHolderSign() {
console.log("error", error);
}
}
if (sendMail.data.result.status === "success") {
if (sendMail?.data?.result?.status === "success") {
setMailStatus("success");
try {
let data;
@@ -1177,9 +1180,8 @@ function PlaceHolderSign() {
} else {
data = { SendMail: true };
}
await axios
.put(
try {
await axios.put(
`${localStorage.getItem(
"baseUrl"
)}classes/contracts_Document/${documentId}`,
@@ -1191,21 +1193,21 @@ function PlaceHolderSign() {
"X-Parse-Session-Token": localStorage.getItem("accesstoken")
}
}
)
.then(() => {})
.catch((err) => {
console.log("axois err ", err);
});
);
} catch (err) {
console.log("axois err ", err);
}
} catch (e) {
console.log("error", e);
}
setIsSend(true);
setIsMailSend(true);
const loadObj = {
isLoad: false
};
setIsLoading(loadObj);
setIsLoading({ isLoad: false });
setIsUiLoading(false);
} else if (sendMail?.data?.result?.status === "quota-reached") {
setMailStatus("quotareached");
setIsSend(true);
setIsMailSend(true);
setIsUiLoading(false);
} else {
setMailStatus("failed");
@@ -1862,7 +1864,7 @@ function PlaceHolderSign() {
<span className="ml-[5px] mr-[5px]">{t("or")}</span>
<span className="h-[1px] w-[20%] bg-[#ccc]"></span>
</div>
<div className="mt-3 mb-3">{handleShareList()}</div>
<div className="my-3">{handleShareList()}</div>
</>
)}
</div>
@@ -1871,7 +1873,11 @@ function PlaceHolderSign() {
{/* this modal is used show send mail message and after send mail success message */}
<ModalUi
isOpen={isSend}
title={t("Mails Sent")}
title={
mailStatus === "quotareached"
? t("quotamailhead")
: t("Mails Sent")
}
handleClose={() => {
setIsSend(false);
setSignerPos([]);
@@ -1885,40 +1891,53 @@ function PlaceHolderSign() {
<p>{t("placeholder-alert-4")}</p>
{isCurrUser && <p>{t("placeholder-alert-5")}</p>}
</div>
) : mailStatus === "quotareached" ? (
<div className="flex flex-col gap-y-3">
<QuotaCard
handleClose={() => {
setIsSend(false);
setSignerPos([]);
navigate("/report/1MwEuxLEkF");
}}
/>
<div className="my-3">{handleShareList()}</div>
</div>
) : (
<p>{t("placeholder-alert-6")}</p>
)}
{!mailStatus && (
<div className="w-full h-[1px] bg-[#9f9f9f] my-[15px]"></div>
)}
<div
className={
mailStatus === "success"
? "flex justify-center mt-1"
: ""
}
>
{isCurrUser && (
<button
onClick={() => handleRecipientSign()}
type="button"
className="op-btn op-btn-primary mr-1"
>
{t("yes")}
</button>
)}
<button
onClick={() => {
setIsSend(false);
setSignerPos([]);
navigate("/report/1MwEuxLEkF");
}}
type="button"
className="op-btn op-btn-ghost"
{mailStatus !== "quotareached" && (
<div
className={
mailStatus === "success"
? "flex justify-center mt-1"
: ""
}
>
{isCurrUser ? t("no") : t("close")}
</button>
</div>
{isCurrUser && (
<button
onClick={() => handleRecipientSign()}
type="button"
className="op-btn op-btn-primary mr-1"
>
{t("yes")}
</button>
)}
<button
onClick={() => {
setIsSend(false);
setSignerPos([]);
navigate("/report/1MwEuxLEkF");
}}
type="button"
className="op-btn op-btn-ghost"
>
{isCurrUser ? t("no") : t("close")}
</button>
</div>
)}
</div>
</ModalUi>
<ModalUi
+38 -2
View File
@@ -4,7 +4,7 @@ import checkmark from "../assets/images/checkmark.png";
import plansArr from "../json/plansArr";
import Title from "../components/Title";
import Parse from "parse";
import { openInNewTab } from "../constant/Utils";
import { openInNewTab, saveLanguageInLocal } from "../constant/Utils";
import Loader from "../primitives/Loader";
import { useTranslation } from "react-i18next";
const listItemStyle = {
@@ -119,6 +119,30 @@ const PlanSubscriptions = () => {
}
}
};
const handleLogout = async () => {
try {
Parse?.User?.logOut();
} catch (err) {
console.log("Err", err);
}
let appdata = localStorage.getItem("userSettings");
let applogo = localStorage.getItem("appLogo");
let defaultmenuid = localStorage.getItem("defaultmenuid");
let PageLanding = localStorage.getItem("PageLanding");
let baseUrl = localStorage.getItem("baseUrl");
let appid = localStorage.getItem("parseAppId");
localStorage.clear();
saveLanguageInLocal(i18n);
localStorage.setItem("appLogo", applogo);
localStorage.setItem("defaultmenuid", defaultmenuid);
localStorage.setItem("PageLanding", PageLanding);
localStorage.setItem("userSettings", appdata);
localStorage.setItem("baseUrl", baseUrl);
localStorage.setItem("parseAppId", appid);
navigate("/");
};
return (
<>
<Title title={"Subscriptions"} />
@@ -129,7 +153,13 @@ const PlanSubscriptions = () => {
) : (
<div className="overflow-y-auto max-h-full">
<div className="block my-2">
<div className="flex flex-col justify-center items-center w-full">
<div className="flex flex-col justify-center items-center w-full relative">
<button
className="md:hidden op-btn op-btn-primary op-btn-sm h-[40px] w-[250px] shadow-lg"
onClick={() => handleLogout()}
>
Log out
</button>
<div
role="tablist"
className="op-tabs op-tabs-boxed bg-base-100 my-2 shadow-lg transition-all"
@@ -150,6 +180,12 @@ const PlanSubscriptions = () => {
</a>
</div>
<ul className="op-card flex flex-col md:flex-row h-full bg-base-100 justify-center shadow-lg">
<button
className="hidden md:block -top-12 right-1 absolute w-[150px] h-[40px] op-btn op-btn-primary op-btn-sm shadow-lg"
onClick={() => handleLogout()}
>
{t("log-out")}
</button>
{plansArr.map((item) => (
<li
className="flex flex-col text-center border-collapse border-[1px] border-gray-300 max-w-[250px]"
+38 -35
View File
@@ -57,6 +57,7 @@ import PdfZoom from "../components/pdf/PdfZoom";
import Loader from "../primitives/Loader";
import { useTranslation } from "react-i18next";
import RotateAlert from "../components/RotateAlert";
import QuotaCard from "../primitives/QuotaCard";
//For signYourself inProgress section signer can add sign and complete doc sign.
function SignYourSelf() {
const { t } = useTranslation();
@@ -128,56 +129,37 @@ function SignYourSelf() {
const isHeader = useSelector((state) => state.showHeader);
const [scale, setScale] = useState(1);
const [pdfRotateBase64, setPdfRotatese64] = useState("");
const [isRotate, setIsRotate] = useState({
status: false,
degree: 0
});
const [isRotate, setIsRotate] = useState({ status: false, degree: 0 });
const [isSubscribe, setIsSubscribe] = useState({ plan: "", isValid: true });
const divRef = useRef(null);
const nodeRef = useRef(null);
const [, drop] = useDrop({
accept: "BOX",
drop: (item, monitor) => addPositionOfSignature(item, monitor),
collect: (monitor) => ({
isOver: !!monitor.isOver()
})
collect: (monitor) => ({ isOver: !!monitor.isOver() })
});
const pdfRef = useRef();
const [{ isDragSign }, dragSignature] = useDrag({
type: "BOX",
item: {
id: 1,
text: "signature"
},
collect: (monitor) => ({
isDragSign: !!monitor.isDragging()
})
item: { id: 1, text: "signature" },
collect: (monitor) => ({ isDragSign: !!monitor.isDragging() })
});
const [{ isDragStamp }, dragStamp] = useDrag({
type: "BOX",
item: {
id: 2,
text: "stamp"
},
collect: (monitor) => ({
isDragStamp: !!monitor.isDragging()
})
item: { id: 2, text: "stamp" },
collect: (monitor) => ({ isDragStamp: !!monitor.isDragging() })
});
const index = xyPostion?.findIndex((object) => {
return object.pageNumber === pageNumber;
});
// rowlevel={JSON.parse(localStorage.getItem("rowlevel"))}
const rowLevel =
localStorage.getItem("rowlevel") &&
JSON.parse(localStorage.getItem("rowlevel"));
const signObjId =
rowLevel && rowLevel?.id
? rowLevel.id
: rowLevel?.objectId && rowLevel.objectId;
const documentId = docId ? docId : signObjId && signObjId;
const senderUser =
localStorage.getItem(
@@ -217,6 +199,12 @@ function SignYourSelf() {
//function for get document details for perticular signer with signer'object id
const getDocumentDetails = async (showComplete) => {
try {
const subscribe = await checkIsSubscribed();
setIsSubscribe(subscribe);
} catch (err) {
console.log("err in fetch sub", err);
}
try {
let isCompleted;
//getting document details
@@ -585,8 +573,7 @@ function SignYourSelf() {
docCls.id = documentId;
docCls.set("Placeholders", xyPostion);
docCls.set("IsSignyourself", true);
const res = await docCls.save();
console.log("Res", res);
await docCls.save();
} catch (e) {
console.log("error", e);
alert(t("something-went-wrong-mssg"));
@@ -730,7 +717,7 @@ function SignYourSelf() {
//function for get digital signature
const signPdfFun = async (base64Url, documentId) => {
let isCustomCompletionMail = false;
const getIsSubscribe = await checkIsSubscribed();
const tenantDetails = await getTenantDetails(jsonSender.objectId);
if (tenantDetails && tenantDetails === "user does not exist!") {
alert(t("user-not-exist"));
@@ -738,7 +725,7 @@ function SignYourSelf() {
if (
tenantDetails?.CompletionBody &&
tenantDetails?.CompletionSubject &&
getIsSubscribe.isValid
isSubscribe?.isValid
) {
isCustomCompletionMail = true;
}
@@ -1255,14 +1242,29 @@ function SignYourSelf() {
<div className="w-full md:w-[95%]">
<ModalUi
isOpen={isAlert.isShow}
title={isAlert?.header || t("alert")}
title={
isAlert.alertMessage === "quotareached"
? false
: isAlert?.header || t("alert")
}
handleClose={() =>
setIsAlert({ isShow: false, alertMessage: "" })
isAlert.alertMessage === "quotareached"
? false
: setIsAlert({ isShow: false, alertMessage: "" })
}
>
<div className="p-[20px] h-full">
<p>{isAlert.alertMessage}</p>
</div>
{isAlert.alertMessage === "quotareached" ? (
<QuotaCard
isSignyourself={true}
handlClose={() =>
setIsAlert({ isShow: false, alertMessage: "" })
}
/>
) : (
<div className="p-[20px] h-full">
<p>{isAlert.alertMessage}</p>
</div>
)}
</ModalUi>
{/* this modal is used show this document is already sign */}
@@ -1342,6 +1344,7 @@ function SignYourSelf() {
setIsAlert={setIsAlert}
extUserId={extUserId}
activeMailAdapter={activeMailAdapter}
planCode={isSubscribe?.plan}
/>
{/* pdf header which contain funish back button */}
<Header
+3 -4
View File
@@ -10,7 +10,6 @@ import Tooltip from "../primitives/Tooltip";
import Loader from "../primitives/Loader";
import SubscribeCard from "../primitives/SubscribeCard";
import Tour from "reactour";
import { validplan } from "../json/plansArr";
import { useTranslation } from "react-i18next";
function Webhook() {
@@ -90,7 +89,7 @@ function Webhook() {
};
const handleModal = () => {
if (!validplan[isSubscribe.plan] && isEnableSubscription) {
if (!isSubscribe?.isValid && isEnableSubscription) {
setIsTour(true);
} else {
setIsModal(!isModal);
@@ -146,7 +145,7 @@ function Webhook() {
</div>
<ModalUi
isOpen={isModal}
title={"Regenerate Token"}
title={t("Add-Webhook")}
handleClose={handleModal}
>
{error && <Alert type="danger">{error}</Alert>}
@@ -178,7 +177,7 @@ function Webhook() {
</div>
</ModalUi>
</div>
{!validplan[isSubscribe.plan] && isEnableSubscription && (
{!isSubscribe?.isValid && isEnableSubscription && (
<div data-tut="webhooksubscribe">
<SubscribeCard plan_code={isSubscribe.plan} />
</div>
+5 -3
View File
@@ -21,9 +21,11 @@ const ModalUi = ({
>
{showHeader && (
<>
<h3 className="text-base-content font-bold text-lg pt-[15px] px-[20px]">
{title}
</h3>
{title && (
<h3 className="text-base-content font-bold text-lg pt-[15px] px-[20px]">
{title}
</h3>
)}
{showClose && (
<button
className="op-btn op-btn-sm op-btn-circle op-btn-ghost text-base-content absolute right-2 top-2"
+53
View File
@@ -0,0 +1,53 @@
import React from "react";
import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";
const QuotaCard = ({ isSignyourself, handlClose }) => {
const { t } = useTranslation();
const navigate = useNavigate();
return isSignyourself ? (
<>
<div
className="op-btn op-btn-sm op-btn-circle op-btn-ghost text-primary-content absolute right-2 top-2 z-40"
onClick={() => handlClose && handlClose()}
>
</div>
<div className="op-card op-bg-primary text-primary-content w-full shadow-lg">
<div className="op-card-body">
<h2 className="op-card-title">
{t("upgrade-to") + " Paid " + t("plan")}
</h2>
<p className="text-primary-content">{t("quotamailselfsign")}</p>
<div className="op-card-actions justify-end">
<button
onClick={() => navigate("/subscription")}
className="op-btn op-btn-accent"
>
{t("upgrade-now")}
</button>
</div>
</div>
</div>
</>
) : (
<>
<div className="op-card op-bg-primary text-primary-content w-full shadow-lg">
<div className="op-card-body">
<p className="text-primary-content">{t("quotamail")}</p>
<p className="text-primary-content">{t("quotamailTip")}</p>
<div className="op-card-actions justify-end">
<button
onClick={() => navigate("/subscription")}
className="op-btn op-btn-accent"
>
{t("upgrade-now")}
</button>
</div>
</div>
</div>
</>
);
};
export default QuotaCard;
+17 -7
View File
@@ -91,7 +91,7 @@ const saveDataFile = async (size, fileUrl, tenantPtr) => {
}
};
export const updateMailCount = async extUserId => {
export const updateMailCount = async (extUserId, plan, monthchange) => {
// Update count in contracts_Users class
const query = new Parse.Query('contracts_Users');
query.equalTo('objectId', extUserId);
@@ -100,13 +100,23 @@ export const updateMailCount = async extUserId => {
const contractUser = await query.first({ useMasterKey: true });
if (contractUser) {
contractUser.increment('EmailCount', 1);
if (plan === 'freeplan') {
if (monthchange) {
contractUser.set('LastEmailCountReset', new Date());
contractUser.set('MontlyfreeEmails', 1);
} else {
if (contractUser?.get('MontlyfreeEmails')) {
contractUser.increment('MontlyfreeEmails', 1);
if (contractUser?.get('LastEmailCountReset')) {
contractUser.set('LastEmailCountReset', new Date());
}
} else {
contractUser.set('MontlyfreeEmails', 1);
contractUser.set('LastEmailCountReset', new Date());
}
}
}
await contractUser.save(null, { useMasterKey: true });
} else {
// Create new entry if not found
const ContractsUsers = Parse.Object.extend('contracts_Users');
const newContractUser = new ContractsUsers();
newContractUser.set('EmailCount', 1);
await newContractUser.save(null, { useMasterKey: true });
}
} catch (error) {
console.log('Error updating EmailCount in contracts_Users: ' + error.message);
@@ -67,7 +67,7 @@ export default async function BuyCredits(request) {
updateSub.set('AddonCredits', addonCredits);
const resupdateSub = await updateSub.save(null, { useMasterKey: true });
// console.log('resupdateSub ', resupdateSub);
return { status: 'success', addon: addonCredits };
return { status: 'success', addon: quantity };
}
} else {
throw new Parse.Error('400', 'Invalid access token.');
@@ -142,8 +142,7 @@ export default async function sendMailGmailProvider(_extRes, template) {
raw: email,
},
});
// console.log('response ', response);
console.log('gmail provider res: ', response?.status);
return { code: 200, message: 'Email sent successfully' };
} catch (error) {
console.error('Error sending email:', error);
@@ -6,7 +6,7 @@ import Mailgun from 'mailgun.js';
import { smtpenable, smtpsecure, updateMailCount, useLocal } from '../../Utils.js';
import sendMailGmailProvider from './sendMailGmailProvider.js';
import { createTransport } from 'nodemailer';
async function sendMailProvider(req) {
async function sendMailProvider(req, plan, monthchange) {
const mailgunApiKey = process.env.MAILGUN_API_KEY;
try {
let transporterSMTP;
@@ -69,18 +69,23 @@ async function sendMailProvider(req) {
};
let attachment;
// `certificateBuffer` used to create buffer from pdf file
try {
const certificateBuffer = fs.readFileSync('./exports/certificate.pdf');
const certificate = {
filename: 'certificate.pdf',
content: smtpenable ? certificateBuffer : undefined, //fs.readFileSync('./exports/exported_file_1223.pdf'),
data: smtpenable ? undefined : certificateBuffer,
};
attachment = [file, certificate];
} catch (err) {
const certificatePath = './exports/certificate.pdf';
if (fs.existsSync(certificatePath)) {
try {
// `certificateBuffer` used to create buffer from pdf file
const certificateBuffer = fs.readFileSync(certificatePath);
const certificate = {
filename: 'certificate.pdf',
content: smtpenable ? certificateBuffer : undefined, //fs.readFileSync('./exports/exported_file_1223.pdf'),
data: smtpenable ? undefined : certificateBuffer,
};
attachment = [file, certificate];
} catch (err) {
attachment = [file];
console.log('Err in read certificate sendmailv3', err);
}
} else {
attachment = [file];
console.log('Err in read certificate sendmailv3', err);
}
const from = req.params.from || '';
const mailsender = smtpenable ? process.env.SMTP_USER_EMAIL : process.env.MAILGUN_SENDER;
@@ -96,38 +101,44 @@ async function sendMailProvider(req) {
};
if (transporterSMTP) {
const res = await transporterSMTP.sendMail(messageParams);
console.log('Res ', res);
console.log('smtp transporter res: ', res?.response);
if (!res.err) {
if (req.params?.extUserId) {
await updateMailCount(req.params.extUserId);
await updateMailCount(req.params.extUserId, plan, monthchange);
}
try {
fs.unlinkSync('./exports/certificate.pdf');
} catch (err) {
console.log('Err in unlink certificate sendmailv3');
if (fs.existsSync(certificatePath)) {
try {
fs.unlinkSync(certificatePath);
} catch (err) {
console.log('Err in unlink certificate sendmailv3');
}
}
return { status: 'success' };
}
} else {
if (mailgunApiKey) {
const res = await mailgunClient.messages.create(mailgunDomain, messageParams);
console.log('Res ', res);
console.log('mailgun res: ', res?.status);
if (res.status === 200) {
if (req.params?.extUserId) {
await updateMailCount(req.params.extUserId);
await updateMailCount(req.params.extUserId, plan, monthchange);
}
try {
fs.unlinkSync('./exports/certificate.pdf');
} catch (err) {
console.log('Err in unlink certificate sendmailv3');
if (fs.existsSync(certificatePath)) {
try {
fs.unlinkSync(certificatePath);
} catch (err) {
console.log('Err in unlink certificate sendmailv3');
}
}
return { status: 'success' };
}
} else {
try {
fs.unlinkSync('./exports/certificate.pdf');
} catch (err) {
console.log('Err in unlink certificate sendmailv3');
if (fs.existsSync(certificatePath)) {
try {
fs.unlinkSync(certificatePath);
} catch (err) {
console.log('Err in unlink certificate sendmailv3');
}
}
return { status: 'error' };
}
@@ -147,20 +158,20 @@ async function sendMailProvider(req) {
if (transporterSMTP) {
const res = await transporterSMTP.sendMail(messageParams);
console.log('Res ', res);
console.log('smtp transporter res: ', res?.response);
if (!res.err) {
if (req.params?.extUserId) {
await updateMailCount(req.params.extUserId);
await updateMailCount(req.params.extUserId, plan, monthchange);
}
return { status: 'success' };
}
} else {
if (mailgunApiKey) {
const res = await mailgunClient.messages.create(mailgunDomain, messageParams);
console.log('Res ', res);
console.log('mailgun res: ', res?.status);
if (res.status === 200) {
if (req.params?.extUserId) {
await updateMailCount(req.params.extUserId);
await updateMailCount(req.params.extUserId, plan, monthchange);
}
return { status: 'success' };
}
@@ -180,6 +191,7 @@ async function sendmailv3(req) {
const mailProvider = req.params.mailProvider || 'default';
if (mailProvider) {
try {
const Plan = req.params.plan;
const extUserId = req.params.extUserId || '';
const pdfName = req.params.pdfName || '';
const template = {
@@ -203,8 +215,31 @@ async function sendmailv3(req) {
return { status: 'error' };
}
} else {
const nonCustomMail = await sendMailProvider(req);
return nonCustomMail;
if (Plan && Plan === 'freeplan') {
let MontlyfreeEmails = _extRes?.MontlyfreeEmails || 0;
if (_extRes?.LastEmailCountReset?.iso) {
const lastDate = new Date(_extRes?.LastEmailCountReset?.iso);
const newDate = new Date();
const isMonthChange = newDate.getMonth() > lastDate.getMonth();
if (isMonthChange) {
const nonCustomMail = await sendMailProvider(req, Plan, true);
return nonCustomMail;
} else {
if (MontlyfreeEmails >= 20) {
return { status: 'quota-reached' };
} else {
const nonCustomMail = await sendMailProvider(req, Plan);
return nonCustomMail;
}
}
} else {
const nonCustomMail = await sendMailProvider(req, Plan);
return nonCustomMail;
}
} else {
const nonCustomMail = await sendMailProvider(req, '');
return nonCustomMail;
}
}
}
} catch (err) {
+1 -1
View File
@@ -9,7 +9,7 @@ services:
env_file: .env.prod
environment:
- NODE_ENV=production
- SERVER_URL=${HOST_URL:-https://localhost:3001/app}
- SERVER_URL=${HOST_URL:-https://localhost:3001}/app
networks:
- app-network
mongo: