Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: stacksjs/stacks
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 18d3ace9af8209824834127edaaf028078e0e0bf
Choose a base ref
..
head repository: stacksjs/stacks
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 7a79fe0b562ab2b37f1b826f33fcd422cca25e94
Choose a head ref
Showing with 2,750 additions and 72 deletions.
  1. 0 ...base/migrations/{1742726743139-create-projects-table.ts → 1742737139847-create-projects-table.ts}
  2. 0 ...742726743157-create-subscriber_emails-table.ts → 1742737139864-create-subscriber_emails-table.ts}
  3. 0 ...73-create-personal_access_tokens-table.ts → 1742737139880-create-personal_access_tokens-table.ts}
  4. 0 .../migrations/{1742726743175-create-team_users-table.ts → 1742737139882-create-team_users-table.ts}
  5. 0 database/migrations/{1742726743187-create-teams-table.ts → 1742737139895-create-teams-table.ts}
  6. 0 ...igrations/{1742726743201-create-subscribers-table.ts → 1742737139909-create-subscribers-table.ts}
  7. 0 ...igrations/{1742726743215-create-deployments-table.ts → 1742737139926-create-deployments-table.ts}
  8. 0 ...base/migrations/{1742726743228-create-releases-table.ts → 1742737139941-create-releases-table.ts}
  9. 0 ...base/migrations/{1742726743240-create-passkeys-table.ts → 1742737139953-create-passkeys-table.ts}
  10. 0 database/migrations/{1742726743241-create-users-table.ts → 1742737139954-create-users-table.ts}
  11. 0 database/migrations/{1742726743254-create-posts-table.ts → 1742737139968-create-posts-table.ts}
  12. 0 .../migrations/{1742726743268-create-categories-table.ts → 1742737139981-create-categories-table.ts}
  13. 0 ...base/migrations/{1742726743281-create-payments-table.ts → 1742737139994-create-payments-table.ts}
  14. 0 ...tions/{1742726743295-create-manufacturers-table.ts → 1742737140007-create-manufacturers-table.ts}
  15. 0 ...igrations/{1742726743309-create-order_items-table.ts → 1742737140020-create-order_items-table.ts}
  16. +19 −0 database/migrations/1742737140035-create-shipping_zones-table.ts
  17. 0 ...se/migrations/{1742726743322-create-customers-table.ts → 1742737140048-create-customers-table.ts}
  18. 0 ...base/migrations/{1742726743335-create-products-table.ts → 1742737140061-create-products-table.ts}
  19. 0 ...{1742726743348-create-product_variants-table.ts → 1742737140074-create-product_variants-table.ts}
  20. 0 database/migrations/{1742726743360-create-reviews-table.ts → 1742737140087-create-reviews-table.ts}
  21. 0 ...tions/{1742726743373-create-product_units-table.ts → 1742737140100-create-product_units-table.ts}
  22. 0 .../migrations/{1742726743386-create-gift_cards-table.ts → 1742737140113-create-gift_cards-table.ts}
  23. 0 database/migrations/{1742726743398-create-orders-table.ts → 1742737140126-create-orders-table.ts}
  24. 0 database/migrations/{1742726743411-create-coupons-table.ts → 1742737140139-create-coupons-table.ts}
  25. 0 ...rations/{1742726743424-create-transactions-table.ts → 1742737140153-create-transactions-table.ts}
  26. 0 ...ons/{1742726743437-create-loyalty_points-table.ts → 1742737140166-create-loyalty_points-table.ts}
  27. 0 ...tions/{1742726743450-create-product_items-table.ts → 1742737140180-create-product_items-table.ts}
  28. 0 ...s/{1742726743462-create-loyalty_rewards-table.ts → 1742737140193-create-loyalty_rewards-table.ts}
  29. +1 −2 ...{1742726743476-create-shipping_methods-table.ts → 1742737140208-create-shipping_methods-table.ts}
  30. 0 ...igrations/{1742726743489-create-failed_jobs-table.ts → 1742737140222-create-failed_jobs-table.ts}
  31. 0 ...s/{1742726743502-create-payment_methods-table.ts → 1742737140235-create-payment_methods-table.ts}
  32. 0 ...743515-create-payment_transactions-table.ts → 1742737140248-create-payment_transactions-table.ts}
  33. 0 ...base/migrations/{1742726743529-create-requests-table.ts → 1742737140263-create-requests-table.ts}
  34. 0 database/migrations/{1742726743542-create-jobs-table.ts → 1742737140276-create-jobs-table.ts}
  35. 0 ...tions/{1742726743555-create-subscriptions-table.ts → 1742737140290-create-subscriptions-table.ts}
  36. 0 ...{1742726743568-create-payment_products-table.ts → 1742737140305-create-payment_products-table.ts}
  37. 0 database/migrations/{1742726743581-create-errors-table.ts → 1742737140320-create-errors-table.ts}
  38. +17 −0 storage/framework/actions/src/ShippingRateDestroyOrmAction.ts
  39. +13 −0 storage/framework/actions/src/ShippingRateIndexOrmAction.ts
  40. +17 −0 storage/framework/actions/src/ShippingRateShowOrmAction.ts
  41. +16 −0 storage/framework/actions/src/ShippingRateStoreOrmAction.ts
  42. +20 −0 storage/framework/actions/src/ShippingRateUpdateOrmAction.ts
  43. +13 −0 storage/framework/core/commerce/src/rates.ts/fetch.ts
  44. 0 storage/framework/core/commerce/src/rates.ts/store.ts
  45. +150 −0 storage/framework/core/commerce/src/rates/store.ts
  46. +1 −1 storage/framework/core/commerce/src/shipping/fetch.ts
  47. +27 −0 storage/framework/core/commerce/src/shipping/index.ts
  48. +1 −1 storage/framework/core/commerce/src/shipping/store.ts
  49. +0 −7 storage/framework/core/commerce/src/shipping/update.ts
  50. +2 −29 storage/framework/core/commerce/src/tests/shipping.test.ts
  51. +94 −0 storage/framework/core/commerce/src/tests/storage/logs/stacks.log
  52. +512 −0 storage/framework/core/commerce/src/tests/zones.test.ts
  53. +111 −0 storage/framework/core/commerce/src/zones/destroy.ts
  54. +13 −0 storage/framework/core/commerce/src/zones/fetch.ts
  55. +29 −0 storage/framework/core/commerce/src/zones/index.ts
  56. +179 −0 storage/framework/core/commerce/src/zones/store.ts
  57. +198 −0 storage/framework/core/commerce/src/zones/update.ts
  58. +1 −1 storage/framework/core/types/src/model-names.ts
  59. +1 −1 storage/framework/core/types/src/table-names.ts
  60. +1 −2 storage/framework/defaults/models/ecommerce/ShippingMethod.ts
  61. +102 −0 storage/framework/defaults/models/ecommerce/ShippingRate.ts
  62. +5 −27 storage/framework/models/ShippingMethod.ts
  63. +117 −0 storage/framework/models/ShippingZone.ts
  64. +10 −0 storage/framework/orm/routes.ts
  65. +2 −0 storage/framework/orm/src/index.ts
  66. +980 −0 storage/framework/orm/src/models/ShippingRate.ts
  67. +2 −0 storage/framework/orm/src/types.ts
  68. +44 −0 storage/framework/requests/ShippingRateRequest.ts
  69. +9 −0 storage/framework/server-auto-imports.json
  70. +4 −0 storage/framework/types/attributes.ts
  71. +4 −0 storage/framework/types/events.ts
  72. +25 −1 storage/framework/types/requests.d.ts
  73. +9 −0 storage/framework/types/server-auto-imports.d.ts
  74. +1 −0 storage/framework/views/dashboard/storage/logs/stacks.log
