Files
Sathira Sri Sathara f920ca8920
CI / test (push) Successful in 10m22s
CI / test (pull_request) Successful in 10m53s
feat: Implement Phase 10 support and recommendations features
- Added models for support messages, SLA policies, tickets, ticket events, and ticket links.
- Created routes for help, help admin, newsletter, recommendations, and support for both customer and admin.
- Developed services for help, marketing (newsletter), and recommendations.
- Introduced support service for ticket management, including creation, replies, transitions, and attachments.
- Added validation schemas for support recommendations and ticket management.
- Implemented a cron job for support reconciliation and recommendation cleanup.
- Created migration for new support and recommendation database tables.
- Added unit tests for validation and policy checks related to Phase 10 features.
2026-09-09 16:07:31 +05:30

2 lines
1.4 KiB
JavaScript

const crypto=require("crypto"),db=require("../../models");const hash=x=>crypto.createHash("sha256").update(x).digest("hex"),normalize=x=>x.trim().toLowerCase();async function subscribe({email,locale,source,userId}){const normalized=normalize(email),token=crypto.randomBytes(32).toString("base64url");return db.sequelize.transaction(async t=>{let row=await db.NewsletterSubscription.findOne({where:{email_normalized:normalized},transaction:t,lock:t.LOCK.UPDATE});if(row?.status==="SUBSCRIBED")return{subscription:row,idempotent:true};if(row)await row.update({status:"SUBSCRIBED",locale,source,user_id:row.user_id||userId||null,consented_at:new Date(),confirmed_at:new Date(),unsubscribed_at:null,unsubscribe_token_hash:hash(token)},{transaction:t});else row=await db.NewsletterSubscription.create({id:crypto.randomUUID(),email_normalized:normalized,user_id:userId||null,status:"SUBSCRIBED",locale,source,consented_at:new Date(),confirmed_at:new Date(),unsubscribe_token_hash:hash(token)},{transaction:t});return{subscription:row,idempotent:false,unsubscribeToken:token};});}async function unsubscribe(token){const row=await db.NewsletterSubscription.findOne({where:{unsubscribe_token_hash:hash(token)}});if(!row)return false;if(row.status!=="UNSUBSCRIBED")await row.update({status:"UNSUBSCRIBED",unsubscribed_at:new Date()});return true;}module.exports={subscribe,unsubscribe,normalize,hash};