| 1 |
import{h as k,l as L,v as ae,i as oe,c as E,w as u,r as b,o as y,d as w,a as i,f as C,t as h,u as d,e as F,b as B,n as N,F as ne,g as se}from"./vue.esm-bundler.js?ver=1.6.3";import{_ as le}from"./UserCan.js?ver=1.6.3";import{_ as ie}from"./DynamicIcon.js?ver=1.6.3";import{b as ue,C as ce,a as _e}from"./CardBody.js?ver=1.6.3";import{_ as pe}from"./_plugin-vue_export-helper.js?ver=1.6.3";import{P as me,_ as de}from"./Empty.js?ver=1.6.3";import{t as s}from"./Translator.js?ver=1.6.3";import{R}from"./Rest.js?ver=1.6.3";import{C as fe}from"./CurrencyFormatter.js?ver=1.6.3";import{E as ve}from"../app.js";import{$ as he,j as A,h as I,a as V}from"./common.js?ver=1.6.3";import"./Arr.js?ver=1.6.3";import"./vue-router.js?ver=1.6.3";import"./dayjs.min.js?ver=1.6.3";import"./Badge.js?ver=1.6.3";import"./Model.js?ver=1.6.3";import"./Url.js?ver=1.6.3";import"./Str.js?ver=1.6.3";import"./timezone.js?ver=1.6.3";import"./Notify.js?ver=1.6.3";import"./index.js?ver=1.6.3";import"./index3.js?ver=1.6.3";import"./IconButton.js?ver=1.6.3";import"./Utils.js?ver=1.6.3";import"./TransitionAccordion.js?ver=1.6.3";import"./OrderCustomerInformation.js?ver=1.6.3";import"./Animation.js?ver=1.6.3";import"./Asset.js?ver=1.6.3";import"./AddressComponent2.js?ver=1.6.3";import"./NotFound.js?ver=1.6.3";import"./productService.js?ver=1.6.3";import"./Activity.js?ver=1.6.3";import"./BundleProducts.js?ver=1.6.3";import"./dateShortCuts.js?ver=1.6.3";import"./index4.js?ver=1.6.3";import"./countries.js?ver=1.6.3";import"./index2.js?ver=1.6.3";import"./AttrGroups.js?ver=1.6.3";import"./DynamicTemplateParser.js?ver=1.6.3";import"./ProductVariationSelector.js?ver=1.6.3";import"./FileUploaderDialog.js?ver=1.6.3";import"./Screenshot.js?ver=1.6.3";import"./useElementPlusComponents.js?ver=1.6.3";const ge={class:"fct-cohort-report-page"},we={class:"page-title"},be={class:"fct-cohort-settings"},ye={class:"fct-cohort-settings-group"},$e={class:"flex gap-2 items-center"},ke={key:0,class:"px-4 pb-4"},Ce=["innerHTML"],xe={__name:"Cohort",props:{reportFilter:{type:Object,required:!0}},setup(P){const T=P.reportFilter,g=k({cohorts:[],weighted_averages:[],group_by:"year",metric:"subscribers"}),m=k(!0),f=k("year"),n=k("subscribers"),p=k("percent"),W=k(12),M=L(()=>!g.value.cohorts||g.value.cohorts.length===0),j=L(()=>{var t;if(M.value)return[];const e=[];if(g.value.cohorts.forEach(r=>{const a={cohort:r.cohort,start_value:n.value==="mrr"?r.start_mrr:r.start_count};r.periods.forEach((o,l)=>{const _=l+1,v=f.value==="year"?`year_${_}`:`month_${_}`;n.value==="mrr"?(a[`${v}_retained`]=o.retained_mrr,a[`${v}_retention_rate`]=o.retention_rate_mrr):(a[`${v}_retained`]=o.retained_count,a[`${v}_retention_rate`]=o.retention_rate_count)}),e.push(a)}),((t=g.value.weighted_averages)==null?void 0:t.length)>0){const r={cohort:"Weighted Average",start_value:"-"};g.value.weighted_averages.forEach((a,o)=>{const l=o+1,_=f.value==="year"?`year_${l}`:`month_${l}`;r[`${_}_retained`]="-",r[`${_}_retention_rate`]=n.value==="mrr"?a.weighted_avg_mrr:a.weighted_avg_count}),e.push(r)}return e}),H=L(()=>{var t;if(M.value)return[];const e=[];if(g.value.cohorts.forEach(r=>{const a={cohort:r.cohort,cohort_label:U(r.cohort),start_value:K(r),start_mrr:r.start_mrr,start_count:r.start_count,is_weighted_avg:!1};r.periods.forEach((o,l)=>{const _=l+1;if(a[`period_${_}`]=z(o),a[`period_${_}_data`]=o,z(o)){let v="";if(n.value==="mrr"?v=`<strong>${o.retention_rate_mrr}%</strong> (${D(o.retained_mrr)}) of ${D(r.start_mrr)} remains`:v=`<strong>${o.retention_rate_count}%</strong> (${o.retained_count}) of ${r.start_count} remains`,o.churned_mrr>0||o.churned_count>0){const S=n.value==="mrr"?D(o.churned_mrr):o.churned_count;v+=`<div class="mt-1 text-gray-400">${S} churned in this period</div>`}a[`period_${_}_tooltip`]=v}}),e.push(a)}),((t=g.value.weighted_averages)==null?void 0:t.length)>0){const r={cohort:"weighted_avg",cohort_label:s("Weighted Avg. Retained"),start_value:"",is_weighted_avg:!0};g.value.weighted_averages.forEach((a,o)=>{const l=o+1;r[`period_${l}`]=Q(a),r[`period_${l}_data`]=a,r[`period_${l}_is_weighted`]=!0}),e.push(r)}return e}),J=({row:e,column:t,rowIndex:r,columnIndex:a})=>{const o=a-1,l=e[`period_${o}_data`];return l?e.is_weighted_avg?Z(l):X(l):{}},O=({row:e,rowIndex:t})=>e.is_weighted_avg?"weighted-average-row":"cohort-row",Y=({row:e,column:t,rowIndex:r,columnIndex:a})=>{if(e.is_weighted_avg){if(a===0)return{rowspan:1,colspan:2};if(a===1)return{rowspan:0,colspan:0}}return{rowspan:1,colspan:1}},x=(e=null)=>{m.value=!0;const t=T.applicableFilters.params;R.get("reports/subscription-cohorts",{params:{...t,groupBy:f.value,metric:n.value}}).then(r=>{g.value=r,r.max_periods&&(W.value=r.max_periods)}).finally(()=>m.value=!1)},G=e=>({month:`Month ${e}`,week:`Week ${e}`,year:`Year ${e}`})[f.value]||`Period ${e}`,q=(e,t)=>{const r=new Date(e,0,4),a=r.getDay()||7,o=new Date(r);o.setDate(r.getDate()-a+1);const l=new Date(o);l.setDate(o.getDate()+(t-1)*7);const _=new Date(l);return _.setDate(l.getDate()+6),_},U=e=>{const t=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];if(f.value==="month"){const[r,a]=e.split("-");return`${t[parseInt(a)-1]} ${r}`}else if(f.value==="week"){const[r,a]=e.split("-"),o=q(parseInt(r),parseInt(a)),l=t[o.getMonth()],_=o.getDate();return`${l} ${_}, ${o.getFullYear()}`}return e},K=e=>n.value==="mrr"?D(e.start_mrr):e.start_count.toLocaleString(),D=e=>fe.scaled(e),z=e=>{if(p.value==="percent"){const t=n.value==="mrr"?e.retention_rate_mrr:e.retention_rate_count;return t==null?"":`${t}%`}else if(p.value==="percent_previous"){const t=n.value==="mrr"?e.retention_rate_previous_mrr:e.retention_rate_previous_count;return t==null?"":`${t}%`}else if(p.value==="value"){const t=n.value==="mrr"?e.retained_mrr:e.retained_count;return t==null?"":n.value==="mrr"?D(t):t.toLocaleString()}else if(p.value==="percent_ended"){const t=n.value==="mrr"?e.churn_rate_total_mrr:e.churn_rate_total_count;return t==null?"":`${t}%`}return""},Q=e=>p.value==="percent"?`${n.value==="mrr"?e.weighted_avg_mrr:e.weighted_avg_count}%`:p.value==="percent_previous"?`${n.value==="mrr"?e.weighted_avg_prev_mrr:e.weighted_avg_prev_count}%`:p.value==="value"?`${n.value==="mrr"?e.weighted_avg_mrr:e.weighted_avg_count}%`:p.value==="percent_ended"?`${n.value==="mrr"?e.weighted_avg_churn_mrr:e.weighted_avg_churn_count}%`:"-",X=e=>{let t;if(p.value==="percent_ended"?t=n.value==="mrr"?e.churn_rate_total_mrr:e.churn_rate_total_count:p.value==="percent_previous"?t=n.value==="mrr"?e.retention_rate_previous_mrr:e.retention_rate_previous_count:(p.value,t=n.value==="mrr"?e.retention_rate_mrr:e.retention_rate_count),t==null||t===0)return{};const a=Math.floor(t/5)*5/100;return{backgroundColor:`rgba(51, 92, 255, ${a})`,color:a>.5?"#ffffff":"#1f2937"}},Z=e=>{let t;p.value==="percent_ended"?t=n.value==="mrr"?e.weighted_avg_churn_mrr:e.weighted_avg_churn_count:p.value==="percent_previous"?t=n.value==="mrr"?e.weighted_avg_prev_mrr:e.weighted_avg_prev_count:t=n.value==="mrr"?e.weighted_avg_mrr:e.weighted_avg_count;const a=Math.floor(t/5)*5/100;return{backgroundColor:`rgba(51, 92, 255, ${a})`,color:a>.5?"#ffffff":"#1f2937"}},ee=async()=>{he(s("This will regenerate all retention snapshots. This may take 30-60 seconds."),s("Please confirm"),{confirmButtonText:s("Continue"),cancelButtonText:s("Cancel"),type:"warning"}).then(async()=>{m.value=!0;try{const e=await R.post("reports/retention-snapshots/generate");e.success&&e.mode==="background"?(A(s("Snapshot generation started in background!")),te(e.job_id)):e.success&&e.mode==="synchronous"?(I(s("Snapshots generated successfully!")),m.value=!1,await x()):(V(e.message||s("Failed to generate snapshots!")),m.value=!1)}catch{V(s("Error generating snapshots")),m.value=!1}}).catch(()=>{})},te=async e=>{let r=0;const a=async()=>{try{const o=await R.get("reports/retention-snapshots/status",{params:{job_id:e}});if(o.success&&o.status==="completed"){I(s("Snapshots generated successfully!")),m.value=!1,await x();return}if(o.success&&o.status==="failed"){V(o.message||s("Snapshot generation failed!")),m.value=!1;return}r++,r<10?setTimeout(a,1e4):(A(s("Job is still running. Please refresh the page in a moment!")),m.value=!1)}catch{V(s("Error checking job status!")),m.value=!1}};a()};return ae([f],()=>{x()}),oe(()=>{x(),T.addListener("cohort-report",x)}),(e,t)=>{const r=b("el-tooltip"),a=b("el-button"),o=b("el-button-group"),l=b("el-option"),_=b("el-select"),v=b("el-skeleton"),S=b("el-table-column"),re=b("el-table");return y(),E(le,{permission:"reports/view"},{default:u(()=>[w("div",ge,[i(me,null,{title:u(()=>[w("h1",we,[C(h(d(s)("Subscription Cohorts"))+" ",1),i(r,{"popper-class":"fct-tooltip",content:d(s)("A cohort is considered churned either when it went on hold or when it officially ended (factoring in the end date)."),placement:"top"},{default:u(()=>[i(ie,{class:"text-gray-500 w-4 h-4 cursor-pointer",name:"InformationFill"})]),_:1},8,["content"])])]),_:1}),i(ue,{class:"overflow-hidden"},{default:u(()=>[i(ce,null,{default:u(()=>[w("div",be,[w("div",ye,[i(o,null,{default:u(()=>[i(a,{type:f.value==="year"?"primary":"",size:"small",onClick:t[0]||(t[0]=c=>f.value="year")},{default:u(()=>[C(h(d(s)("Year")),1)]),_:1},8,["type"]),i(a,{type:f.value==="month"?"primary":"",size:"small",onClick:t[1]||(t[1]=c=>f.value="month")},{default:u(()=>[C(h(d(s)("Month")),1)]),_:1},8,["type"])]),_:1}),i(o,null,{default:u(()=>[i(a,{type:n.value==="subscribers"?"primary":"",size:"small",onClick:t[2]||(t[2]=c=>n.value="subscribers")},{default:u(()=>[C(h(d(s)("Subscriptions")),1)]),_:1},8,["type"]),i(a,{type:n.value==="mrr"?"primary":"",size:"small",onClick:t[3]||(t[3]=c=>n.value="mrr")},{default:u(()=>[C(h(d(s)("MRR")),1)]),_:1},8,["type"])]),_:1}),i(_,{modelValue:p.value,"onUpdate:modelValue":t[4]||(t[4]=c=>p.value=c),size:"small",class:"w-[150px]"},{default:u(()=>[i(l,{value:"percent",label:d(s)("% of total")},null,8,["label"]),i(l,{value:"percent_previous",label:d(s)("% of previous")},null,8,["label"]),i(l,{value:"value",label:d(s)("Total Value")},null,8,["label"]),i(l,{value:"percent_ended",label:d(s)("% of total ended")},null,8,["label"])]),_:1},8,["modelValue"])]),w("div",$e,[i(a,{size:"small",onClick:ee,loading:m.value},{default:u(()=>[C(h(d(s)("Generate Snapshots")),1)]),_:1},8,["loading"]),i(ve,{data:j.value,filename:"subscription_cohorts.csv"},null,8,["data"])])])]),_:1}),i(_e,{class:"px-0 pb-0"},{default:u(()=>[m.value?(y(),F("div",ke,[i(v,{animated:"",rows:10})])):B("",!0),!m.value&&!M.value?(y(),E(re,{key:1,data:H.value,border:"",class:"fct-cohort-el-table","cell-style":J,"row-class-name":O,"span-method":Y},{default:u(()=>[i(S,{prop:"cohort_label",label:d(s)("Subscribed"),fixed:"left",width:"150"},{default:u(c=>[w("span",{class:N({"font-bold":c.row.is_weighted_avg})},h(c.row.cohort_label),3)]),_:1},8,["label"]),i(S,{prop:"start_value",label:d(s)("Start"),align:"right"},{default:u(c=>[w("span",{class:N({"font-bold":c.row.is_weighted_avg})},h(c.row.start_value),3)]),_:1},8,["label"]),(y(!0),F(ne,null,se(W.value,c=>(y(),E(S,{key:c,prop:"period_"+c,label:G(c),width:"120",align:"center"},{default:u($=>[$.row["period_"+c+"_tooltip"]?(y(),E(r,{key:0,placement:"top","popper-class":"fct-tooltip"},{content:u(()=>[w("div",{class:"text-sm",innerHTML:$.row["period_"+c+"_tooltip"]},null,8,Ce)]),default:u(()=>[w("span",{class:N({"font-bold":$.row.is_weighted_avg})},h($.row["period_"+c]),3)]),_:2},1024)):(y(),F("span",{key:1,class:N({"font-bold":$.row.is_weighted_avg})},h($.row["period_"+c]||""),3))]),_:2},1032,["prop","label"]))),128))]),_:1},8,["data"])):B("",!0),!m.value&&M.value?(y(),E(de,{key:2,icon:"Empty/ListView","has-dark":!0,text:d(s)("Click Generate Snapshots above to view cohort data."),class:"fct-report-empty-state"},null,8,["text"])):B("",!0)]),_:1})]),_:1})])]),_:1})}}},vt=pe(xe,[["__scopeId","data-v-dbdcb606"]]);export{vt as default}; |