19 changes: 19 additions & 0 deletions database/migrations/1742737140035-create-shipping_zones-table.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { Database } from '@stacksjs/database'
import { sql } from '@stacksjs/database'

export async function up(db: Database<any>) {
await db.schema
.createTable('shipping_zones')
.addColumn('id', 'integer', col => col.primaryKey().autoIncrement())
.addColumn('uuid', 'text')
.addColumn('name', 'text', col => col.notNull())
.addColumn('countries', 'text')
.addColumn('regions', 'text')
.addColumn('postal_codes', 'text')
.addColumn('status', 'text', col => col.notNull())
.addColumn('shipping_method_id', 'integer', col =>
col.references('shipping_methods.id').onDelete('cascade'))
.addColumn('created_at', 'timestamp', col => col.notNull().defaultTo(sql`CURRENT_TIMESTAMP`))
.addColumn('updated_at', 'timestamp')
.execute()
}
Original file line number Diff line number Diff line change
@@ -9,8 +9,7 @@ export async function up(db: Database<any>) {
.addColumn('name', 'text', col => col.notNull())
.addColumn('description', 'text')
.addColumn('base_rate', 'numeric', col => col.notNull())
.addColumn('free_shipping', 'text')
.addColumn('zones', 'text', col => col.notNull())
.addColumn('free_shipping', 'numeric')
.addColumn('status', 'text', col => col.notNull())
.addColumn('created_at', 'timestamp', col => col.notNull().defaultTo(sql`CURRENT_TIMESTAMP`))
.addColumn('updated_at', 'timestamp')
17 changes: 17 additions & 0 deletions storage/framework/actions/src/ShippingRateDestroyOrmAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { ShippingRateRequestType } from '@stacksjs/orm'
import { Action } from '@stacksjs/actions'

export default new Action({
name: 'ShippingRate Destroy',
description: 'ShippingRate Destroy ORM Action',
method: 'DELETE',
async handle(request: ShippingRateRequestType) {
const id = request.getParam('id')

const model = await ShippingRate.findOrFail(Number(id))

model.delete()

return 'Model deleted!'
},
})
13 changes: 13 additions & 0 deletions storage/framework/actions/src/ShippingRateIndexOrmAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Action } from '@stacksjs/actions'
import { response } from '@stacksjs/router'

