3 lines
23 KiB
JavaScript
3 lines
23 KiB
JavaScript
"use strict";var DatewiseEngine=(()=>{var K=Object.defineProperty;var Ue=Object.getOwnPropertyDescriptor;var $e=Object.getOwnPropertyNames;var Be=Object.prototype.hasOwnProperty;var Fe=(e,t,n)=>t in e?K(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var Ne=(e,t)=>{for(var n in t)K(e,n,{get:t[n],enumerable:!0})},We=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of $e(t))!Be.call(e,r)&&r!==n&&K(e,r,{get:()=>t[r],enumerable:!(o=Ue(t,r))||o.enumerable});return e};var Ke=e=>We(K({},"__esModule",{value:!0}),e);var O=(e,t,n)=>Fe(e,typeof t!="symbol"?t+"":t,n);var Je={};Ne(Je,{METHODS:()=>H,MemoryReservationStore:()=>se,addDays:()=>I,addOperatingMinutes:()=>Oe,buildRunSheet:()=>Xe,canCustomerReschedule:()=>Ve,capsFor:()=>ze,checkFreshness:()=>G,computeAvailability:()=>V,diffDays:()=>Ye,evaluateRules:()=>F,firstAvailable:()=>ne,fromMinutes:()=>Y,haversineKm:()=>Z,hoursFor:()=>te,iso:()=>B,itemMatches:()=>Te,localParts:()=>L,mapsUrls:()=>Ee,matchZone:()=>J,normalizePostal:()=>q,peakFor:()=>j,planReminders:()=>Qe,postalMatches:()=>Me,quoteFee:()=>ee,rankLocations:()=>je,renderTemplate:()=>Le,slotId:()=>we,slotStartMs:()=>re,stockedAt:()=>oe,toCsv:()=>Ge,toMinutes:()=>D,tzOffsetMinutes:()=>X,usageKey:()=>z,validateSelection:()=>Ze,weekdayOf:()=>$,zonedToUtc:()=>v});var H=["pickup","delivery","shipping"];var De=new Map;function Ie(e){let t=De.get(e);return t||(t=new Intl.DateTimeFormat("en-US",{timeZone:e,hourCycle:"h23",year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",weekday:"short"}),De.set(e,t)),t}var He={Sun:0,Mon:1,Tue:2,Wed:3,Thu:4,Fri:5,Sat:6};function L(e,t){let n={};for(let r of Ie(t).formatToParts(new Date(e)))n[r.type]=r.value;let o=n.hour==="24"?"00":n.hour;return{date:`${n.year}-${n.month}-${n.day}`,time:`${o}:${n.minute}`,minutes:Number(o)*60+Number(n.minute),weekday:He[n.weekday]}}function X(e,t){let n={};for(let i of Ie(t).formatToParts(new Date(e)))n[i.type]=i.value;let o=n.hour==="24"?0:Number(n.hour),r=Date.UTC(+n.year,+n.month-1,+n.day,o,+n.minute,+n.second);return Math.round((r-Math.floor(e/1e3)*1e3)/6e4)}function v(e,t,n){let[o,r,i]=e.split("-").map(Number),[s,a]=t.split(":").map(Number),u=Date.UTC(o,r-1,i,s,a),d=X(u,n),l=u-d*6e4,c=X(l,n);if(c!==d){let g=u-c*6e4;L(g,n).time===t?l=Math.min(l,g):L(l,n).time!==t&&(l=Math.max(l,g))}return l}function D(e){let[t,n]=e.split(":").map(Number);return t*60+n}function Y(e){let t=Math.floor(e/60),n=e%60;return`${String(t).padStart(2,"0")}:${String(n).padStart(2,"0")}`}function I(e,t){let[n,o,r]=e.split("-").map(Number);return new Date(Date.UTC(n,o-1,r+t)).toISOString().slice(0,10)}function Ye(e,t){let[n,o,r]=e.split("-").map(Number),[i,s,a]=t.split("-").map(Number);return Math.round((Date.UTC(n,o-1,r)-Date.UTC(i,s-1,a))/864e5)}function $(e){let[t,n,o]=e.split("-").map(Number);return new Date(Date.UTC(t,n-1,o)).getUTCDay()}function B(e){return new Date(e).toISOString()}function Te(e,t){var r,i;let n=t.target,o=n.values.map(s=>String(s).toLowerCase());switch(n.type){case"product":return o.includes(String(e.productId).toLowerCase());case"variant":return o.includes(String(e.variantId).toLowerCase());case"collection":return((r=e.collectionIds)!=null?r:[]).some(s=>o.includes(String(s).toLowerCase()));case"vendor":return!!e.vendor&&o.includes(e.vendor.toLowerCase());case"productType":return!!e.productType&&o.includes(e.productType.toLowerCase());case"tag":return((i=e.tags)!=null?i:[]).some(s=>o.includes(s.toLowerCase()))}}function E(e,t,n){return{code:"BLOCKED_BY_PRODUCT",message:e.message||n.replace("{item}",t.title),ruleId:e.id}}function F(e,t,n="longest"){var a,u,d,l;let o={allowedMethods:new Set(H),methodReasons:new Map,allowedLocations:null,locationReasons:[],extraPrepMinutes:0,blockedWeekdays:new Map,blockedDates:new Map,windows:[],freshness:[],requiresScheduling:!1,matched:[]},r=t.filter(c=>c.enabled).sort((c,g)=>c.priority-g.priority),i=[],s=0;for(let c of e.items){let g=0,y;for(let m of r){if(!Te(c,m))continue;o.matched.push({ruleId:m.id,ruleName:m.name,itemTitle:c.title});let f=m.action;switch(f.type){case"allowOnlyMethods":for(let h of H)!f.methods.includes(h)&&o.allowedMethods.has(h)&&(o.allowedMethods.delete(h),ve(o.methodReasons,h,{...E(m,c,`{item} is only available for ${f.methods.join(" or ")}`),code:"METHOD_PROHIBITED_BY_PRODUCT"}));break;case"prohibitMethods":for(let h of f.methods)i.push({m:h,reason:{...E(m,c,`{item} can't be sent by ${h}`),code:"METHOD_PROHIBITED_BY_PRODUCT"}});break;case"restrictLocations":{let h=new Set(f.locationIds);o.allowedLocations=o.allowedLocations?new Set([...o.allowedLocations].filter(C=>h.has(C))):h,o.locationReasons.push({...E(m,c,"{item} is only available from selected locations"),code:"LOCATION_PROHIBITED_BY_PRODUCT"});break}case"addPrep":g+=f.minutes,y=m.id;break;case"blockWeekdays":for(let h of f.weekdays)o.blockedWeekdays.has(h)||o.blockedWeekdays.set(h,E(m,c,"{item} isn't available on this day"));break;case"blockDates":for(let h of f.dates)o.blockedDates.has(h)||o.blockedDates.set(h,E(m,c,"{item} isn't available on this date"));break;case"dateWindow":o.windows.push({from:f.from,to:f.to,reason:E(m,c,"{item} is only available in a limited window")});break;case"freshness":o.freshness.push({ruleId:m.id,itemTitle:c.title,arrivals:f.arrivals,minDaysAfterArrival:f.minDaysAfterArrival,shelfLifeDays:f.shelfLifeDays,message:m.message});break;case"requireScheduling":o.requiresScheduling=!0;break}}n==="sum"&&(s+=g),g>((u=(a=o.prepDriver)==null?void 0:a.minutes)!=null?u:0)&&y&&(o.prepDriver={itemTitle:c.title,ruleId:y,minutes:g})}for(let{m:c,reason:g}of i)o.allowedMethods.delete(c),ve(o.methodReasons,c,g);return o.extraPrepMinutes=n==="sum"?s:(l=(d=o.prepDriver)==null?void 0:d.minutes)!=null?l:0,o}function ve(e,t,n){var r;let o=(r=e.get(t))!=null?r:[];o.some(i=>i.ruleId===n.ruleId&&i.message===n.message)||o.push(n),e.set(t,o)}function G(e,t,n){for(let o of e){let r=o.arrivals.filter(s=>{var a;return!((a=s.locationIds)!=null&&a.length)||s.locationIds.includes(n)});if(!r.length)return{code:"NO_STOCK_ARRIVAL",message:o.message||`${o.itemTitle}: no fresh stock is scheduled for this location yet`,ruleId:o.ruleId};if(!r.some(s=>t>=I(s.date,o.minDaysAfterArrival)&&t<=I(s.date,o.shelfLifeDays))){let s=r.map(a=>I(a.date,o.minDaysAfterArrival)).filter(a=>a>t).sort()[0];return s?{code:"NOT_FRESH_YET",message:o.message||`${o.itemTitle}: next fresh batch is ready from ${s}`,ruleId:o.ruleId}:{code:"PAST_FRESHNESS",message:o.message||`${o.itemTitle}: outside its freshness window on this date`,ruleId:o.ruleId}}}return null}function q(e){return(e||"").toUpperCase().replace(/[\s-]/g,"")}function Me(e,t){let n=q(e),o=t.trim().toUpperCase();if(!n||!o)return!1;if(o.includes("..")){let[i,s]=o.split("..").map(q);if(!i||i.length!==s.length)return!1;let a=n.slice(0,i.length);return a>=i&&a<=s}let r=q(o);return r.endsWith("*")?n.startsWith(r.slice(0,-1)):n===r||r.length===3&&n.startsWith(r)}function Z(e,t,n,o){let i=d=>d*Math.PI/180,s=i(n-e),a=i(o-t),u=Math.sin(s/2)**2+Math.cos(i(e))*Math.cos(i(n))*Math.sin(a/2)**2;return 2*6371*Math.asin(Math.sqrt(u))}function J(e,t){var r,i;let n=e.lat!=null&&e.lng!=null&&t.lat!=null&&t.lng!=null?Z(e.lat,e.lng,t.lat,t.lng):null,o=!1;for(let s of e.zones){if((r=s.postalPatterns)!=null&&r.length&&t.postal&&s.postalPatterns.some(a=>Me(t.postal,a)))return{zone:s,distanceKm:n};if(s.radiusKm!=null&&n!=null&&n<=s.radiusKm)return{zone:s,distanceKm:n};if(s.drivingKm!=null){let a=(i=t.drivingKm)==null?void 0:i[e.id];if(a==null)o=!0;else if(a<=s.drivingKm)return{zone:s,distanceKm:a}}}return{zone:null,distanceKm:n,unverified:o,reason:{code:"OUTSIDE_DELIVERY_AREA",message:o?"We couldn't verify your address right now. Please try pickup or check again shortly.":`${e.name} doesn't deliver to this address yet`}}}function ee(e,t,n=[]){var a,u;let o=(a=e==null?void 0:e.fee)!=null?a:0,r=(e==null?void 0:e.freeOver)!=null&&t>=e.freeOver,i=n.filter(d=>d.amount>0),s=(u=e==null?void 0:e.minOrder)!=null?u:null;return{baseFee:o,waived:r,surcharges:i,fee:(r?0:o)+i.reduce((d,l)=>d+l.amount,0),belowMinimum:s!=null&&t<s,minOrder:s}}var z=(e,t,n)=>`${e}|${t}|${n}`,we=(e,t)=>`${e}-${t}`;function te(e,t,n){var i,s;let o=e.methods[t],r=e.exceptions.find(a=>{var u;return a.date===n&&(!((u=a.methods)!=null&&u.length)||a.methods.includes(t))});return r!=null&&r.closed?{hours:[],exception:{code:"CLOSED_EXCEPTION",message:r.note||"Closed on this date"}}:(i=r==null?void 0:r.hours)!=null&&i.length?{hours:r.hours,special:!0}:{hours:(s=o==null?void 0:o.weeklyHours[$(n)])!=null?s:[]}}function j(e,t,n,o){var r;return(r=e.find(i=>{var s,a;return i.dates.includes(o)&&(!((s=i.locationIds)!=null&&s.length)||i.locationIds.includes(t))&&(!((a=i.methods)!=null&&a.length)||i.methods.includes(n))}))!=null?r:null}function qe(e,t,n,o){var s,a;if(!n.length)return[];if(e.slotMode==="dateOnly")return[{start:n[0].start,end:n[n.length-1].end}];if(e.slotMode==="explicit"&&!o)return((a=(s=e.slots)==null?void 0:s[$(t)])!=null?a:[]).filter(d=>n.some(l=>D(d.start)>=D(l.start)&&D(d.end)<=D(l.end)));let r=e.slotMinutes||60,i=[];for(let u of n)for(let d=D(u.start);d+r<=D(u.end);d+=r)i.push({start:Y(d),end:Y(d+r)});return i}function Oe(e,t,n,o){if(t<=0)return e;let r=t*6e4,i=L(e,n.timezone).date;for(let s=0;s<400;s++,i=I(i,1))for(let a of te(n,o,i).hours){let u=v(i,a.start,n.timezone),d=v(i,a.end,n.timezone);if(d<=e)continue;let l=Math.max(u,e),c=d-l;if(r<=c)return l+r;r-=c}return Number.POSITIVE_INFINITY}function V(e){var f,h,C,M,w,P,N,_,ie,ae,le,de,ue,ce;let{location:t,method:n,now:o,usage:r}=e,i=t.timezone,s=t.methods[n],a=(f=e.constraints)!=null?f:F(e.cart,e.rules,e.settings.mixedPrepPolicy),u=[];t.enabled||u.push({code:"LOCATION_DISABLED",message:`${t.name} isn't taking bookings right now`}),s!=null&&s.enabled||u.push({code:"METHOD_DISABLED",message:`${t.name} doesn't offer ${n}`}),a.allowedMethods.has(n)||u.push(...(h=a.methodReasons.get(n))!=null?h:[]),a.allowedLocations&&!a.allowedLocations.has(t.id)&&u.push(...a.locationReasons);let d=((C=s==null?void 0:s.prepMinutes)!=null?C:0)+a.extraPrepMinutes,l=new Map,c=x=>(l.has(x)||l.set(x,(s==null?void 0:s.prepMode)==="operating"?Oe(o,x,t,n):o+x*6e4),l.get(x)),g={locationId:t.id,method:n,timezone:i,dateOnly:(s==null?void 0:s.slotMode)==="dateOnly",prepMinutes:d,earliestReadyUtc:B(c(d)),blockers:u,dates:[]};if(u.length||!s)return g;let y=L(o,i),m=Math.min(s.horizonDays,(M=e.maxDays)!=null?M:s.horizonDays);for(let x=0;x<m;x++){let R=I(y.date,x),me=$(R),p=j(e.peakDays,t.id,n,R),k={date:R,weekday:me,available:!1,remaining:null,peak:p?{id:p.id,name:p.name,message:p.message}:null,surcharge:(w=p==null?void 0:p.surcharge)!=null?w:0,waitlist:!1,reasons:[],slots:[]};g.dates.push(k);let ge=a.blockedWeekdays.get(me);ge&&k.reasons.push(ge);let fe=a.blockedDates.get(R);fe&&k.reasons.push(fe);for(let b of a.windows)(b.from&&R<b.from||b.to&&R>b.to)&&k.reasons.push(b.reason);let he=G(a.freshness,R,t.id);if(he&&k.reasons.push(he),k.reasons.length)continue;let{hours:pe,exception:ye,special:Pe}=te(t,n,R);if(ye){k.reasons.push(ye);continue}if(!pe.length){k.reasons.push({code:"CLOSED_WEEKLY",message:"Closed on this day"});continue}if(x===0&&s.sameDayCutoff&&y.minutes>=D(s.sameDayCutoff)){k.reasons.push({code:"PAST_CUTOFF",message:`Same-day orders close at ${s.sameDayCutoff}`});continue}if(x===1&&s.nextDayCutoff&&y.minutes>=D(s.nextDayCutoff)){k.reasons.push({code:"PAST_CUTOFF",message:`Next-day orders close at ${s.nextDayCutoff}`});continue}if(p!=null&&p.cutoff){let b=v(I(R,-p.cutoff.daysBefore),p.cutoff.time,i);if(o>=b){k.reasons.push({code:"PEAK_CUTOFF",message:`${p.name} orders closed on ${I(R,-p.cutoff.daysBefore)} at ${p.cutoff.time}`});continue}}let be=c(d+((P=p==null?void 0:p.extraPrepMinutes)!=null?P:0)),_e=z(t.id,n,R),ke=(N=r[_e])!=null?N:{day:0,slots:{}},Re=(ie=(_=p==null?void 0:p.dailyCapacity)!=null?_:s.dailyCapacity)!=null?ie:null,A=Re==null?null:Math.max(0,Re-ke.day);k.remaining=A;let Ce=qe(s,R,pe,!!Pe);if(!Ce.length){k.reasons.push({code:"CLOSED_WEEKLY",message:"No time slots on this day"});continue}for(let b of Ce){let U=v(R,b.start,i),T=v(R,b.end,i),Se=we(b.start,b.end),S={id:Se,start:b.start,end:b.end,startUtc:B(U),endUtc:B(T),available:!1,remaining:null,surcharge:(ae=b.surcharge)!=null?ae:0,waitlist:!1,reasons:[]};if(k.slots.push(S),g.dateOnly?T<=o?S.reasons.push({code:"SLOT_IN_PAST",message:"Closed for today"}):be>T&&S.reasons.push({code:"PREP_TIME",message:"Not enough preparation time"}):U<=o?S.reasons.push({code:"SLOT_IN_PAST",message:"This time has passed"}):be>U&&S.reasons.push({code:"PREP_TIME",message:"Not enough preparation time"}),S.reasons.length)continue;let xe=(ue=(de=(le=p==null?void 0:p.slotCapacity)!=null?le:b.capacity)!=null?de:s.slotCapacity)!=null?ue:null,Ae=(ce=ke.slots[Se])!=null?ce:0,W=xe==null?null:Math.max(0,xe-Ae);if(S.remaining=W==null?A:A==null?W:Math.min(W,A),A===0?S.reasons.push({code:"DAY_FULL",message:"Fully booked for this day"}):W===0&&S.reasons.push({code:"SLOT_FULL",message:"This time slot is full"}),S.reasons.length){S.waitlist=!!(p!=null&&p.waitlist);continue}S.available=!0}if(k.available=k.slots.some(b=>b.available),k.waitlist=!k.available&&k.slots.some(b=>b.waitlist),!k.available){let b=new Set;for(let U of k.slots)for(let T of U.reasons)b.has(T.code)||(b.add(T.code),k.reasons.push(T))}}return g}function ne(e){for(let t of e.dates){let n=t.slots.find(o=>o.available);if(n)return{date:t.date,slot:n}}return null}function Ze(e,t,n){let o=V(e);if(o.blockers.length)return{ok:!1,reasons:o.blockers};let r=o.dates.find(s=>s.date===t);if(!r)return{ok:!1,reasons:[{code:"BEYOND_HORIZON",message:"This date can't be booked"}]};let i=r.slots.find(s=>s.id===n);return i?i.available?{ok:!0,slot:i,date:r}:{ok:!1,reasons:i.reasons.length?i.reasons:r.reasons}:{ok:!1,reasons:r.reasons.length?r.reasons:[{code:"CLOSED_WEEKLY",message:"Slot not offered"}]}}function ze(e,t,n,o,r){var u,d,l,c,g,y;let i=e.methods[t],s=j(r,e.id,t,n),a;if((i==null?void 0:i.slotMode)==="explicit"){let[m,f]=o.split("-");for(let h of Object.values((u=i.slots)!=null?u:{}))for(let C of h!=null?h:[])C.start===m&&C.end===f&&C.capacity!=null&&(a=C.capacity)}return{dayCap:(l=(d=s==null?void 0:s.dailyCapacity)!=null?d:i==null?void 0:i.dailyCapacity)!=null?l:null,slotCap:(y=(g=(c=s==null?void 0:s.slotCapacity)!=null?c:a)!=null?g:i==null?void 0:i.slotCapacity)!=null?y:null}}var se=class{constructor(){O(this,"holds",new Map);O(this,"bookings",new Map);O(this,"waitlist",[]);O(this,"audit",[]);O(this,"seq",0)}counts(t,n,o,r){let i=0,s=0,a=u=>u.locationId===t.locationId&&u.method===t.method&&u.date===t.date;for(let u of this.bookings.values()){if(u.id===r||u.status!=="confirmed")continue;let d={locationId:u.locationId,method:u.method,date:u.date,slot:`${u.slotStart}-${u.slotEnd}`};a(d)&&(i++,d.slot===t.slot&&s++)}for(let u of this.holds.values())u.token===o||u.expiresAt<=n||a(u)&&(i++,u.slot===t.slot&&s++);return{day:i,slot:s}}usage(t){let n={},o=r=>{var s,a;let i=z(r.locationId,r.method,r.date);(s=n[i])!=null||(n[i]={day:0,slots:{}}),n[i].day++,n[i].slots[r.slot]=((a=n[i].slots[r.slot])!=null?a:0)+1};for(let r of this.bookings.values())r.status==="confirmed"&&o({locationId:r.locationId,method:r.method,date:r.date,slot:`${r.slotStart}-${r.slotEnd}`});for(let r of this.holds.values())r.expiresAt>t&&o(r);return n}fits(t,n,o,r,i){let s=this.counts(t,o,r,i);return n.dayCap!=null&&s.day>=n.dayCap?"DAY_FULL":n.slotCap!=null&&s.slot>=n.slotCap?"SLOT_FULL":null}hold(t,n,o,r,i){let s=this.fits(n,o,r,t);if(s)return{ok:!1,code:s,message:s==="DAY_FULL"?"Fully booked for this day":"This time slot was just taken"};let a={...n,token:t,expiresAt:r+i*6e4};return this.holds.set(t,a),{ok:!0,hold:a}}release(t){this.holds.delete(t)}sweep(t){let n=0;for(let[o,r]of this.holds)r.expiresAt<=t&&(this.holds.delete(o),n++);return n}confirm(t,n,o,r,i,s){let a=[...this.bookings.values()].find(m=>m.orderId===t);if(a)return{ok:!0,booking:a,duplicate:!0};let u=n?this.holds.get(n):void 0,d=u!=null?u:o,l=`bk_${++this.seq}`,c=m=>({...s,id:l,orderId:t,status:m,method:d.method,locationId:d.locationId,date:d.date,slotStart:d.slot.split("-")[0],slotEnd:d.slot.split("-")[1],rescheduleCount:0});if(!d){let m={...s,id:l,orderId:t,status:"needs_review",method:"pickup",locationId:"",date:""};return this.bookings.set(l,m),{ok:!1,booking:m,code:"NEEDS_REVIEW",message:"Order has no scheduling data"}}let g=u&&u.expiresAt>i;if(!g){let m=this.fits(d,r,i,n!=null?n:void 0);if(m){let f=c("needs_review");return this.bookings.set(l,f),n&&this.holds.delete(n),this.log(i,"system",l,"flagged",void 0,{reason:m}),{ok:!1,booking:f,code:"NEEDS_REVIEW",message:"Hold expired and the slot filled up"}}}let y=c("confirmed");return this.bookings.set(l,y),n&&this.holds.delete(n),this.log(i,"system",l,"confirmed"),{ok:!0,booking:y,duplicate:!1,reReserved:!g}}reschedule(t,n,o,r,i){var g;let s=this.bookings.get(t);if(!s||s.status!=="confirmed")return{ok:!1,message:"Booking can't be rescheduled"};let a=this.fits(n,o,r,void 0,t);if(a)return{ok:!1,message:a==="DAY_FULL"?"That day is fully booked":"That slot is full"};let u={...s},d={locationId:s.locationId,method:s.method,date:s.date,slot:`${s.slotStart}-${s.slotEnd}`},[l,c]=n.slot.split("-");return Object.assign(s,{locationId:n.locationId,method:n.method,date:n.date,slotStart:l,slotEnd:c,rescheduleCount:((g=s.rescheduleCount)!=null?g:0)+1}),this.log(r,i,t,"rescheduled",Q(u),Q(s)),{ok:!0,booking:s,freed:d}}cancel(t,n,o=!0){let r=[...this.bookings.values()].find(s=>s.orderId===t);if(!r||r.status==="cancelled")return r!=null?r:null;let i={...r};return r.status=o?"cancelled":r.status,this.log(n,"system",r.id,"cancelled",Q(i),Q(r)),r}joinWaitlist(t,n,o){let r={...t,id:`wl_${++this.seq}`,contact:n,createdAt:o};return this.waitlist.push(r),r}nextWaitlisted(t){var n;return(n=this.waitlist.find(o=>!o.notifiedAt&&o.locationId===t.locationId&&o.method===t.method&&o.date===t.date&&(o.slot===t.slot||o.slot==="*")))!=null?n:null}log(t,n,o,r,i,s){this.audit.push({at:t,actor:n,bookingId:o,action:r,before:i,after:s})}};function Q(e){return{locationId:e.locationId,method:e.method,date:e.date,slotStart:e.slotStart,slotEnd:e.slotEnd,status:e.status}}function oe(e,t,n){if(!e||!e[t])return!0;let o=e[t];return n.items.every(r=>{var i;return((i=o[r.variantId])!=null?i:0)>=r.quantity})}function je(e){var s,a,u;let t=F(e.cart,e.rules,e.settings.mixedPrepPolicy),n=(s=e.cart.subtotal)!=null?s:e.cart.items.reduce((d,l)=>d+l.price*l.quantity,0),o=[];for(let d of e.locations){let l={location:d,eligible:!0,reasons:[],distanceKm:null,first:null};if(o.push(l),e.method==="delivery"){let y=J(d,(a=e.address)!=null?a:{});l.zone=y,l.distanceKm=y.distanceKm,y.zone?(l.fee=ee(y.zone,n),l.fee.belowMinimum&&(l.eligible=!1,l.reasons.push({code:"BELOW_MINIMUM_ORDER",message:`Delivery needs a minimum order of $${(l.fee.minOrder/100).toFixed(2)}`}))):(l.eligible=!1,l.reasons.push(y.reason))}e.method!=="shipping"&&!oe(e.inventory,d.id,e.cart)&&(l.eligible=!1,l.reasons.push({code:"OUT_OF_STOCK_AT_LOCATION",message:`Not all items are in stock at ${d.name}`}));let c=V({...e,location:d,constraints:t});l.availability=c,c.blockers.length&&(l.eligible=!1,l.reasons.push(...c.blockers));let g=ne(c);l.first=g?{date:g.date,slot:g.slot.id}:null,l.eligible&&!g&&(l.eligible=!1,l.reasons.push({code:"DAY_FULL",message:"No available dates in the booking window"}))}let r=(u=e.ranking)!=null?u:"priority";o.sort((d,l)=>{if(d.eligible!==l.eligible)return d.eligible?-1:1;if(r==="distance"&&d.distanceKm!=null&&l.distanceKm!=null&&d.distanceKm!==l.distanceKm)return d.distanceKm-l.distanceKm;if(r==="earliest"&&d.first&&l.first){let c=`${d.first.date} ${d.first.slot}`,g=`${l.first.date} ${l.first.slot}`;if(c!==g)return c<g?-1:1}return d.location.priority-l.location.priority});let i=null;if(e.inventory&&e.method!=="shipping"&&!o.some(d=>d.eligible)){let d=e.cart.items.every(c=>e.locations.reduce((g,y)=>{var m,f;return g+((f=(m=e.inventory[y.id])==null?void 0:m[c.variantId])!=null?f:0)},0)>=c.quantity),l=e.locations.some(c=>oe(e.inventory,c.id,e.cart));d&&!l&&(i={code:"OUT_OF_STOCK_AT_LOCATION",message:"Your items are stocked at different locations. Choose shipping, or remove some items to schedule a single pickup or delivery."})}return{ranked:o,splitRequired:i}}function re(e){var t;return v(e.date,(t=e.slotStart)!=null?t:"00:00",e.timezone)}function Ve(e,t,n){var r;if(!t.enabled)return{ok:!1,reason:"Rescheduling isn't available for this store. Please contact us."};if(e.status!=="confirmed")return{ok:!1,reason:"This booking can't be changed."};if(((r=e.rescheduleCount)!=null?r:0)>=t.maxChanges)return{ok:!1,reason:`You've already changed this booking ${t.maxChanges} time(s). Please contact us.`};let o=re(e)-t.minHoursBefore*36e5;return n>=o?{ok:!1,reason:`Changes are allowed up to ${t.minHoursBefore} hours before your time slot.`}:{ok:!0,deadline:o}}function Qe(e,t,n,o={}){let r=re(e);return t.filter(i=>{var s;return i.enabled&&(!((s=i.methods)!=null&&s.length)||i.methods.includes(e.method))}).map(i=>{var s,a,u;return{policyId:i.id,channel:i.channel,sendAt:r-i.minutesBefore*6e4,body:Le(i.template,{name:(a=(s=e.customer)==null?void 0:s.name)!=null?a:"there",order:(u=e.orderName)!=null?u:"",date:e.date,time:e.slotStart&&e.slotEnd?`${e.slotStart}\u2013${e.slotEnd}`:"",method:e.method,...o})}}).filter(i=>i.sendAt>n).filter(i=>{var s,a;return i.channel==="email"?!!((s=e.customer)!=null&&s.email):!!((a=e.customer)!=null&&a.phone)})}function Le(e,t){return e.replace(/\{\{\s*(\w+)\s*\}\}/g,(n,o)=>{var r;return(r=t[o])!=null?r:""})}function Xe(e,t,n){var c,g,y;let o=e.filter(m=>m.method==="delivery"&&m.locationId===t.id&&m.date===n&&m.status==="confirmed"),r=o.filter(m=>{var f,h;return((f=m.address)==null?void 0:f.lat)!=null&&((h=m.address)==null?void 0:h.lng)!=null}),i=o.filter(m=>!r.includes(m)),s=new Map;for(let m of r){let f=`${m.slotStart}-${m.slotEnd}`;s.set(f,[...(c=s.get(f))!=null?c:[],m])}let a=[],u={lat:(g=t.lat)!=null?g:0,lng:(y=t.lng)!=null?y:0},d=0,l=t.lat!=null&&t.lng!=null;for(let m of[...s.keys()].sort()){let f=[...s.get(m)];for(;f.length;){let h=0,C=1/0;f.forEach((P,N)=>{let _=Z(u.lat,u.lng,P.address.lat,P.address.lng);_<C&&(C=_,h=N)});let[M]=f.splice(h,1),w=l||a.length?C:null;w!=null&&(d+=w),a.push({seq:a.length+1,booking:M,window:m,legKm:w}),u={lat:M.address.lat,lng:M.address.lng}}}return{locationId:t.id,date:n,stops:a,totalKm:a.length?Math.round(d*10)/10:null,unlocated:i,mapsUrls:Ee(t,a)}}function Ee(e,t){if(!t.length)return[];let n=s=>`${s.address.lat},${s.address.lng}`,o=e.lat!=null?`${e.lat},${e.lng}`:encodeURIComponent(e.address),r=[],i=o;for(let s=0;s<t.length;s+=10){let a=t.slice(s,s+10),u=n(a[a.length-1].booking),d=a.slice(0,-1).map(l=>n(l.booking)).join("|");r.push(`https://www.google.com/maps/dir/?api=1&origin=${i}&destination=${u}`+(d?`&waypoints=${encodeURIComponent(d)}`:"")+"&travelmode=driving"),i=u}return r}function Ge(e,t){var r;let n=t!=null?t:Object.keys((r=e[0])!=null?r:{}),o=i=>{let s=i==null?"":String(i);return/[",\r\n]/.test(s)?`"${s.replace(/"/g,'""')}"`:s};return"\uFEFF"+[n.join(","),...e.map(i=>n.map(s=>o(i[s])).join(","))].join(`\r
|
|
`)}return Ke(Je);})();
|