@porulle/core 0.52.0 → 0.53.1
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/modules/customers/repository/index.d.ts +6 -0
- package/dist/modules/customers/repository/index.d.ts.map +1 -1
- package/dist/modules/customers/repository/index.js +18 -0
- package/dist/modules/customers/service.d.ts.map +1 -1
- package/dist/modules/customers/service.js +11 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/modules/customers/repository/index.ts +22 -0
- package/src/modules/customers/service.ts +9 -1
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { eq, and, desc } from "drizzle-orm";
|
|
2
2
|
import type { TxContext } from "../../../kernel/database/tx-context.js";
|
|
3
|
+
import { user } from "../../../auth/auth-schema.js";
|
|
3
4
|
import type {
|
|
4
5
|
DrizzleDatabase,
|
|
5
6
|
DbOrTx,
|
|
@@ -51,6 +52,27 @@ export class CustomersRepository {
|
|
|
51
52
|
return rows[0];
|
|
52
53
|
}
|
|
53
54
|
|
|
55
|
+
/**
|
|
56
|
+
* The auth user's email, when no OTHER customer profile in this organization already holds it
|
|
57
|
+
* (`customers` is unique on organization + email). Undefined otherwise — the caller then leaves the
|
|
58
|
+
* profile's email as it is rather than fail the whole profile read on the unique index.
|
|
59
|
+
*/
|
|
60
|
+
async claimableUserEmail(
|
|
61
|
+
orgId: string,
|
|
62
|
+
userId: string,
|
|
63
|
+
ctx?: TxContext,
|
|
64
|
+
): Promise<string | undefined> {
|
|
65
|
+
const db = this.getDb(ctx);
|
|
66
|
+
const [account] = await db.select({ email: user.email }).from(user).where(eq(user.id, userId));
|
|
67
|
+
if (!account?.email) return undefined;
|
|
68
|
+
const [holder] = await db
|
|
69
|
+
.select({ userId: customers.userId })
|
|
70
|
+
.from(customers)
|
|
71
|
+
.where(and(eq(customers.organizationId, orgId), eq(customers.email, account.email)))
|
|
72
|
+
.limit(1);
|
|
73
|
+
return holder === undefined || holder.userId === userId ? account.email : undefined;
|
|
74
|
+
}
|
|
75
|
+
|
|
54
76
|
async findByUserId(
|
|
55
77
|
orgId: string,
|
|
56
78
|
userId: string,
|
|
@@ -177,16 +177,24 @@ export class CustomerService {
|
|
|
177
177
|
actor: Actor | null,
|
|
178
178
|
ctx?: TxContext,
|
|
179
179
|
): Promise<Customer> {
|
|
180
|
+
// The profile carries the shopper's email: it is the key channel redaction uses, so a profile
|
|
181
|
+
// without one cannot be erased once its orders have been exported. Filled on creation, and on
|
|
182
|
+
// the next access of a profile created before this (never overwriting an email it has).
|
|
180
183
|
const existing = await this.repo.findByUserId(orgId, userId, ctx);
|
|
181
184
|
if (existing) {
|
|
182
|
-
return existing;
|
|
185
|
+
if (existing.email) return existing;
|
|
186
|
+
const email = await this.repo.claimableUserEmail(orgId, userId, ctx);
|
|
187
|
+
if (!email) return existing;
|
|
188
|
+
return (await this.repo.update(existing.id, { email }, ctx)) ?? existing;
|
|
183
189
|
}
|
|
184
190
|
|
|
191
|
+
const email = await this.repo.claimableUserEmail(orgId, userId, ctx);
|
|
185
192
|
const customer = await this.repo.create(
|
|
186
193
|
{
|
|
187
194
|
organizationId: orgId,
|
|
188
195
|
userId,
|
|
189
196
|
metadata: {},
|
|
197
|
+
...(email !== undefined ? { email } : {}),
|
|
190
198
|
},
|
|
191
199
|
ctx,
|
|
192
200
|
);
|