@stacksjs/orm 0.72.16 → 0.72.18
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/dist/index.d.ts +97 -97
- package/dist/index.js +7 -7
- package/dist/models/Activity.ts +95 -0
- package/dist/models/AnalyticsEvent.ts +70 -0
- package/dist/models/Automation.ts +23 -0
- package/dist/models/AutomationRun.ts +26 -0
- package/dist/models/Board.ts +104 -0
- package/dist/models/BoardColumn.ts +88 -0
- package/dist/models/Campaign.ts +321 -0
- package/dist/models/CampaignSend.ts +191 -0
- package/dist/models/CampaignVariant.ts +25 -0
- package/dist/models/Card.ts +118 -0
- package/dist/models/CardComment.ts +68 -0
- package/dist/models/Comment.ts +109 -0
- package/dist/models/CommunicationSuppression.ts +22 -0
- package/dist/models/ConsentEvent.ts +30 -0
- package/dist/models/Content/Author.ts +109 -0
- package/dist/models/Content/Menu.ts +56 -0
- package/dist/models/Content/MenuItem.ts +91 -0
- package/dist/models/Content/Page.ts +205 -0
- package/dist/models/Content/PageRevision.ts +86 -0
- package/dist/models/Content/Post.ts +230 -0
- package/dist/models/Content/Redirect.ts +80 -0
- package/dist/models/Deployment.ts +117 -0
- package/dist/models/EmailIdempotency.ts +64 -0
- package/dist/models/EmailList.ts +134 -0
- package/dist/models/EmailListSubscriber.ts +91 -0
- package/dist/models/EmailSuppression.ts +52 -0
- package/dist/models/EmailWebhookEvent.ts +51 -0
- package/dist/models/Error.ts +77 -0
- package/dist/models/FailedJob.ts +84 -0
- package/dist/models/Forms/Form.ts +91 -0
- package/dist/models/Forms/FormField.ts +127 -0
- package/dist/models/Forms/FormSubmission.ts +114 -0
- package/dist/models/Job.ts +69 -0
- package/dist/models/Label.ts +67 -0
- package/dist/models/Log.ts +134 -0
- package/dist/models/MagicLinkToken.ts +97 -0
- package/dist/models/MailPreference.ts +213 -0
- package/dist/models/Notification.ts +68 -0
- package/dist/models/NotificationDelivery.ts +102 -0
- package/dist/models/PaymentMethod.ts +98 -0
- package/dist/models/PaymentProduct.ts +91 -0
- package/dist/models/PaymentTransaction.ts +78 -0
- package/dist/models/QueryLog.ts +182 -0
- package/dist/models/README.md +31 -0
- package/dist/models/Release.ts +90 -0
- package/dist/models/Request.ts +133 -0
- package/dist/models/SenderDomain.ts +22 -0
- package/dist/models/Site.ts +112 -0
- package/dist/models/SiteDomain.ts +74 -0
- package/dist/models/SmsOptOut.ts +65 -0
- package/dist/models/SocialAccount.ts +70 -0
- package/dist/models/SocialPost.ts +144 -0
- package/dist/models/Subscriber.ts +89 -0
- package/dist/models/SubscriberEmail.ts +55 -0
- package/dist/models/Subscription.ts +153 -0
- package/dist/models/Tag.ts +105 -0
- package/dist/models/Team.ts +75 -0
- package/dist/models/TeamInvitation.ts +159 -0
- package/dist/models/TeamMember.ts +88 -0
- package/dist/models/UsageEvent.ts +24 -0
- package/dist/models/User.ts +142 -0
- package/dist/models/commerce/Auction.ts +173 -0
- package/dist/models/commerce/AuctionItem.ts +204 -0
- package/dist/models/commerce/Bid.ts +129 -0
- package/dist/models/commerce/Cart.ts +140 -0
- package/dist/models/commerce/CartItem.ts +138 -0
- package/dist/models/commerce/Category.ts +125 -0
- package/dist/models/commerce/Coupon.ts +186 -0
- package/dist/models/commerce/Customer.ts +132 -0
- package/dist/models/commerce/DeliveryRoute.ts +127 -0
- package/dist/models/commerce/DeliveryStop.ts +166 -0
- package/dist/models/commerce/DigitalDelivery.ts +106 -0
- package/dist/models/commerce/Driver.ts +168 -0
- package/dist/models/commerce/DriverPing.ts +103 -0
- package/dist/models/commerce/GiftCard.ts +195 -0
- package/dist/models/commerce/LicenseKey.ts +89 -0
- package/dist/models/commerce/LoyaltyPoint.ts +108 -0
- package/dist/models/commerce/LoyaltyReward.ts +129 -0
- package/dist/models/commerce/Manufacturer.ts +90 -0
- package/dist/models/commerce/Order.ts +198 -0
- package/dist/models/commerce/OrderIdempotency.ts +34 -0
- package/dist/models/commerce/OrderItem.ts +51 -0
- package/dist/models/commerce/Payment.ts +182 -0
- package/dist/models/commerce/Pledge.ts +112 -0
- package/dist/models/commerce/PrintDevice.ts +120 -0
- package/dist/models/commerce/Product.ts +153 -0
- package/dist/models/commerce/ProductUnit.ts +113 -0
- package/dist/models/commerce/ProductVariant.ts +111 -0
- package/dist/models/commerce/Receipt.ts +144 -0
- package/dist/models/commerce/Review.ts +171 -0
- package/dist/models/commerce/ShippingMethod.ts +102 -0
- package/dist/models/commerce/ShippingRate.ts +79 -0
- package/dist/models/commerce/ShippingZone.ts +116 -0
- package/dist/models/commerce/TaxRate.ts +167 -0
- package/dist/models/commerce/Transaction.ts +127 -0
- package/dist/models/commerce/WaitlistProduct.ts +151 -0
- package/dist/models/commerce/WaitlistRestaurant.ts +189 -0
- package/dist/models/realtime/Websocket.ts +78 -0
- package/dist/password-policy.ts +46 -0
- package/package.json +4 -4
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { defineModel } from '@stacksjs/orm'
|
|
2
|
+
import { schema } from '@stacksjs/validation'
|
|
3
|
+
|
|
4
|
+
export default defineModel({
|
|
5
|
+
name: 'ShippingMethod',
|
|
6
|
+
table: 'shipping_methods',
|
|
7
|
+
primaryKey: 'id',
|
|
8
|
+
autoIncrement: true,
|
|
9
|
+
|
|
10
|
+
traits: {
|
|
11
|
+
useUuid: true,
|
|
12
|
+
useTimestamps: true,
|
|
13
|
+
useSearch: {
|
|
14
|
+
displayable: ['id', 'name', 'description', 'baseRate', 'freeShipping', 'status'],
|
|
15
|
+
searchable: ['name', 'description'],
|
|
16
|
+
sortable: ['name', 'baseRate', 'createdAt', 'updatedAt'],
|
|
17
|
+
filterable: ['status'],
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
useSeeder: {
|
|
21
|
+
count: 10,
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
useApi: {
|
|
25
|
+
// Public catalog: anyone may browse, only authenticated callers may
|
|
26
|
+
// write. Declared explicitly because the trait now defaults BOTH sides to
|
|
27
|
+
// `auth` — an undeclared read route is how a customer list leaks
|
|
28
|
+
// (stacksjs/stacks#2224). Behaviour here is unchanged.
|
|
29
|
+
middleware: { read: [], write: ['auth'] },
|
|
30
|
+
uri: 'shipping-methods',
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
observe: true,
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
hasMany: ['ShippingZone', 'ShippingRate'],
|
|
37
|
+
|
|
38
|
+
attributes: {
|
|
39
|
+
name: {
|
|
40
|
+
order: 2,
|
|
41
|
+
fillable: true,
|
|
42
|
+
validation: {
|
|
43
|
+
rule: schema.string().required().max(100),
|
|
44
|
+
message: {
|
|
45
|
+
max: 'Name must have a maximum of 100 characters',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
factory: faker => faker.commerce.productName(),
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
description: {
|
|
52
|
+
order: 3,
|
|
53
|
+
fillable: true,
|
|
54
|
+
validation: {
|
|
55
|
+
rule: schema.string().max(500),
|
|
56
|
+
message: {
|
|
57
|
+
max: 'Description must have a maximum of 500 characters',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
factory: faker => faker.lorem.paragraph(),
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
baseRate: {
|
|
64
|
+
order: 4,
|
|
65
|
+
fillable: true,
|
|
66
|
+
validation: {
|
|
67
|
+
rule: schema.number().required().min(0),
|
|
68
|
+
message: {
|
|
69
|
+
min: 'Base rate cannot be negative',
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
factory: faker => faker.number.int({ min: 500, max: 5000 }), // 5.00 to 50.00
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
freeShipping: {
|
|
76
|
+
order: 5,
|
|
77
|
+
fillable: true,
|
|
78
|
+
validation: {
|
|
79
|
+
rule: schema.number().min(0),
|
|
80
|
+
},
|
|
81
|
+
factory: (faker) => {
|
|
82
|
+
// 30% chance of being null (N/A), otherwise a minimum order amount
|
|
83
|
+
return faker.datatype.boolean({ probability: 0.3 })
|
|
84
|
+
? null
|
|
85
|
+
: faker.number.int({ min: 5000, max: 20000 }) // 50.00 to 200.00
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
status: {
|
|
90
|
+
order: 7,
|
|
91
|
+
fillable: true,
|
|
92
|
+
validation: {
|
|
93
|
+
rule: schema.enum(['active', 'inactive', 'draft']).required(),
|
|
94
|
+
},
|
|
95
|
+
factory: faker => faker.helpers.arrayElement(['active', 'inactive', 'draft']),
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
dashboard: {
|
|
100
|
+
highlight: true,
|
|
101
|
+
},
|
|
102
|
+
} as const)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { defineModel } from '@stacksjs/orm'
|
|
2
|
+
import { schema } from '@stacksjs/validation'
|
|
3
|
+
|
|
4
|
+
export default defineModel({
|
|
5
|
+
name: 'ShippingRate',
|
|
6
|
+
table: 'shipping_rates',
|
|
7
|
+
primaryKey: 'id',
|
|
8
|
+
autoIncrement: true,
|
|
9
|
+
|
|
10
|
+
traits: {
|
|
11
|
+
useUuid: true,
|
|
12
|
+
useTimestamps: true,
|
|
13
|
+
useSearch: {
|
|
14
|
+
displayable: ['id', 'shipping_method_id', 'weight_from', 'weight_to', 'rate'],
|
|
15
|
+
searchable: ['shipping_method_id'],
|
|
16
|
+
sortable: ['shipping_method_id', 'weight_from', 'weight_to', 'rate', 'created_at', 'updated_at'],
|
|
17
|
+
filterable: ['shipping_method_id'],
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
useSeeder: {
|
|
21
|
+
count: 10,
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
useApi: {
|
|
25
|
+
// Public catalog: anyone may browse, only authenticated callers may
|
|
26
|
+
// write. Declared explicitly because the trait now defaults BOTH sides to
|
|
27
|
+
// `auth` — an undeclared read route is how a customer list leaks
|
|
28
|
+
// (stacksjs/stacks#2224). Behaviour here is unchanged.
|
|
29
|
+
middleware: { read: [], write: ['auth'] },
|
|
30
|
+
uri: 'shipping-rates',
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
observe: true,
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
belongsTo: ['ShippingMethod', 'ShippingZone'],
|
|
37
|
+
|
|
38
|
+
attributes: {
|
|
39
|
+
weightFrom: {
|
|
40
|
+
order: 4,
|
|
41
|
+
fillable: true,
|
|
42
|
+
validation: {
|
|
43
|
+
rule: schema.float().required().min(0),
|
|
44
|
+
message: {
|
|
45
|
+
min: 'Weight from cannot be negative',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
factory: faker => faker.number.float({ min: 0, max: 10 }),
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
weightTo: {
|
|
52
|
+
order: 5,
|
|
53
|
+
fillable: true,
|
|
54
|
+
validation: {
|
|
55
|
+
rule: schema.float().required().min(0),
|
|
56
|
+
message: {
|
|
57
|
+
min: 'Weight to cannot be negative',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
factory: faker => faker.number.float({ min: 10, max: 50 }),
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
rate: {
|
|
64
|
+
order: 6,
|
|
65
|
+
fillable: true,
|
|
66
|
+
validation: {
|
|
67
|
+
rule: schema.number().required().min(0),
|
|
68
|
+
message: {
|
|
69
|
+
min: 'Rate cannot be negative',
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
factory: faker => faker.number.int({ min: 500, max: 5000 }), // 5.00 to 50.00
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
dashboard: {
|
|
77
|
+
highlight: true,
|
|
78
|
+
},
|
|
79
|
+
} as const)
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { defineModel } from '@stacksjs/orm'
|
|
2
|
+
import { schema } from '@stacksjs/validation'
|
|
3
|
+
|
|
4
|
+
export default defineModel({
|
|
5
|
+
name: 'ShippingZone',
|
|
6
|
+
table: 'shipping_zones',
|
|
7
|
+
primaryKey: 'id',
|
|
8
|
+
autoIncrement: true,
|
|
9
|
+
|
|
10
|
+
traits: {
|
|
11
|
+
useUuid: true,
|
|
12
|
+
useTimestamps: true,
|
|
13
|
+
useSearch: {
|
|
14
|
+
displayable: ['id', 'name', 'countries', 'regions', 'postalCodes', 'status'],
|
|
15
|
+
searchable: ['name'],
|
|
16
|
+
sortable: ['name', 'createdAt', 'updatedAt'],
|
|
17
|
+
filterable: ['status'],
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
useSeeder: {
|
|
21
|
+
count: 10,
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
useApi: {
|
|
25
|
+
// Public catalog: anyone may browse, only authenticated callers may
|
|
26
|
+
// write. Declared explicitly because the trait now defaults BOTH sides to
|
|
27
|
+
// `auth` — an undeclared read route is how a customer list leaks
|
|
28
|
+
// (stacksjs/stacks#2224). Behaviour here is unchanged.
|
|
29
|
+
middleware: { read: [], write: ['auth'] },
|
|
30
|
+
uri: 'shipping-zones',
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
observe: true,
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
belongsTo: ['ShippingMethod'],
|
|
37
|
+
hasMany: ['ShippingRate'],
|
|
38
|
+
attributes: {
|
|
39
|
+
name: {
|
|
40
|
+
order: 2,
|
|
41
|
+
fillable: true,
|
|
42
|
+
validation: {
|
|
43
|
+
rule: schema.string().required().max(100),
|
|
44
|
+
message: {
|
|
45
|
+
max: 'Name must have a maximum of 100 characters',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
factory: faker => `${faker.location.country()} Zone`,
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
countries: {
|
|
52
|
+
order: 3,
|
|
53
|
+
fillable: true,
|
|
54
|
+
validation: {
|
|
55
|
+
rule: schema.string().max(1000),
|
|
56
|
+
message: {
|
|
57
|
+
max: 'Countries must have a maximum of 1000 characters',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
factory: (faker) => {
|
|
61
|
+
const countriesCount = faker.number.int({ min: 1, max: 5 })
|
|
62
|
+
const countries = Array.from({ length: countriesCount }, () => faker.location.country())
|
|
63
|
+
return JSON.stringify(countries)
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
regions: {
|
|
68
|
+
order: 4,
|
|
69
|
+
fillable: true,
|
|
70
|
+
validation: {
|
|
71
|
+
rule: schema.string().max(500),
|
|
72
|
+
message: {
|
|
73
|
+
max: 'Regions must have a maximum of 500 characters',
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
factory: (faker) => {
|
|
77
|
+
const continents = ['North America', 'South America', 'Europe', 'Asia', 'Africa', 'Oceania', 'Antarctica']
|
|
78
|
+
const regionsCount = faker.number.int({ min: 0, max: 3 })
|
|
79
|
+
const regions = faker.helpers.arrayElements(continents, regionsCount)
|
|
80
|
+
return JSON.stringify(regions)
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
postalCodes: {
|
|
85
|
+
order: 5,
|
|
86
|
+
fillable: true,
|
|
87
|
+
validation: {
|
|
88
|
+
rule: schema.string().max(1000),
|
|
89
|
+
message: {
|
|
90
|
+
max: 'Postal codes must have a maximum of 1000 characters',
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
factory: (faker) => {
|
|
94
|
+
const codesCount = faker.number.int({ min: 0, max: 10 })
|
|
95
|
+
// Generate postal/zip codes in various formats
|
|
96
|
+
const codes = Array.from({ length: codesCount }, () => {
|
|
97
|
+
return faker.location.zipCode()
|
|
98
|
+
})
|
|
99
|
+
return JSON.stringify(codes)
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
status: {
|
|
104
|
+
order: 6,
|
|
105
|
+
fillable: true,
|
|
106
|
+
validation: {
|
|
107
|
+
rule: schema.enum(['active', 'inactive', 'draft']).required(),
|
|
108
|
+
},
|
|
109
|
+
factory: faker => faker.helpers.arrayElement(['active', 'inactive', 'draft']),
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
dashboard: {
|
|
114
|
+
highlight: true,
|
|
115
|
+
},
|
|
116
|
+
} as const)
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { defineModel } from '@stacksjs/orm'
|
|
2
|
+
import { schema } from '@stacksjs/validation'
|
|
3
|
+
|
|
4
|
+
export default defineModel({
|
|
5
|
+
name: 'TaxRate',
|
|
6
|
+
table: 'tax_rates',
|
|
7
|
+
primaryKey: 'id',
|
|
8
|
+
autoIncrement: true,
|
|
9
|
+
|
|
10
|
+
traits: {
|
|
11
|
+
useUuid: true,
|
|
12
|
+
useTimestamps: true,
|
|
13
|
+
useSearch: {
|
|
14
|
+
displayable: ['id', 'name', 'rate', 'type', 'country', 'region', 'status', 'isDefault'],
|
|
15
|
+
searchable: ['name', 'country', 'region'],
|
|
16
|
+
sortable: ['name', 'rate', 'status', 'createdAt', 'updatedAt'],
|
|
17
|
+
filterable: ['status', 'isDefault'],
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
useSeeder: {
|
|
21
|
+
count: 5,
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
useApi: {
|
|
25
|
+
// Public catalog: anyone may browse, only authenticated callers may
|
|
26
|
+
// write. Declared explicitly because the trait now defaults BOTH sides to
|
|
27
|
+
// `auth` — an undeclared read route is how a customer list leaks
|
|
28
|
+
// (stacksjs/stacks#2224). Behaviour here is unchanged.
|
|
29
|
+
middleware: { read: [], write: ['auth'] },
|
|
30
|
+
uri: 'tax-rates',
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
observe: true,
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
attributes: {
|
|
37
|
+
name: {
|
|
38
|
+
order: 1,
|
|
39
|
+
fillable: true,
|
|
40
|
+
validation: {
|
|
41
|
+
rule: schema.string().required().max(255),
|
|
42
|
+
message: {
|
|
43
|
+
max: 'Name must have a maximum of 255 characters',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
factory: faker => faker.commerce.productName(),
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
rate: {
|
|
50
|
+
order: 2,
|
|
51
|
+
fillable: true,
|
|
52
|
+
validation: {
|
|
53
|
+
rule: schema.number().required().min(0).max(100),
|
|
54
|
+
message: {
|
|
55
|
+
min: 'Rate must be greater than or equal to 0',
|
|
56
|
+
max: 'Rate must be less than or equal to 100',
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
factory: faker => faker.number.int({ min: 0, max: 100 }),
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
type: {
|
|
63
|
+
order: 3,
|
|
64
|
+
fillable: true,
|
|
65
|
+
validation: {
|
|
66
|
+
rule: schema.string().required().max(100),
|
|
67
|
+
message: {
|
|
68
|
+
max: 'Type must have a maximum of 100 characters',
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
factory: faker => faker.helpers.arrayElement(['VAT', 'GST', 'Sales Tax', 'Customs Duty']),
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
country: {
|
|
75
|
+
order: 4,
|
|
76
|
+
fillable: true,
|
|
77
|
+
validation: {
|
|
78
|
+
rule: schema.string().required().max(100),
|
|
79
|
+
message: {
|
|
80
|
+
max: 'Country must have a maximum of 100 characters',
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
factory: faker => faker.location.country(),
|
|
84
|
+
},
|
|
85
|
+
|
|
86
|
+
region: {
|
|
87
|
+
order: 5,
|
|
88
|
+
fillable: true,
|
|
89
|
+
validation: {
|
|
90
|
+
rule: schema.enum(['North America', 'South America', 'Europe', 'Asia', 'Africa', 'Oceania', 'Antarctica']),
|
|
91
|
+
},
|
|
92
|
+
factory: faker => faker.helpers.arrayElement(['North America', 'South America', 'Europe', 'Asia', 'Africa', 'Oceania', 'Antarctica']),
|
|
93
|
+
},
|
|
94
|
+
|
|
95
|
+
status: {
|
|
96
|
+
default: 'active',
|
|
97
|
+
order: 6,
|
|
98
|
+
fillable: true,
|
|
99
|
+
validation: {
|
|
100
|
+
rule: schema.enum(['active', 'inactive']),
|
|
101
|
+
},
|
|
102
|
+
factory: faker => faker.helpers.arrayElement(['active', 'inactive']),
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
isDefault: {
|
|
106
|
+
default: false,
|
|
107
|
+
order: 7,
|
|
108
|
+
fillable: true,
|
|
109
|
+
validation: {
|
|
110
|
+
rule: schema.boolean(),
|
|
111
|
+
},
|
|
112
|
+
factory: () => false,
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* A stable name for this component, for code to reference.
|
|
117
|
+
*
|
|
118
|
+
* `name` is what an operator reads and edits in the dashboard, so it is
|
|
119
|
+
* the wrong thing for an application to branch on — renaming "State sales
|
|
120
|
+
* tax" to "Sales tax (CA)" should not change what gets charged. A code is
|
|
121
|
+
* the identifier that survives the rename.
|
|
122
|
+
*
|
|
123
|
+
* Free-form on purpose. What counts as a component differs by
|
|
124
|
+
* jurisdiction: `vat`, `gst`, `excise`, `city`, `eco-fee`.
|
|
125
|
+
*/
|
|
126
|
+
code: {
|
|
127
|
+
order: 8,
|
|
128
|
+
fillable: true,
|
|
129
|
+
default: '',
|
|
130
|
+
validation: {
|
|
131
|
+
rule: schema.string().max(64),
|
|
132
|
+
message: {
|
|
133
|
+
max: 'Code must have a maximum of 64 characters',
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
factory: faker => faker.helpers.arrayElement(['vat', 'gst', 'sales', 'excise', 'city']),
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Whether a qualifying exemption removes this component.
|
|
141
|
+
*
|
|
142
|
+
* Most places tax in parts, and an exemption usually lifts some of them
|
|
143
|
+
* and not others: groceries escape VAT but not a deposit levy, and a
|
|
144
|
+
* Californian medical cannabis patient is exempt from sales tax while
|
|
145
|
+
* still paying excise and the city's business tax. Modelling tax as one
|
|
146
|
+
* blended number cannot say that, so an app either over-charges the
|
|
147
|
+
* exempt customer or under-collects tax it owes.
|
|
148
|
+
*
|
|
149
|
+
* What *qualifies* is the application's business — a card, a resale
|
|
150
|
+
* certificate, a charity registration. This only records that the
|
|
151
|
+
* component is the kind that can be lifted.
|
|
152
|
+
*/
|
|
153
|
+
exemptible: {
|
|
154
|
+
order: 9,
|
|
155
|
+
fillable: true,
|
|
156
|
+
default: false,
|
|
157
|
+
validation: {
|
|
158
|
+
rule: schema.boolean(),
|
|
159
|
+
},
|
|
160
|
+
factory: () => false,
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
|
|
164
|
+
dashboard: {
|
|
165
|
+
highlight: true,
|
|
166
|
+
},
|
|
167
|
+
} as const)
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { defineModel } from '@stacksjs/orm'
|
|
2
|
+
import { schema } from '@stacksjs/validation'
|
|
3
|
+
|
|
4
|
+
export default defineModel({
|
|
5
|
+
name: 'Transaction',
|
|
6
|
+
table: 'transactions',
|
|
7
|
+
primaryKey: 'id',
|
|
8
|
+
autoIncrement: true,
|
|
9
|
+
|
|
10
|
+
traits: {
|
|
11
|
+
useUuid: true,
|
|
12
|
+
useTimestamps: true,
|
|
13
|
+
useSearch: {
|
|
14
|
+
displayable: ['id', 'orderId', 'amount', 'status', 'paymentMethod', 'createdAt'],
|
|
15
|
+
searchable: ['id', 'orderId', 'status', 'paymentMethod', 'transactionReference'],
|
|
16
|
+
sortable: ['createdAt', 'amount'],
|
|
17
|
+
filterable: ['status', 'paymentMethod'],
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
useSeeder: {
|
|
21
|
+
count: 20,
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
useApi: {
|
|
25
|
+
uri: 'transactions',
|
|
26
|
+
middleware: ['auth'],
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
observe: true,
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
belongsTo: ['Order'],
|
|
33
|
+
|
|
34
|
+
attributes: {
|
|
35
|
+
amount: {
|
|
36
|
+
order: 2,
|
|
37
|
+
fillable: true,
|
|
38
|
+
validation: {
|
|
39
|
+
rule: schema.number().required().min(0.01),
|
|
40
|
+
},
|
|
41
|
+
factory: faker => faker.number.int({ min: 5, max: 500 }),
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
status: {
|
|
45
|
+
order: 3,
|
|
46
|
+
fillable: true,
|
|
47
|
+
validation: {
|
|
48
|
+
rule: schema.string().required(),
|
|
49
|
+
},
|
|
50
|
+
factory: faker => faker.helpers.arrayElement(['PENDING', 'COMPLETED', 'FAILED', 'REFUNDED']),
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
paymentMethod: {
|
|
54
|
+
order: 4,
|
|
55
|
+
fillable: true,
|
|
56
|
+
validation: {
|
|
57
|
+
rule: schema.string().required(),
|
|
58
|
+
},
|
|
59
|
+
factory: faker => faker.helpers.arrayElement(['CREDIT_CARD', 'DEBIT_CARD', 'CASH', 'WALLET']),
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
paymentDetails: {
|
|
63
|
+
order: 5,
|
|
64
|
+
fillable: true,
|
|
65
|
+
hidden: true,
|
|
66
|
+
validation: {
|
|
67
|
+
rule: schema.string(),
|
|
68
|
+
},
|
|
69
|
+
factory: (faker) => {
|
|
70
|
+
const paymentMethod = faker.helpers.arrayElement(['CREDIT_CARD', 'DEBIT_CARD', 'CASH', 'WALLET'])
|
|
71
|
+
|
|
72
|
+
let details
|
|
73
|
+
if (paymentMethod === 'CREDIT_CARD' || paymentMethod === 'DEBIT_CARD') {
|
|
74
|
+
details = {
|
|
75
|
+
last4: faker.finance.creditCardNumber('####'),
|
|
76
|
+
expiry: `${faker.date.future().getMonth() + 1}/${String(faker.date.future().getFullYear()).slice(-2)}`,
|
|
77
|
+
brand: faker.helpers.arrayElement(['Visa', 'Mastercard', 'Amex', 'Discover']),
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else if (paymentMethod === 'WALLET') {
|
|
81
|
+
details = {
|
|
82
|
+
wallet_id: faker.string.uuid(),
|
|
83
|
+
transaction_id: faker.string.alphanumeric(12),
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
details = {
|
|
88
|
+
receipt_number: faker.string.alphanumeric(8).toUpperCase(),
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return JSON.stringify(details)
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
transactionReference: {
|
|
97
|
+
order: 6,
|
|
98
|
+
fillable: true,
|
|
99
|
+
validation: {
|
|
100
|
+
rule: schema.string(),
|
|
101
|
+
},
|
|
102
|
+
factory: faker => faker.string.alphanumeric(16).toUpperCase(),
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
loyaltyPointsEarned: {
|
|
106
|
+
order: 7,
|
|
107
|
+
fillable: true,
|
|
108
|
+
validation: {
|
|
109
|
+
rule: schema.number().min(0),
|
|
110
|
+
},
|
|
111
|
+
factory: faker => faker.number.int({ min: 0, max: 100 }),
|
|
112
|
+
},
|
|
113
|
+
|
|
114
|
+
loyaltyPointsRedeemed: {
|
|
115
|
+
order: 8,
|
|
116
|
+
fillable: true,
|
|
117
|
+
validation: {
|
|
118
|
+
rule: schema.number().min(0),
|
|
119
|
+
},
|
|
120
|
+
factory: faker => faker.number.int({ min: 0, max: 50 }),
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
dashboard: {
|
|
125
|
+
highlight: true,
|
|
126
|
+
},
|
|
127
|
+
} as const)
|