Skip to content

Commit 73406b0

Browse files
chore: wip
1 parent dde71e3 commit 73406b0

35 files changed

+296
-67
lines changed

storage/framework/core/commerce/src/orders/fetch.ts

Lines changed: 251 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,11 @@
11
import type {
2-
OrderResponse,
32
OrderStats,
43
OrderType,
54
OrderTypeCount,
65
StatusCount,
76
} from '../../types'
87
import { db } from '@stacksjs/database'
98

10-
export interface FetchOrdersOptions {
11-
page?: number
12-
limit?: number
13-
search?: string
14-
status?: string
15-
order_type?: string
16-
customer_id?: number
17-
sortBy?: string
18-
sortOrder?: 'asc' | 'desc'
19-
from_date?: string
20-
to_date?: string
21-
}
22-
239
/**
2410
* Fetch all orders from the database with their items
2511
*/
@@ -57,26 +43,6 @@ export async function fetchById(id: number): Promise<OrderType | undefined> {
5743
return order
5844
}
5945

60-
/**
61-
* Fetch orders for a specific customer
62-
*/
63-
export async function fetchByCustomer(customerId: number, options: FetchOrdersOptions = {}): Promise<OrderResponse> {
64-
return fetchPaginated({
65-
...options,
66-
customer_id: customerId,
67-
})
68-
}
69-
70-
/**
71-
* Fetch orders by status
72-
*/
73-
export async function fetchByStatus(status: string, options: FetchOrdersOptions = {}): Promise<OrderResponse> {
74-
return fetchPaginated({
75-
...options,
76-
status,
77-
})
78-
}
79-
8046
/**
8147
* Get order statistics
8248
*/
@@ -137,3 +103,254 @@ export async function fetchStats(): Promise<OrderStats> {
137103
revenue: Number(revenue?.total || 0),
138104
}
139105
}
106+
107+
/**
108+
* Compare orders between different time periods
109+
* @param daysRange Number of days to look back (7, 30, 60, etc.)
110+
*/
111+
export async function compareOrdersByPeriod(daysRange: number = 30): Promise<{
112+
current_period: number
113+
previous_period: number
114+
difference: number
115+
percentage_change: number
116+
days_range: number
117+
}> {
118+
const today = new Date()
119+
120+
// Current period (last N days)
121+
const currentPeriodStart = new Date(today)
122+
currentPeriodStart.setDate(today.getDate() - daysRange)
123+
124+
// Previous period (N days before the current period)
125+
const previousPeriodEnd = new Date(currentPeriodStart)
126+
previousPeriodEnd.setDate(previousPeriodEnd.getDate() - 1)
127+
128+
const previousPeriodStart = new Date(previousPeriodEnd)
129+
previousPeriodStart.setDate(previousPeriodEnd.getDate() - daysRange)
130+
131+
// Get orders for current period
132+
const currentPeriodOrders = await db
133+
.selectFrom('orders')
134+
.select(db.fn.count('id').as('count'))
135+
.where('created_at', '>=', currentPeriodStart.toISOString())
136+
.where('created_at', '<=', today.toISOString())
137+
.executeTakeFirst()
138+
139+
// Get orders for previous period
140+
const previousPeriodOrders = await db
141+
.selectFrom('orders')
142+
.select(db.fn.count('id').as('count'))
143+
.where('created_at', '>=', previousPeriodStart.toISOString())
144+
.where('created_at', '<=', previousPeriodEnd.toISOString())
145+
.executeTakeFirst()
146+
147+
const currentCount = Number(currentPeriodOrders?.count || 0)
148+
const previousCount = Number(previousPeriodOrders?.count || 0)
149+
const difference = currentCount - previousCount
150+
151+
// Calculate percentage change, handling division by zero
152+
const percentageChange = previousCount !== 0
153+
? (difference / previousCount) * 100
154+
: (currentCount > 0 ? 100 : 0)
155+
156+
return {
157+
current_period: currentCount,
158+
previous_period: previousCount,
159+
difference,
160+
percentage_change: percentageChange,
161+
days_range: daysRange,
162+
}
163+
}
164+
165+
/**
166+
* Calculate order values and metrics for different time periods
167+
* @param daysRange Number of days to look back (7, 30, 60, etc.)
168+
*/
169+
export async function calculateOrderMetrics(daysRange: number = 30): Promise<{
170+
current_period: {
171+
total_orders: number
172+
total_revenue: number
173+
average_order_value: number
174+
orders_by_status: { status: string, count: number }[]
175+
orders_by_type: { order_type: string, count: number }[]
176+
}
177+
previous_period: {
178+
total_orders: number
179+
total_revenue: number
180+
average_order_value: number
181+
}
182+
comparison: {
183+
orders: {
184+
difference: number
185+
percentage: number
186+
is_increase: boolean
187+
}
188+
revenue: {
189+
difference: number
190+
percentage: number
191+
is_increase: boolean
192+
}
193+
average_order_value: {
194+
difference: number
195+
percentage: number
196+
is_increase: boolean
197+
}
198+
}
199+
days_range: number
200+
}> {
201+
const today = new Date()
202+
203+
// Current period (last N days)
204+
const currentPeriodStart = new Date(today)
205+
currentPeriodStart.setDate(today.getDate() - daysRange)
206+
207+
// Previous period (N days before the current period)
208+
const previousPeriodEnd = new Date(currentPeriodStart)
209+
previousPeriodEnd.setDate(previousPeriodEnd.getDate() - 1)
210+
211+
const previousPeriodStart = new Date(previousPeriodEnd)
212+
previousPeriodStart.setDate(previousPeriodEnd.getDate() - daysRange)
213+
214+
// Get values for current period
215+
const currentPeriodValues = await db
216+
.selectFrom('orders')
217+
.select([
218+
db.fn.count('id').as('total_orders'),
219+
db.fn.sum('total_amount').as('total_revenue'),
220+
])
221+
.where('created_at', '>=', currentPeriodStart.toISOString())
222+
.where('created_at', '<=', today.toISOString())
223+
.executeTakeFirst()
224+
225+
// Get values for previous period
226+
const previousPeriodValues = await db
227+
.selectFrom('orders')
228+
.select([
229+
db.fn.count('id').as('total_orders'),
230+
db.fn.sum('total_amount').as('total_revenue'),
231+
])
232+
.where('created_at', '>=', previousPeriodStart.toISOString())
233+
.where('created_at', '<=', previousPeriodEnd.toISOString())
234+
.executeTakeFirst()
235+
236+
// Get orders by status for current period
237+
const ordersByStatus = await db
238+
.selectFrom('orders')
239+
.select(['status', db.fn.count('id').as('count')])
240+
.where('created_at', '>=', currentPeriodStart.toISOString())
241+
.where('created_at', '<=', today.toISOString())
242+
.groupBy('status')
243+
.execute()
244+
245+
// Get orders by type for current period
246+
const ordersByType = await db
247+
.selectFrom('orders')
248+
.select(['order_type', db.fn.count('id').as('count')])
249+
.where('created_at', '>=', currentPeriodStart.toISOString())
250+
.where('created_at', '<=', today.toISOString())
251+
.groupBy('order_type')
252+
.execute()
253+
254+
// Calculate values for current period
255+
const currentTotalOrders = Number(currentPeriodValues?.total_orders || 0)
256+
const currentTotalRevenue = Number(currentPeriodValues?.total_revenue || 0)
257+
const currentAverageOrderValue = currentTotalOrders > 0
258+
? currentTotalRevenue / currentTotalOrders
259+
: 0
260+
261+
// Calculate values for previous period
262+
const previousTotalOrders = Number(previousPeriodValues?.total_orders || 0)
263+
const previousTotalRevenue = Number(previousPeriodValues?.total_revenue || 0)
264+
const previousAverageOrderValue = previousTotalOrders > 0
265+
? previousTotalRevenue / previousTotalOrders
266+
: 0
267+
268+
// Calculate differences
269+
const ordersDifference = currentTotalOrders - previousTotalOrders
270+
const revenueDifference = currentTotalRevenue - previousTotalRevenue
271+
const aovDifference = currentAverageOrderValue - previousAverageOrderValue
272+
273+
// Calculate percentage changes
274+
const ordersPercentageChange = previousTotalOrders !== 0
275+
? (ordersDifference / previousTotalOrders) * 100
276+
: (currentTotalOrders > 0 ? 100 : 0)
277+
278+
const revenuePercentageChange = previousTotalRevenue !== 0
279+
? (revenueDifference / previousTotalRevenue) * 100
280+
: (currentTotalRevenue > 0 ? 100 : 0)
281+
282+
const aovPercentageChange = previousAverageOrderValue !== 0
283+
? (aovDifference / previousAverageOrderValue) * 100
284+
: (currentAverageOrderValue > 0 ? 100 : 0)
285+
286+
return {
287+
current_period: {
288+
total_orders: currentTotalOrders,
289+
total_revenue: currentTotalRevenue,
290+
average_order_value: currentAverageOrderValue,
291+
orders_by_status: ordersByStatus.map(item => ({
292+
status: item.status,
293+
count: Number(item.count),
294+
})),
295+
orders_by_type: ordersByType.map(item => ({
296+
order_type: item.order_type,
297+
count: Number(item.count),
298+
})),
299+
},
300+
previous_period: {
301+
total_orders: previousTotalOrders,
302+
total_revenue: previousTotalRevenue,
303+
average_order_value: previousAverageOrderValue,
304+
},
305+
comparison: {
306+
orders: {
307+
difference: ordersDifference,
308+
percentage: Math.abs(ordersPercentageChange),
309+
is_increase: ordersDifference >= 0,
310+
},
311+
revenue: {
312+
difference: revenueDifference,
313+
percentage: Math.abs(revenuePercentageChange),
314+
is_increase: revenueDifference >= 0,
315+
},
316+
average_order_value: {
317+
difference: aovDifference,
318+
percentage: Math.abs(aovPercentageChange),
319+
is_increase: aovDifference >= 0,
320+
},
321+
},
322+
days_range: daysRange,
323+
}
324+
}
325+
326+
/**
327+
* Get daily order counts for a time period
328+
* @param daysRange Number of days to look back
329+
*/
330+
export async function fetchDailyOrderTrends(daysRange: number = 30): Promise<{
331+
date: Date
332+
order_count: number
333+
revenue: number
334+
}[]> {
335+
const today = new Date()
336+
const startDate = new Date(today)
337+
startDate.setDate(today.getDate() - daysRange)
338+
339+
// Query to get daily order counts and revenue
340+
const dailyOrders = await db
341+
.selectFrom('orders')
342+
.select([
343+
db.fn.count('id').as('order_count'),
344+
db.fn.sum('total_amount').as('revenue'),
345+
'created_at',
346+
])
347+
.where('created_at', '>=', startDate)
348+
.where('created_at', '<=', today)
349+
.execute()
350+
351+
return dailyOrders.map(day => ({
352+
date: day.created_at,
353+
order_count: Number(day.order_count || 0),
354+
revenue: Number(day.revenue || 0),
355+
}))
356+
}

