PageSourceSearch

https://app.backstagebaton.com/app/assets/PaymentsReportPage-C9AMGGvi.js

js backstagebaton.com collected 2026-10-07 08:49:26 UTC 31,334 bytes, 1 lines download raw bytes

1import{j as e,B as F,d as E,r as p,g as Ce,G as P,c as Oe,l as be,M as Me,T as at,E as Ae,C as nt,a as rt,e as it,t as lt,S as K,H as dt,I as ot,p as ct}from"./index-_aijvlUq.js";import{P as mt}from"./PageHeader-DCofr6qo.js";import{I as X}from"./Input-ysTyZFq5.js";import{T as ut}from"./Tabs-CGDUdv1I.js";import{M as G}from"./Menu-CATQC14B.js";import{C as xt}from"./ConfirmDialog-CODvETNM.js";import{B as pt}from"./Badge-DJIi163x.js";import{C as ge}from"./ChipToggle-hmCaOMqs.js";import{b as ht,c as gt,d as C,e as yt,T as ft,a as w}from"./Table-Yng-lqpt.js";import{E as q}from"./EmptyState-CPGKooqj.js";import{s as $,K as Ne,M as Y,m as R,l as ye,F as de,i as we,S as ze,f as fe,a as jt}from"./format-BheQoBt9.js";import{p as Z}from"./payments-BcDSbBQ_.js";import{p as re,P as bt}from"./paymentsReport-nJtEMH9X.js";import{s as Nt}from"./exportCsv-CZAUSrIW.js";import"./PrintSheet-BwuplKw5.js";const vt={succeeded:"success",refunded:"danger",disputed:"danger",processing:"info"};function De({status:t}){return e.jsx(pt,{variant:vt[t],color:"gray",children:ze[t]||t})}function ie(t){return we(t)?"text-red-700":"text-gray-900"}function Q({value:t}){return t?e.jsx("span",{className:"font-mono text-xs text-gray-600 break-all",children:t}):e.jsx("span",{className:"text-gray-300",children:"—"})}function St({rows:t,loading:a,isMobile:d,canExport:i,showRefs:m,onToggleRefs:g,includeWaived:j,onToggleWaived:f,includeUnsettled:l,onToggleUnsettled:o,onExport:x,exporting:v}){const h=d?"md":"sm",D=i&&e.jsx(F,{variant:"primary",size:"md",onClick:()=>x("xlsx"),isLoading:v==="xlsx",disabled:!t.length,"data-testid":"transactions-primary",children:"Export Excel"}),b=e.jsxs("div",{className:"flex flex-wrap items-center gap-2 mb-3",children:[e.jsx(ge,{size:h,selected:m,onClick:g,children:"Show Stripe references"}),e.jsx(ge,{size:h,selected:j,onClick:f,children:"Show waived"}),e.jsx(ge,{size:h,selected:l,onClick:o,children:"Show still processing"}),D&&e.jsx("div",{className:"ml-auto",children:D})]});return!a&&t.length===0?e.jsx("div",{"data-testid":"transactions-tab",children:e.jsx(q,{card:!0,title:"No transactions in this range.",description:"Payments, refunds and disputes appear here as they settle. Widen the dates or clear a filter.",action:D||void 0})}):d?e.jsxs("div",{"data-testid":"transactions-tab",children:[b,e.jsx("ul",{className:"space-y-2",children:t.map(n=>e.jsxs("li",{className:"bg-white rounded-xl border border-gray-200 p-3","data-testid":`tx-card-${n.id}`,children:[e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:"font-medium text-gray-900 truncate",children:n.memberName||"—"}),e.jsxs("p",{className:"text-sm text-gray-600 truncate",children:[n.productName,n.periodKey?` · ${n.periodKey}`:""]})]}),e.jsx("p",{className:`shrink-0 text-base font-semibold tabular-nums ${ie(n)}`,children:$(n.grossCents)})]}),e.jsxs("div",{className:"mt-1 flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-gray-500",children:[e.jsx("span",{children:Ne[n.kind]||n.kind}),e.jsx("span",{children:"·"}),e.jsxs("span",{children:[Y[n.method]||n.method,R(n)?` ${R(n)}`:""]}),e.jsx("span",{children:"·"}),e.jsx("span",{children:n.paidOn?E(n.paidOn):"—"}),e.jsx(De,{status:n.status})]}),(n.feeCents!==0||n.netCents!==n.grossCents)&&e.jsxs("p",{className:"mt-1 text-xs text-gray-500",children:["Fee ",$(n.feeCents)," · Net ",e.jsx("span",{className:ie(n),children:$(n.netCents)})]}),ye(n)&&e.jsx("p",{className:"mt-1 text-xs text-gray-500",children:ye(n)})]},n.id))})]}):e.jsxs("div",{"data-testid":"transactions-tab",children:[b,e.jsxs(ht,{children:[e.jsx(gt,{children:e.jsxs("tr",{children:[e.jsx(C,{children:"Date"}),e.jsx(C,{children:"Member"}),e.jsx(C,{children:"Product"}),e.jsx(C,{children:"Fund"}),e.jsx(C,{children:"Method"}),e.jsx(C,{className:"text-right",children:"Gross"}),e.jsx(C,{className:"text-right",children:"Fee"}),e.jsx(C,{className:"text-right",children:"Net"}),e.jsx(C,{children:"In the bank"}),e.jsx(C,{children:"Status"}
1),m&&e.jsxs(e.Fragment,{children:[e.jsx(C,{children:"Payout (bank line)"}),e.jsx(C,{children:"Stripe fee record"}),e.jsx(C,{children:"Stripe payment"}),e.jsx(C,{children:"Stripe charge"}),e.jsx(C,{children:"Stripe refund"})]})]})}),e.jsx(yt,{children:t.map(n=>e.jsxs(ft,{className:we(n)?"bg-red-50/40":"",children:[e.jsx(w,{className:"text-gray-700 tabular-nums",title:n.paidAt||void 0,children:n.paidOn?E(n.paidOn):"—"}),e.jsx(w,{className:"font-medium text-gray-900",children:n.memberName||"—"}),e.jsxs(w,{className:"text-gray-700",children:[n.productName,n.periodKey?e.jsxs("span",{className:"text-gray-400",children:[" · ",n.periodKey]}):null,n.kind!=="payment"&&e.jsxs("span",{className:"ml-1.5 text-xs text-gray-500",children:["(",Ne[n.kind]||n.kind,")"]})]}),e.jsx(w,{className:"text-gray-700",children:de[n.fund]||n.fund}),e.jsxs(w,{className:"text-gray-700",children:[Y[n.method]||n.method,R(n)&&e.jsx("span",{className:"ml-1 text-xs text-gray-500",children:R(n)})]}),e.jsx(w,{className:`text-right tabular-nums ${ie(n)}`,children:$(n.grossCents)}),e.jsx(w,{className:"text-right tabular-nums text-gray-600",children:$(n.feeCents)}),e.jsx(w,{className:`text-right tabular-nums font-medium ${ie(n)}`,children:$(n.netCents)}),e.jsx(w,{className:"text-xs text-gray-500",children:ye(n)||"—"}),e.jsx(w,{children:e.jsx(De,{status:n.status})}),m&&e.jsxs(e.Fragment,{children:[e.jsx(w,{children:e.jsx(Q,{value:n.stripePayoutId})}),e.jsx(w,{children:e.jsx(Q,{value:n.balanceTransactionId})}),e.jsx(w,{children:e.jsx(Q,{value:n.paymentIntentId})}),e.jsx(w,{children:e.jsx(Q,{value:n.stripeChargeId})}),e.jsx(w,{children:e.jsx(Q,{value:n.stripeRefundId})})]})]},n.id))})]}),t.some(n=>n.memo||n.recordedByName)&&e.jsx("p",{className:"mt-2 text-xs text-gray-400",children:"Memo, member note, recorded by and the fee covered by the member are in the Excel and CSV exports."})]})}function Ct({rows:t}){return e.jsx("ul",{className:"mt-2 divide-y divide-gray-100 border-t border-gray-100",children:t.map(a=>e.jsxs("li",{className:"flex flex-col gap-0.5 md:flex-row md:items-center md:justify-between md:gap-3 py-1.5 text-sm",children:[e.jsxs("span",{className:"min-w-0 truncate text-gray-700",children:[a.memberName||"—"," ",e.jsxs("span",{className:"text-gray-400",children:["· ",a.productName,a.periodKey?` · ${a.periodKey}`:""]}),a.kind!=="payment"&&e.jsxs("span",{className:"ml-1 text-xs text-gray-500",children:["(",Ne[a.kind]||a.kind,")"]})]}),e.jsxs("span",{className:"shrink-0 text-xs text-gray-500",children:[Y[a.method]||a.method,R(a)?` ${R(a)}`:""," · ",a.paidOn?E(a.paidOn):""]}),e.jsx("span",{className:`shrink-0 tabular-nums ${we(a)?"text-red-700":"text-gray-900"}`,children:$(a.grossCents)})]},a.id))})}function Pe({id:t,summaryLeft:a,summaryRight:d,rows:i,actions:m}){const[g,j]=p.useState(!1),f=i.length>0;return e.jsxs("li",{className:"bg-white rounded-xl border border-gray-200","data-testid":t,children:[e.jsxs("div",{className:"flex items-stretch",children:[e.jsxs("button",{type:"button",onClick:()=>f&&j(l=>!l),"aria-expanded":f?g:void 0,disabled:!f,"data-testid":`${t}-toggle`,className:"min-w-0 flex-1 flex flex-wrap items-center gap-x-4 gap-y-1 p-3 text-left rounded-xl focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-band-500 disabled:cursor-default",children:[e.jsx("span",{className:"min-w-0 flex-1",children:a}),e.jsx("span",{className:"flex items-center gap-3",children:d}),e.jsx("svg",{className:`h-4 w-4 shrink-0 text-gray-400 transition-transform ${g?"rotate-180":""} ${f?"":"invisible"}`,fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:"2","aria-hidden":"true",children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M19 9l-7 7-7-7"})})]}),m&&e.jsx("div",{className:"flex items-center gap-1 pr-3",children:m})]}),g&&e.jsx("div",{className:"px-3 pb-3",children:e.jsx(Ct,{rows:i})})]})}const H=({label:t,cents:a,tone:d="text-gray-900"})=>e.jsxs("span",{className:"text-sm",children:[e.jsx("span",{className:"text-xs text-gray-500 mr-1",children:t}),e.jsx("span",{className:`tabular-nums ${d}`,children:$(a)})]});function wt({data:t,loading:a,canManage:d,onRecordDeposit:i,onEditDeposit:m,onDeleteDeposit:g}){const[j,f]=p.useState(()=>new Set),o=Ce()?"md":"sm",x=t?.payouts||[],v=t?.deposits||[],h=t?.undeposited||[],D=h.filter(r=>j.has(r.id)),b=D.reduce((r,y)=>r+y.grossCents,0);function n(r){f(y=>{const L=new Set(y);return L.has(r)?L.delete(r):L.add(r),L})}const I=d&&e.jsx(F,{variant:"primary",size:"md",onClick:()=>{i([...j]),f(new Set)},disabled:h.length===0,"data-testid":"payouts-primary",children:"Record deposit…"});return!a&&!x.length&&!v.length&&!h.length?e.jsx("div",{"data-testid":"payouts-tab",children:e.jsx(q,{card:!0,title:"Nothing to re
1concile in this range.",description:"Stripe payouts appear after the nightly sync (or Refresh from Stripe); cash and checks appear here as you record them.",action:I||void 0})}):e.jsxs("div",{"data-testid":"payouts-tab",className:"space-y-6",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("p",{className:"text-sm text-gray-500",children:D.length?`${D.length} ticked · ${P(b)}`:"Tick cash and checks below to put them in a deposit."}),e.jsx("div",{className:"ml-auto",children:I})]}),e.jsxs("section",{children:[e.jsx("h3",{className:"text-sm font-semibold text-gray-500 uppercase tracking-wide mb-2",children:"Stripe payouts"}),x.length===0?e.jsx(q,{size:"compact",title:"No Stripe payouts in this range."}):e.jsx("ul",{className:"space-y-2",children:x.map(r=>e.jsx(Pe,{id:`payout-${r.id}`,rows:r.rows,summaryLeft:e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"font-medium text-gray-900",children:[r.arrivalDate?E(r.arrivalDate):"Arrival date pending"," ",e.jsx("span",{className:"ml-2 text-xs font-mono text-gray-500",children:r.stripePayoutId})]}),e.jsxs("p",{className:"text-xs text-gray-500",children:[r.paymentCount," payment",r.paymentCount===1?"":"s",r.refundCount?` · ${r.refundCount} refund${r.refundCount===1?"":"s"}`:"",r.status&&r.status!=="paid"?` · ${r.status.replace("_"," ")}`:""]})]}),summaryRight:e.jsxs(e.Fragment,{children:[e.jsx(H,{label:"Gross",cents:r.grossCents}),e.jsx(H,{label:"Fees",cents:r.feeCents,tone:"text-gray-600"}),r.refundCents!==0&&e.jsx(H,{label:"Refunds",cents:r.refundCents,tone:"text-red-700"}),e.jsx(H,{label:"Net",cents:r.netCents,tone:"font-semibold text-gray-900"}),!!r.differenceCents&&e.jsx(H,{label:"Difference",cents:r.differenceCents,tone:"text-amber-700"})]})},r.id))})]}),e.jsxs("section",{children:[e.jsx("h3",{className:"text-sm font-semibold text-gray-500 uppercase tracking-wide mb-2",children:"Deposit batches"}),v.length===0?e.jsx(q,{size:"compact",title:"No deposits recorded in this range."}):e.jsx("ul",{className:"space-y-2",children:v.map(r=>e.jsx(Pe,{id:`deposit-${r.id}`,rows:r.rows,summaryLeft:e.jsxs(e.Fragment,{children:[e.jsxs("p",{className:"font-medium text-gray-900",children:[E(r.depositedOn),r.reference?e.jsx("span",{className:"ml-2 text-xs text-gray-500",children:r.reference}):null]}),e.jsxs("p",{className:"text-xs text-gray-500",children:[r.paymentCount," payment",r.paymentCount===1?"":"s",r.note?` · ${r.note}`:""]})]}),summaryRight:e.jsx(H,{label:"Total",cents:r.totalCents,tone:"font-semibold text-gray-900"}),actions:d&&e.jsxs(e.Fragment,{children:[e.jsx(F,{type:"button",variant:"ghost",size:o,onClick:()=>m(r),children:"Edit"}),e.jsx(F,{type:"button",variant:"danger",size:o,onClick:()=>g(r),children:"Delete"})]})},r.id))})]}),e.jsxs("section",{children:[e.jsx("h3",{className:"text-sm font-semibold text-gray-500 uppercase tracking-wide mb-2",children:"Not yet deposited"}),h.length===0?e.jsx(q,{size:"compact",title:"Every cash and check payment is in a deposit."}):e.jsxs("ul",{className:"bg-white rounded-xl border border-gray-200 divide-y divide-gray-100",children:[h.map(r=>e.jsx("li",{children:e.jsxs("label",{className:`flex items-center gap-3 px-3 py-2 min-h-[44px] ${d?"cursor-pointer hover:bg-gray-50":""}`,children:[d&&e.jsx("input",{type:"checkbox",className:"h-4 w-4 rounded border-gray-300 text-band-600 focus:ring-band-500",checked:j.has(r.id),onChange:()=>n(r.id),"aria-label":`${r.memberName} ${P(r.grossCents)}`}),e.jsxs("span",{className:"flex-1 min-w-0",children:[e.jsx("span",{className:"block text-sm font-medium text-gray-900 truncate",children:r.memberName}),e.jsxs("span",{className:"block text-xs text-gray-500 truncate",children:[Y[r.method]||r.method,R(r)?` ${R(r)}`:""," · ",r.paidOn?E(r.paidOn):""," · ",r.productName,r.recordedByName?` · recorded by ${r.recordedByName}`:""]})]}),e.jsx("span",{className:"text-sm tabular-nums text-gray-900",children:P(r.grossCents)})]})},r.id)),e.jsxs("li",{className:"flex justify-between px-3 py-2 text-sm font-semibold text-gray-900",children:[e.jsxs("span",{children:[h.length," in the drawer"]}),e.jsx("span",{className:"tabular-nums",children:P(t?.undepositedTotalCents||0)})]})]})]})]})}const $t=["card","ach","cash","check"],ve="bg-gray-50/70";function je({cents:t,tone:a="text-gray-900",bold:d=!1,first:i=!1,tint:m=!1}){return e.jsx("td",{className:`px-3 py-2 text-right tabular-nums ${i?"border-l border-gray-200":""} ${m?ve:""} ${d?"font-semibold":""} ${t===0?"text-gray-300":a}`,children:$(t)})}function kt({summary:t,loading:a,onPrint:d,printing:i}){const m=Ce(),g=e.jsx(F,{variant:"primary",size:"md",onClick:d,isLoading:i,disabled:!t,"data-testid":"summary-primary",children:"Print summary"});if(!a&&(!t||t.totals.total.count===0))return e.jsx("div",{"data-testid":"summary-tab",children:e.jsx(q,{card:!0,title:"Nothing collected in this range.",description:"The summary fills in as payments settle.",action:g})});if(!t)return e.jsx("div",{"data-testid":"summary-tab"});const j=m?[]:$t.filter(o=>t.totals.byMethod[o].count>0),f=t.funds.filter(o=>o.total.count>0),l=(t.refundsByFund||[]).filter(o=>o.count>0);return e.jsxs("div",{"data-testid":"summary-tab",children:[e.jsx("div",{className:"flex mb-3",children:e.jsx("div",{className:"ml-auto",children:g})}),e.jsx("div",{className:"bg-white rounded-xl border border-gray-200 overflow-x-auto",children:e.jsxs("table",{className:"min-w-full text-sm",children:[e.jsxs("thead",{children:[e.jsxs("tr",{className:"text-xs font-semibold text-gray-500 uppercase tracking-wide",children:[e.jsx("th",{className:"px-3 py-2 text-left",rowSpan:2,children:"Fund"}),[...j,"all"].map((o,x)=>e.jsx("th",{colSpan:3,scope:"colgroup",className:`px-3 py-2 text-center border-l border-gray-200 ${x%2===1?ve:""}`,children:o==="all"?"All methods":Y[o]},o))]}),e.jsx("tr",{className:"text-[11px] text-gray-500 border-b border-gray-200",children:[...j,"all"].map((o,x)=>["Gross","Fees","Net"].map((v,h)=>e.jsx("th",{scope:"col",className:`px-3 pb-1 text-right font-medium ${h===0?"border-l border-gray-200":""} ${x%2===1?ve:""}`,children:v},`${o}-${v}`)))})]}),e.jsxs("tbody",{children:[f.map(o=>e.jsxs("tr",{className:"border-b border-gray-100","data-testid":`summary-fund-${o.fund}`,children:[e.jsx("td",{className:"px-3 py-2 font-medium text-gray-900",children:de[o.fund]||o.fund}),j.map((x,v)=>e.jsx(le,{cell:o.methods[x],tint:v%2===1},x)),e.jsx(le,{cell:o.total,bold:!0,tint:j.length%2===1})]},o.fund)),e.jsxs("tr",{className:"bg-gray-50","data-testid":"summary-total",children:[e.jsx("td",{className:"px-3 py-2 font-semibold text-gray-900",children:"All funds"}),j.map((o,x)=>e.jsx(le,{cell:t.totals.byMethod[o],bold:!0,tint:x%2===1},o)),e.jsx(le,{cell:t.totals.total,bold:!0,tint:j.length%2===1})]})]})]})}),e.jsxs("dl",{className:"mt-4 grid grid-cols-1 sm:grid-cols-2 gap-2 text-sm",children:[l.map(o=>e.jsx(z,{label:`Refunds and disputes — ${de[o.fund]||o.fund} (${o.count})`,cents:o.netCents,tone:"text-red-700"},o.fund)),e.jsx(z,{label:`Refunds and disputes (${t.refunds.count})`,cents:t.refunds.netCents,tone:"text-red-700"}),e.jsx(z,{label:"Net after refunds",cents:t.afterRefundsNetCents,bold:!0}),e.jsx(z,{label:"Fee covered by members (inside gross)",cents:t.feeCoveredByMembersCents||0,tone:"text-gray-600"}),e.jsx(z,{label:`Outstanding owed today (${t.outstanding.count} charge${t.outstanding.count===1?"":"s"})`,cents:t.outstanding.amountCents,tone:"text-amber-700"}),e.jsx(z,{label:`Waived in this period (${t.waived.count})`,cents:t.waived.amountCents,tone:"text-gray-600"}),e.jsx(z,{label:`Not yet deposited (${t.undeposited.count} cash / check)`,cents:t.undeposited.amountCents,tone:"text-amber-700"})]}),e.jsx("p",{className:"mt-3 text-xs text-gray-400",children:"Gross is what members paid, including any fee they covered; fees are what Stripe charged. The 990 reports gross receipts with fees as an expense. Donations stay on their own line and never blend with dues."})]})}function le({cell:t,bold:a=!1,tint:d=!1}){return e.jsxs(e.Fragment,{children:[e.jsx(je,{cents:t.grossCents,bold:a,first:!0,tint:d}),e.jsx(je,{cents:t.feeCents,tone:"text-gray-600",bold:a,tint:d}),e.jsx(je,{cents:t.netCents,bold:a,tint:d})]})}function z({label:t,cents:a,tone:d="text-gray-900",bold:i=!1}){return e.jsxs("div",{className:"flex items-center justify-between bg-white rounded-xl border border-gray-200 px-4 py-2",children:[e.jsx("dt",{className:"text-gray-600",children:t}),e.jsx("dd",{className:`tabular-nums ${i?"font-semibold":""} ${d}`,children:$(a)})]})}function Tt({isOpen:t,onClose:a,undeposited:d=[],deposit:i=null,initialSelected:m=[],onSaved:g}){const{showSuccess:j,showError:f}=Oe(),[l,o]=p.useState(be()),[x,v]=p.useState(""),[h,D]=p.useState(""),[b,n]=p.useState(()=>new Set(m)),[I,r]=p.useState(!1);p.useEffect(()=>{t&&(o(i?.depositedOn||be()),v(i?.reference||""),D(i?.note||""),n(new Set(i?i.rows.map(c=>c.id):m)))},[t,i?.id]);const y=p.useMemo(()=>{const c=i?i.rows:[],N=new Set(c.map(S=>S.id));return[...c,...d.filter(S=>!N.has(S.id))]},[i,d]),L=y.reduce((c,N)=>
1b.has(N.id)?c+N.grossCents:c,0);function k(c){n(N=>{const S=new Set(N);return S.has(c)?S.delete(c):S.add(c),S})}function ee(c){n(c?new Set(y.map(N=>N.id)):new Set)}async function V(c){c?.preventDefault?.(),r(!0);try{if(i){const N=new Set(i.rows.map(O=>O.id)),S=[...b].filter(O=>!N.has(O)),se=[...N].filter(O=>!b.has(O));await Z.deposits.update(i.id,{depositedOn:l,reference:x||null,note:h||null,addPaymentIds:S,removePaymentIds:se}),j(`Deposit updated — ${P(L)} on ${E(l)}.`)}else await Z.deposits.create({depositedOn:l,reference:x||null,note:h||null,paymentIds:[...b]}),j(`Deposit recorded — ${b.size} payment${b.size===1?"":"s"}, ${P(L)}.`);g?.(),a()}catch(N){f(N?.message||Ae)}finally{r(!1)}}const te=e.jsxs("div",{className:"flex gap-2",children:[e.jsx(F,{type:"submit",form:"record-deposit-form",variant:"primary",size:"md",isLoading:I,disabled:!b.size,"data-testid":"deposit-save",children:i?"Save changes":"Record deposit"}),e.jsx(F,{type:"button",variant:"secondary",size:"md",onClick:a,disabled:I,children:"Cancel"}),e.jsx("span",{className:"ml-auto self-center text-sm font-semibold text-gray-900 tabular-nums","data-testid":"deposit-total",children:P(L)})]});return e.jsx(Me,{isOpen:t,onClose:a,title:i?"Edit deposit":"Record deposit",size:"md",footer:te,children:e.jsxs("form",{id:"record-deposit-form",onSubmit:V,className:"space-y-4",children:[e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3",children:[e.jsx(X,{label:"Deposit date",type:"date",value:l,onChange:c=>o(c.target.value),required:!0}),e.jsx(X,{label:"Slip reference (optional)",value:x,onChange:c=>v(c.target.value),placeholder:"Slip 17",maxLength:80})]}),e.jsx(at,{label:"Note (optional)",value:h,onChange:c=>D(c.target.value),rows:2,maxLength:500}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-1",children:[e.jsx("h3",{className:"text-sm font-semibold text-gray-500 uppercase tracking-wide",children:"Payments in this deposit"}),y.length>1&&e.jsxs("div",{className:"flex gap-1",children:[e.jsx(F,{type:"button",variant:"ghost",size:"sm",onClick:()=>ee(!0),children:"Tick all"}),e.jsx(F,{type:"button",variant:"ghost",size:"sm",onClick:()=>ee(!1),children:"Clear"})]})]}),i&&b.size===0&&y.length>0&&e.jsx("p",{className:"text-xs text-amber-700 mb-1",children:"A deposit needs at least one payment — to remove the batch, use Delete on the Payouts and deposits tab."}),y.length===0?e.jsx("p",{className:"text-sm text-gray-500",children:"Every cash and check payment is already in a deposit."}):e.jsx("ul",{className:"divide-y divide-gray-100 border border-gray-200 rounded-lg max-h-72 overflow-y-auto",children:y.map(c=>e.jsx("li",{children:e.jsxs("label",{className:"flex items-center gap-3 px-3 py-2 min-h-[44px] cursor-pointer hover:bg-gray-50",children:[e.jsx("input",{type:"checkbox",className:"h-4 w-4 rounded border-gray-300 text-band-600 focus:ring-band-500",checked:b.has(c.id),onChange:()=>k(c.id),"aria-label":`${c.memberName} ${P(c.grossCents)}`}),e.jsxs("span",{className:"flex-1 min-w-0",children:[e.jsx("span",{className:"block text-sm font-medium text-gray-900 truncate",children:c.memberName}),e.jsxs("span",{className:"block text-xs text-gray-500 truncate",children:[Y[c.method]||c.method,R(c)?` ${R(c)}`:""," · ",c.paidOn?E(c.paidOn):"",c.productName?` · ${c.productName}`:""]})]}),e.jsx("span",{className:"text-sm tabular-nums text-gray-900",children:P(c.grossCents)})]})},c.id))})]})]})})}const Ye=t=>!t||t==="01-01",Be=t=>t.slice(5,10),Ue=t=>Number(t.slice(0,4));function oe(t,a){const[d,i,m]=t.split("-").map(Number),g=new Date(d,i-1,m);return g.setDate(g.getDate()+a),nt(g)}function Se(t,a,d=0){const i=Ue(t);if(Ye(a)){const g=i+d;return{start:`${g}-01-01`,end:`${g}-12-31`,label:`FY${g}`}}const m=(Be(t)>=a?i+1:i)+d;return{start:`${m-1}-${a}`,end:oe(`${m}-${a}`,-1),label:`FY${m}`}}function Ft(t,a,d=0){if(Ye(a))return Se(t,"01-01",d);const i=Ue(t),m=(Be(t)>=a?i:i-1)+d;return{start:`${m}-${a}`,end:oe(`${m+1}-${a}`,-1),label:`${m}-${String((m+1)%100).padStart(2,"0")}`}}const Dt=[{value:"thisFiscalYear",label:"This fiscal year"},{value:"lastFiscalYear",label:"Last fiscal year"},{value:"thisSeason",label:"This season"},{value:"last30",label:"Last 30 days"},{value:"last90",label:"Last 90 days"},{value:"custom",label:"Custom"}];function Ee(t,{today:a=be(),fiscalYearStart:d="01-01",seasonStart:i=null}={}){switch(t){case"thisFiscalYear":return Se(a,d,0);case"lastFiscalYear":return Se(a,d,-1);case"thisSeason":return Ft(a,i,0);case"last30":return{start:oe(a,-29),end:a,label:"Last 30 days"};case"last90":return{start:oe(a,-89),end:a,label:"Last 90 days"};default:return null}}const Le=[{key:"transactions",label:"Transactions"},{key:"payouts",label:"Payouts and deposits"},{key:"summary",label:"Summary"}],Pt=Object.entries(de).map(([t,a])=>({value:t,label:a})),Et=Object.entries(Y).map(([t,a])=>({value:t,label:a})),Lt=Object.entries(ze).filter(([t])=>t!=="disputed").map(([t,a])=>({value:t,label:a})),Re={start:"",end:"",preset:"thisFiscalYear",fund:"",method:"",status:"",productId:""};function Ie(t,{includeWaived:a,includeUnsettled:d}){const i={};for(const m of["start","end","fund","method","status","productId"])t[m]&&(i[m]=t[m]);return a&&(i.includeWaived=!0),d&&(i.includeUnsettled=!0),i}function Jt(){const{showError:t,showSuccess:a}
1=Oe(),{canAny:d}=rt(),i=d("payments:manage"),m=Ce(),[g,j]=it(),f=Le.some(s=>s.key===g.get("tab"))?g.get("tab"):"payouts",[l,o]=p.useState(Re),[x,v]=p.useState(!1),[h,D]=p.useState(!1),[b,n]=p.useState(!1),[I,r]=p.useState(null),[y,L]=p.useState(null),[k,ee]=p.useState(null),[V,te]=p.useState(!0),[c,N]=p.useState(null),[S,se]=p.useState(!1),[O,ce]=p.useState(null),[A,me]=p.useState(null),[B,U]=p.useState(null),[_e,$e]=p.useState(!1),ae=p.useRef(0),M=p.useCallback(async(s,u)=>{const T=++ae.current;te(!0);try{const J=Ie(s,u),[he,et,tt]=await Promise.all([re.transactions(J),re.payouts(J),re.summary(J)]);if(T!==ae.current)return;r(he),L(et),ee(tt),(!s.start||!s.end)&&o(st=>({...st,start:he.range.start,end:he.range.end}))}catch(J){if(T!==ae.current)return;t(J?.message||lt("the payments report"))}finally{T===ae.current&&te(!1)}},[t]);p.useEffect(()=>{M(Re,{includeWaived:!1,includeUnsettled:!1})},[M]);const ue=I||y||k,xe=ue?.fiscalYearStart||"01-01",ne=(ue?.products||[]).find(s=>s.type==="dues"&&s.seasonStart)?.seasonStart||null;function _(s,u={includeWaived:x,includeUnsettled:h}){o(s),M(s,u)}function We(s){const u=Ee(s,{fiscalYearStart:xe,seasonStart:ne});_(u?{...l,preset:s,start:u.start,end:u.end}:{...l,preset:s})}function ke(s,u){const T={...l,preset:"custom",[s]:u};o(T),T.start&&T.end&&T.start<=T.end&&M(T,{includeWaived:x,includeUnsettled:h})}function Ke(){const s=!x;v(s),M(l,{includeWaived:s,includeUnsettled:h})}function Ge(){const s=!h;D(s),M(l,{includeWaived:x,includeUnsettled:s})}function He(s){const u=new URLSearchParams(g);s==="payouts"?u.delete("tab"):u.set("tab",s),j(u,{replace:!0})}async function pe(s){N(s);try{Nt(await re.exportFile(Ie(l,{includeWaived:x,includeUnsettled:h}),s))}catch(u){t(u?.message||"Couldn’t export the report. Try again.")}finally{N(null)}}function Te(){if(!(!l.start||!l.end)){if(m||dt()){ot(`/app/print/payments-summary?start=${l.start}&end=${l.end}`);return}se(!0)}}p.useEffect(()=>{if(!S)return;const s=setTimeout(()=>{try{window.print()}catch{}se(!1)},60);return()=>clearTimeout(s)},[S]);async function qe(){try{const s=await Z.payouts.sync();a(`Stripe checked — ${s.payouts} payout${s.payouts===1?"":"s"} seen, ${s.stamped} row${s.stamped===1?"":"s"} tied to a payout.`),await M(l,{includeWaived:x,includeUnsettled:h})}catch(s){t(s?.message||"Couldn’t reach Stripe. Try again in a minute.")}}function Fe(){const[s,u]=xe.split("-").map(Number);U({month:s||1,day:u||1})}async function Ve(s){s.preventDefault(),$e(!0);try{const u=`${String(B.month).padStart(2,"0")}-${String(B.day).padStart(2,"0")}`;await Z.settings.setFiscalYear(u),a(`Fiscal year now starts ${fe(u)}.`),U(null);const T=Ee("thisFiscalYear",{fiscalYearStart:u,seasonStart:ne});_({...l,preset:"thisFiscalYear",start:T.start,end:T.end})}catch(u){t(u?.message||Ae)}finally{$e(!1)}}async function Je(){try{await Z.deposits.remove(A.id),a("Deposit deleted — its payments are back in the drawer."),me(null),await M(l,{includeWaived:x,includeUnsettled:h})}catch(s){t(s?.message||ct)}}const Qe=I?.rows||[],W=I?.totals,Xe=f==="transactions"?W?`${W.count} transaction${W.count===1?"":"s"} · ${$(W.grossCents)} gross · ${$(W.feeCents)} fees · ${$(W.netCents)} net`:"Loading…":f==="payouts"?y?`${y.payouts.length} Stripe payout${y.payouts.length===1?"":"s"} · ${y.deposits.length} deposit${y.deposits.length===1?"":"s"} · ${P(y.undepositedTotalCents)} not yet deposited — each payout's net is one line on your statement.`:"Loading…":k?`${E(k.range.start)} – ${E(k.range.end)} · ${$(k.summary.totals.total.grossCents)} gross · ${$(k.summary.afterRefundsNetCents)} net after refunds`:"Loading…",Ze=(ue?.products||[]).map(s=>({value:s.id,label:s.name}));return e.jsxs("div",{className:"px-4 md:px-0",children:[e.jsx(mt,{title:"Payments",subtitle:"Every payment, refund, payout and deposit, in the order the bank statement reads. Dates are the band's local dates; fees are what Stripe charged.",breadcrumbs:[{label:"Reports",to:"/reports"},{label:"Payments"}],actions:e.jsxs(G,{align:"right",menuId:"payments-report-more",trigger:e.jsx(F,{variant:"ghost",size:"md",children:"More"}),children:[e.jsx(G.Item,{onClick:()=>pe("xlsx"),children:"Export Excel"}),e.jsx(G.Item,{onClick:()=>
1pe("csv"),children:"Export CSV"}),e.jsx(G.Item,{onClick:Te,children:"Print summary"}),i&&e.jsx(G.Item,{onClick:qe,children:"Refresh from Stripe"}),i&&e.jsx(G.Item,{onClick:Fe,children:"Change fiscal year…"})]})}),e.jsxs("div",{className:"bg-white rounded-xl border border-gray-200 p-4 mb-4",children:[e.jsxs("div",{className:"flex flex-wrap items-end gap-3",children:[e.jsx(K,{label:"Period",value:l.preset,onChange:s=>We(s.target.value),options:Dt,active:l.preset!=="thisFiscalYear"}),e.jsx(X,{label:"From",type:"date",value:l.start,onChange:s=>ke("start",s.target.value)}),e.jsx(X,{label:"To",type:"date",value:l.end,onChange:s=>ke("end",s.target.value)}),e.jsx(K,{label:"Fund",value:l.fund,onChange:s=>_({...l,fund:s.target.value}),options:Pt,placeholder:"All funds",active:!!l.fund}),e.jsx(K,{label:"Method",value:l.method,onChange:s=>_({...l,method:s.target.value}),options:Et,placeholder:"All methods",active:!!l.method}),e.jsx(K,{label:"Status",value:l.status,onChange:s=>_({...l,status:s.target.value}),options:Lt,placeholder:"All statuses",active:!!l.status}),e.jsx(K,{label:"Product",value:l.productId,onChange:s=>_({...l,productId:s.target.value}),options:Ze,placeholder:"All products",active:!!l.productId})]}),e.jsxs("p",{className:"mt-3 text-xs text-gray-500 flex flex-wrap items-center gap-x-2",children:[e.jsxs("span",{children:["Fiscal year starts ",fe(xe),ne?` · season starts ${fe(ne)} (from the dues product)`:""]}),i&&e.jsx(F,{type:"button",variant:"ghost",size:"sm",onClick:Fe,children:"Change…"})]})]}),e.jsx(ut,{tabs:Le,value:f,onChange:He,ariaLabel:"Payments report views",className:"mb-2"}),e.jsx("p",{"aria-live":"polite",className:"text-sm text-gray-600 mb-4","data-testid":"payments-status",children:Xe}),f==="transactions"&&e.jsx(St,{rows:Qe,loading:V,isMobile:m,canExport:!0,showRefs:b,onToggleRefs:()=>n(s=>!s),includeWaived:x,onToggleWaived:Ke,includeUnsettled:h,onToggleUnsettled:Ge,onExport:pe,exporting:c}),f==="payouts"&&e.jsx(wt,{data:y,loading:V,canManage:i,onRecordDeposit:s=>ce({deposit:null,initialSelected:s}),onEditDeposit:s=>ce({deposit:s,initialSelected:[]}),onDeleteDeposit:s=>me(s)}),f==="summary"&&e.jsx(kt,{summary:k?.summary,loading:V,onPrint:Te,printing:S}),e.jsx(Tt,{isOpen:!!O,onClose:()=>ce(null),undeposited:y?.undeposited||[],deposit:O?.deposit||null,initialSelected:O?.initialSelected||[],onSaved:()=>M(l,{includeWaived:x,includeUnsettled:h})}),e.jsx(xt,{isOpen:!!A,onClose:()=>me(null),onConfirm:Je,title:"Delete this deposit?",message:A?`The ${P(A.totalCents)} batch from ${E(A.depositedOn)} goes away and its ${A.paymentCount} payment${A.paymentCount===1?"":"s"} return to "Not yet deposited". The payments themselves are untouched.`:"",confirmLabel:"Delete"}),e.jsx(Me,{isOpen:!!B,onClose:()=>U(null),title:"Fiscal year",size:"sm",children:B&&e.jsxs("form",{onSubmit:Ve,className:"space-y-4",children:[e.jsx("p",{className:"text-sm text-gray-600",children:"The report's presets and the fiscal-year column cut on this date. A year that starts on any day but January 1 is named by the calendar year it ends in (July 2026 – June 2027 is FY2027). The season stays what the dues product says."}),e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsx(K,{label:"Starts in",value:String(B.month),onChange:s=>U(u=>({...u,month:Number(s.target.value)})),options:jt.map((s,u)=>({value:String(u+1),label:s}))}),e.jsx(X,{label:"Day",type:"number",min:"1",max:"31",value:B.day,onChange:s=>U(u=>({...u,day:Math.min(31,Math.max(1,Number(s.target.value)||1))}))})]}),e.jsxs("div",{className:"flex gap-2 pt-2",children:[e.jsx(F,{type:"submit",variant:"primary",size:"md",isLoading:_e,children:"Save changes"}),e.jsx(F,{type:"button",variant:"secondary",size:"md",onClick:()=>U(null),children:"Cancel"})]})]})}),S&&k&&y&&e.jsx(bt,{orgName:k.orgName,range:k.range,fiscalYearStart:k.fiscalYearStart,summary:k.summary,payouts:y.payouts,deposits:y.deposits,undeposited:y.undeposited})]})}export{Jt as PaymentsReportPage};

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.