@voyantjs/suppliers 0.2.0 → 0.3.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.
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,sBAAsB,EACtB,2BAA2B,EAC3B,2BAA2B,EAC3B,aAAa,IAAI,qBAAqB,EACtC,kBAAkB,IAAI,0BAA0B,EAChD,kBAAkB,IAAI,0BAA0B,EACjD,MAAM,+BAA+B,CAAA;AAEtC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AACjE,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAC5B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAS3C,OAAO,KAAK,EACV,uBAAuB,EACvB,wBAAwB,EACxB,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,wBAAwB,EACxB,oBAAoB,EACpB,uBAAuB,EACvB,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,oBAAoB,EACrB,MAAM,iBAAiB,CAAA;AAExB,KAAK,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA;AAChE,KAAK,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA;AAChE,KAAK,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AAC/D,KAAK,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AAC/D,KAAK,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC7D,KAAK,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC7D,KAAK,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAA;AACvD,KAAK,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAA;AACvD,KAAK,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA;AACvE,KAAK,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAA;AACvE,KAAK,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AAC/D,KAAK,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAA;AAoB/D,KAAK,sBAAsB,GAAG;IAC5B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B,CAAA;AAED,KAAK,gBAAgB,GAAG,QAAQ,GAAG,sBAAsB,CAAA;AAqSzD,eAAO,MAAM,gBAAgB;sBACH,kBAAkB,SAAS,iBAAiB;;;;;;;;;;;;;;;;;;wBA8E1C,kBAAkB,MAAM,MAAM;uBAU/B,kBAAkB,QAAQ,mBAAmB;;;;;;;;;;;;;;;;;;;;;;uBA4C7C,kBAAkB,MAAM,MAAM,QAAQ,mBAAmB;;;;;;;;;;;;;;;;;;;;;;uBAuDzD,kBAAkB,MAAM,MAAM;;;0BASjC,kBAAkB,cAAc,MAAM;;;;;;;;;;;;;;0BAItC,kBAAkB,cAAc,MAAM;;;;;;;;;;;;;;;2BAKtD,kBAAkB,cACV,MAAM,QACZ,2BAA2B;;;;;;;;;;;;;;;2BAmBZ,kBAAkB,aAAa,MAAM,QAAQ,0BAA0B;;;;;;;;;;;;;;;2BAIvE,kBAAkB,aAAa,MAAM;;;2BAKtD,kBAAkB,cACV,MAAM,QACZ,2BAA2B;;;;;;;;;;;;;;2BAoB7B,kBAAkB,kBACN,MAAM,QAChB,0BAA0B;;;;;;;;;;;;;;2BAKX,kBAAkB,kBAAkB,MAAM;;;sBAI/C,kBAAkB,cAAc,MAAM;;;;;;;;;;;;;;;;;;;;;sBAIhC,kBAAkB,cAAc,MAAM,QAAQ,sBAAsB;;;;;;;;;;;;;;;;;;;;;sBAkB1E,kBAAkB,aAAa,MAAM,QAAQ,qBAAqB;;;;;;;;;;;;;;;;;;;;;sBAIlE,kBAAkB,aAAa,MAAM;;;qBAItC,kBAAkB,cAAc,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBAQ/B,kBAAkB,cAAc,MAAM,QAAQ,kBAAkB;;;;;;;;;;;;;;sBAmBhE,kBAAkB,aAAa,MAAM,QAAQ,kBAAkB;;;;;;;;;;;;;;sBAU/D,kBAAkB,aAAa,MAAM;;;kBAS/C,kBAAkB,aAAa,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mBAQ9B,kBAAkB,aAAa,MAAM,QAAQ,eAAe;;;;;;;;;;;;;;mBAmB5D,kBAAkB,UAAU,MAAM,QAAQ,eAAe;;;;;;;;;;;;;;mBAUzD,kBAAkB,UAAU,MAAM;;;kBASzC,kBAAkB,cAAc,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mBAS9C,kBAAkB,cACV,MAAM,UACV,MAAM,QACR,uBAAuB;;;;;;;yBAwBJ,kBAAkB,cAAc,MAAM,SAAS,iBAAiB;;;;;;;;2BAmBrF,kBAAkB,cACV,MAAM,WACT,uBAAuB,EAAE;;;;;;;;sBAyBlB,kBAAkB,cAAc,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uBAQ/B,kBAAkB,cAAc,MAAM,QAAQ,mBAAmB;;;;;;;;;;;;uBAmBjE,kBAAkB,cAAc,MAAM,QAAQ,mBAAmB;;;;;;;;;;;;uBAUjE,kBAAkB,cAAc,MAAM;;;CAQhE,CAAA"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,cAAc,EACd,eAAe,EACf,aAAa,EACb,cAAc,EACf,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,UAAU,EACV,UAAU,EACV,aAAa,EACb,cAAc,EACd,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,SAAS,EACT,YAAY,EACZ,cAAc,EACd,UAAU,EACV,aAAa,EACd,MAAM,yBAAyB,CAAA;AAEhC,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkC5B,CAAA"}
package/dist/service.js CHANGED
@@ -1,602 +1,38 @@
1
- import { identityAddresses, identityContactPoints, identityNamedContacts, } from "@voyantjs/identity/schema";
2
- import { identityService } from "@voyantjs/identity/service";
3
- import { and, asc, desc, eq, gte, inArray, lte, sql } from "drizzle-orm";
4
- import { supplierAvailability, supplierContracts, supplierNotes, supplierRates, supplierServices, suppliers, } from "./schema.js";
5
- const supplierEntityType = "supplier";
6
- const supplierBaseIdentitySource = "suppliers.base";
7
- const supplierPrimaryNamedContactSource = "suppliers.primary_contact";
8
- function normalizeContactValue(kind, value) {
9
- if (kind === "email") {
10
- return value.trim().toLowerCase();
11
- }
12
- if (kind === "website") {
13
- return value.trim().toLowerCase();
14
- }
15
- return value.trim();
16
- }
17
- function isManagedBySource(metadata, source) {
18
- return metadata?.managedBy === source;
19
- }
20
- function toNullableTrimmed(value) {
21
- const trimmed = value?.trim();
22
- return trimmed ? trimmed : null;
23
- }
24
- function formatAddress(address) {
25
- if (address.fullText) {
26
- return address.fullText;
27
- }
28
- const parts = [
29
- address.line1,
30
- address.line2,
31
- address.city,
32
- address.region,
33
- address.postalCode,
34
- address.country,
35
- ].filter(Boolean);
36
- return parts.length > 0 ? parts.join(", ") : null;
37
- }
38
- async function syncSupplierIdentity(db, supplierId, data) {
39
- const existingContactPoints = await identityService.listContactPointsForEntity(db, supplierEntityType, supplierId);
40
- const existingAddresses = await identityService.listAddressesForEntity(db, supplierEntityType, supplierId);
41
- const existingNamedContacts = await identityService.listNamedContactsForEntity(db, supplierEntityType, supplierId);
42
- const managedContactPoints = existingContactPoints.filter((point) => isManagedBySource(point.metadata, supplierBaseIdentitySource));
43
- const managedAddress = existingAddresses.find((address) => isManagedBySource(address.metadata, supplierBaseIdentitySource));
44
- const managedPrimaryContact = existingNamedContacts.find((contact) => isManagedBySource(contact.metadata, supplierPrimaryNamedContactSource));
45
- for (const [kind, rawValue] of Object.entries({
46
- email: data.email,
47
- phone: data.phone,
48
- website: data.website,
49
- })) {
50
- const value = toNullableTrimmed(rawValue);
51
- const existing = managedContactPoints.find((point) => point.kind === kind) ??
52
- existingContactPoints.find((point) => point.kind === kind && point.isPrimary);
53
- if (!value) {
54
- if (existing) {
55
- await identityService.deleteContactPoint(db, existing.id);
56
- }
57
- continue;
58
- }
59
- const payload = {
60
- entityType: supplierEntityType,
61
- entityId: supplierId,
62
- kind,
63
- label: kind === "website" ? "website" : "primary",
64
- value,
65
- normalizedValue: normalizeContactValue(kind, value),
66
- isPrimary: true,
67
- metadata: {
68
- managedBy: supplierBaseIdentitySource,
69
- },
70
- };
71
- if (existing) {
72
- await identityService.updateContactPoint(db, existing.id, payload);
73
- }
74
- else {
75
- await identityService.createContactPoint(db, payload);
76
- }
77
- }
78
- const addressLine = toNullableTrimmed(data.address);
79
- const city = toNullableTrimmed(data.city);
80
- const country = toNullableTrimmed(data.country);
81
- const hasAddress = Boolean(addressLine || city || country);
82
- if (!hasAddress) {
83
- if (managedAddress) {
84
- await identityService.deleteAddress(db, managedAddress.id);
85
- }
86
- }
87
- else {
88
- const addressPayload = {
89
- entityType: supplierEntityType,
90
- entityId: supplierId,
91
- label: "primary",
92
- fullText: addressLine,
93
- line1: addressLine,
94
- city,
95
- country,
96
- isPrimary: true,
97
- metadata: {
98
- managedBy: supplierBaseIdentitySource,
99
- },
100
- };
101
- if (managedAddress) {
102
- await identityService.updateAddress(db, managedAddress.id, addressPayload);
103
- }
104
- else {
105
- await identityService.createAddress(db, addressPayload);
106
- }
107
- }
108
- const contactName = toNullableTrimmed(data.contactName);
109
- const contactEmail = toNullableTrimmed(data.contactEmail);
110
- const contactPhone = toNullableTrimmed(data.contactPhone);
111
- const hasPrimaryContact = Boolean(contactName || contactEmail || contactPhone);
112
- if (!hasPrimaryContact) {
113
- if (managedPrimaryContact) {
114
- await identityService.deleteNamedContact(db, managedPrimaryContact.id);
115
- }
116
- return;
117
- }
118
- const namedContactPayload = {
119
- entityType: supplierEntityType,
120
- entityId: supplierId,
121
- role: "primary",
122
- name: contactName ?? contactEmail ?? contactPhone ?? "Primary contact",
123
- email: contactEmail,
124
- phone: contactPhone,
125
- isPrimary: true,
126
- metadata: {
127
- managedBy: supplierPrimaryNamedContactSource,
128
- },
129
- };
130
- if (managedPrimaryContact) {
131
- await identityService.updateNamedContact(db, managedPrimaryContact.id, namedContactPayload);
132
- }
133
- else {
134
- await identityService.createNamedContact(db, namedContactPayload);
135
- }
136
- }
137
- async function hydrateSuppliers(db, rows) {
138
- if (rows.length === 0) {
139
- return rows.map((row) => ({
140
- ...row,
141
- email: null,
142
- phone: null,
143
- website: null,
144
- address: null,
145
- city: null,
146
- country: null,
147
- contactName: null,
148
- contactEmail: null,
149
- contactPhone: null,
150
- }));
151
- }
152
- const ids = rows.map((row) => row.id);
153
- const [contactPoints, addresses, namedContacts] = await Promise.all([
154
- db
155
- .select()
156
- .from(identityContactPoints)
157
- .where(and(eq(identityContactPoints.entityType, supplierEntityType), inArray(identityContactPoints.entityId, ids))),
158
- db
159
- .select()
160
- .from(identityAddresses)
161
- .where(and(eq(identityAddresses.entityType, supplierEntityType), inArray(identityAddresses.entityId, ids))),
162
- db
163
- .select()
164
- .from(identityNamedContacts)
165
- .where(and(eq(identityNamedContacts.entityType, supplierEntityType), inArray(identityNamedContacts.entityId, ids))),
166
- ]);
167
- const contactPointMap = new Map();
168
- const addressMap = new Map();
169
- const namedContactMap = new Map();
170
- for (const point of contactPoints) {
171
- const bucket = contactPointMap.get(point.entityId) ?? [];
172
- bucket.push(point);
173
- contactPointMap.set(point.entityId, bucket);
174
- }
175
- for (const address of addresses) {
176
- const bucket = addressMap.get(address.entityId) ?? [];
177
- bucket.push(address);
178
- addressMap.set(address.entityId, bucket);
179
- }
180
- for (const contact of namedContacts) {
181
- const bucket = namedContactMap.get(contact.entityId) ?? [];
182
- bucket.push(contact);
183
- namedContactMap.set(contact.entityId, bucket);
184
- }
185
- return rows.map((row) => {
186
- const entityContactPoints = contactPointMap.get(row.id) ?? [];
187
- const entityAddresses = addressMap.get(row.id) ?? [];
188
- const entityNamedContacts = namedContactMap.get(row.id) ?? [];
189
- const pickContactValue = (kind) => entityContactPoints.find((point) => point.kind === kind && point.isPrimary)?.value ??
190
- entityContactPoints.find((point) => point.kind === kind)?.value ??
191
- null;
192
- const primaryAddress = entityAddresses.find((address) => address.isPrimary) ?? entityAddresses[0] ?? null;
193
- const primaryContact = entityNamedContacts.find((contact) => contact.isPrimary) ?? entityNamedContacts[0] ?? null;
194
- return {
195
- ...row,
196
- email: pickContactValue("email"),
197
- phone: pickContactValue("phone"),
198
- website: pickContactValue("website"),
199
- address: primaryAddress ? formatAddress(primaryAddress) : null,
200
- city: primaryAddress?.city ?? null,
201
- country: primaryAddress?.country ?? null,
202
- contactName: primaryContact?.name ?? null,
203
- contactEmail: primaryContact?.email ?? null,
204
- contactPhone: primaryContact?.phone ?? null,
205
- };
206
- });
207
- }
1
+ import { createSupplier, deleteSupplier, getSupplierById, listSuppliers, updateSupplier, } from "./service-core.js";
2
+ import { createAddress, createContactPoint, createNamedContact, deleteAddress, deleteContactPoint, deleteNamedContact, listAddresses, listContactPoints, listNamedContacts, updateAddress, updateContactPoint, updateNamedContact, } from "./service-identity.js";
3
+ import { createAvailability, createContract, createNote, createRate, createService, deleteContract, deleteRate, deleteService, listAvailability, listContracts, listNotes, listRates, listServices, updateContract, updateRate, updateService, } from "./service-operations.js";
208
4
  export const suppliersService = {
209
- async listSuppliers(db, query) {
210
- const conditions = [];
211
- if (query.type) {
212
- conditions.push(eq(suppliers.type, query.type));
213
- }
214
- if (query.status) {
215
- conditions.push(eq(suppliers.status, query.status));
216
- }
217
- if (query.primaryFacilityId) {
218
- conditions.push(eq(suppliers.primaryFacilityId, query.primaryFacilityId));
219
- }
220
- if (query.search) {
221
- const term = `%${query.search}%`;
222
- conditions.push(sql `(
223
- ${suppliers.name} ilike ${term}
224
- or
225
- exists (
226
- select 1
227
- from ${identityContactPoints}
228
- where ${identityContactPoints.entityType} = ${supplierEntityType}
229
- and ${identityContactPoints.entityId} = ${suppliers.id}
230
- and (
231
- ${identityContactPoints.value} ilike ${term}
232
- or ${identityContactPoints.normalizedValue} ilike ${term}
233
- )
234
- )
235
- or exists (
236
- select 1
237
- from ${identityNamedContacts}
238
- where ${identityNamedContacts.entityType} = ${supplierEntityType}
239
- and ${identityNamedContacts.entityId} = ${suppliers.id}
240
- and (
241
- ${identityNamedContacts.name} ilike ${term}
242
- or ${identityNamedContacts.email} ilike ${term}
243
- or ${identityNamedContacts.phone} ilike ${term}
244
- )
245
- )
246
- or exists (
247
- select 1
248
- from ${identityAddresses}
249
- where ${identityAddresses.entityType} = ${supplierEntityType}
250
- and ${identityAddresses.entityId} = ${suppliers.id}
251
- and (
252
- ${identityAddresses.fullText} ilike ${term}
253
- or ${identityAddresses.city} ilike ${term}
254
- or ${identityAddresses.country} ilike ${term}
255
- )
256
- )
257
- )`);
258
- }
259
- const where = conditions.length > 0 ? and(...conditions) : undefined;
260
- const [rows, countResult] = await Promise.all([
261
- db
262
- .select()
263
- .from(suppliers)
264
- .where(where)
265
- .limit(query.limit)
266
- .offset(query.offset)
267
- .orderBy(suppliers.createdAt),
268
- db.select({ count: sql `count(*)::int` }).from(suppliers).where(where),
269
- ]);
270
- return {
271
- data: await hydrateSuppliers(db, rows),
272
- total: countResult[0]?.count ?? 0,
273
- limit: query.limit,
274
- offset: query.offset,
275
- };
276
- },
277
- async getSupplierById(db, id) {
278
- const [row] = await db.select().from(suppliers).where(eq(suppliers.id, id)).limit(1);
279
- if (!row) {
280
- return null;
281
- }
282
- const [hydrated] = await hydrateSuppliers(db, [row]);
283
- return hydrated ?? null;
284
- },
285
- async createSupplier(db, data) {
286
- const { email, phone, website, address, city, country, contactName, contactEmail, contactPhone, ...supplierValues } = data;
287
- const [row] = await db.insert(suppliers).values(supplierValues).returning();
288
- if (!row) {
289
- throw new Error("Failed to create supplier");
290
- }
291
- await syncSupplierIdentity(db, row.id, {
292
- email,
293
- phone,
294
- website,
295
- address,
296
- city,
297
- country,
298
- contactName,
299
- contactEmail,
300
- contactPhone,
301
- });
302
- return {
303
- ...row,
304
- email: email ?? null,
305
- phone: phone ?? null,
306
- website: website ?? null,
307
- address: address ?? null,
308
- city: city ?? null,
309
- country: country ?? null,
310
- contactName: contactName ?? null,
311
- contactEmail: contactEmail ?? null,
312
- contactPhone: contactPhone ?? null,
313
- };
314
- },
315
- async updateSupplier(db, id, data) {
316
- const existing = await this.getSupplierById(db, id);
317
- if (!existing) {
318
- return null;
319
- }
320
- const { email, phone, website, address, city, country, contactName, contactEmail, contactPhone, ...supplierValues } = data;
321
- const [row] = await db
322
- .update(suppliers)
323
- .set({ ...supplierValues, updatedAt: new Date() })
324
- .where(eq(suppliers.id, id))
325
- .returning();
326
- if (!row) {
327
- return null;
328
- }
329
- await syncSupplierIdentity(db, id, {
330
- email: email ?? existing.email,
331
- phone: phone ?? existing.phone,
332
- website: website ?? existing.website,
333
- address: address ?? existing.address,
334
- city: city ?? existing.city,
335
- country: country ?? existing.country,
336
- contactName: contactName ?? existing.contactName,
337
- contactEmail: contactEmail ?? existing.contactEmail,
338
- contactPhone: contactPhone ?? existing.contactPhone,
339
- });
340
- return {
341
- ...row,
342
- email: email ?? existing.email,
343
- phone: phone ?? existing.phone,
344
- website: website ?? existing.website,
345
- address: address ?? existing.address,
346
- city: city ?? existing.city,
347
- country: country ?? existing.country,
348
- contactName: contactName ?? existing.contactName,
349
- contactEmail: contactEmail ?? existing.contactEmail,
350
- contactPhone: contactPhone ?? existing.contactPhone,
351
- };
352
- },
353
- async deleteSupplier(db, id) {
354
- const [row] = await db
355
- .delete(suppliers)
356
- .where(eq(suppliers.id, id))
357
- .returning({ id: suppliers.id });
358
- return row ?? null;
359
- },
360
- listContactPoints(db, supplierId) {
361
- return identityService.listContactPointsForEntity(db, supplierEntityType, supplierId);
362
- },
363
- listNamedContacts(db, supplierId) {
364
- return identityService.listNamedContactsForEntity(db, supplierEntityType, supplierId);
365
- },
366
- async createNamedContact(db, supplierId, data) {
367
- const [supplier] = await db
368
- .select({ id: suppliers.id })
369
- .from(suppliers)
370
- .where(eq(suppliers.id, supplierId))
371
- .limit(1);
372
- if (!supplier) {
373
- return null;
374
- }
375
- return identityService.createNamedContact(db, {
376
- ...data,
377
- entityType: supplierEntityType,
378
- entityId: supplierId,
379
- });
380
- },
381
- updateNamedContact(db, contactId, data) {
382
- return identityService.updateNamedContact(db, contactId, data);
383
- },
384
- deleteNamedContact(db, contactId) {
385
- return identityService.deleteNamedContact(db, contactId);
386
- },
387
- async createContactPoint(db, supplierId, data) {
388
- const [supplier] = await db
389
- .select({ id: suppliers.id })
390
- .from(suppliers)
391
- .where(eq(suppliers.id, supplierId))
392
- .limit(1);
393
- if (!supplier) {
394
- return null;
395
- }
396
- return identityService.createContactPoint(db, {
397
- ...data,
398
- entityType: supplierEntityType,
399
- entityId: supplierId,
400
- });
401
- },
402
- updateContactPoint(db, contactPointId, data) {
403
- return identityService.updateContactPoint(db, contactPointId, data);
404
- },
405
- deleteContactPoint(db, contactPointId) {
406
- return identityService.deleteContactPoint(db, contactPointId);
407
- },
408
- listAddresses(db, supplierId) {
409
- return identityService.listAddressesForEntity(db, supplierEntityType, supplierId);
410
- },
411
- async createAddress(db, supplierId, data) {
412
- const [supplier] = await db
413
- .select({ id: suppliers.id })
414
- .from(suppliers)
415
- .where(eq(suppliers.id, supplierId))
416
- .limit(1);
417
- if (!supplier) {
418
- return null;
419
- }
420
- return identityService.createAddress(db, {
421
- ...data,
422
- entityType: supplierEntityType,
423
- entityId: supplierId,
424
- });
425
- },
426
- updateAddress(db, addressId, data) {
427
- return identityService.updateAddress(db, addressId, data);
428
- },
429
- deleteAddress(db, addressId) {
430
- return identityService.deleteAddress(db, addressId);
431
- },
432
- listServices(db, supplierId) {
433
- return db
434
- .select()
435
- .from(supplierServices)
436
- .where(eq(supplierServices.supplierId, supplierId))
437
- .orderBy(supplierServices.createdAt);
438
- },
439
- async createService(db, supplierId, data) {
440
- const [supplier] = await db
441
- .select({ id: suppliers.id })
442
- .from(suppliers)
443
- .where(eq(suppliers.id, supplierId))
444
- .limit(1);
445
- if (!supplier) {
446
- return null;
447
- }
448
- const [row] = await db
449
- .insert(supplierServices)
450
- .values({ ...data, supplierId })
451
- .returning();
452
- return row ?? null;
453
- },
454
- async updateService(db, serviceId, data) {
455
- const [row] = await db
456
- .update(supplierServices)
457
- .set({ ...data, updatedAt: new Date() })
458
- .where(eq(supplierServices.id, serviceId))
459
- .returning();
460
- return row ?? null;
461
- },
462
- async deleteService(db, serviceId) {
463
- const [row] = await db
464
- .delete(supplierServices)
465
- .where(eq(supplierServices.id, serviceId))
466
- .returning({ id: supplierServices.id });
467
- return row ?? null;
468
- },
469
- listRates(db, serviceId) {
470
- return db
471
- .select()
472
- .from(supplierRates)
473
- .where(eq(supplierRates.serviceId, serviceId))
474
- .orderBy(supplierRates.createdAt);
475
- },
476
- async createRate(db, serviceId, data) {
477
- const [service] = await db
478
- .select({ id: supplierServices.id })
479
- .from(supplierServices)
480
- .where(eq(supplierServices.id, serviceId))
481
- .limit(1);
482
- if (!service) {
483
- return null;
484
- }
485
- const [row] = await db
486
- .insert(supplierRates)
487
- .values({ ...data, serviceId })
488
- .returning();
489
- return row;
490
- },
491
- async updateRate(db, rateId, data) {
492
- const [row] = await db
493
- .update(supplierRates)
494
- .set(data)
495
- .where(eq(supplierRates.id, rateId))
496
- .returning();
497
- return row ?? null;
498
- },
499
- async deleteRate(db, rateId) {
500
- const [row] = await db
501
- .delete(supplierRates)
502
- .where(eq(supplierRates.id, rateId))
503
- .returning({ id: supplierRates.id });
504
- return row ?? null;
505
- },
506
- listNotes(db, supplierId) {
507
- return db
508
- .select()
509
- .from(supplierNotes)
510
- .where(eq(supplierNotes.supplierId, supplierId))
511
- .orderBy(supplierNotes.createdAt);
512
- },
513
- async createNote(db, supplierId, userId, data) {
514
- const [supplier] = await db
515
- .select({ id: suppliers.id })
516
- .from(suppliers)
517
- .where(eq(suppliers.id, supplierId))
518
- .limit(1);
519
- if (!supplier) {
520
- return null;
521
- }
522
- const [row] = await db
523
- .insert(supplierNotes)
524
- .values({
525
- supplierId,
526
- authorId: userId,
527
- content: data.content,
528
- })
529
- .returning();
530
- return row;
531
- },
532
- async listAvailability(db, supplierId, query) {
533
- const conditions = [eq(supplierAvailability.supplierId, supplierId)];
534
- if (query.from) {
535
- conditions.push(gte(supplierAvailability.date, query.from));
536
- }
537
- if (query.to) {
538
- conditions.push(lte(supplierAvailability.date, query.to));
539
- }
540
- return db
541
- .select()
542
- .from(supplierAvailability)
543
- .where(and(...conditions))
544
- .orderBy(asc(supplierAvailability.date));
545
- },
546
- async createAvailability(db, supplierId, entries) {
547
- const [supplier] = await db
548
- .select({ id: suppliers.id })
549
- .from(suppliers)
550
- .where(eq(suppliers.id, supplierId))
551
- .limit(1);
552
- if (!supplier) {
553
- return null;
554
- }
555
- return db
556
- .insert(supplierAvailability)
557
- .values(entries.map((entry) => ({
558
- supplierId,
559
- date: entry.date,
560
- available: entry.available,
561
- notes: entry.notes ?? null,
562
- })))
563
- .returning();
564
- },
565
- listContracts(db, supplierId) {
566
- return db
567
- .select()
568
- .from(supplierContracts)
569
- .where(eq(supplierContracts.supplierId, supplierId))
570
- .orderBy(desc(supplierContracts.createdAt));
571
- },
572
- async createContract(db, supplierId, data) {
573
- const [supplier] = await db
574
- .select({ id: suppliers.id })
575
- .from(suppliers)
576
- .where(eq(suppliers.id, supplierId))
577
- .limit(1);
578
- if (!supplier) {
579
- return null;
580
- }
581
- const [row] = await db
582
- .insert(supplierContracts)
583
- .values({ ...data, supplierId })
584
- .returning();
585
- return row;
586
- },
587
- async updateContract(db, contractId, data) {
588
- const [row] = await db
589
- .update(supplierContracts)
590
- .set({ ...data, updatedAt: new Date() })
591
- .where(eq(supplierContracts.id, contractId))
592
- .returning();
593
- return row ?? null;
594
- },
595
- async deleteContract(db, contractId) {
596
- const [row] = await db
597
- .delete(supplierContracts)
598
- .where(eq(supplierContracts.id, contractId))
599
- .returning({ id: supplierContracts.id });
600
- return row ?? null;
601
- },
5
+ listSuppliers,
6
+ getSupplierById,
7
+ createSupplier,
8
+ updateSupplier,
9
+ deleteSupplier,
10
+ listContactPoints,
11
+ listNamedContacts,
12
+ createNamedContact,
13
+ updateNamedContact,
14
+ deleteNamedContact,
15
+ createContactPoint,
16
+ updateContactPoint,
17
+ deleteContactPoint,
18
+ listAddresses,
19
+ createAddress,
20
+ updateAddress,
21
+ deleteAddress,
22
+ listServices,
23
+ createService,
24
+ updateService,
25
+ deleteService,
26
+ listRates,
27
+ createRate,
28
+ updateRate,
29
+ deleteRate,
30
+ listNotes,
31
+ createNote,
32
+ listAvailability,
33
+ createAvailability,
34
+ listContracts,
35
+ createContract,
36
+ updateContract,
37
+ deleteContract,
602
38
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voyantjs/suppliers",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "license": "FSL-1.1-Apache-2.0",
5
5
  "type": "module",
6
6
  "exports": {
@@ -25,11 +25,11 @@
25
25
  "drizzle-orm": "^0.45.2",
26
26
  "hono": "^4.12.10",
27
27
  "zod": "^4.3.6",
28
- "@voyantjs/core": "0.2.0",
29
- "@voyantjs/db": "0.2.0",
30
- "@voyantjs/facilities": "0.2.0",
31
- "@voyantjs/hono": "0.2.0",
32
- "@voyantjs/identity": "0.2.0"
28
+ "@voyantjs/core": "0.3.0",
29
+ "@voyantjs/db": "0.3.0",
30
+ "@voyantjs/facilities": "0.3.0",
31
+ "@voyantjs/hono": "0.3.0",
32
+ "@voyantjs/identity": "0.3.0"
33
33
  },
34
34
  "devDependencies": {
35
35
  "typescript": "^6.0.2",