storage/framework/core/commerce/src/payments/store.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export async function store(request: PaymentRequestType): Promise<PaymentJsonRes
1313

1414
const paymentData: NewPayment = {
1515
order_id: request.get<number>('order_id'),
16-
user_id: request.get<number>('user_id'),
16+
customer_id: request.get<number>('user_id'),
1717
amount: request.get<number>('amount'),
1818
method: request.get('method'),
1919
status: request.get('status') || 'PENDING',

storage/framework/core/commerce/types.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,3 +330,15 @@ export interface CouponRedemptionStats {
330330
year: number
331331
by_type: Record<string, number>
332332
}
333+
export interface FetchOrdersOptions {
334+
page?: number
335+
limit?: number
336+
search?: string
337+
status?: string
338+
order_type?: string
339+
customer_id?: number
340+
sortBy?: string
341+
sortOrder?: 'asc' | 'desc'
342+
from_date?: string
343+
to_date?: string
344+
}

storage/framework/core/orm/src/generate.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -871,7 +871,7 @@ export async function generateModelString(
871871

872872
if (useTimestamps) {
873873
fieldString += `
874-
created_at?: Date\n
874+
created_at: Date\n
875875
updated_at?: Date
876876
`
877877
}

storage/framework/orm/src/models/AccessToken.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export interface PersonalAccessTokensTable {
2727
device_name?: string
2828
is_single_use?: boolean
2929

30-
created_at?: Date
30+
created_at: Date
3131

3232
updated_at?: Date
3333

storage/framework/orm/src/models/Coupon.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export interface CouponsTable {
3131
applicable_categories?: string
3232
uuid?: string
3333

34-
created_at?: Date
34+
created_at: Date
3535

3636
updated_at?: Date
3737

storage/framework/orm/src/models/Customer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export interface CustomersTable {
2424
avatar?: string
2525
uuid?: string
2626

27-
created_at?: Date
27+
created_at: Date
2828

2929
updated_at?: Date
3030

storage/framework/orm/src/models/Deployment.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export interface DeploymentsTable {
2121
terminal_output: string
2222
uuid?: string
2323

24-
created_at?: Date
24+
created_at: Date
2525

2626
updated_at?: Date
2727

storage/framework/orm/src/models/Error.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export interface ErrorsTable {
1313
status: number
1414
additional_info?: string
1515

16-
created_at?: Date
16+
created_at: Date
1717

1818
updated_at?: Date
1919

storage/framework/orm/src/models/FailedJob.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export interface FailedJobsTable {
1313
exception: string
1414
failed_at?: Date | string
1515

16-
created_at?: Date
16+
created_at: Date
1717

1818
updated_at?: Date
1919

0 commit comments

Comments
 (0)