export default new Action({
name: 'ShippingRate Index',
description: 'ShippingRate Index ORM Action',
method: 'GET',
async handle() {
const results = ShippingRate.all()

return response.json(results)
},
})
17 changes: 17 additions & 0 deletions storage/framework/actions/src/ShippingRateShowOrmAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { ShippingRateRequestType } from '@stacksjs/orm'
import { Action } from '@stacksjs/actions'

import { response } from '@stacksjs/router'

export default new Action({
name: 'ShippingRate Show',
description: 'ShippingRate Show ORM Action',
method: 'GET',
async handle(request: ShippingRateRequestType) {
const id = request.getParam('id')

const model = await ShippingRate.findOrFail(Number(id))

return response.json(model)
},
})
16 changes: 16 additions & 0 deletions storage/framework/actions/src/ShippingRateStoreOrmAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { ShippingRateRequestType } from '@stacksjs/orm'
import { Action } from '@stacksjs/actions'

import { response } from '@stacksjs/router'

export default new Action({
name: 'ShippingRate Store',
description: 'ShippingRate Store ORM Action',
method: 'POST',
async handle(request: ShippingRateRequestType) {
await request.validate()
const model = await ShippingRate.create(request.all())

return response.json(model)
},
})
20 changes: 20 additions & 0 deletions storage/framework/actions/src/ShippingRateUpdateOrmAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { ShippingRateRequestType } from '@stacksjs/orm'
import { Action } from '@stacksjs/actions'

import { response } from '@stacksjs/router'

export default new Action({
name: 'ShippingRate Update',
description: 'ShippingRate Update ORM Action',
method: 'PATCH',
async handle(request: ShippingRateRequestType) {
await request.validate()

const id = request.getParam('id')
const model = await ShippingRate.findOrFail(Number(id))

const result = model.update(request.all())

return response.json(result)
},
})
13 changes: 13 additions & 0 deletions storage/framework/core/commerce/src/rates.ts/fetch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type { ShippingRateJsonResponse } from '../../../../orm/src/models/ShippingRate'
import { db } from '@stacksjs/database'

