@stacksjs/commerce 0.70.53 → 0.70.55
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/package.json +3 -2
- package/src/carts/destroy.ts +54 -0
- package/src/carts/fetch.ts +20 -0
- package/src/carts/index.ts +13 -0
- package/src/carts/store.ts +75 -0
- package/src/carts/update.ts +78 -0
- package/src/coupons/destroy.ts +49 -0
- package/src/coupons/fetch.ts +510 -0
- package/src/coupons/index.ts +30 -0
- package/src/coupons/store.ts +46 -0
- package/src/coupons/update.ts +147 -0
- package/src/customers/destroy.ts +62 -0
- package/src/customers/fetch.ts +20 -0
- package/src/customers/index.ts +17 -0
- package/src/customers/store.ts +45 -0
- package/src/customers/update.ts +44 -0
- package/src/devices/destroy.ts +54 -0
- package/src/devices/export.ts +98 -0
- package/src/devices/fetch.ts +125 -0
- package/src/devices/index.ts +31 -0
- package/src/devices/store.ts +82 -0
- package/src/devices/update.ts +125 -0
- package/src/errors/destroy.ts +54 -0
- package/src/errors/fetch.ts +197 -0
- package/src/errors/index.ts +28 -0
- package/src/errors/update.ts +116 -0
- package/src/gift-cards/destroy.ts +87 -0
- package/src/gift-cards/fetch.ts +431 -0
- package/src/gift-cards/index.ts +26 -0
- package/src/gift-cards/store.ts +56 -0
- package/src/gift-cards/update.ts +102 -0
- package/src/index.ts +78 -0
- package/src/orders/destroy.ts +111 -0
- package/src/orders/events.ts +121 -0
- package/src/orders/export.ts +158 -0
- package/src/orders/fetch.ts +379 -0
- package/src/orders/guards.ts +261 -0
- package/src/orders/index.ts +91 -0
- package/src/orders/place-order.ts +274 -0
- package/src/orders/store.ts +51 -0
- package/src/orders/totals.ts +190 -0
- package/src/orders/update.ts +164 -0
- package/src/orders/webhook.ts +312 -0
- package/src/payments/destroy.ts +56 -0
- package/src/payments/fetch.ts +288 -0
- package/src/payments/index.ts +16 -0
- package/src/payments/store.ts +63 -0
- package/src/payments/update.ts +52 -0
- package/src/product.ts +0 -0
- package/src/products/categories/destroy.ts +103 -0
- package/src/products/categories/fetch.ts +285 -0
- package/src/products/categories/index.ts +36 -0
- package/src/products/categories/store.ts +87 -0
- package/src/products/categories/update.ts +251 -0
- package/src/products/index.ts +35 -0
- package/src/products/items/destroy.ts +54 -0
- package/src/products/items/fetch.ts +282 -0
- package/src/products/items/index.ts +26 -0
- package/src/products/items/store.ts +84 -0
- package/src/products/items/update.ts +324 -0
- package/src/products/manufacturers/destroy.ts +56 -0
- package/src/products/manufacturers/fetch.ts +117 -0
- package/src/products/manufacturers/index.ts +24 -0
- package/src/products/manufacturers/store.ts +82 -0
- package/src/products/manufacturers/update.ts +113 -0
- package/src/products/reviews/destroy.ts +56 -0
- package/src/products/reviews/fetch.ts +63 -0
- package/src/products/reviews/index.ts +25 -0
- package/src/products/reviews/store.ts +46 -0
- package/src/products/reviews/update.ts +82 -0
- package/src/products/units/destroy.ts +56 -0
- package/src/products/units/fetch.ts +20 -0
- package/src/products/units/index.ts +13 -0
- package/src/products/units/store.ts +162 -0
- package/src/products/units/update.ts +159 -0
- package/src/products/variants/destroy.ts +56 -0
- package/src/products/variants/fetch.ts +20 -0
- package/src/products/variants/index.ts +21 -0
- package/src/products/variants/store.ts +136 -0
- package/src/products/variants/update.ts +104 -0
- package/src/receipts/destroy.ts +54 -0
- package/src/receipts/export.ts +0 -0
- package/src/receipts/fetch.ts +222 -0
- package/src/receipts/index.ts +24 -0
- package/src/receipts/printer.ts +69 -0
- package/src/receipts/store.ts +69 -0
- package/src/receipts/update.ts +124 -0
- package/src/shippings/delivery-routes/destroy.ts +54 -0
- package/src/shippings/delivery-routes/fetch.ts +42 -0
- package/src/shippings/delivery-routes/index.ts +26 -0
- package/src/shippings/delivery-routes/store.ts +69 -0
- package/src/shippings/delivery-routes/update.ts +120 -0
- package/src/shippings/digital-deliveries/destroy.ts +111 -0
- package/src/shippings/digital-deliveries/fetch.ts +20 -0
- package/src/shippings/digital-deliveries/index.ts +26 -0
- package/src/shippings/digital-deliveries/store.ts +76 -0
- package/src/shippings/digital-deliveries/update.ts +129 -0
- package/src/shippings/drivers/destroy.ts +78 -0
- package/src/shippings/drivers/fetch.ts +20 -0
- package/src/shippings/drivers/index.ts +24 -0
- package/src/shippings/drivers/store.ts +69 -0
- package/src/shippings/drivers/update.ts +117 -0
- package/src/shippings/index.ts +39 -0
- package/src/shippings/license-keys/destroy.ts +111 -0
- package/src/shippings/license-keys/fetch.ts +20 -0
- package/src/shippings/license-keys/index.ts +26 -0
- package/src/shippings/license-keys/store.ts +77 -0
- package/src/shippings/license-keys/update.ts +117 -0
- package/src/shippings/shipping-methods/destroy.ts +111 -0
- package/src/shippings/shipping-methods/fetch.ts +62 -0
- package/src/shippings/shipping-methods/index.ts +28 -0
- package/src/shippings/shipping-methods/store.ts +123 -0
- package/src/shippings/shipping-methods/update.ts +120 -0
- package/src/shippings/shipping-rates/destroy.ts +102 -0
- package/src/shippings/shipping-rates/fetch.ts +320 -0
- package/src/shippings/shipping-rates/index.ts +36 -0
- package/src/shippings/shipping-rates/store.ts +102 -0
- package/src/shippings/shipping-rates/update.ts +139 -0
- package/src/shippings/shipping-zones/destroy.ts +111 -0
- package/src/shippings/shipping-zones/fetch.ts +96 -0
- package/src/shippings/shipping-zones/index.ts +26 -0
- package/src/shippings/shipping-zones/store.ts +74 -0
- package/src/shippings/shipping-zones/update.ts +156 -0
- package/src/tax/destroy.ts +54 -0
- package/src/tax/fetch.ts +20 -0
- package/src/tax/index.ts +24 -0
- package/src/tax/store.ts +69 -0
- package/src/tax/update.ts +119 -0
- package/src/tests/coupons.test.ts +90 -0
- package/src/tests/customers.test.ts +39 -0
- package/src/tests/device.test.ts +111 -0
- package/src/tests/digitals.test.ts +31 -0
- package/src/tests/drivers.test.ts +25 -0
- package/src/tests/gift-cards.test.ts +36 -0
- package/src/tests/license.test.ts +31 -0
- package/src/tests/manufacturers.test.ts +80 -0
- package/src/tests/orders.test.ts +25 -0
- package/src/tests/payments.test.ts +75 -0
- package/src/tests/rates.test.ts +367 -0
- package/src/tests/receipts.test.ts +287 -0
- package/src/tests/restaurant.test.ts +522 -0
- package/src/tests/reviews.test.ts +165 -0
- package/src/tests/routes.test.ts +51 -0
- package/src/tests/setup.ts +149 -0
- package/src/tests/shipping.test.ts +88 -0
- package/src/tests/tax.test.ts +25 -0
- package/src/tests/units.test.ts +110 -0
- package/src/tests/variants.test.ts +133 -0
- package/src/tests/waitlist.test.ts +303 -0
- package/src/tests/zones.test.ts +86 -0
- package/src/types.ts +312 -0
- package/src/utils/typed-stats.ts +67 -0
- package/src/waitlists/index.ts +19 -0
- package/src/waitlists/products/destroy.ts +65 -0
- package/src/waitlists/products/export.ts +113 -0
- package/src/waitlists/products/fetch.ts +362 -0
- package/src/waitlists/products/index.ts +33 -0
- package/src/waitlists/products/store.ts +112 -0
- package/src/waitlists/products/update.ts +125 -0
- package/src/waitlists/restaurant/destroy.ts +65 -0
- package/src/waitlists/restaurant/export.ts +107 -0
- package/src/waitlists/restaurant/fetch.ts +538 -0
- package/src/waitlists/restaurant/index.ts +43 -0
- package/src/waitlists/restaurant/store.ts +109 -0
- package/src/waitlists/restaurant/update.ts +198 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// Import dependencies
|
|
2
|
+
type ShippingRateJsonResponse = ModelRow<typeof ShippingRate>
|
|
3
|
+
type NewShippingRate = NewModelData<typeof ShippingRate>
|
|
4
|
+
import { randomUUIDv7 } from 'bun'
|
|
5
|
+
import { db } from '@stacksjs/database'
|
|
6
|
+
import { fetchById as fetchShippingMethodById } from '../shipping-methods/fetch'
|
|
7
|
+
import { fetchById as fetchShippingZoneById } from '../shipping-zones/fetch'
|
|
8
|
+
import { fetchById } from './fetch'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Create a new shipping rate
|
|
12
|
+
*
|
|
13
|
+
* @param data The shipping rate data to store
|
|
14
|
+
* @returns The newly created shipping rate record
|
|
15
|
+
*/
|
|
16
|
+
export async function store(data: NewShippingRate): Promise<ShippingRateJsonResponse> {
|
|
17
|
+
try {
|
|
18
|
+
// Validate that the shipping method and zone exist
|
|
19
|
+
const method = await fetchShippingMethodById(Number(data.shippingmethod_id))
|
|
20
|
+
const zone = await fetchShippingZoneById(Number(data.shippingzone_id))
|
|
21
|
+
|
|
22
|
+
const rateData = {
|
|
23
|
+
weightFrom: data.weightFrom,
|
|
24
|
+
weightTo: data.weightTo,
|
|
25
|
+
rate: data.rate,
|
|
26
|
+
shippingmethod_id: method?.id,
|
|
27
|
+
shippingzone_id: zone?.id,
|
|
28
|
+
uuid: randomUUIDv7(),
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const result = await db
|
|
32
|
+
.insertInto('shipping_rates')
|
|
33
|
+
.values(rateData)
|
|
34
|
+
.executeTakeFirst()
|
|
35
|
+
|
|
36
|
+
if (!result)
|
|
37
|
+
throw new Error('Failed to create shipping rate')
|
|
38
|
+
|
|
39
|
+
const insertId = Number(result.insertId) || Number(result.numInsertedOrUpdatedRows)
|
|
40
|
+
|
|
41
|
+
const model = await fetchById(insertId)
|
|
42
|
+
|
|
43
|
+
return model as ShippingRateJsonResponse
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
if (error instanceof Error) {
|
|
47
|
+
throw new TypeError(`Failed to create shipping rate: ${error.message}`)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
throw error
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Create multiple shipping rates at once
|
|
56
|
+
*
|
|
57
|
+
* @param data Array of shipping rate data to store
|
|
58
|
+
* @returns Number of shipping rates created
|
|
59
|
+
*/
|
|
60
|
+
export async function bulkStore(data: NewShippingRate[]): Promise<number> {
|
|
61
|
+
if (!data.length)
|
|
62
|
+
return 0
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
// Validate all methods and zones before bulk insert
|
|
66
|
+
for (const item of data) {
|
|
67
|
+
const method = await fetchShippingMethodById(Number(item.shippingmethod_id))
|
|
68
|
+
const zone = await fetchShippingZoneById(Number(item.shippingzone_id))
|
|
69
|
+
|
|
70
|
+
if (!method) {
|
|
71
|
+
console.warn(`Shipping method with ID "${item.shippingmethod_id}" not found for bulk insert`)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (!zone) {
|
|
75
|
+
console.warn(`Shipping zone with ID "${item.shippingzone_id}" not found for bulk insert`)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const rateDataArray = data.map(item => ({
|
|
80
|
+
weightFrom: item.weightFrom,
|
|
81
|
+
weightTo: item.weightTo,
|
|
82
|
+
rate: item.rate,
|
|
83
|
+
shippingmethod_id: item.shippingmethod_id,
|
|
84
|
+
shippingzone_id: item.shippingzone_id,
|
|
85
|
+
uuid: randomUUIDv7(),
|
|
86
|
+
}))
|
|
87
|
+
|
|
88
|
+
const result = await db
|
|
89
|
+
.insertInto('shipping_rates')
|
|
90
|
+
.values(rateDataArray)
|
|
91
|
+
.executeTakeFirst()
|
|
92
|
+
|
|
93
|
+
return Number(result.numInsertedOrUpdatedRows)
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
if (error instanceof Error) {
|
|
97
|
+
throw new TypeError(`Failed to create shipping rates in bulk: ${error.message}`)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
throw error
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { db } from '@stacksjs/database'
|
|
2
|
+
import { formatDate } from '@stacksjs/orm'
|
|
3
|
+
type ShippingRateJsonResponse = ModelRow<typeof ShippingRate>
|
|
4
|
+
type ShippingRateUpdate = UpdateModelData<typeof ShippingRate>
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Update a shipping rate
|
|
8
|
+
*
|
|
9
|
+
* @param id The shipping rate ID to update
|
|
10
|
+
* @param data The shipping rate data to update
|
|
11
|
+
* @returns The updated shipping rate record
|
|
12
|
+
*/
|
|
13
|
+
export async function update(id: number, data: ShippingRateUpdate): Promise<ShippingRateJsonResponse> {
|
|
14
|
+
try {
|
|
15
|
+
if (!id)
|
|
16
|
+
throw new Error('Shipping rate ID is required for update')
|
|
17
|
+
|
|
18
|
+
const result = await db
|
|
19
|
+
.updateTable('shipping_rates')
|
|
20
|
+
.set({
|
|
21
|
+
...data,
|
|
22
|
+
updated_at: formatDate(new Date()),
|
|
23
|
+
})
|
|
24
|
+
.where('id', '=', id)
|
|
25
|
+
.returningAll()
|
|
26
|
+
.executeTakeFirst()
|
|
27
|
+
|
|
28
|
+
if (!result)
|
|
29
|
+
throw new Error('Failed to update shipping rate')
|
|
30
|
+
|
|
31
|
+
return result as ShippingRateJsonResponse
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
if (error instanceof Error) {
|
|
35
|
+
throw new TypeError(`Failed to update shipping rate: ${error.message}`)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
throw error
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Update multiple shipping rates at once
|
|
44
|
+
*
|
|
45
|
+
* @param updates Array of objects containing rate ID and update data
|
|
46
|
+
* @returns Number of shipping rates updated
|
|
47
|
+
*/
|
|
48
|
+
export async function bulkUpdate(updates: Array<{
|
|
49
|
+
id: number
|
|
50
|
+
data: ShippingRateUpdate
|
|
51
|
+
}>): Promise<number> {
|
|
52
|
+
if (!updates.length)
|
|
53
|
+
return 0
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
let updatedCount = 0
|
|
57
|
+
|
|
58
|
+
for (const { id, data } of updates) {
|
|
59
|
+
const result = await db
|
|
60
|
+
.updateTable('shipping_rates')
|
|
61
|
+
.set({
|
|
62
|
+
...data,
|
|
63
|
+
updated_at: formatDate(new Date()),
|
|
64
|
+
})
|
|
65
|
+
.where('id', '=', id)
|
|
66
|
+
.executeTakeFirst()
|
|
67
|
+
|
|
68
|
+
if (Number(result.numUpdatedRows) > 0)
|
|
69
|
+
updatedCount++
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return updatedCount
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
if (error instanceof Error) {
|
|
76
|
+
throw new TypeError(`Failed to update shipping rates in bulk: ${error.message}`)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
throw error
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Update shipping rates by zone
|
|
85
|
+
*
|
|
86
|
+
* @param zone The zone to update rates for
|
|
87
|
+
* @param data The update data to apply
|
|
88
|
+
* @returns Number of shipping rates updated
|
|
89
|
+
*/
|
|
90
|
+
export async function updateByZone(zone: number, data: ShippingRateUpdate): Promise<number> {
|
|
91
|
+
try {
|
|
92
|
+
const result = await db
|
|
93
|
+
.updateTable('shipping_rates')
|
|
94
|
+
.set({
|
|
95
|
+
...data,
|
|
96
|
+
updated_at: formatDate(new Date()),
|
|
97
|
+
})
|
|
98
|
+
.where('zone_id', '=', zone)
|
|
99
|
+
.executeTakeFirst()
|
|
100
|
+
|
|
101
|
+
return Number(result.numUpdatedRows)
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
if (error instanceof Error) {
|
|
105
|
+
throw new TypeError(`Failed to update shipping rates by zone: ${error.message}`)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
throw error
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Update shipping rates by method
|
|
114
|
+
*
|
|
115
|
+
* @param method The shipping method to update rates for
|
|
116
|
+
* @param data The update data to apply
|
|
117
|
+
* @returns Number of shipping rates updated
|
|
118
|
+
*/
|
|
119
|
+
export async function updateByMethod(method: string, data: ShippingRateUpdate): Promise<number> {
|
|
120
|
+
try {
|
|
121
|
+
const result = await db
|
|
122
|
+
.updateTable('shipping_rates')
|
|
123
|
+
.set({
|
|
124
|
+
...data,
|
|
125
|
+
updated_at: formatDate(new Date()),
|
|
126
|
+
})
|
|
127
|
+
.where('method', '=', method)
|
|
128
|
+
.executeTakeFirst()
|
|
129
|
+
|
|
130
|
+
return Number(result.numUpdatedRows)
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
if (error instanceof Error) {
|
|
134
|
+
throw new TypeError(`Failed to update shipping rates by method: ${error.message}`)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
throw error
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { db } from '@stacksjs/database'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Delete a shipping zone by ID
|
|
5
|
+
*
|
|
6
|
+
* @param id The ID of the shipping zone to delete
|
|
7
|
+
* @returns True if the shipping zone was deleted, false otherwise
|
|
8
|
+
*/
|
|
9
|
+
export async function destroy(id: number): Promise<boolean> {
|
|
10
|
+
try {
|
|
11
|
+
const result = await db
|
|
12
|
+
.deleteFrom('shipping_zones')
|
|
13
|
+
.where('id', '=', id)
|
|
14
|
+
.executeTakeFirst()
|
|
15
|
+
|
|
16
|
+
return Number(result.numDeletedRows) > 0
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
if (error instanceof Error) {
|
|
20
|
+
throw new TypeError(`Failed to delete shipping zone: ${error.message}`)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
throw error
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Soft delete a shipping zone by ID (updates status to 'inactive')
|
|
29
|
+
*
|
|
30
|
+
* @param id The ID of the shipping zone to soft delete
|
|
31
|
+
* @returns True if the shipping zone was soft deleted, false otherwise
|
|
32
|
+
*/
|
|
33
|
+
export async function softDelete(id: number): Promise<boolean> {
|
|
34
|
+
try {
|
|
35
|
+
// Update the status to 'inactive' instead of deleting
|
|
36
|
+
const result = await db
|
|
37
|
+
.updateTable('shipping_zones')
|
|
38
|
+
.set({ status: 'inactive' })
|
|
39
|
+
.where('id', '=', id)
|
|
40
|
+
.executeTakeFirst()
|
|
41
|
+
|
|
42
|
+
// Return true if any row was affected (updated)
|
|
43
|
+
return Number(result.numUpdatedRows) > 0
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
if (error instanceof Error) {
|
|
47
|
+
throw new TypeError(`Failed to soft delete shipping zone: ${error.message}`)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
throw error
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Delete multiple shipping zones by ID
|
|
56
|
+
*
|
|
57
|
+
* @param ids Array of shipping zone IDs to delete
|
|
58
|
+
* @returns Number of shipping zones deleted
|
|
59
|
+
*/
|
|
60
|
+
export async function bulkDestroy(ids: number[]): Promise<number> {
|
|
61
|
+
if (!ids.length)
|
|
62
|
+
return 0
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
// Perform the delete operation
|
|
66
|
+
const result = await db
|
|
67
|
+
.deleteFrom('shipping_zones')
|
|
68
|
+
.where('id', 'in', ids)
|
|
69
|
+
.executeTakeFirst()
|
|
70
|
+
|
|
71
|
+
// Return the number of deleted rows
|
|
72
|
+
return Number(result.numDeletedRows)
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
if (error instanceof Error) {
|
|
76
|
+
throw new TypeError(`Failed to delete shipping zones: ${error.message}`)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
throw error
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Soft delete multiple shipping zones by ID (updates status to 'inactive')
|
|
85
|
+
*
|
|
86
|
+
* @param ids Array of shipping zone IDs to soft delete
|
|
87
|
+
* @returns Number of shipping zones soft deleted
|
|
88
|
+
*/
|
|
89
|
+
export async function bulkSoftDelete(ids: number[]): Promise<number> {
|
|
90
|
+
if (!ids.length)
|
|
91
|
+
return 0
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
// Update the status to 'inactive' instead of deleting
|
|
95
|
+
const result = await db
|
|
96
|
+
.updateTable('shipping_zones')
|
|
97
|
+
.set({ status: 'inactive' })
|
|
98
|
+
.where('id', 'in', ids)
|
|
99
|
+
.executeTakeFirst()
|
|
100
|
+
|
|
101
|
+
// Return the number of updated rows
|
|
102
|
+
return Number(result.numUpdatedRows)
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
if (error instanceof Error) {
|
|
106
|
+
throw new TypeError(`Failed to soft delete shipping zones: ${error.message}`)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
throw error
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
type ShippingZoneJsonResponse = ModelRow<typeof ShippingZone>
|
|
2
|
+
import { db } from '@stacksjs/database'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Fetch all shipping zones
|
|
6
|
+
*/
|
|
7
|
+
export async function fetchAll(): Promise<ShippingZoneJsonResponse[]> {
|
|
8
|
+
return await db.selectFrom('shipping_zones').selectAll().execute() as ShippingZoneJsonResponse[]
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Fetch a shipping zone by ID
|
|
13
|
+
*/
|
|
14
|
+
export async function fetchById(id: number): Promise<ShippingZoneJsonResponse | undefined> {
|
|
15
|
+
return await db
|
|
16
|
+
.selectFrom('shipping_zones')
|
|
17
|
+
.where('id', '=', id)
|
|
18
|
+
.selectAll()
|
|
19
|
+
.executeTakeFirst() as ShippingZoneJsonResponse | undefined
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Format shipping zone options for dropdown menus or selectors
|
|
24
|
+
*
|
|
25
|
+
* @returns Array of formatted shipping zone options with id, name, and status
|
|
26
|
+
*/
|
|
27
|
+
export function formatZoneOptions(): Promise<{ id: number, name: string, status: string | string[], countries: string | undefined }[]> {
|
|
28
|
+
try {
|
|
29
|
+
return db
|
|
30
|
+
.selectFrom('shipping_zones')
|
|
31
|
+
.select(['id', 'name', 'status', 'countries'])
|
|
32
|
+
.orderBy('name')
|
|
33
|
+
.execute() as any
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
if (error instanceof Error) {
|
|
37
|
+
throw new TypeError(`Failed to format shipping zone options: ${error.message}`)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
throw error
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Get active shipping zones
|
|
46
|
+
*
|
|
47
|
+
* @returns List of active shipping zones
|
|
48
|
+
*/
|
|
49
|
+
export async function getActiveShippingZones(): Promise<ShippingZoneJsonResponse[]> {
|
|
50
|
+
try {
|
|
51
|
+
const activeZones = await db
|
|
52
|
+
.selectFrom('shipping_zones')
|
|
53
|
+
.selectAll()
|
|
54
|
+
.where('status', '=', 'active')
|
|
55
|
+
.orderBy('name')
|
|
56
|
+
.execute()
|
|
57
|
+
|
|
58
|
+
return activeZones as ShippingZoneJsonResponse[]
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
if (error instanceof Error) {
|
|
62
|
+
throw new TypeError(`Failed to get active shipping zones: ${error.message}`)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
throw error
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Get shipping zones by country code
|
|
71
|
+
*
|
|
72
|
+
* @param countryCode ISO country code
|
|
73
|
+
* @returns List of shipping zones covering the specified country
|
|
74
|
+
*/
|
|
75
|
+
export async function getZonesByCountry(countryCode: string): Promise<ShippingZoneJsonResponse[]> {
|
|
76
|
+
try {
|
|
77
|
+
// This uses a LIKE query assuming countries are stored as JSON strings
|
|
78
|
+
// You may need to adjust based on your actual data structure
|
|
79
|
+
const zones = await db
|
|
80
|
+
.selectFrom('shipping_zones')
|
|
81
|
+
.selectAll()
|
|
82
|
+
.where('countries', 'like', `%${countryCode}%`)
|
|
83
|
+
.where('status', '=', 'active')
|
|
84
|
+
.orderBy('name')
|
|
85
|
+
.execute()
|
|
86
|
+
|
|
87
|
+
return zones as ShippingZoneJsonResponse[]
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
if (error instanceof Error) {
|
|
91
|
+
throw new TypeError(`Failed to get shipping zones by country: ${error.message}`)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
throw error
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export {
|
|
2
|
+
bulkDestroy,
|
|
3
|
+
bulkSoftDelete,
|
|
4
|
+
destroy,
|
|
5
|
+
softDelete,
|
|
6
|
+
} from './destroy'
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
fetchAll,
|
|
10
|
+
fetchById,
|
|
11
|
+
formatZoneOptions,
|
|
12
|
+
getActiveShippingZones,
|
|
13
|
+
getZonesByCountry,
|
|
14
|
+
} from './fetch'
|
|
15
|
+
|
|
16
|
+
export {
|
|
17
|
+
bulkStore,
|
|
18
|
+
store,
|
|
19
|
+
} from './store'
|
|
20
|
+
|
|
21
|
+
export {
|
|
22
|
+
update,
|
|
23
|
+
updateCountries,
|
|
24
|
+
updateRegionsAndPostalCodes,
|
|
25
|
+
updateStatus,
|
|
26
|
+
} from './update'
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// Import dependencies
|
|
2
|
+
type ShippingZoneJsonResponse = ModelRow<typeof ShippingZone>
|
|
3
|
+
type NewShippingZone = NewModelData<typeof ShippingZone>
|
|
4
|
+
import { randomUUIDv7 } from 'bun'
|
|
5
|
+
import { db } from '@stacksjs/database'
|
|
6
|
+
import { fetchById } from './fetch'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Create a new shipping zone
|
|
10
|
+
*
|
|
11
|
+
* @param data The shipping zone data to store
|
|
12
|
+
* @returns The newly created shipping zone record
|
|
13
|
+
*/
|
|
14
|
+
export async function store(data: NewShippingZone): Promise<ShippingZoneJsonResponse> {
|
|
15
|
+
try {
|
|
16
|
+
const zoneData = {
|
|
17
|
+
...data,
|
|
18
|
+
uuid: randomUUIDv7(),
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const result = await db
|
|
22
|
+
.insertInto('shipping_zones')
|
|
23
|
+
.values(zoneData)
|
|
24
|
+
.executeTakeFirst()
|
|
25
|
+
|
|
26
|
+
if (!result)
|
|
27
|
+
throw new Error('Failed to create shipping zone')
|
|
28
|
+
|
|
29
|
+
const insertId = Number(result.insertId) || Number(result.numInsertedOrUpdatedRows)
|
|
30
|
+
|
|
31
|
+
const model = await fetchById(insertId)
|
|
32
|
+
|
|
33
|
+
return model as ShippingZoneJsonResponse
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
if (error instanceof Error) {
|
|
37
|
+
throw new TypeError(`Failed to create shipping zone: ${error.message}`)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
throw error
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Create multiple shipping zones at once
|
|
46
|
+
*
|
|
47
|
+
* @param data Array of shipping zone data to store
|
|
48
|
+
* @returns Number of shipping zones created
|
|
49
|
+
*/
|
|
50
|
+
export async function bulkStore(data: NewShippingZone[]): Promise<number> {
|
|
51
|
+
if (!data.length)
|
|
52
|
+
return 0
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
const zoneDataArray = data.map(item => ({
|
|
56
|
+
...item,
|
|
57
|
+
uuid: randomUUIDv7(),
|
|
58
|
+
}))
|
|
59
|
+
|
|
60
|
+
const result = await db
|
|
61
|
+
.insertInto('shipping_zones')
|
|
62
|
+
.values(zoneDataArray)
|
|
63
|
+
.executeTakeFirst()
|
|
64
|
+
|
|
65
|
+
return Number(result.numInsertedOrUpdatedRows)
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
if (error instanceof Error) {
|
|
69
|
+
throw new TypeError(`Failed to create shipping zones in bulk: ${error.message}`)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
throw error
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { db } from '@stacksjs/database'
|
|
2
|
+
import { formatDate } from '@stacksjs/orm'
|
|
3
|
+
type ShippingZoneJsonResponse = ModelRow<typeof ShippingZone>
|
|
4
|
+
type ShippingZoneUpdate = UpdateModelData<typeof ShippingZone>
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Update a shipping zone
|
|
8
|
+
*
|
|
9
|
+
* @param id The ID of the shipping zone
|
|
10
|
+
* @param data The shipping zone data to update
|
|
11
|
+
* @returns The updated shipping zone record
|
|
12
|
+
*/
|
|
13
|
+
export async function update(id: number, data: ShippingZoneUpdate): Promise<ShippingZoneJsonResponse> {
|
|
14
|
+
try {
|
|
15
|
+
if (!id)
|
|
16
|
+
throw new Error('Shipping zone ID is required for update')
|
|
17
|
+
|
|
18
|
+
const result = await db
|
|
19
|
+
.updateTable('shipping_zones')
|
|
20
|
+
.set({
|
|
21
|
+
...data,
|
|
22
|
+
updated_at: formatDate(new Date()),
|
|
23
|
+
})
|
|
24
|
+
.where('id', '=', id)
|
|
25
|
+
.returningAll()
|
|
26
|
+
.executeTakeFirst()
|
|
27
|
+
|
|
28
|
+
if (!result)
|
|
29
|
+
throw new Error('Failed to update shipping zone')
|
|
30
|
+
|
|
31
|
+
return result as ShippingZoneJsonResponse
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
if (error instanceof Error) {
|
|
35
|
+
throw new TypeError(`Failed to update shipping zone: ${error.message}`)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
throw error
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Update a shipping zone's status
|
|
44
|
+
*
|
|
45
|
+
* @param id The ID of the shipping zone
|
|
46
|
+
* @param status The new status
|
|
47
|
+
* @returns The updated shipping zone with the new status
|
|
48
|
+
*/
|
|
49
|
+
export async function updateStatus(
|
|
50
|
+
id: number,
|
|
51
|
+
status: string | string[],
|
|
52
|
+
): Promise<ShippingZoneJsonResponse> {
|
|
53
|
+
try {
|
|
54
|
+
const result = await db
|
|
55
|
+
.updateTable('shipping_zones')
|
|
56
|
+
.set({
|
|
57
|
+
status,
|
|
58
|
+
updated_at: formatDate(new Date()),
|
|
59
|
+
})
|
|
60
|
+
.where('id', '=', id)
|
|
61
|
+
.returningAll()
|
|
62
|
+
.executeTakeFirst()
|
|
63
|
+
|
|
64
|
+
if (!result)
|
|
65
|
+
throw new Error('Failed to update shipping zone status')
|
|
66
|
+
|
|
67
|
+
return result as ShippingZoneJsonResponse
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
if (error instanceof Error) {
|
|
71
|
+
throw new TypeError(`Failed to update shipping zone status: ${error.message}`)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
throw error
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Update countries for a shipping zone
|
|
80
|
+
*
|
|
81
|
+
* @param id The ID of the shipping zone
|
|
82
|
+
* @param countries The updated countries JSON string
|
|
83
|
+
* @returns The updated shipping zone
|
|
84
|
+
*/
|
|
85
|
+
export async function updateCountries(
|
|
86
|
+
id: number,
|
|
87
|
+
countries: string,
|
|
88
|
+
): Promise<ShippingZoneJsonResponse> {
|
|
89
|
+
try {
|
|
90
|
+
const result = await db
|
|
91
|
+
.updateTable('shipping_zones')
|
|
92
|
+
.set({
|
|
93
|
+
countries,
|
|
94
|
+
updated_at: formatDate(new Date()),
|
|
95
|
+
})
|
|
96
|
+
.where('id', '=', id)
|
|
97
|
+
.returningAll()
|
|
98
|
+
.executeTakeFirst()
|
|
99
|
+
|
|
100
|
+
if (!result)
|
|
101
|
+
throw new Error('Failed to update shipping zone countries')
|
|
102
|
+
|
|
103
|
+
return result as ShippingZoneJsonResponse
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
if (error instanceof Error) {
|
|
107
|
+
throw new TypeError(`Failed to update shipping zone countries: ${error.message}`)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
throw error
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Update regions and/or postal codes for a shipping zone
|
|
116
|
+
*
|
|
117
|
+
* @param id The ID of the shipping zone
|
|
118
|
+
* @param regions Optional updated regions JSON string
|
|
119
|
+
* @param postal_codes Optional updated postal codes JSON string
|
|
120
|
+
* @returns The updated shipping zone
|
|
121
|
+
*/
|
|
122
|
+
export async function updateRegionsAndPostalCodes(
|
|
123
|
+
id: number,
|
|
124
|
+
regions?: string,
|
|
125
|
+
postal_codes?: string,
|
|
126
|
+
): Promise<ShippingZoneJsonResponse> {
|
|
127
|
+
try {
|
|
128
|
+
const updateData: Record<string, any> = {
|
|
129
|
+
updated_at: formatDate(new Date()),
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (regions !== undefined)
|
|
133
|
+
updateData.regions = regions
|
|
134
|
+
if (postal_codes !== undefined)
|
|
135
|
+
updateData.postal_codes = postal_codes
|
|
136
|
+
|
|
137
|
+
const result = await db
|
|
138
|
+
.updateTable('shipping_zones')
|
|
139
|
+
.set(updateData)
|
|
140
|
+
.where('id', '=', id)
|
|
141
|
+
.returningAll()
|
|
142
|
+
.executeTakeFirst()
|
|
143
|
+
|
|
144
|
+
if (!result)
|
|
145
|
+
throw new Error('Failed to update regions and postal codes')
|
|
146
|
+
|
|
147
|
+
return result as ShippingZoneJsonResponse
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
if (error instanceof Error) {
|
|
151
|
+
throw new TypeError(`Failed to update regions and postal codes: ${error.message}`)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
throw error
|
|
155
|
+
}
|
|
156
|
+
}
|