1import{a_ as b}from"./api-By18TgAG.js";import{A as Y}from"./public-shell-B_x5oatf.js";import{_ as q}from"./AppPageLayout-Bh1yRcus.js";import{_ as z}from"./AdminMobileNavDropdown-C0WpnzE-.js";import{b as o,c as P,D as H,o as d,m as W,y as $,e as n,f as e,z as s,q as g,F as T,k as S,j as x,A as Z}from"./vue-1AtMcz7l.js";import"./axios-CH-jSbCW.js";import"./content-CdKKYwFJ.js";import"./guestSession-DuFht6JD.js";import"./mixpanel-DT0Ikp3G.js";import"./timezone-C1WFMaLm.js";import"./vue-router-BL0W4KYo.js";import"./Sidebar-BIa60X3P.js";import"./usePressOrLongPress-Bo2AzNjN.js";import"./notesListScopeCache-BTTJbRCz.js";import"./useNoteLock-DAH1Drl9.js";import"./reminderNotificationPlatformCopy-Lh4Xwm6U.js";import"./reminderNotificationSupport-DrOlugB6.js";import"./nativeReminderNotifications-WBUuc_UT.js";import"./useSearchDialog-PJA20_B2.js";import"./useNotesLayoutUi-rLFSmLjJ.js";import"./adminNavItems-BdRUj1aQ.js";(function(){try{var c=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{};c.SENTRY_RELEASE={id:"8ed42405eab16ca6f21c30b45346c6f30a2e6f72"};var m=new c.Error().stack;m&&(c._sentryDebugIds=c._sentryDebugIds||{},c._sentryDebugIds[m]="c2928c07-c75c-4b18-abdb-693ead83a99b",c._sentryDebugIdIdentifier="sentry-dbid-c2928c07-c75c-4b18-abdb-693ead83a99b")}catch{}})();const J={key:0,class:"flex justify-center items-center py-12"},Q={key:1,class:"bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg p-4 mb-6"},X={class:"text-red-800 dark:text-red-200"},ee={key:2,class:"space-y-6"},te={class:"card p-6"},ae={key:0,class:"mb-6 rounded-lg border border-amber-200 dark:border-amber-800 bg-amber-50 dark:bg-amber-900/20 px-4 py-3 text-sm text-amber-900 dark:text-amber-100"},re={key:1,class:"mb-6 rounded-lg border border-amber-200 dark:border-amber-800 bg-amber-50 dark:bg-amber-900/20 px-4 py-3 text-sm text-amber-900 dark:text-amber-100"},se={class:"space-y-5"},de={class:"min-w-0"},ne={class:"flex flex-wrap items-center gap-2"},ie={class:"text-sm font-medium text-gray-900 dark:text-gray-100"},oe={class:"text-[11px] font-medium uppercase tracking-wide text-gray-500 dark:text-gray-400 bg-gray-100 dark:bg-gray-800 px-2 py-0.5 rounded"},le={class:"text-xs text-gray-500 dark:text-gray-400 mt-1"},ue=["aria-checked","aria-label","disabled","onClick"],ce={class:"card p-6"},ye={class:"flex flex-wrap items-start justify-between gap-3 mb-4"},ge=["disabled"],me={key:0,class:"mb-4 rounded-lg border border-red-200 dark:border-red-800 bg-red-50 dark:bg-red-900/20 px-4 py-3 text-sm text-red-800 dark:text-red-200"},pe={key:1,class:"text-sm text-gray-500 dark:text-gray-400 py-4"},be={key:2,class:"text-sm text-gray-500 dark:text-gray-400 py-4"},xe={key:3,class:"space-y-3"},fe=["onClick"],ve={class:"flex flex-wrap items-center justify-between gap-2"},he={class:"flex flex-wrap items-center gap-2"},ke={class:"text-sm font-medium text-gray-900 dark:text-gray-100"},_e={class:"text-[11px] text-gray-500 dark:text-gray-400"},we={class:"text-xs text-gray-500 dark:text-gray-400"},Re={key:4,class:"mt-5 border-t border-gray-200 dark:border-gray-700 pt-5"},Ee={class:"text-sm font-semibold text-gray-900 dark:text-gray-100 mb-3"},Ae={class:"grid grid-cols-2 sm:grid-cols-3 gap-3 mb-4 text-sm"},De={class:"rounded-lg bg-gray-50 dark:bg-gray-900/40 px-3 py-2"},Ce={class:"font-semibold text-gray-900 dark:text-gray-100"},Pe={class:"rounded-lg bg-gray-50 dark:bg-gray-900/40 px-3 py-2"},Te={class:"font-semibold text-gray-900 dark:text-gray-100"},Se={class:"rounded-lg bg-gray-50 dark:bg-gray-900/40 px-3 py-2"},Ue={class:"font-semibold text-gray-900 dark:text-gray-100"},Ie={class:"rounded-lg bg-gray-50 dark:bg-gray-900/40 px-3 py-2"},Ne={class:"font-semibold text-gray-900 dark:text-gray-100"},Fe={class:"rounded-lg bg-gray-50 dark:bg-gray-900/40 px-3 py-2"},Le={class:"font-semibold text-gray-900 dark:text-gray-100"},$e={class:"rounded-lg bg-gray-50 dark:bg-gray-900/40 px-3 py-2"},Be={class:"font-semibold text-gray-900 dark:text-gray-100"},je={class:"rounded-lg bg-gray-50 dark:bg-gray-900/40 px-3 py-2"},Me={class:"font-semibold text-gray-900 dark:text-gray-100"},Ve={class:"rounded-lg bg-gray-50 dark:bg-gray-900/40 px-3 py-2"},Oe={class:"font-semibold text-gray-900 dark:text-gray-100"},Ge={key:0,class:"mb-3 text-sm text-red-600 dark:text-red-400"},Ke={key:1,class:"text-sm text-gray-500 dark:text-gray-400 py-2"},Ye={key:2,class:"text-sm text-gray-500 dark:text-gray-400 py-2"},qe={key:3,class:"space-y-2 max-h-96 overflow-y-auto"},ze={class:"flex flex-wrap items-center gap-2 mb-1"},He={class:"text-xs text-gray-500 dark:text-gray-400"},We={key:0,class:"text-xs text-emerald-600 dark:text-emerald-400"},Ze={class:"text-gray-900 dark:text-gray-100"},ft={__name:"AdminDailyCron",setup(c){const{showSuccess:m,showError:f}=Y(),_=o(!0),v=o(null),w=o(null),R=o(!0),l=o({usageAlertEmails:null,reminderPush:null}),u=o({usageCacheRefresh:!0,trashCleanup:!0,usageAlertEmails:!1,accountDeleti
1on:!0,userTrends:!0,paymentReconciliation:!0,reminderPush:!0}),h=o(!1),p=o(null),y=o([]),E=o(null),i=o(null),A=o(!1),k=o(!1),U=P(()=>[{key:"usageCacheRefresh",title:"Usage cache refresh",schedule:"Daily · 00:00 UTC",description:"Recomputes subscription usage for all users and stores snapshots in Redis.",disabled:!1},{key:"trashCleanup",title:"Trash cleanup",schedule:"Daily · 00:00 UTC",description:"On every regional datacenter: permanently deletes trashed notes past each planâs retention period, removes their attached files, and purges orphaned note media not linked to any note.",disabled:!1},{key:"usageAlertEmails",title:"Usage limit alert emails",schedule:"Daily · 00:00 UTC",description:"Sends one-time 90% warning and 100% danger emails when notes count or total storage limits are reached (blocks new note creation). Disabled by default.",disabled:l.value.usageAlertEmails==="false"||l.value.usageAlertEmails==="true"},{key:"accountDeletion",title:"Account deletion",schedule:"Daily · 00:00 UTC",description:"Sends a reminder email one day before deletion, permanently deletes accounts after the grace period, then sends a confirmation email.",disabled:!1},{key:"paymentReconciliation",title:"Payment / subscription reconciliation",schedule:"Daily · 00:00 UTC",description:"Refunds duplicate charges, cancels stale checkouts, marks missed renewals as past due, retries stuck refunds, and expires subscriptions after the 7-day past-due grace period.",disabled:!1},{key:"userTrends",title:"User trends snapshot",schedule:"Daily · 00:00 UTC",description:"Precomputes admin user metrics and successful-payment revenue for the prior UTC day and stores them for the User Management charts.",disabled:!1},{key:"reminderPush",title:"Reminder push delivery",schedule:"Every minute",description:"On every regional datacenter: delivers due note and checklist reminders via Web Push to subscribed devices. Requires VAPID keys on each regional API.",disabled:!R.value||l.value.reminderPush==="false"||l.value.reminderPush==="true"}]),I=P(()=>{const t=[];return l.value.usageAlertEmails==="false"?t.push("Usage alert emails are forced off by USAGE_ALERT_EMAILS_ENABLED=false. Remove that override to control them here."):l.value.usageAlertEmails==="true"&&t.push("Usage alert emails are forced on by USAGE_ALERT_EMAILS_ENABLED=true."),l.value.reminderPush==="false"?t.push("Reminder push is forced off by REMINDER_PUSH_CRON_ENABLED=false. Remove that override to control them here."):l.value.reminderPush==="true"&&t.push("Reminder push is forced on by REMINDER_PUSH_CRON_ENABLED=true."),t.length>0?t.join(" "):null}),N=P(()=>R.value?null:"Reminder push delivery is unavailable because VAPID keys are not configured on regional APIs (VAPID_PUBLIC_KEY / VAPID_PRIVATE_KEY).");function F(t){if(!t)return"â";try{return new Intl.DateTimeFormat(void 0,{dateStyle:"medium",timeStyle:"short",timeZone:"UTC"}).format(new Date(t))+" UTC"}catch{return String(t)}}function B(t){return Number.isFinite(t)?t<1e3?`${t} ms`:`${(t/1e3).toFixed(1)} s`:"â"}function j(t){return t==="completed"?"bg-emerald-100 dark:bg-emerald-900/40 text-emerald-800 dark:text-emerald-200":t==="failed"?"bg-red-100 dark:bg-red-900/40 text-red-800 dark:text-red-200":t==="running"?"bg-amber-100 dark:bg-amber-900/40 text-amber-800 dark:text-amber-200":"bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-300"}function M(t){return t==="fixed"?"bg-emerald-100 dark:bg-emerald-900/40 text-emerald-800 dark:text-emerald-200":t==="error"?"bg-red-100 dark:bg-red-900/40 text-red-800 dark:text-red-200":t==="warning"?"bg-amber-100 dark:bg-amber-900/40 text-amber-800 dark:text-amber-200":"bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-300"}const V=async()=>{try{_.value=!0,v.value=null;const t=await b.getDailyCronSettings();u.value={...u.value,...t.subprocesses||{}},l.value=t.envOverrides||{},R.value=t.reminderPushAvailable!==!1}catch(t){v.value=t.response?.data?.error||"Failed to load cron settings"}finally{_.value=!1}},L=async()=>{try{h.value=!0,p.value=null;const t=await b.getPaymentReconciliationAudits({limit:20});y.value=t.runs||[],!E.value&&y.value[0]&&await D(y.value[0].id)}catch(t){p.value=t.response?.data?.error||"Failed to load reconciliation audits"}finally{h.value=!1}},D=async t=>{E.value=t,A.value=!0;try{const r=await b.getPaymentReconciliationAudit(t);i.value={...r.run||null,issues:r.issues||[]}}catch(r){f(r.response?.data?.error||"Failed to load run detail"),i.value=y.value.find(a=>a.id===t)||null}finally{A.value=!1}},O=async()=>{try{k.value=!0,p.value=null;const t=await b.runPaymentReconciliation();m(`Reconciliation finished: ${t.issuesFixed||0} fixed, ${t.issuesFound||0} issues found`),await L(),t.runId&&await D(t.runId)}catch(t){f(t.response?.data?.error||"Reconciliation failed")}finally{k.value=!1}},G=async t=>{const r=!u.value[t];try{w.value=t;const a=await b.updateDailyCronSettings({[t]:r});u.value={...u.value,...a.subprocesses||{}},m(`${K(t)} ${r?"enabled":"disabled"}`)}catch(a){f(a.response?.data?.error||"Failed to update cron settings")}finally{w.value=null}},K=t=>U.value.find(a=>a.key===t)?.title||t;return H(async()=>{await V(),await L()}),(t,r)=>(d(),W(q,{title:"Cron","show-sidebar":!1,"account-manage-chrome":!0,"wide-content":!0},{"header-actions":$(()=>[Z(z)]),default:$(()=>[_.value?(d(),n("div",J,[...r[0]||(r[0]=[e("div",{class:"text-gray-600 dark:text-gray-400"},"Loading cron settings...",-1)])])):v.value?(d(),n("div",Q,[e("p",X,s(v.value),1)])):(d(),n("div",ee,[e("div",te,[r[1]||(r[1]=e("h2",{class:"text-xl font-bold text-gray-900 dark:text-gray-100 mb-1"},"Scheduled jobs",-1)),r[2]||(r[2]=e("p",{class:"text-sm text-gray-600 dark:text-gray-400 mb-6"}," Enable or disable background cron jobs below. Settings are stored on central and apply to every regional datacenter (trash cleanup and reminder push). Daily batch jobs run together at 00:00 UTC. Reminder push runs every minute. ",-1)),I.value?(d(),n("div",ae,s(I.value),1)):g("",!0),N.value?(d(),n("div",re,s(N.value),1)):g("",!0),e("div",se,[(d(!0),n(T,null,S(U.value,a=>(d(),n("div",{key:a.key,class:"flex items-start justify-between gap-4 pb-5 border-b border-gray-200 dark:border-gray-700 last:border-b-0 last:pb-0"},[e("div",de,[e("div",ne,[e("p",ie,s(a.title),1),e("span",oe,s(a.schedule),1)]),e("p",le,s(a.description),1)]),e("button",{type:"button",role:"switch","aria-checked":u.value[a.key],"aria-label":`${a.title} ${u.value[a.key]?"enabled":"disabled"}`,disabled:w.value===a.key||a.disabled,class:x(["relative inline-flex h-6 w-11 shrink-0 items-center rounded-full transition-colors duration-200 disabled:opacity-50",u.value[a.key]?"bg-xn-primary":"bg-gray-300 dark:bg-gray-600"]),onClick:C=>G(a.key)},[e("span",{class:x(["inline-block h-5 w-5 transform rounded-full bg-white shadow transition-transform duration-200",u.value[a.key]?"translate-x-5":"translate-x-0.5"])},null,2)],10,ue)]))),128))])]),e("div",ce,[e("div",ye,[r[3]||(r[3]=e("div",null,[e("h2",{class:"text-xl font-bold text-gray-900 dark:text-gray-100 mb-1"},"Payment reconciliation audit"),e("p",{class:"text-sm text-gray-600 dark:text-gray-400"}," Daily 00:00 UTC scan of missed plan-change refunds, missed renew
1als, expired subscriptions still marked active, and other payment issues. Fixes are applied when safe; everything is logged here. ")],-1)),e("button",{type:"button",class:"inline-flex items-center justify-center px-3 py-2 rounded-lg bg-xn-primary text-white text-sm font-medium hover:bg-xn-primary-dark disabled:opacity-60",disabled:k.value||h.value,onClick:O},s(k.value?"Runningâ¦":"Run now"),9,ge)]),p.value?(d(),n("div",me,s(p.value),1)):g("",!0),h.value?(d(),n("div",pe," Loading audit history⦠")):y.value.length===0?(d(),n("div",be," No reconciliation runs yet. The next daily cron (00:00 UTC) will create the first audit, or use Run now. ")):(d(),n("div",xe,[(d(!0),n(T,null,S(y.value,a=>(d(),n("button",{key:a.id,type:"button",class:x(["w-full text-left rounded-lg border border-gray-200 dark:border-gray-700 px-4 py-3 hover:border-xn-primary/50 transition-colors",E.value===a.id?"border-xn-primary bg-xn-primary/5":""]),onClick:C=>D(a.id)},[e("div",ve,[e("div",he,[e("span",ke,s(F(a.startedAt)),1),e("span",{class:x(["text-[11px] font-medium uppercase tracking-wide px-2 py-0.5 rounded",j(a.status)])},s(a.status),3),e("span",_e,s(a.trigger==="manual"?"Manual":"Daily cron"),1)]),e("span",we,s(a.summary?.issuesFound||0)+" issues · "+s(a.summary?.issuesFixed||0)+" fixed ",1)])],10,fe))),128))])),i.value?(d(),n("div",Re,[e("h3",Ee," Run detail · "+s(F(i.value.startedAt)),1),e("div",Ae,[e("div",De,[r[4]||(r[4]=e("p",{class:"text-xs text-gray-500 dark:text-gray-400"},"Duplicate charges refunded",-1)),e("p",Ce,s(i.value.summary?.duplicateRefunds??0),1)]),e("div",Pe,[r[5]||(r[5]=e("p",{class:"text-xs text-gray-500 dark:text-gray-400"},"Stale pending cancelled",-1)),e("p",Te,s(i.value.summary?.stalePendingCancelled??0),1)]),e("div",Se,[r[6]||(r[6]=e("p",{class:"text-xs text-gray-500 dark:text-gray-400"},"Missed renewals â past due",-1)),e("p",Ue,s(i.value.summary?.missedRenewalsMarkedPastDue??0),1)]),e("div",Ie,[r[7]||(r[7]=e("p",{class:"text-xs text-gray-500 dark:text-gray-400"},"Grace periods expired",-1)),e("p",Ne,s(i.value.summary?.graceExpired??0),1)]),e("div",Fe,[r[8]||(r[8]=e("p",{class:"text-xs text-gray-500 dark:text-gray-400"},"Stuck refunds retried",-1)),e("p",Le,s(i.value.summary?.stuckRefundsRetried??0),1)]),e("div",$e,[r[9]||(r[9]=e("p",{class:"text-xs text-gray-500 dark:text-gray-400"},"Expired â free backfill",-1)),e("p",Be,s(i.value.summary?.expiredBackfilledToFree??0),1)]),e("div",je,[r[10]||(r[10]=e("p",{class:"text-xs text-gray-500 dark:text-gray-400"},"Success without activation refunded",-1)),e("p",Me,s(i.value.summary?.successWithoutActivationRefunds??0),1)]),e("div",Ve,[r[11]||(r[11]=e("p",{class:"text-xs text-gray-500 dark:text-gray-400"},"Duration",-1)),e("p",Oe,s(B(i.value.durationMs)),1)])]),i.value.error?(d(),n("p",Ge,s(i.value.error),1)):g("",!0),A.value?(d(),n("div",Ke," Loading issues⦠")):i.value.issues&&i.value.issues.length?(d(),n("ul",qe,[(d(!0),n(T,null,S(i.value.issues,(a,C)=>(d(),n("li",{key:`${a.issueType}-${C}`,class:"rounded-lg border border-gray-200 dark:border-gray-700 px-3 py-2 text-sm"},[e("div",ze,[e("span",{class:x(["text-[11px] font-medium uppercase tracking-wide px-2 py-0.5 rounded",M(a.severity)])},s(a.severity||"info"),3),e("span",He,s(a.issueType),1),a.corrected?(d(),n("span",We,"corrected")):g("",!0)]),e("p",Ze,s(a.message),1)]))),128))])):(d(),n("div",Ye," No issues recorded in this run. "))])):g("",!0)])]))]),_:1}))}};export{ft as default};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.