/**
* Fetch a shipping zone by ID
*/
export async function fetchById(id: number): Promise<ShippingRateJsonResponse | undefined> {
return await db
.selectFrom('shipping_rates')
.where('id', '=', id)
.selectAll()
.executeTakeFirst()
}
Empty file.
150 changes: 150 additions & 0 deletions storage/framework/core/commerce/src/rates/store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// Import dependencies
import type { ShippingRateRequestType } from '@stacksjs/orm'
import type { NewShippingRate, ShippingRateJsonResponse } from '../../../../orm/src/models/ShippingRate'
import { randomUUIDv7 } from 'bun'
import { db } from '@stacksjs/database'

/**
* Create a new shipping rate
*
* @param request Shipping rate data to store
* @returns The newly created shipping rate record
*/
export async function store(request: ShippingRateRequestType): Promise<ShippingRateJsonResponse | undefined> {
// Validate the request data
await request.validate()

try {
// Prepare shipping rate data
const shippingRateData: NewShippingRate = {
method: request.get('method'),
zone: request.get('zone'),
weight_from: request.get<number>('weight_from'),
weight_to: request.get<number>('weight_to'),
rate: request.get<number>('rate'),
uuid: randomUUIDv7(),
}

// Insert the shipping rate
const result = await db
.insertInto('shipping_rates')
.values(shippingRateData)
.executeTakeFirst()

const rateId = Number(result.insertId) || Number(result.numInsertedOrUpdatedRows)

// Retrieve the newly created shipping rate
const shippingRate = await db
.selectFrom('shipping_rates')
.where('id', '=', rateId)
.selectAll()
.executeTakeFirst()

return shippingRate
}
catch (error) {
if (error instanceof Error) {
throw new TypeError(`Failed to create shipping rate: ${error.message}`)
}

throw error
}
}

/**
* Create multiple shipping rates at once
*
* @param requests Array of shipping rate data to store
* @returns Number of shipping rates created
*/
export async function bulkStore(requests: ShippingRateRequestType[]): Promise<number> {
if (!requests.length)
return 0

let createdCount = 0

try {
// Process each shipping rate
await db.transaction().execute(async (trx) => {
for (const request of requests) {
// Validate request data
request.validate()

// Prepare shipping rate data
const shippingRateData: NewShippingRate = {
method: request.get('method'),
zone: request.get('zone'),
weight_from: request.get<number>('weight_from'),
weight_to: request.get<number>('weight_to'),
rate: request.get<number>('rate'),
uuid: randomUUIDv7(),
}

// Insert the shipping rate
await trx
.insertInto('shipping_rates')
.values(shippingRateData)
.execute()

createdCount++
}
})

return createdCount
}
catch (error) {
if (error instanceof Error) {
throw new TypeError(`Failed to create shipping rates in bulk: ${error.message}`)
}

throw error
}
}

/**
* Format shipping rate options for dropdown menus or selectors
*
* @returns Array of formatted shipping rate options with id, method, zone, and rate
*/
export function formatShippingRateOptions(): Promise<{ id: number, method: string, zone: string, rate: number }[]> {
try {
return db
.selectFrom('shipping_rates')
.select(['id', 'method', 'zone', 'rate'])
.orderBy('method')
.execute()
}
catch (error) {
if (error instanceof Error) {
throw new TypeError(`Failed to format shipping rate options: ${error.message}`)
}

throw error
}
}

