@unchainedshop/core-quotations 5.0.0-alpha.1 → 5.0.0-alpha.10
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/README.md
CHANGED
|
@@ -13,89 +13,21 @@ npm install @unchainedshop/core-quotations
|
|
|
13
13
|
|
|
14
14
|
## Usage
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
import { configureQuotationsModule, QuotationStatus } from '@unchainedshop/core-quotations';
|
|
18
|
-
|
|
19
|
-
const quotationsModule = await configureQuotationsModule({ db });
|
|
20
|
-
|
|
21
|
-
// Create a quotation request
|
|
22
|
-
const quotationId = await quotationsModule.create({
|
|
23
|
-
userId: 'user-123',
|
|
24
|
-
productId: 'custom-product-456',
|
|
25
|
-
configuration: [{ key: 'quantity', value: '1000' }],
|
|
26
|
-
});
|
|
16
|
+
The platform initializes this module as `platform.unchainedAPI.modules.quotations`.
|
|
27
17
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
price: { amount: 5000, currency: 'CHF' },
|
|
31
|
-
expiresAt: new Date('2024-12-31'),
|
|
32
|
-
});
|
|
18
|
+
```typescript
|
|
19
|
+
import { QuotationStatus } from '@unchainedshop/core-quotations';
|
|
33
20
|
|
|
34
|
-
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
21
|
+
const { quotations } = platform.unchainedAPI.modules;
|
|
22
|
+
const userQuotations = await quotations.findQuotations({ userId: 'user-123' });
|
|
23
|
+
const proposals = userQuotations.filter(
|
|
24
|
+
(quotation) => quotations.normalizedStatus(quotation) === QuotationStatus.PROPOSED,
|
|
25
|
+
);
|
|
38
26
|
```
|
|
39
27
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
### Module Configuration
|
|
43
|
-
|
|
44
|
-
| Export | Description |
|
|
45
|
-
|--------|-------------|
|
|
46
|
-
| `configureQuotationsModule` | Configure and return the quotations module |
|
|
47
|
-
|
|
48
|
-
### Queries
|
|
49
|
-
|
|
50
|
-
| Method | Description |
|
|
51
|
-
|--------|-------------|
|
|
52
|
-
| `findQuotation` | Find quotation by ID |
|
|
53
|
-
| `findQuotations` | Find quotations with filtering and pagination |
|
|
54
|
-
| `count` | Count quotations matching query |
|
|
55
|
-
| `quotationExists` | Check if quotation exists |
|
|
56
|
-
|
|
57
|
-
### Mutations
|
|
58
|
-
|
|
59
|
-
| Method | Description |
|
|
60
|
-
|--------|-------------|
|
|
61
|
-
| `create` | Create a quotation request |
|
|
62
|
-
| `update` | Update quotation data |
|
|
63
|
-
| `delete` | Delete a quotation |
|
|
64
|
-
| `propose` | Propose a quote |
|
|
65
|
-
| `verify` | Verify a quotation |
|
|
66
|
-
| `reject` | Reject a quotation |
|
|
67
|
-
| `fulfill` | Mark quotation as fulfilled |
|
|
68
|
-
|
|
69
|
-
### Constants
|
|
70
|
-
|
|
71
|
-
| Export | Description |
|
|
72
|
-
|--------|-------------|
|
|
73
|
-
| `QuotationStatus` | Status values (REQUESTED, PROCESSING, PROPOSED, FULFILLED, REJECTED) |
|
|
74
|
-
|
|
75
|
-
### Settings
|
|
76
|
-
|
|
77
|
-
| Export | Description |
|
|
78
|
-
|--------|-------------|
|
|
79
|
-
| `quotationsSettings` | Access quotation module settings |
|
|
80
|
-
|
|
81
|
-
### Types
|
|
82
|
-
|
|
83
|
-
| Export | Description |
|
|
84
|
-
|--------|-------------|
|
|
85
|
-
| `Quotation` | Quotation document type |
|
|
86
|
-
| `QuotationConfiguration` | Configuration item type |
|
|
87
|
-
| `QuotationsModule` | Module interface type |
|
|
88
|
-
|
|
89
|
-
## Events
|
|
28
|
+
Use the GraphQL quotation mutations or `unchainedAPI.services.quotations` to request, propose, and verify quotations through the configured adapter. A proposal's `price` is an integer amount in the quotation currency's minor units, and its expiration field is `expires`.
|
|
90
29
|
|
|
91
|
-
|
|
92
|
-
|-------|-------------|
|
|
93
|
-
| `QUOTATION_CREATE` | Quotation requested |
|
|
94
|
-
| `QUOTATION_UPDATE` | Quotation updated |
|
|
95
|
-
| `QUOTATION_REMOVE` | Quotation deleted |
|
|
96
|
-
| `QUOTATION_PROPOSE` | Quote proposed |
|
|
97
|
-
| `QUOTATION_REJECT` | Quotation rejected |
|
|
98
|
-
| `QUOTATION_FULLFILL` | Quotation fulfilled |
|
|
30
|
+
See the [module guide](https://docs.unchained.shop/platform-configuration/modules/quotations), [quotation extension guide](https://docs.unchained.shop/extend/quotation), [public exports](src/quotations-index.ts), and [module implementation](src/module/configureQuotationsModule.ts).
|
|
99
31
|
|
|
100
32
|
## License
|
|
101
33
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { mongodb, buildDbIndexes
|
|
1
|
+
import { mongodb, buildDbIndexes } from '@unchainedshop/mongodb';
|
|
2
2
|
export const QuotationStatus = {
|
|
3
3
|
REQUESTED: 'REQUESTED',
|
|
4
4
|
PROCESSING: 'PROCESSING',
|
|
@@ -8,30 +8,28 @@ export const QuotationStatus = {
|
|
|
8
8
|
};
|
|
9
9
|
export const QuotationsCollection = async (db) => {
|
|
10
10
|
const Quotations = db.collection('quotations');
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
{
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
status: 1,
|
|
26
|
-
},
|
|
27
|
-
name: 'quotation_fulltext_search',
|
|
11
|
+
await buildDbIndexes(Quotations, [
|
|
12
|
+
{
|
|
13
|
+
index: {
|
|
14
|
+
_id: 'text',
|
|
15
|
+
userId: 'text',
|
|
16
|
+
quotationNumber: 'text',
|
|
17
|
+
status: 'text',
|
|
18
|
+
},
|
|
19
|
+
options: {
|
|
20
|
+
weights: {
|
|
21
|
+
_id: 8,
|
|
22
|
+
userId: 3,
|
|
23
|
+
quotationNumber: 6,
|
|
24
|
+
status: 1,
|
|
28
25
|
},
|
|
26
|
+
name: 'quotation_fulltext_search',
|
|
29
27
|
},
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
},
|
|
29
|
+
]);
|
|
32
30
|
await buildDbIndexes(Quotations, [
|
|
33
|
-
{ index: { userId: 1 } },
|
|
34
|
-
{ index: { productId: 1 } },
|
|
31
|
+
{ index: { userId: 1, status: 1 } },
|
|
32
|
+
{ index: { productId: 1, status: 1 } },
|
|
35
33
|
{ index: { status: 1 } },
|
|
36
34
|
]);
|
|
37
35
|
return Quotations;
|
|
@@ -31,8 +31,8 @@ export declare const configureQuotationsModule: ({ db, migrationRepository, opti
|
|
|
31
31
|
sort?: SortOption[];
|
|
32
32
|
}, options?: mongodb.FindOptions) => Promise<Quotation[]>;
|
|
33
33
|
normalizedStatus: (quotation: Quotation) => QuotationStatus;
|
|
34
|
-
isExpired(quotation: Quotation, { referenceDate }
|
|
35
|
-
referenceDate
|
|
34
|
+
isExpired(quotation: Quotation, { referenceDate }?: {
|
|
35
|
+
referenceDate?: Date;
|
|
36
36
|
}): boolean;
|
|
37
37
|
isProposalValid(quotation: Quotation): boolean;
|
|
38
38
|
create: ({ countryCode, currencyCode, ...quotationData }: QuotationData & {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SortDirection } from '@unchainedshop/utils';
|
|
2
2
|
import { QuotationStatus } from "../db/QuotationsCollection.js";
|
|
3
3
|
import { emit, registerEvents } from '@unchainedshop/events';
|
|
4
|
-
import { generateDbFilterById, buildSortOptions, mongodb, generateDbObjectId,
|
|
4
|
+
import { generateDbFilterById, buildSortOptions, mongodb, generateDbObjectId, } from '@unchainedshop/mongodb';
|
|
5
5
|
import { QuotationsCollection } from "../db/QuotationsCollection.js";
|
|
6
6
|
import { quotationsSettings } from "../quotations-settings.js";
|
|
7
7
|
import renameCurrencyCode from "../migrations/20250502111800-currency-code.js";
|
|
@@ -15,7 +15,6 @@ export const buildFindSelector = ({ userId, queryString, quotationIds } = {}) =>
|
|
|
15
15
|
selector._id = { $in: quotationIds };
|
|
16
16
|
}
|
|
17
17
|
if (queryString) {
|
|
18
|
-
assertDocumentDBCompatMode();
|
|
19
18
|
selector.$text = { $search: queryString };
|
|
20
19
|
}
|
|
21
20
|
return selector;
|
|
@@ -84,7 +83,7 @@ export const configureQuotationsModule = async ({ db, migrationRepository, optio
|
|
|
84
83
|
updated: new Date(),
|
|
85
84
|
...fieldKeys.reduce((set, key) => ({ ...set, [key]: values[key] }), {}),
|
|
86
85
|
},
|
|
87
|
-
});
|
|
86
|
+
}, { returnDocument: 'after' });
|
|
88
87
|
if (!quotation)
|
|
89
88
|
return null;
|
|
90
89
|
await emit('QUOTATION_UPDATE', { quotation, fields: fieldKeys });
|
|
@@ -119,7 +118,7 @@ export const configureQuotationsModule = async ({ db, migrationRepository, optio
|
|
|
119
118
|
? QuotationStatus.REQUESTED
|
|
120
119
|
: quotation.status;
|
|
121
120
|
},
|
|
122
|
-
isExpired(quotation, { referenceDate }) {
|
|
121
|
+
isExpired(quotation, { referenceDate } = {}) {
|
|
123
122
|
const relevantDate = referenceDate ? new Date(referenceDate) : new Date();
|
|
124
123
|
if (!quotation.expires)
|
|
125
124
|
return false;
|
|
@@ -146,10 +145,13 @@ export const configureQuotationsModule = async ({ db, migrationRepository, optio
|
|
|
146
145
|
return quotation;
|
|
147
146
|
},
|
|
148
147
|
deleteRequestedUserQuotations: async (userId) => {
|
|
149
|
-
const
|
|
148
|
+
const selector = {
|
|
150
149
|
userId,
|
|
151
150
|
status: { $in: [QuotationStatus.REQUESTED, null] },
|
|
152
|
-
}
|
|
151
|
+
};
|
|
152
|
+
const quotations = await Quotations.find(selector, { projection: { _id: 1 } }).toArray();
|
|
153
|
+
const { deletedCount } = await Quotations.deleteMany(selector);
|
|
154
|
+
await Promise.all(quotations.map((quotation) => emit('QUOTATION_REMOVE', { quotationId: quotation._id })));
|
|
153
155
|
return deletedCount;
|
|
154
156
|
},
|
|
155
157
|
updateContext: updateQuotationFields(['context']),
|
package/package.json
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unchainedshop/core-quotations",
|
|
3
3
|
"description": "Quotation and RFQ management module for the Unchained Engine",
|
|
4
|
-
"version": "5.0.0-alpha.
|
|
4
|
+
"version": "5.0.0-alpha.10",
|
|
5
|
+
"files": [
|
|
6
|
+
"lib"
|
|
7
|
+
],
|
|
5
8
|
"main": "lib/quotations-index.js",
|
|
6
9
|
"types": "lib/quotations-index.d.ts",
|
|
7
10
|
"type": "module",
|
|
@@ -35,12 +38,12 @@
|
|
|
35
38
|
},
|
|
36
39
|
"homepage": "https://github.com/unchainedshop/unchained#readme",
|
|
37
40
|
"dependencies": {
|
|
38
|
-
"@unchainedshop/events": "^5.0.0-alpha.
|
|
39
|
-
"@unchainedshop/
|
|
40
|
-
"@unchainedshop/utils": "^5.0.0-alpha.
|
|
41
|
+
"@unchainedshop/events": "^5.0.0-alpha.10",
|
|
42
|
+
"@unchainedshop/mongodb": "^5.0.0-alpha.10",
|
|
43
|
+
"@unchainedshop/utils": "^5.0.0-alpha.10"
|
|
41
44
|
},
|
|
42
45
|
"devDependencies": {
|
|
43
|
-
"@types/node": "^
|
|
44
|
-
"typescript": "^
|
|
46
|
+
"@types/node": "^26.2.0",
|
|
47
|
+
"typescript": "^6.0.3"
|
|
45
48
|
}
|
|
46
49
|
}
|