@porulle/core 0.41.0 → 0.42.0
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/interfaces/rest/customer-portal.d.ts.map +1 -1
- package/dist/interfaces/rest/customer-portal.js +1 -1
- package/dist/interfaces/rest/routes/orders.js +1 -1
- package/dist/modules/fulfillment/repository/index.d.ts +11 -11
- package/dist/modules/fulfillment/repository/index.d.ts.map +1 -1
- package/dist/modules/fulfillment/repository/index.js +54 -27
- package/dist/modules/fulfillment/service.d.ts +2 -2
- package/dist/modules/fulfillment/service.d.ts.map +1 -1
- package/dist/modules/fulfillment/service.js +29 -8
- package/package.json +3 -3
- package/src/interfaces/rest/customer-portal.ts +1 -0
- package/src/interfaces/rest/routes/orders.ts +1 -1
- package/src/modules/fulfillment/repository/index.ts +96 -18
- package/src/modules/fulfillment/service.ts +41 -5
- package/dist/tsconfig.tsbuildinfo +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"customer-portal.d.ts","sourceRoot":"","sources":["../../../src/interfaces/rest/customer-portal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAQtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAkBzC,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"customer-portal.d.ts","sourceRoot":"","sources":["../../../src/interfaces/rest/customer-portal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAQtD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAkBzC,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,gCA2SxD"}
|
|
@@ -116,7 +116,7 @@ export function createCustomerPortalRoutes(kernel) {
|
|
|
116
116
|
if (!orderResult.ok) {
|
|
117
117
|
return c.json({ error: orderResult.error }, mapErrorToStatus(orderResult.error));
|
|
118
118
|
}
|
|
119
|
-
const fulfillments = await kernel.services.fulfillment.getByOrderId(orderResult.value.id);
|
|
119
|
+
const fulfillments = await kernel.services.fulfillment.getByOrderId(orderResult.value.id, customerActor);
|
|
120
120
|
if (!fulfillments.ok)
|
|
121
121
|
return c.json({ error: fulfillments.error }, 500);
|
|
122
122
|
return c.json({
|
|
@@ -254,7 +254,7 @@ export function orderRoutes(kernel) {
|
|
|
254
254
|
: await kernel.services.orders.getByNumber(orderId, actor, undefined, guestCredential);
|
|
255
255
|
if (!orderResult.ok)
|
|
256
256
|
return c.json(mapErrorToResponse(orderResult.error), mapErrorToStatus(orderResult.error));
|
|
257
|
-
const result = await kernel.services.fulfillment.getByOrderId(orderResult.value.id);
|
|
257
|
+
const result = await kernel.services.fulfillment.getByOrderId(orderResult.value.id, actor);
|
|
258
258
|
if (!result.ok)
|
|
259
259
|
return c.json(mapErrorToResponse(result.error), mapErrorToStatus(result.error));
|
|
260
260
|
return c.json({ data: result.value });
|
|
@@ -18,8 +18,8 @@ export declare class FulfillmentRepository {
|
|
|
18
18
|
private readonly db;
|
|
19
19
|
constructor(db: DrizzleDatabase);
|
|
20
20
|
private getDb;
|
|
21
|
-
findById(id: string, ctx?: TxContext): Promise<FulfillmentRecord | undefined>;
|
|
22
|
-
findByOrderId(orderId: string, ctx?: TxContext): Promise<FulfillmentRecord[]>;
|
|
21
|
+
findById(orgId: string, id: string, ctx?: TxContext): Promise<FulfillmentRecord | undefined>;
|
|
22
|
+
findByOrderId(orgId: string, orderId: string, ctx?: TxContext): Promise<FulfillmentRecord[]>;
|
|
23
23
|
findByCustomerId(customerId: string, ctx?: TxContext): Promise<FulfillmentRecord[]>;
|
|
24
24
|
findByStatus(status: string, ctx?: TxContext): Promise<FulfillmentRecord[]>;
|
|
25
25
|
findByType(type: string, ctx?: TxContext): Promise<FulfillmentRecord[]>;
|
|
@@ -30,14 +30,14 @@ export declare class FulfillmentRepository {
|
|
|
30
30
|
offset?: number;
|
|
31
31
|
}, ctx?: TxContext): Promise<FulfillmentRecord[]>;
|
|
32
32
|
create(data: FulfillmentRecordInsert, ctx?: TxContext): Promise<FulfillmentRecord>;
|
|
33
|
-
update(id: string, data: Partial<Omit<FulfillmentRecordInsert, "id">>, ctx?: TxContext): Promise<FulfillmentRecord | undefined>;
|
|
34
|
-
updateStatus(id: string, status: string, ctx?: TxContext): Promise<FulfillmentRecord | undefined>;
|
|
33
|
+
update(orgId: string, id: string, data: Partial<Omit<FulfillmentRecordInsert, "id">>, ctx?: TxContext): Promise<FulfillmentRecord | undefined>;
|
|
34
|
+
updateStatus(orgId: string, id: string, status: string, ctx?: TxContext): Promise<FulfillmentRecord | undefined>;
|
|
35
35
|
delete(id: string, ctx?: TxContext): Promise<boolean>;
|
|
36
|
-
incrementDownloadCount(id: string, ctx?: TxContext): Promise<FulfillmentRecord | undefined>;
|
|
37
|
-
isDownloadAllowed(id: string, ctx?: TxContext): Promise<boolean>;
|
|
38
|
-
deactivateAccessGrant(id: string, ctx?: TxContext): Promise<FulfillmentRecord | undefined>;
|
|
39
|
-
activateAccessGrant(id: string, ctx?: TxContext): Promise<FulfillmentRecord | undefined>;
|
|
40
|
-
isAccessGrantActive(id: string, ctx?: TxContext): Promise<boolean>;
|
|
36
|
+
incrementDownloadCount(orgId: string, id: string, ctx?: TxContext): Promise<FulfillmentRecord | undefined>;
|
|
37
|
+
isDownloadAllowed(orgId: string, id: string, ctx?: TxContext): Promise<boolean>;
|
|
38
|
+
deactivateAccessGrant(orgId: string, id: string, ctx?: TxContext): Promise<FulfillmentRecord | undefined>;
|
|
39
|
+
activateAccessGrant(orgId: string, id: string, ctx?: TxContext): Promise<FulfillmentRecord | undefined>;
|
|
40
|
+
isAccessGrantActive(orgId: string, id: string, ctx?: TxContext): Promise<boolean>;
|
|
41
41
|
findLineItemsByFulfillmentId(fulfillmentId: string, ctx?: TxContext): Promise<FulfillmentLineItem[]>;
|
|
42
42
|
findLineItemsByOrderLineItemId(orderLineItemId: string, ctx?: TxContext): Promise<FulfillmentLineItem[]>;
|
|
43
43
|
createLineItem(data: FulfillmentLineItemInsert, ctx?: TxContext): Promise<FulfillmentLineItem>;
|
|
@@ -46,11 +46,11 @@ export declare class FulfillmentRepository {
|
|
|
46
46
|
findEventsByFulfillmentId(fulfillmentId: string, ctx?: TxContext): Promise<FulfillmentEvent[]>;
|
|
47
47
|
createEvent(data: FulfillmentEventInsert, ctx?: TxContext): Promise<FulfillmentEvent>;
|
|
48
48
|
recordStatusChange(fulfillmentId: string, fromStatus: string, toStatus: string, actorId?: string, description?: string, ctx?: TxContext): Promise<FulfillmentEvent>;
|
|
49
|
-
findWithLineItems(id: string, ctx?: TxContext): Promise<{
|
|
49
|
+
findWithLineItems(orgId: string, id: string, ctx?: TxContext): Promise<{
|
|
50
50
|
fulfillment: FulfillmentRecord;
|
|
51
51
|
lineItems: FulfillmentLineItem[];
|
|
52
52
|
} | undefined>;
|
|
53
|
-
findWithEvents(id: string, ctx?: TxContext): Promise<{
|
|
53
|
+
findWithEvents(orgId: string, id: string, ctx?: TxContext): Promise<{
|
|
54
54
|
fulfillment: FulfillmentRecord;
|
|
55
55
|
events: FulfillmentEvent[];
|
|
56
56
|
} | undefined>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modules/fulfillment/repository/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAC;AACxE,OAAO,KAAK,EACV,eAAe,EAEhB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EAClB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modules/fulfillment/repository/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { eq, desc, and, sql } from "drizzle-orm";
|
|
1
|
+
import { eq, desc, and, sql, exists } from "drizzle-orm";
|
|
2
2
|
import { fulfillmentRecords, fulfillmentLineItems, fulfillmentEvents, } from "../schema.js";
|
|
3
|
+
import { orders } from "../../orders/schema.js";
|
|
3
4
|
/**
|
|
4
5
|
* FulfillmentRepository provides type-safe database operations for fulfillments.
|
|
5
6
|
*
|
|
@@ -18,22 +19,26 @@ export class FulfillmentRepository {
|
|
|
18
19
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
19
20
|
// Fulfillment Records
|
|
20
21
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
21
|
-
async findById(id, ctx) {
|
|
22
|
+
async findById(orgId, id, ctx) {
|
|
22
23
|
const db = this.getDb(ctx);
|
|
23
24
|
const rows = await db
|
|
24
|
-
.select()
|
|
25
|
+
.select({ fulfillment: fulfillmentRecords })
|
|
25
26
|
.from(fulfillmentRecords)
|
|
26
|
-
.
|
|
27
|
-
|
|
27
|
+
.innerJoin(orders, eq(fulfillmentRecords.orderId, orders.id))
|
|
28
|
+
.where(and(eq(fulfillmentRecords.id, id), eq(orders.organizationId, orgId)));
|
|
29
|
+
return rows[0]?.fulfillment;
|
|
28
30
|
}
|
|
29
|
-
async findByOrderId(orderId, ctx) {
|
|
31
|
+
async findByOrderId(orgId, orderId, ctx) {
|
|
30
32
|
const db = this.getDb(ctx);
|
|
31
|
-
|
|
32
|
-
.select()
|
|
33
|
+
const rows = await db
|
|
34
|
+
.select({ fulfillment: fulfillmentRecords })
|
|
33
35
|
.from(fulfillmentRecords)
|
|
34
|
-
.
|
|
36
|
+
.innerJoin(orders, eq(fulfillmentRecords.orderId, orders.id))
|
|
37
|
+
.where(and(eq(fulfillmentRecords.orderId, orderId), eq(orders.organizationId, orgId)))
|
|
35
38
|
.orderBy(desc(fulfillmentRecords.createdAt));
|
|
39
|
+
return rows.map((row) => row.fulfillment);
|
|
36
40
|
}
|
|
41
|
+
// not tenant-scoped; do not use for tenant-facing access
|
|
37
42
|
async findByCustomerId(customerId, ctx) {
|
|
38
43
|
const db = this.getDb(ctx);
|
|
39
44
|
return db
|
|
@@ -42,6 +47,7 @@ export class FulfillmentRepository {
|
|
|
42
47
|
.where(eq(fulfillmentRecords.customerId, customerId))
|
|
43
48
|
.orderBy(desc(fulfillmentRecords.createdAt));
|
|
44
49
|
}
|
|
50
|
+
// not tenant-scoped; do not use for tenant-facing access
|
|
45
51
|
async findByStatus(status, ctx) {
|
|
46
52
|
const db = this.getDb(ctx);
|
|
47
53
|
return db
|
|
@@ -50,6 +56,7 @@ export class FulfillmentRepository {
|
|
|
50
56
|
.where(eq(fulfillmentRecords.status, status))
|
|
51
57
|
.orderBy(desc(fulfillmentRecords.createdAt));
|
|
52
58
|
}
|
|
59
|
+
// not tenant-scoped; do not use for tenant-facing access
|
|
53
60
|
async findByType(type, ctx) {
|
|
54
61
|
const db = this.getDb(ctx);
|
|
55
62
|
return db
|
|
@@ -58,6 +65,7 @@ export class FulfillmentRepository {
|
|
|
58
65
|
.where(eq(fulfillmentRecords.type, type))
|
|
59
66
|
.orderBy(desc(fulfillmentRecords.createdAt));
|
|
60
67
|
}
|
|
68
|
+
// not tenant-scoped; do not use for tenant-facing access
|
|
61
69
|
async findByOrderIdAndStatus(orderId, status, ctx) {
|
|
62
70
|
const db = this.getDb(ctx);
|
|
63
71
|
return db
|
|
@@ -66,6 +74,7 @@ export class FulfillmentRepository {
|
|
|
66
74
|
.where(and(eq(fulfillmentRecords.orderId, orderId), eq(fulfillmentRecords.status, status)))
|
|
67
75
|
.orderBy(desc(fulfillmentRecords.createdAt));
|
|
68
76
|
}
|
|
77
|
+
// not tenant-scoped; do not use for tenant-facing access
|
|
69
78
|
async findActiveAccessGrants(customerId, ctx) {
|
|
70
79
|
const db = this.getDb(ctx);
|
|
71
80
|
return db
|
|
@@ -74,6 +83,7 @@ export class FulfillmentRepository {
|
|
|
74
83
|
.where(and(eq(fulfillmentRecords.customerId, customerId), eq(fulfillmentRecords.type, "access_grant"), eq(fulfillmentRecords.isActive, true)))
|
|
75
84
|
.orderBy(desc(fulfillmentRecords.grantedAt));
|
|
76
85
|
}
|
|
86
|
+
// not tenant-scoped; do not use for tenant-facing access
|
|
77
87
|
async findAll(options, ctx) {
|
|
78
88
|
const db = this.getDb(ctx);
|
|
79
89
|
let query = db
|
|
@@ -94,16 +104,19 @@ export class FulfillmentRepository {
|
|
|
94
104
|
const rows = await db.insert(fulfillmentRecords).values(data).returning();
|
|
95
105
|
return rows[0];
|
|
96
106
|
}
|
|
97
|
-
async update(id, data, ctx) {
|
|
107
|
+
async update(orgId, id, data, ctx) {
|
|
98
108
|
const db = this.getDb(ctx);
|
|
99
109
|
const rows = await db
|
|
100
110
|
.update(fulfillmentRecords)
|
|
101
111
|
.set({ ...data, updatedAt: new Date() })
|
|
102
|
-
.where(eq(fulfillmentRecords.id, id)
|
|
112
|
+
.where(and(eq(fulfillmentRecords.id, id), exists(db
|
|
113
|
+
.select({ id: orders.id })
|
|
114
|
+
.from(orders)
|
|
115
|
+
.where(and(eq(orders.id, fulfillmentRecords.orderId), eq(orders.organizationId, orgId))))))
|
|
103
116
|
.returning();
|
|
104
117
|
return rows[0];
|
|
105
118
|
}
|
|
106
|
-
async updateStatus(id, status, ctx) {
|
|
119
|
+
async updateStatus(orgId, id, status, ctx) {
|
|
107
120
|
const data = { status };
|
|
108
121
|
// Set timestamps based on status
|
|
109
122
|
if (status === "shipped") {
|
|
@@ -112,8 +125,10 @@ export class FulfillmentRepository {
|
|
|
112
125
|
else if (status === "delivered") {
|
|
113
126
|
data.deliveredAt = new Date();
|
|
114
127
|
}
|
|
115
|
-
return this.update(id, data, ctx);
|
|
128
|
+
return this.update(orgId, id, data, ctx);
|
|
116
129
|
}
|
|
130
|
+
// not tenant-scoped; do not use for tenant-facing access — this is an unscoped WRITE and
|
|
131
|
+
// has no caller today; it needs the same orgId predicate as `update` before it gains one
|
|
117
132
|
async delete(id, ctx) {
|
|
118
133
|
const db = this.getDb(ctx);
|
|
119
134
|
const result = await db
|
|
@@ -125,7 +140,7 @@ export class FulfillmentRepository {
|
|
|
125
140
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
126
141
|
// Digital Delivery Operations
|
|
127
142
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
128
|
-
async incrementDownloadCount(id, ctx) {
|
|
143
|
+
async incrementDownloadCount(orgId, id, ctx) {
|
|
129
144
|
const db = this.getDb(ctx);
|
|
130
145
|
const rows = await db
|
|
131
146
|
.update(fulfillmentRecords)
|
|
@@ -133,12 +148,15 @@ export class FulfillmentRepository {
|
|
|
133
148
|
downloadCount: sql `${fulfillmentRecords.downloadCount} + 1`,
|
|
134
149
|
updatedAt: new Date(),
|
|
135
150
|
})
|
|
136
|
-
.where(eq(fulfillmentRecords.id, id)
|
|
151
|
+
.where(and(eq(fulfillmentRecords.id, id), exists(db
|
|
152
|
+
.select({ id: orders.id })
|
|
153
|
+
.from(orders)
|
|
154
|
+
.where(and(eq(orders.id, fulfillmentRecords.orderId), eq(orders.organizationId, orgId))))))
|
|
137
155
|
.returning();
|
|
138
156
|
return rows[0];
|
|
139
157
|
}
|
|
140
|
-
async isDownloadAllowed(id, ctx) {
|
|
141
|
-
const fulfillment = await this.findById(id, ctx);
|
|
158
|
+
async isDownloadAllowed(orgId, id, ctx) {
|
|
159
|
+
const fulfillment = await this.findById(orgId, id, ctx);
|
|
142
160
|
if (!fulfillment || fulfillment.type !== "digital")
|
|
143
161
|
return false;
|
|
144
162
|
// Check expiration
|
|
@@ -156,14 +174,14 @@ export class FulfillmentRepository {
|
|
|
156
174
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
157
175
|
// Access Grant Operations
|
|
158
176
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
159
|
-
async deactivateAccessGrant(id, ctx) {
|
|
160
|
-
return this.update(id, { isActive: false }, ctx);
|
|
177
|
+
async deactivateAccessGrant(orgId, id, ctx) {
|
|
178
|
+
return this.update(orgId, id, { isActive: false }, ctx);
|
|
161
179
|
}
|
|
162
|
-
async activateAccessGrant(id, ctx) {
|
|
163
|
-
return this.update(id, { isActive: true, grantedAt: new Date() }, ctx);
|
|
180
|
+
async activateAccessGrant(orgId, id, ctx) {
|
|
181
|
+
return this.update(orgId, id, { isActive: true, grantedAt: new Date() }, ctx);
|
|
164
182
|
}
|
|
165
|
-
async isAccessGrantActive(id, ctx) {
|
|
166
|
-
const fulfillment = await this.findById(id, ctx);
|
|
183
|
+
async isAccessGrantActive(orgId, id, ctx) {
|
|
184
|
+
const fulfillment = await this.findById(orgId, id, ctx);
|
|
167
185
|
if (!fulfillment || fulfillment.type !== "access_grant")
|
|
168
186
|
return false;
|
|
169
187
|
if (!fulfillment.isActive)
|
|
@@ -177,6 +195,7 @@ export class FulfillmentRepository {
|
|
|
177
195
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
178
196
|
// Fulfillment Line Items
|
|
179
197
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
198
|
+
// not tenant-scoped; do not use for tenant-facing access
|
|
180
199
|
async findLineItemsByFulfillmentId(fulfillmentId, ctx) {
|
|
181
200
|
const db = this.getDb(ctx);
|
|
182
201
|
return db
|
|
@@ -184,6 +203,7 @@ export class FulfillmentRepository {
|
|
|
184
203
|
.from(fulfillmentLineItems)
|
|
185
204
|
.where(eq(fulfillmentLineItems.fulfillmentId, fulfillmentId));
|
|
186
205
|
}
|
|
206
|
+
// not tenant-scoped; do not use for tenant-facing access
|
|
187
207
|
async findLineItemsByOrderLineItemId(orderLineItemId, ctx) {
|
|
188
208
|
const db = this.getDb(ctx);
|
|
189
209
|
return db
|
|
@@ -191,17 +211,20 @@ export class FulfillmentRepository {
|
|
|
191
211
|
.from(fulfillmentLineItems)
|
|
192
212
|
.where(eq(fulfillmentLineItems.orderLineItemId, orderLineItemId));
|
|
193
213
|
}
|
|
214
|
+
// not tenant-scoped; do not use for tenant-facing access
|
|
194
215
|
async createLineItem(data, ctx) {
|
|
195
216
|
const db = this.getDb(ctx);
|
|
196
217
|
const rows = await db.insert(fulfillmentLineItems).values(data).returning();
|
|
197
218
|
return rows[0];
|
|
198
219
|
}
|
|
220
|
+
// not tenant-scoped; do not use for tenant-facing access
|
|
199
221
|
async createLineItems(data, ctx) {
|
|
200
222
|
if (data.length === 0)
|
|
201
223
|
return [];
|
|
202
224
|
const db = this.getDb(ctx);
|
|
203
225
|
return db.insert(fulfillmentLineItems).values(data).returning();
|
|
204
226
|
}
|
|
227
|
+
// not tenant-scoped; do not use for tenant-facing access
|
|
205
228
|
async deleteLineItemsByFulfillmentId(fulfillmentId, ctx) {
|
|
206
229
|
const db = this.getDb(ctx);
|
|
207
230
|
await db
|
|
@@ -211,6 +234,7 @@ export class FulfillmentRepository {
|
|
|
211
234
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
212
235
|
// Fulfillment Events
|
|
213
236
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
237
|
+
// not tenant-scoped; do not use for tenant-facing access
|
|
214
238
|
async findEventsByFulfillmentId(fulfillmentId, ctx) {
|
|
215
239
|
const db = this.getDb(ctx);
|
|
216
240
|
return db
|
|
@@ -219,11 +243,13 @@ export class FulfillmentRepository {
|
|
|
219
243
|
.where(eq(fulfillmentEvents.fulfillmentId, fulfillmentId))
|
|
220
244
|
.orderBy(desc(fulfillmentEvents.occurredAt));
|
|
221
245
|
}
|
|
246
|
+
// not tenant-scoped; do not use for tenant-facing access
|
|
222
247
|
async createEvent(data, ctx) {
|
|
223
248
|
const db = this.getDb(ctx);
|
|
224
249
|
const rows = await db.insert(fulfillmentEvents).values(data).returning();
|
|
225
250
|
return rows[0];
|
|
226
251
|
}
|
|
252
|
+
// not tenant-scoped; do not use for tenant-facing access
|
|
227
253
|
async recordStatusChange(fulfillmentId, fromStatus, toStatus, actorId, description, ctx) {
|
|
228
254
|
return this.createEvent({
|
|
229
255
|
fulfillmentId,
|
|
@@ -237,15 +263,15 @@ export class FulfillmentRepository {
|
|
|
237
263
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
238
264
|
// Aggregate Operations
|
|
239
265
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
240
|
-
async findWithLineItems(id, ctx) {
|
|
241
|
-
const fulfillment = await this.findById(id, ctx);
|
|
266
|
+
async findWithLineItems(orgId, id, ctx) {
|
|
267
|
+
const fulfillment = await this.findById(orgId, id, ctx);
|
|
242
268
|
if (!fulfillment)
|
|
243
269
|
return undefined;
|
|
244
270
|
const lineItems = await this.findLineItemsByFulfillmentId(id, ctx);
|
|
245
271
|
return { fulfillment, lineItems };
|
|
246
272
|
}
|
|
247
|
-
async findWithEvents(id, ctx) {
|
|
248
|
-
const fulfillment = await this.findById(id, ctx);
|
|
273
|
+
async findWithEvents(orgId, id, ctx) {
|
|
274
|
+
const fulfillment = await this.findById(orgId, id, ctx);
|
|
249
275
|
if (!fulfillment)
|
|
250
276
|
return undefined;
|
|
251
277
|
const events = await this.findEventsByFulfillmentId(id, ctx);
|
|
@@ -255,6 +281,7 @@ export class FulfillmentRepository {
|
|
|
255
281
|
* Get fulfilled quantity for an order line item.
|
|
256
282
|
* Sums all fulfillment line items linked to the order line item.
|
|
257
283
|
*/
|
|
284
|
+
// not tenant-scoped; do not use for tenant-facing access
|
|
258
285
|
async getFulfilledQuantity(orderLineItemId, ctx) {
|
|
259
286
|
const db = this.getDb(ctx);
|
|
260
287
|
const result = await db
|
|
@@ -57,14 +57,14 @@ export declare class FulfillmentService {
|
|
|
57
57
|
status?: string;
|
|
58
58
|
metadata?: Record<string, unknown>;
|
|
59
59
|
}, actor?: Actor | null, ctx?: TxContext): Promise<Result<FulfillmentRecord>>;
|
|
60
|
-
getByOrderId(orderId: string, ctx?: TxContext): Promise<Result<FulfillmentRecord[]>>;
|
|
60
|
+
getByOrderId(orderId: string, actor?: Actor | null, ctx?: TxContext): Promise<Result<FulfillmentRecord[]>>;
|
|
61
61
|
updateTracking(input: {
|
|
62
62
|
fulfillmentId: string;
|
|
63
63
|
carrier?: string;
|
|
64
64
|
trackingNumber?: string;
|
|
65
65
|
trackingUrl?: string;
|
|
66
66
|
status?: string;
|
|
67
|
-
}, ctx?: TxContext): Promise<Result<void>>;
|
|
67
|
+
}, actor?: Actor | null, ctx?: TxContext): Promise<Result<void>>;
|
|
68
68
|
getDownloadUrl(orderId: string, lineItemId: string, userId: string, actor?: Actor | null, ctx?: TxContext): Promise<Result<{
|
|
69
69
|
url: string;
|
|
70
70
|
remaining: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/modules/fulfillment/service.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAExE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAC;AAIrE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAEnE,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAE9D,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/modules/fulfillment/service.ts"],"names":[],"mappings":"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"}
|
|
@@ -291,8 +291,19 @@ export class FulfillmentService {
|
|
|
291
291
|
await runAfterHooks(afterHooks, null, record, "create", hookCtx, (hook) => this.deps.hooks.runsInTransaction(hook));
|
|
292
292
|
return Ok(record);
|
|
293
293
|
}
|
|
294
|
-
async getByOrderId(orderId, ctx) {
|
|
295
|
-
|
|
294
|
+
async getByOrderId(orderId, actor, ctx) {
|
|
295
|
+
// Fail closed through the Result boundary, as updateTracking does. Strict org resolution
|
|
296
|
+
// THROWS, and this method did not resolve an org before this change — so leaving it
|
|
297
|
+
// unwrapped would add a throw to a Result-returning method whose REST callers branch on
|
|
298
|
+
// `!result.ok` and would never see it.
|
|
299
|
+
let orgId;
|
|
300
|
+
try {
|
|
301
|
+
orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
|
|
302
|
+
}
|
|
303
|
+
catch (error) {
|
|
304
|
+
return Err(toCommerceError(error));
|
|
305
|
+
}
|
|
306
|
+
const dbRecords = await this.deps.repository.findByOrderId(orgId, orderId, ctx);
|
|
296
307
|
// Hydrate each record with its associated line items
|
|
297
308
|
const records = [];
|
|
298
309
|
for (const dbRecord of dbRecords) {
|
|
@@ -301,8 +312,15 @@ export class FulfillmentService {
|
|
|
301
312
|
}
|
|
302
313
|
return Ok(records);
|
|
303
314
|
}
|
|
304
|
-
async updateTracking(input, ctx) {
|
|
305
|
-
|
|
315
|
+
async updateTracking(input, actor, ctx) {
|
|
316
|
+
let orgId;
|
|
317
|
+
try {
|
|
318
|
+
orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
|
|
319
|
+
}
|
|
320
|
+
catch (error) {
|
|
321
|
+
return Err(toCommerceError(error));
|
|
322
|
+
}
|
|
323
|
+
const existing = await this.deps.repository.findById(orgId, input.fulfillmentId, ctx);
|
|
306
324
|
if (!existing) {
|
|
307
325
|
return Err(new CommerceNotFoundError("Fulfillment record not found."));
|
|
308
326
|
}
|
|
@@ -319,11 +337,15 @@ export class FulfillmentService {
|
|
|
319
337
|
updateData.shippedAt = new Date();
|
|
320
338
|
if (input.status === "delivered")
|
|
321
339
|
updateData.deliveredAt = new Date();
|
|
322
|
-
await this.deps.repository.update(input.fulfillmentId, updateData, ctx);
|
|
340
|
+
const updated = await this.deps.repository.update(orgId, input.fulfillmentId, updateData, ctx);
|
|
341
|
+
if (!updated) {
|
|
342
|
+
return Err(new CommerceNotFoundError("Fulfillment record not found."));
|
|
343
|
+
}
|
|
323
344
|
return Ok(undefined);
|
|
324
345
|
}
|
|
325
346
|
async getDownloadUrl(orderId, lineItemId, userId, actor, ctx) {
|
|
326
|
-
const
|
|
347
|
+
const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
|
|
348
|
+
const dbRecords = await this.deps.repository.findByOrderId(orgId, orderId, ctx);
|
|
327
349
|
let matchedRecord;
|
|
328
350
|
for (const dbRecord of dbRecords) {
|
|
329
351
|
if (dbRecord.type !== "digital-download" && dbRecord.type !== "digital")
|
|
@@ -337,7 +359,6 @@ export class FulfillmentService {
|
|
|
337
359
|
if (!matchedRecord) {
|
|
338
360
|
return Err(new CommerceNotFoundError("Digital download not found."));
|
|
339
361
|
}
|
|
340
|
-
const orgId = resolveOrgIdForCommerce(actor ?? ctx?.actor ?? null, this.deps.config);
|
|
341
362
|
const order = await this.deps.ordersRepository.findById(orgId, orderId, ctx);
|
|
342
363
|
if (!order || order.customerId !== userId) {
|
|
343
364
|
return Err(new CommerceNotFoundError("Order not found."));
|
|
@@ -348,7 +369,7 @@ export class FulfillmentService {
|
|
|
348
369
|
if (new Date(matchedRecord.downloadExpiresAt).getTime() < Date.now()) {
|
|
349
370
|
return Err(new CommerceNotFoundError("Download link expired."));
|
|
350
371
|
}
|
|
351
|
-
const updated = await this.deps.repository.incrementDownloadCount(matchedRecord.id, ctx);
|
|
372
|
+
const updated = await this.deps.repository.incrementDownloadCount(orgId, matchedRecord.id, ctx);
|
|
352
373
|
const downloadCount = updated?.downloadCount ?? matchedRecord.downloadCount + 1;
|
|
353
374
|
const remaining = Math.max(0, (matchedRecord.maxDownloads ?? 5) - downloadCount);
|
|
354
375
|
return Ok({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@porulle/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.42.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -62,8 +62,8 @@
|
|
|
62
62
|
"eslint": "^9.39.1",
|
|
63
63
|
"typescript": "5.9.2",
|
|
64
64
|
"vitest": "^3.2.4",
|
|
65
|
-
"@porulle/
|
|
66
|
-
"@porulle/
|
|
65
|
+
"@porulle/eslint-config": "0.1.0",
|
|
66
|
+
"@porulle/typescript-config": "0.1.0"
|
|
67
67
|
},
|
|
68
68
|
"publishConfig": {
|
|
69
69
|
"access": "public"
|
|
@@ -174,6 +174,7 @@ export function createCustomerPortalRoutes(kernel: Kernel) {
|
|
|
174
174
|
|
|
175
175
|
const fulfillments = await kernel.services.fulfillment.getByOrderId(
|
|
176
176
|
orderResult.value.id,
|
|
177
|
+
customerActor,
|
|
177
178
|
);
|
|
178
179
|
if (!fulfillments.ok) return c.json({ error: fulfillments.error }, 500);
|
|
179
180
|
|
|
@@ -325,7 +325,7 @@ export function orderRoutes(kernel: Kernel) {
|
|
|
325
325
|
|
|
326
326
|
if (!orderResult.ok) return c.json(mapErrorToResponse(orderResult.error), mapErrorToStatus(orderResult.error));
|
|
327
327
|
|
|
328
|
-
const result = await kernel.services.fulfillment.getByOrderId(orderResult.value.id);
|
|
328
|
+
const result = await kernel.services.fulfillment.getByOrderId(orderResult.value.id, actor);
|
|
329
329
|
if (!result.ok) return c.json(mapErrorToResponse(result.error), mapErrorToStatus(result.error));
|
|
330
330
|
return c.json({ data: result.value });
|
|
331
331
|
});
|