@stacksjs/commerce 0.75.112 → 0.75.113
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/dist/auctions/bids/fetch.js +1 -0
- package/dist/auctions/bids/index.js +1 -0
- package/dist/auctions/bids/place.js +1 -0
- package/dist/auctions/engine/anti-snipe.js +1 -0
- package/dist/auctions/engine/increments.js +1 -0
- package/dist/auctions/engine/index.js +1 -0
- package/dist/auctions/engine/proxy.js +1 -0
- package/dist/auctions/engine/winners.js +1 -0
- package/dist/auctions/index.js +1 -0
- package/dist/auctions/lots/fetch.js +1 -0
- package/dist/auctions/lots/index.js +1 -0
- package/dist/auctions/lots/lifecycle.js +1 -0
- package/dist/auctions/notifications.js +1 -0
- package/dist/auctions/pledges/index.js +1 -0
- package/dist/auctions/realtime.js +1 -0
- package/dist/auctions/rules.js +1 -0
- package/dist/auctions/types.js +0 -0
- package/dist/carts/destroy.js +1 -0
- package/dist/carts/fetch.js +1 -0
- package/dist/carts/index.js +1 -0
- package/dist/carts/store.js +1 -0
- package/dist/carts/update.js +1 -0
- package/dist/catalog.js +1 -2
- package/dist/coupons/destroy.js +1 -0
- package/dist/coupons/fetch.js +1 -0
- package/dist/coupons/index.js +1 -0
- package/dist/coupons/store.js +1 -0
- package/dist/coupons/update.js +7 -0
- package/dist/customers/destroy.js +1 -0
- package/dist/customers/fetch.js +1 -0
- package/dist/customers/index.js +1 -0
- package/dist/customers/store.js +1 -0
- package/dist/customers/update.js +1 -0
- package/dist/devices/destroy.js +1 -0
- package/dist/devices/export.js +1 -0
- package/dist/devices/fetch.js +1 -0
- package/dist/devices/index.js +1 -0
- package/dist/devices/store.js +1 -0
- package/dist/devices/update.js +1 -0
- package/dist/errors/destroy.js +1 -0
- package/dist/errors/fetch.js +1 -0
- package/dist/errors/index.js +1 -0
- package/dist/errors/update.js +1 -0
- package/dist/gift-cards/destroy.js +1 -0
- package/dist/gift-cards/fetch.js +1 -0
- package/dist/gift-cards/index.js +1 -0
- package/dist/gift-cards/store.js +1 -0
- package/dist/gift-cards/update.js +10 -0
- package/dist/imports/account-mapping.js +1 -0
- package/dist/imports/account-types.js +0 -0
- package/dist/imports/account-writer.js +1 -0
- package/dist/imports/admin-http.js +1 -0
- package/dist/imports/credentials.js +1 -0
- package/dist/imports/http.js +1 -0
- package/dist/imports/identity.js +1 -0
- package/dist/imports/index.js +1 -0
- package/dist/imports/money.js +1 -0
- package/dist/imports/shopify-admin.js +1 -0
- package/dist/imports/shopify.js +1 -0
- package/dist/imports/shopware-admin.js +1 -0
- package/dist/imports/shopware.js +1 -0
- package/dist/imports/text.js +1 -0
- package/dist/imports/types.js +0 -0
- package/dist/imports/woocommerce-admin.js +1 -0
- package/dist/imports/woocommerce.js +1 -0
- package/dist/imports/writer.js +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -28
- package/dist/inventory.d.ts +2 -0
- package/dist/inventory.js +1 -0
- package/dist/money.js +1 -2
- package/dist/orders/destroy.js +1 -0
- package/dist/orders/events.js +1 -0
- package/dist/orders/export.js +1 -0
- package/dist/orders/fetch.js +1 -0
- package/dist/orders/guards.js +1 -0
- package/dist/orders/index.js +1 -0
- package/dist/orders/place-order.js +1 -0
- package/dist/orders/store.js +1 -0
- package/dist/orders/totals.js +1 -0
- package/dist/orders/transition.js +1 -0
- package/dist/orders/update.js +1 -0
- package/dist/orders/webhook.js +1 -0
- package/dist/payments/destroy.js +1 -0
- package/dist/payments/fetch.js +1 -0
- package/dist/payments/index.js +1 -0
- package/dist/payments/store.js +1 -0
- package/dist/payments/update.js +8 -0
- package/dist/product.d.ts +1 -0
- package/dist/product.js +0 -0
- package/dist/products/categories/destroy.js +1 -0
- package/dist/products/categories/fetch.js +1 -0
- package/dist/products/categories/index.js +1 -0
- package/dist/products/categories/store.js +1 -0
- package/dist/products/categories/types.js +0 -0
- package/dist/products/categories/update.js +1 -0
- package/dist/products/index.js +1 -0
- package/dist/products/items/destroy.js +1 -0
- package/dist/products/items/fetch.js +1 -0
- package/dist/products/items/index.d.ts +1 -0
- package/dist/products/items/index.js +1 -0
- package/dist/products/items/store.js +1 -0
- package/dist/products/items/update.d.ts +2 -0
- package/dist/products/items/update.js +1 -0
- package/dist/products/manufacturers/destroy.js +1 -0
- package/dist/products/manufacturers/fetch.js +1 -0
- package/dist/products/manufacturers/index.js +1 -0
- package/dist/products/manufacturers/store.js +1 -0
- package/dist/products/manufacturers/update.js +1 -0
- package/dist/products/reviews/destroy.js +1 -0
- package/dist/products/reviews/fetch.js +1 -0
- package/dist/products/reviews/index.js +1 -0
- package/dist/products/reviews/stats.js +1 -0
- package/dist/products/reviews/store.js +1 -0
- package/dist/products/reviews/update.js +1 -0
- package/dist/products/units/destroy.js +1 -0
- package/dist/products/units/fetch.js +1 -0
- package/dist/products/units/index.js +1 -0
- package/dist/products/units/store.js +1 -0
- package/dist/products/units/types.js +0 -0
- package/dist/products/units/update.js +1 -0
- package/dist/products/variants/destroy.js +1 -0
- package/dist/products/variants/fetch.js +1 -0
- package/dist/products/variants/index.js +1 -0
- package/dist/products/variants/store.js +1 -0
- package/dist/products/variants/update.js +1 -0
- package/dist/receipts/destroy.js +1 -0
- package/dist/receipts/export.d.ts +1 -0
- package/dist/receipts/export.js +0 -0
- package/dist/receipts/fetch.js +1 -0
- package/dist/receipts/index.js +1 -0
- package/dist/receipts/printer.d.ts +37 -0
- package/dist/receipts/printer.js +1 -0
- package/dist/receipts/store.js +1 -0
- package/dist/receipts/timestamp.js +1 -0
- package/dist/receipts/update.js +1 -0
- package/dist/refund-allocation.js +1 -2
- package/dist/register.js +1 -2
- package/dist/releases.js +1 -2
- package/dist/sales-tax.js +1 -2
- package/dist/shippings/couriers/destroy.js +1 -0
- package/dist/shippings/couriers/fetch.js +1 -0
- package/dist/shippings/couriers/index.js +1 -0
- package/dist/shippings/couriers/store.js +1 -0
- package/dist/shippings/couriers/update.js +1 -0
- package/dist/shippings/delivery-routes/destroy.js +1 -0
- package/dist/shippings/delivery-routes/fetch.js +1 -0
- package/dist/shippings/delivery-routes/index.js +1 -0
- package/dist/shippings/delivery-routes/store.js +1 -0
- package/dist/shippings/delivery-routes/update.js +1 -0
- package/dist/shippings/delivery-routes/validate-write.js +1 -0
- package/dist/shippings/digital-deliveries/destroy.js +1 -0
- package/dist/shippings/digital-deliveries/fetch.js +1 -0
- package/dist/shippings/digital-deliveries/index.js +1 -0
- package/dist/shippings/digital-deliveries/store.js +1 -0
- package/dist/shippings/digital-deliveries/update.js +1 -0
- package/dist/shippings/geocoding/index.js +1 -0
- package/dist/shippings/geocoding/nominatim.js +1 -0
- package/dist/shippings/geocoding/types.js +1 -0
- package/dist/shippings/index.js +1 -0
- package/dist/shippings/license-keys/destroy.js +1 -0
- package/dist/shippings/license-keys/fetch.js +1 -0
- package/dist/shippings/license-keys/index.js +1 -0
- package/dist/shippings/license-keys/store.js +1 -0
- package/dist/shippings/license-keys/update.js +1 -0
- package/dist/shippings/license-keys/validate-write.js +1 -0
- package/dist/shippings/shipping-methods/destroy.js +1 -0
- package/dist/shippings/shipping-methods/fetch.js +1 -0
- package/dist/shippings/shipping-methods/index.js +1 -0
- package/dist/shippings/shipping-methods/store.js +1 -0
- package/dist/shippings/shipping-methods/update.js +1 -0
- package/dist/shippings/shipping-rates/destroy.js +1 -0
- package/dist/shippings/shipping-rates/fetch.js +1 -0
- package/dist/shippings/shipping-rates/index.js +1 -0
- package/dist/shippings/shipping-rates/store.js +1 -0
- package/dist/shippings/shipping-rates/update.js +1 -0
- package/dist/shippings/shipping-rates/validate-write.js +1 -0
- package/dist/shippings/shipping-zones/destroy.js +1 -0
- package/dist/shippings/shipping-zones/fetch.js +1 -0
- package/dist/shippings/shipping-zones/index.js +1 -0
- package/dist/shippings/shipping-zones/store.js +1 -0
- package/dist/shippings/shipping-zones/update.js +1 -0
- package/dist/shippings/tracking/events.js +1 -0
- package/dist/shippings/tracking/geo.js +1 -0
- package/dist/shippings/tracking/index.js +1 -0
- package/dist/shippings/tracking/ping.js +1 -0
- package/dist/shippings/tracking/stops.js +1 -0
- package/dist/shippings/write-data.js +1 -0
- package/dist/tax/breakdown.js +1 -0
- package/dist/tax/destroy.js +1 -0
- package/dist/tax/fetch.js +1 -0
- package/dist/tax/index.js +1 -0
- package/dist/tax/store.js +1 -0
- package/dist/tax/types.js +0 -0
- package/dist/tax/update.js +1 -0
- package/dist/tax-input.d.ts +7 -0
- package/dist/tax-input.js +1 -0
- package/dist/tests/fixtures/returning-all-writes.d.ts +1 -0
- package/dist/tests/fixtures/returning-all-writes.js +1 -0
- package/dist/tests/fixtures/soft-delete-counts.d.ts +1 -0
- package/dist/tests/fixtures/soft-delete-counts.js +1 -0
- package/dist/tests/fixtures/write-counts.d.ts +1 -0
- package/dist/tests/fixtures/write-counts.js +8 -0
- package/dist/tests/setup.d.ts +5 -0
- package/dist/tests/setup.js +1 -0
- package/dist/types.js +0 -0
- package/dist/utils/inserted-id.js +1 -0
- package/dist/utils/inventory-adjustment.js +5 -0
- package/dist/utils/model-row.js +1 -0
- package/dist/utils/mutation-count.js +1 -0
- package/dist/utils/typed-stats.js +1 -0
- package/dist/waitlists/index.js +1 -0
- package/dist/waitlists/products/destroy.js +1 -0
- package/dist/waitlists/products/export.d.ts +41 -0
- package/dist/waitlists/products/export.js +1 -0
- package/dist/waitlists/products/fetch.js +1 -0
- package/dist/waitlists/products/index.js +1 -0
- package/dist/waitlists/products/store.js +1 -0
- package/dist/waitlists/products/update.js +1 -0
- package/dist/waitlists/products/write-data.js +1 -0
- package/dist/waitlists/restaurant/destroy.js +1 -0
- package/dist/waitlists/restaurant/export.d.ts +39 -0
- package/dist/waitlists/restaurant/export.js +1 -0
- package/dist/waitlists/restaurant/fetch.js +1 -0
- package/dist/waitlists/restaurant/index.js +1 -0
- package/dist/waitlists/restaurant/store.js +1 -0
- package/dist/waitlists/restaurant/update.js +1 -0
- package/dist/waitlists/restaurant/write-data.js +1 -0
- package/package.json +13 -12
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{db}from"@stacksjs/database/runtime";import{asModelRow,asModelRows}from"../../utils/model-row";import{formatDate}from"@stacksjs/orm";export async function fetchById(id){const row=await db.selectFrom("waitlist_products").where("id","=",id).selectAll().executeTakeFirst();return asModelRow(row,!0)}export async function fetchAll(){return asModelRows(await db.selectFrom("waitlist_products").selectAll().execute())}export async function fetchCountBySource(startDate,_endDate){let query=db.selectFrom("waitlist_products").select(["source",db.fn.count("id").as("count")]).groupBy("source");if(startDate&&_endDate){const startDateStr=formatDate(startDate),endDateStr=formatDate(_endDate);query=query.where("created_at",">=",startDateStr).where("created_at","<=",endDateStr)}return(await query.execute()).reduce((acc,{source,count})=>{acc[source]=count;return acc},{})}export async function fetchCountByDate(date=new Date){const startOfDay=new Date(date);startOfDay.setHours(0,0,0,0);const endOfDay=new Date(date);endOfDay.setHours(23,59,59,999);const startDateStr=formatDate(startOfDay),endDateStr=formatDate(endOfDay);return(await db.selectFrom("waitlist_products").select(db.fn.count("id").as("count")).where("created_at",">=",startDateStr).where("created_at","<=",endDateStr).executeTakeFirst())?.count??0}export async function fetchCountByQuantity(quantity){return(await db.selectFrom("waitlist_products").select(db.fn.count("id").as("count")).where("quantity","=",quantity).executeTakeFirst())?.count??0}export async function fetchCountByAllQuantities(startDate,_endDate){let query=db.selectFrom("waitlist_products").select(["quantity",db.fn.count("id").as("count")]).groupBy("quantity");if(startDate&&_endDate){const startDateStr=formatDate(startDate),endDateStr=formatDate(_endDate);query=query.where("created_at",">=",startDateStr).where("created_at","<=",endDateStr)}return(await query.execute()).reduce((acc,{quantity,count})=>{acc[quantity]=count;return acc},{})}export async function fetchBetweenDates(startDate,endDate){const startDateStr=formatDate(startDate),endDateStr=formatDate(endDate),rows=await db.selectFrom("waitlist_products").selectAll().where("created_at",">=",startDateStr).where("created_at","<=",endDateStr).execute();return asModelRows(rows)}export async function fetchNotifiedBetweenDates(startDate,endDate){const startDateStr=formatDate(startDate),endDateStr=formatDate(endDate),rows=await db.selectFrom("waitlist_products").selectAll().where("notified_at",">=",startDateStr).where("notified_at","<=",endDateStr).whereNotNull("notified_at").execute();return asModelRows(rows)}export async function fetchPurchasedBetweenDates(startDate,endDate){const startDateStr=formatDate(startDate),endDateStr=formatDate(endDate),rows=await db.selectFrom("waitlist_products").selectAll().where("purchased_at",">=",startDateStr).where("purchased_at","<=",endDateStr).whereNotNull("purchased_at").execute();return asModelRows(rows)}export async function fetchCancelledBetweenDates(startDate,endDate){const startDateStr=formatDate(startDate),endDateStr=formatDate(endDate),rows=await db.selectFrom("waitlist_products").selectAll().where("cancelled_at",">=",startDateStr).where("cancelled_at","<=",endDateStr).whereNotNull("cancelled_at").execute();return asModelRows(rows)}export async function fetchWaiting(){const rows=await db.selectFrom("waitlist_products").selectAll().where("status","=","waiting").execute();return asModelRows(rows)}export async function fetchCountByStatus(status,startDate,_endDate){let query=db.selectFrom("waitlist_products").select(db.fn.count("id").as("count")).where("status","=",status);if(startDate&&_endDate){const startDateStr=formatDate(startDate),endDateStr=formatDate(_endDate);query=query.where("created_at",">=",startDateStr).where("created_at","<=",endDateStr)}return(await query.executeTakeFirst())?.count??0}export async function fetchConversionRates(_startDate,_endDate){let query=db.selectFrom("waitlist_products").select(["status",db.fn.count("id").as("count")]).groupBy("status");if(_startDate&&_endDate){const startDateStr=formatDate(_startDate),endDateStr=formatDate(_endDate);query=query.where("created_at",">=",startDateStr).where("created_at","<=",endDateStr)}const results=await query.execute(),totalCount=results.reduce((sum,{count})=>sum+count,0),purchasedCount=Number(results.find((r)=>r.status==="purchased")?.count??0),totalConversionRate=totalCount>0?purchasedCount/totalCount*100:0,statusBreakdown=results.reduce((acc,{status,count})=>{acc[status]={count,percentage:totalCount>0?count/totalCount*100:0};return acc},{});return{totalConversionRate,statusBreakdown}}export async function fetchCountBetweenDates(startDate,endDate){const startDateStr=formatDate(startDate),endDateStr=formatDate(endDate);return(await db.selectFrom("waitlist_products").select(db.fn.count("id").as("count")).where("created_at",">=",startDateStr).where("created_at","<=",endDateStr).executeTakeFirst())?.count??0}export async function fetchCountByDateGrouped(startDate,_endDate){let query=db.selectFrom("waitlist_products").select(["created_at"]);if(startDate&&_endDate){const startDateStr=formatDate(startDate),endDateStr=formatDate(_endDate);query=query.where("created_at",">=",startDateStr).where("created_at","<=",endDateStr)}const dateCounts=(await query.execute()).reduce((acc,{created_at})=>{const date=(created_at||"").split("T")[0]||"unknown";acc[date]=(acc[date]||0)+1;return acc},{});return Object.entries(dateCounts).map(([date,count])=>({date,count})).sort((a,b)=>a.date.localeCompare(b.date))}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{bulkDestroy,destroy}from"./destroy";export{fetchAll,fetchById,fetchCancelledBetweenDates,fetchConversionRates,fetchCountBetweenDates,fetchCountByAllQuantities,fetchCountByDate,fetchCountByDateGrouped,fetchCountByQuantity,fetchCountBySource,fetchCountByStatus,fetchNotifiedBetweenDates,fetchPurchasedBetweenDates,fetchWaiting}from"./fetch";export{bulkStore,store}from"./store";export{update,updatePartySize,updateStatus}from"./update";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{randomUUIDv7}from"bun";import{db}from"@stacksjs/database/runtime";import{asModelRow}from"../../utils/model-row";import{mutationCount}from"../../utils/mutation-count";import{productWaitlistWriteData}from"./write-data";export async function store(data){try{const uuid=randomUUIDv7(),waitlistData={...productWaitlistWriteData(data),uuid,status:data.status||"waiting"};await db.insertInto("waitlist_products").values(waitlistData).executeTakeFirst();const result=await db.selectFrom("waitlist_products").where("uuid","=",uuid).selectAll().executeTakeFirst();if(!result)throw Error("Failed to create waitlist product");return asModelRow(result)}catch(error){if(error instanceof Error)throw TypeError(`Failed to create waitlist product: ${error.message}`);throw error}}export async function bulkStore(data){if(!data.length)return 0;try{const waitlistDataArray=data.map((item)=>({...productWaitlistWriteData(item),status:item.status||"waiting",uuid:randomUUIDv7()})),result=await db.insertInto("waitlist_products").values(waitlistDataArray).executeTakeFirst();return mutationCount(result)}catch(error){if(error instanceof Error)throw TypeError(`Failed to create waitlist products in bulk: ${error.message}`);throw error}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{db}from"@stacksjs/database/runtime";import{asModelRow}from"../../utils/model-row";import{formatDate}from"@stacksjs/orm";import{fetchById}from"./fetch";import{productWaitlistWriteData}from"./write-data";export async function update(id,data){try{if(!id)throw Error("Waitlist product ID is required for update");const existing=await fetchById(id);if(!existing)return;await db.updateTable("waitlist_products").set({...productWaitlistWriteData(data,existing),updated_at:formatDate(new Date)}).where("id","=",id).execute();const result=await fetchById(id);if(!result)return;return asModelRow(result)}catch(error){if(error instanceof Error)throw TypeError(`Failed to update waitlist product: ${error.message}`);throw error}}export async function updateStatus(id,status){return await update(id,{status})}export async function updatePartySize(id,partySize){return await update(id,{quantity:partySize})}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{formatDate}from"@stacksjs/orm";const statusTimestamp={notified:"notified_at",purchased:"purchased_at",cancelled:"cancelled_at"};function dateValue(value){return typeof value==="number"||value instanceof Date?formatDate(value):value}export function productWaitlistWriteData(data,existing={}){const result=Object.fromEntries(Object.entries(data).filter(([,value])=>value!==void 0));if(result.quantity===void 0&&result.party_size!==void 0)result.quantity=result.party_size;delete result.party_size;for(const field of["notified_at","purchased_at","cancelled_at"])if(result[field]!==void 0)result[field]=dateValue(result[field]);const timestampField=statusTimestamp[result.status];if(timestampField&&result[timestampField]===void 0&&!existing[timestampField])result[timestampField]=formatDate(new Date);return result}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{db}from"@stacksjs/database/runtime";import{asModelRow}from"../../utils/model-row";import{mutationCount}from"../../utils/mutation-count";export async function destroy(id){try{const waitlistEntry=await db.selectFrom("waitlist_restaurants").where("id","=",id).selectAll().executeTakeFirst();if(!waitlistEntry)return;await db.deleteFrom("waitlist_restaurants").where("id","=",id).execute();return asModelRow(waitlistEntry)}catch(error){if(error instanceof Error)throw TypeError(`Failed to delete restaurant waitlist entry: ${error.message}`);throw error}}export async function bulkDestroy(ids){if(!ids.length)return 0;try{const result=await db.deleteFrom("waitlist_restaurants").where("id","in",ids).executeTakeFirst();return mutationCount(result)}catch(error){if(error instanceof Error)throw TypeError(`Failed to delete restaurant waitlist entries in bulk: ${error.message}`);throw error}}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ModelRow, WaitlistRestaurant } from '@stacksjs/orm';
|
|
2
|
+
import type { SpreadsheetWrapper } from 'ts-spreadsheets';
|
|
3
|
+
/**
|
|
4
|
+
* Export restaurant waitlist entries to a spreadsheet
|
|
5
|
+
* @param format The format of the spreadsheet (default is CSV)
|
|
6
|
+
* @returns Spreadsheet object ready for download or storage
|
|
7
|
+
*/
|
|
8
|
+
export declare function exportRestaurantWaitlist(format?: 'csv' | 'excel'): Promise<SpreadsheetWrapper>;
|
|
9
|
+
/**
|
|
10
|
+
* Export restaurant waitlist entries and automatically download
|
|
11
|
+
* @param format The format of the spreadsheet (default is CSV)
|
|
12
|
+
* @param filename Optional filename for the download
|
|
13
|
+
* @returns Download response
|
|
14
|
+
*/
|
|
15
|
+
export declare function downloadRestaurantWaitlist(format?: 'csv' | 'excel', filename?: string): Promise<Response>;
|
|
16
|
+
/**
|
|
17
|
+
* Store restaurant waitlist export to disk
|
|
18
|
+
* @param format The format of the spreadsheet (default is CSV)
|
|
19
|
+
* @param path Optional path to store the file
|
|
20
|
+
* @returns Path where the file is stored
|
|
21
|
+
*/
|
|
22
|
+
export declare function storeRestaurantWaitlistExport(format?: 'csv' | 'excel', path?: string): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Represents the structure of an exported restaurant waitlist entry
|
|
25
|
+
*/
|
|
26
|
+
export declare interface ExportedRestaurantWaitlist {
|
|
27
|
+
'ID': number
|
|
28
|
+
'Name': string
|
|
29
|
+
'Phone': string
|
|
30
|
+
'Party Size': number
|
|
31
|
+
'Table Preference': string
|
|
32
|
+
'Status': string
|
|
33
|
+
'Quoted Wait Time': number
|
|
34
|
+
'Actual Wait Time': number
|
|
35
|
+
'Check In Time': string
|
|
36
|
+
'Created At': string
|
|
37
|
+
'Notes': string
|
|
38
|
+
}
|
|
39
|
+
declare type WaitlistRestaurantJsonResponse = ModelRow<typeof WaitlistRestaurant>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createSpreadsheet}from"ts-spreadsheets";import{fetchAll}from"./fetch";export async function exportRestaurantWaitlist(format="csv"){const waitlistEntries=await fetchAll(),spreadsheetData=prepareRestaurantWaitlistForExport(waitlistEntries);return createSpreadsheet(spreadsheetData,{type:format})}function prepareRestaurantWaitlistForExport(waitlistEntries){const headings=["ID","Name","Phone","Party Size","Table Preference","Status","Quoted Wait Time","Actual Wait Time","Check In Time","Created At","Notes"],data=waitlistEntries.map((entry)=>{return[entry.id,entry.name,entry.phone||"N/A",entry.partySize,entry.tablePreference,entry.status,entry.quoted_wait_time||"N/A",entry.actual_wait_time||"N/A",entry.checkInTime||"N/A",entry.created_at,"N/A"]});return{headings,data}}export async function downloadRestaurantWaitlist(format="csv",filename){const spreadsheet=await exportRestaurantWaitlist(format),defaultFilename=`restaurant_waitlist_export_${new Date().toISOString().split("T")[0]}.${format}`;return spreadsheet.download(filename||defaultFilename)}export async function storeRestaurantWaitlistExport(format="csv",path){const spreadsheet=await exportRestaurantWaitlist(format),defaultPath=`restaurant_waitlist_export_${new Date().toISOString().split("T")[0]}.${format}`;spreadsheet.store(path||defaultPath)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{db}from"@stacksjs/database/runtime";import{asModelRow,asModelRows}from"../../utils/model-row";import{formatDate}from"@stacksjs/orm";export async function fetchById(id){const row=await db.selectFrom("waitlist_restaurants").where("id","=",id).selectAll().executeTakeFirst();return asModelRow(row,!0)}export async function fetchAll(){return asModelRows(await db.selectFrom("waitlist_restaurants").selectAll().execute())}export async function fetchCountByTablePreference(){return(await db.selectFrom("waitlist_restaurants").select(["table_preference",db.fn.count("id").as("count")]).groupBy("table_preference").execute()).reduce((acc,{table_preference,count})=>{acc[table_preference]=count;return acc},{})}export async function fetchCountByDate(date=new Date){const startOfDay=new Date(date);startOfDay.setHours(0,0,0,0);const endOfDay=new Date(date);endOfDay.setHours(23,59,59,999);const startDateStr=formatDate(startOfDay),endDateStr=formatDate(endOfDay);return(await db.selectFrom("waitlist_restaurants").select(db.fn.count("id").as("count")).where("created_at",">=",startDateStr).where("created_at","<=",endDateStr).executeTakeFirst())?.count??0}export async function fetchCountByPartySize(partySize){return(await db.selectFrom("waitlist_restaurants").select(db.fn.count("id").as("count")).where("party_size","=",partySize).executeTakeFirst())?.count??0}export async function fetchCountByAllPartySizes(){return(await db.selectFrom("waitlist_restaurants").select(["party_size",db.fn.count("id").as("count")]).groupBy("party_size").execute()).reduce((acc,{party_size,count})=>{acc[party_size]=count;return acc},{})}export async function fetchBetweenDates(startDate,_endDate){const startDateStr=formatDate(startDate),endDateStr=formatDate(_endDate),rows=await db.selectFrom("waitlist_restaurants").selectAll().where("created_at",">=",startDateStr).where("created_at","<=",endDateStr).execute();return asModelRows(rows)}export async function fetchSeatedBetweenDates(startDate,_endDate){const startDateStr=formatDate(startDate),endDateStr=formatDate(_endDate),rows=await db.selectFrom("waitlist_restaurants").selectAll().where("check_in_time",">=",startDateStr).where("check_in_time","<=",endDateStr).where("status","=","seated").execute();return asModelRows(rows)}export async function fetchWaiting(){const rows=await db.selectFrom("waitlist_restaurants").selectAll().where("status","=","waiting").execute();return asModelRows(rows)}export async function fetchConversionRates(){const results=await db.selectFrom("waitlist_restaurants").select(["status",db.fn.count("id").as("count")]).groupBy("status").execute(),totalCount=results.reduce((sum,{count})=>sum+count,0),seatedCount=results.find((r)=>r.status==="seated")?.count??0,totalConversionRate=totalCount>0?Number(seatedCount)/totalCount*100:0,statusBreakdown=results.reduce((acc,{status,count})=>{acc[status]={count,percentage:totalCount>0?count/totalCount*100:0};return acc},{});return{totalConversionRate,statusBreakdown}}export async function fetchAverageWaitTimes(){const result=await db.selectFrom("waitlist_restaurants").select([db.fn.avg("quoted_wait_time").as("avg_quoted_wait_time"),db.fn.avg("actual_wait_time").as("avg_actual_wait_time")]).executeTakeFirst();return{averageQuotedWaitTime:result?.avg_quoted_wait_time??0,averageActualWaitTime:result?.avg_actual_wait_time??0}}export async function fetchWaitingWithQuotedTimes(){const waitingEntries=asModelRows(await db.selectFrom("waitlist_restaurants").selectAll().where("status","=","waiting").execute()),totalQuotedWaitTime=waitingEntries.reduce((sum,entry)=>sum+(entry.quoted_wait_time??0),0),averageQuotedWaitTime=waitingEntries.length>0?totalQuotedWaitTime/waitingEntries.length:0;return{entries:waitingEntries,totalQuotedWaitTime,averageQuotedWaitTime}}export async function fetchWaitingWithPartySizes(){const waitingEntries=asModelRows(await db.selectFrom("waitlist_restaurants").selectAll().where("status","=","waiting").execute()),totalPartySize=waitingEntries.reduce((sum,entry)=>sum+entry.party_size,0),averagePartySize=waitingEntries.length>0?totalPartySize/waitingEntries.length:0,partySizeBreakdown=waitingEntries.reduce((acc,entry)=>{acc[entry.party_size]=(acc[entry.party_size]||0)+1;return acc},{});return{entries:waitingEntries,totalPartySize,averagePartySize,partySizeBreakdown}}export async function fetchTablesTurnedToday(){const today=new Date,startOfDay=new Date(today);startOfDay.setHours(0,0,0,0);const endOfDay=new Date(today);endOfDay.setHours(23,59,59,999);const startDateStr=formatDate(startOfDay),endDateStr=formatDate(endOfDay),seatedEntries=await db.selectFrom("waitlist_restaurants").selectAll().where("status","=","seated").where("check_in_time",">=",startDateStr).where("check_in_time","<=",endDateStr).execute(),totalTablesTurned=seatedEntries.length,totalCustomersSeated=seatedEntries.reduce((sum,entry)=>sum+entry.party_size,0),averagePartySize=totalTablesTurned>0?totalCustomersSeated/totalTablesTurned:0,breakdownByTablePreference=seatedEntries.reduce((acc,entry)=>{acc[entry.table_preference]=(acc[entry.table_preference]||0)+1;return acc},{}),breakdownByPartySize=seatedEntries.reduce((acc,entry)=>{acc[entry.party_size]=(acc[entry.party_size]||0)+1;return acc},{});return{totalTablesTurned,averagePartySize,totalCustomersSeated,breakdownByTablePreference,breakdownByPartySize}}export async function fetchSeatingRate(_startDate,_endDate){const startDateStr=formatDate(_startDate),endDateStr=formatDate(_endDate),results=await db.selectFrom("waitlist_restaurants").select(["status",db.fn.count("id").as("count")]).where("check_in_time",">=",startDateStr).where("check_in_time","<=",endDateStr).groupBy("status").execute(),totalEntries=results.reduce((sum,{count})=>sum+count,0),seatedCount=results.find((r)=>r.status==="seated")?.count??0,seatingRate=totalEntries>0?Number(seatedCount)/totalEntries*100:0,statusBreakdown=results.reduce((acc,{status,count})=>{acc[status]={count,percentage:totalEntries>0?count/totalEntries*100:0};return acc},{});return{totalEntries,seatedEntries:seatedCount,seatingRate,statusBreakdown}}export async function fetchNoShowStats(_startDate,_endDate){const startDateStr=formatDate(_startDate),endDateStr=formatDate(_endDate),noShowQuery=db.selectFrom("waitlist_restaurants").selectAll().where("status","=","no_show").where("check_in_time",">=",startDateStr).where("check_in_time","<=",endDateStr),totalResult=await db.selectFrom("waitlist_restaurants").select(db.fn.count("id").as("count")).where("check_in_time",">=",startDateStr).where("check_in_time","<=",endDateStr).executeTakeFirst(),noShowEntries=await noShowQuery.execute(),totalNoShows=noShowEntries.length,noShowRate=totalResult?.count&&totalResult.count>0?totalNoShows/totalResult.count*100:0,totalQuotedWaitTime=noShowEntries.reduce((sum,entry)=>sum+(entry.quoted_wait_time??0),0),averageQuotedWaitTime=totalNoShows>0?totalQuotedWaitTime/totalNoShows:0,totalPartySize=noShowEntries.reduce((sum,entry)=>sum+entry.party_size,0),averagePartySize=totalNoShows>0?totalPartySize/totalNoShows:0,breakdownByTablePreference=noShowEntries.reduce((acc,entry)=>{acc[entry.table_preference]=(acc[entry.table_preference]||0)+1;return acc},{}),breakdownByPartySize=noShowEntries.reduce((acc,entry)=>{acc[entry.party_size]=(acc[entry.party_size]||0)+1;return acc},{});return{totalNoShows,noShowRate,averageQuotedWaitTime,averagePartySize,breakdownByTablePreference,breakdownByPartySize}}export async function fetchCurrentWaitTimes(){const waitingEntries=await db.selectFrom("waitlist_restaurants").select(["quoted_wait_time","actual_wait_time"]).where("status","=","waiting").execute(),totalQuoted=waitingEntries.reduce((sum,entry)=>sum+(entry.quoted_wait_time||0),0),totalActual=waitingEntries.reduce((sum,entry)=>sum+(entry.actual_wait_time||0),0),count=waitingEntries.length;return{averageQuoted:count>0?totalQuoted/count:0,averageActual:count>0?totalActual/count:0}}export async function fetchSeatedStats(){const twentyFourHoursAgo=Date.now()-86400000,seatedEntries=await db.selectFrom("waitlist_restaurants").select(["seated_at"]).where("status","=","seated").where("seated_at",">=",twentyFourHoursAgo).execute(),byHour=Array.from({length:24},(_,hour)=>({hour,count:seatedEntries.filter((entry)=>{return entry.seated_at===hour}).length}));return{total:seatedEntries.length,byHour}}export async function fetchTimeSeriesStats(){return(await db.selectFrom("waitlist_restaurants").select(["created_at","status"]).execute()).reduce((acc,curr)=>{const date=curr.created_at;if(!acc[date])acc[date]={total:0,waiting:0,seated:0,cancelled:0,no_show:0};acc[date].total++;acc[date][curr.status]++;return acc},{})}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{bulkDestroy,destroy}from"./destroy";export{fetchAll,fetchAverageWaitTimes,fetchBetweenDates,fetchById,fetchConversionRates,fetchCountByAllPartySizes,fetchCountByDate,fetchCountByPartySize,fetchCountByTablePreference,fetchCurrentWaitTimes,fetchNoShowStats,fetchSeatedBetweenDates,fetchSeatedStats,fetchSeatingRate,fetchTablesTurnedToday,fetchTimeSeriesStats,fetchWaiting,fetchWaitingWithPartySizes,fetchWaitingWithQuotedTimes}from"./fetch";export{bulkStore,store}from"./store";export{update,updatePartySize,updateQueuePosition,updateStatus,updateWaitTimes}from"./update";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{randomUUIDv7}from"bun";import{db}from"@stacksjs/database/runtime";import{asModelRow}from"../../utils/model-row";import{mutationCount}from"../../utils/mutation-count";import{restaurantWaitlistWriteData}from"./write-data";export async function store(data){try{const uuid=randomUUIDv7(),waitlistData={...restaurantWaitlistWriteData(data),status:data.status||"waiting",uuid};await db.insertInto("waitlist_restaurants").values(waitlistData).executeTakeFirst();const result=await db.selectFrom("waitlist_restaurants").where("uuid","=",uuid).selectAll().executeTakeFirst();if(!result)throw Error("Failed to create restaurant waitlist entry");return asModelRow(result)}catch(error){if(error instanceof Error)throw TypeError(`Failed to create restaurant waitlist entry: ${error.message}`);throw error}}export async function bulkStore(data){if(!data.length)return 0;try{const waitlistDataArray=data.map((item)=>({...restaurantWaitlistWriteData(item),status:item.status||"waiting",uuid:randomUUIDv7()})),result=await db.insertInto("waitlist_restaurants").values(waitlistDataArray).executeTakeFirst();return mutationCount(result)}catch(error){if(error instanceof Error)throw TypeError(`Failed to create restaurant waitlist entries in bulk: ${error.message}`);throw error}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{db}from"@stacksjs/database/runtime";import{asModelRow}from"../../utils/model-row";import{formatDate}from"@stacksjs/orm";import{fetchById}from"./fetch";import{restaurantWaitlistWriteData}from"./write-data";export async function update(id,data){try{if(!id)throw Error("Restaurant waitlist entry ID is required for update");const existing=await fetchById(id);if(!existing)return;await db.updateTable("waitlist_restaurants").set({...restaurantWaitlistWriteData(data,existing),updated_at:formatDate(new Date)}).where("id","=",id).execute();const result=await fetchById(id);if(!result)return;return asModelRow(result)}catch(error){if(error instanceof Error)throw TypeError(`Failed to update restaurant waitlist entry: ${error.message}`);throw error}}export async function updateStatus(id,status){return await update(id,{status})}export async function updatePartySize(id,partySize){return await update(id,{party_size:partySize})}export async function updateWaitTimes(id,quotedWaitTime,actualWaitTime){return await update(id,{quoted_wait_time:quotedWaitTime,...actualWaitTime===void 0?{}:{actual_wait_time:actualWaitTime}})}export async function updateQueuePosition(id,queuePosition){return await update(id,{queue_position:queuePosition})}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{formatDate}from"@stacksjs/orm";const statusTimestamp={seated:"seated_at",no_show:"no_show_at",cancelled:"cancelled_at"};function timestamp(value){if(typeof value==="number")return formatDate(value<=2147483647?value*1000:value);if(value instanceof Date)return formatDate(value);return value}export function restaurantWaitlistWriteData(data,existing={}){const result=Object.fromEntries(Object.entries(data).filter(([,value])=>value!==void 0));for(const field of["check_in_time","seated_at","no_show_at","cancelled_at"])if(result[field]!==void 0)result[field]=timestamp(result[field]);const timestampField=statusTimestamp[result.status];if(timestampField&&result[timestampField]===void 0&&!existing[timestampField])result[timestampField]=formatDate(new Date);return result}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/commerce",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.75.
|
|
4
|
+
"version": "0.75.113",
|
|
5
5
|
"description": "Stacks commerce utilities.",
|
|
6
6
|
"author": "Chris Breuer",
|
|
7
7
|
"contributors": [
|
|
@@ -57,17 +57,18 @@
|
|
|
57
57
|
"prepublishOnly": "bun run build"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@stacksjs/cache": "0.75.
|
|
61
|
-
"@stacksjs/config": "0.75.
|
|
62
|
-
"@stacksjs/database": "0.75.
|
|
63
|
-
"@stacksjs/env": "0.75.
|
|
64
|
-
"@stacksjs/error-handling": "0.75.
|
|
65
|
-
"@stacksjs/events": "0.75.
|
|
66
|
-
"@stacksjs/logging": "0.75.
|
|
67
|
-
"@stacksjs/orm": "0.75.
|
|
68
|
-
"@stacksjs/payments": "0.75.
|
|
69
|
-
"@stacksjs/realtime": "0.75.
|
|
70
|
-
"@stacksjs/strings": "0.75.
|
|
60
|
+
"@stacksjs/cache": "0.75.113",
|
|
61
|
+
"@stacksjs/config": "0.75.113",
|
|
62
|
+
"@stacksjs/database": "0.75.113",
|
|
63
|
+
"@stacksjs/env": "0.75.113",
|
|
64
|
+
"@stacksjs/error-handling": "0.75.113",
|
|
65
|
+
"@stacksjs/events": "0.75.113",
|
|
66
|
+
"@stacksjs/logging": "0.75.113",
|
|
67
|
+
"@stacksjs/orm": "0.75.113",
|
|
68
|
+
"@stacksjs/payments": "0.75.113",
|
|
69
|
+
"@stacksjs/realtime": "0.75.113",
|
|
70
|
+
"@stacksjs/strings": "0.75.113",
|
|
71
|
+
"@stacksjs/validation": "0.75.113",
|
|
71
72
|
"ts-spreadsheets": "^0.2.0"
|
|
72
73
|
},
|
|
73
74
|
"devDependencies": {
|