/**
* Get shipping rates for a specific method
*
* @param method The shipping method to filter by
* @returns List of shipping rates for the specified method
*/
export async function getShippingRatesByMethod(method: string): Promise<ShippingRateJsonResponse[]> {
try {
const rates = await db
.selectFrom('shipping_rates')
.selectAll()
.where('method', '=', method)
.orderBy('weight_from')
.execute()

return rates
}
catch (error) {
if (error instanceof Error) {
throw new TypeError(`Failed to get shipping rates by method: ${error.message}`)
}

throw error
}
}
2 changes: 1 addition & 1 deletion storage/framework/core/commerce/src/shipping/fetch.ts
Original file line number Diff line number Diff line change
@@ -10,4 +10,4 @@ export async function fetchById(id: number): Promise<ShippingMethodJsonResponse
.where('id', '=', id)
.selectAll()
.executeTakeFirst()
}
}
27 changes: 27 additions & 0 deletions storage/framework/core/commerce/src/shipping/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Functions from destroy.ts
export {
bulkDestroy,
bulkSoftDelete,
destroy,
softDelete,
} from './destroy'

// Functions from fetch.ts
export {
fetchById,
} from './fetch'

// Functions from store.ts
export {
bulkStore,
formatShippingOptions,
getActiveShippingMethods,
store,
} from './store'

// Functions from update.ts
export {
update,
updatePricing,
updateStatus,
} from './update'
2 changes: 1 addition & 1 deletion storage/framework/core/commerce/src/shipping/store.ts
Original file line number Diff line number Diff line change
@@ -31,7 +31,7 @@ export async function store(request: ShippingMethodRequestType): Promise<Shippin
.values(shippingData)
.executeTakeFirst()

const shippingId = Number(result.insertId)
const shippingId = Number(result.insertId) || Number(result.numInsertedOrUpdatedRows)

// Retrieve the newly created shipping method
const shippingMethod = await db
7 changes: 0 additions & 7 deletions storage/framework/core/commerce/src/shipping/update.ts
Original file line number Diff line number Diff line change
@@ -31,13 +31,6 @@ export async function update(id: number, request: ShippingMethodRequestType): Pr
status: request.get('status'),
}

// Remove undefined values
Object.keys(updateData).forEach((key) => {
if (updateData[key as keyof typeof updateData] === undefined) {
delete updateData[key as keyof typeof updateData]
}
})

// If no fields to update, just return the existing shipping method
if (Object.keys(updateData).length === 0) {
return existingMethod
31 changes: 2 additions & 29 deletions storage/framework/core/commerce/src/tests/shipping.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { beforeEach, describe, expect, it } from 'bun:test'
import { refreshDatabase } from '@stacksjs/testing'
import { bulkDestroy, bulkSoftDelete, destroy, softDelete } from '../shipping/destroy'
import { fetchById, fetchByUuid } from '../shipping/fetch'
import { fetchById } from '../shipping/fetch'
import { bulkStore, formatShippingOptions, getActiveShippingMethods, store } from '../shipping/store'
import { update, updatePricing, updateStatus } from '../shipping/update'

@@ -135,7 +135,7 @@ describe('Shipping Methods Module', () => {
description: 'Initial description',
base_rate: 1000,
free_shipping: 5000,
status: 'active',
status: 'active',
}

// Create the shipping method
@@ -390,33 +390,6 @@ describe('Shipping Methods Module', () => {
})

describe('fetch', () => {
it('should fetch a shipping method by UUID', async () => {
// Create a shipping method
const requestData = {
name: 'UUID Test Shipping',
base_rate: 1000,
status: 'active',
}

const request = new TestRequest(requestData)
const method = await store(request as any)

expect(method?.uuid).toBeDefined()
const uuid = method?.uuid

// Make sure we have a valid UUID before proceeding
expect(uuid).toBeDefined()
if (!uuid) {
throw new Error('Failed to create test shipping method with UUID')
}

// Fetch by UUID
const fetchedMethod = await fetchByUuid(uuid)
expect(fetchedMethod).toBeDefined()
expect(fetchedMethod?.uuid).toBe(uuid)
expect(fetchedMethod?.name).toBe('UUID Test Shipping')
})

it('should get active shipping methods only', async () => {
// Create an active shipping method
const activeRequest = new TestRequest({
Loading