n8n-nodes-didar-crm 0.0.14 → 0.0.15
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/lib/loadOptions.d.ts +1 -0
- package/dist/lib/loadOptions.js +13 -0
- package/dist/nodes/DidarCrm.node.d.ts +1 -0
- package/dist/nodes/DidarCrm.node.js +29 -0
- package/dist/nodes/product/create.operation.d.ts +2 -0
- package/dist/nodes/product/create.operation.js +126 -0
- package/dist/nodes/product/create.properties.d.ts +2 -0
- package/dist/nodes/product/create.properties.js +125 -0
- package/dist/nodes/product/index.d.ts +4 -0
- package/dist/nodes/product/index.js +12 -0
- package/dist/nodes/product/update.operation.d.ts +2 -0
- package/dist/nodes/product/update.operation.js +110 -0
- package/dist/nodes/product/update.properties.d.ts +2 -0
- package/dist/nodes/product/update.properties.js +96 -0
- package/package.json +1 -1
|
@@ -3,3 +3,4 @@ export declare function getPipelines(this: ILoadOptionsFunctions): Promise<INode
|
|
|
3
3
|
export declare function getStagesForPipeline(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
|
|
4
4
|
export declare function getUsers(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
|
|
5
5
|
export declare function getActivityTypes(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
|
|
6
|
+
export declare function getProductCategories(this: ILoadOptionsFunctions): Promise<any>;
|
package/dist/lib/loadOptions.js
CHANGED
|
@@ -4,6 +4,8 @@ exports.getPipelines = getPipelines;
|
|
|
4
4
|
exports.getStagesForPipeline = getStagesForPipeline;
|
|
5
5
|
exports.getUsers = getUsers;
|
|
6
6
|
exports.getActivityTypes = getActivityTypes;
|
|
7
|
+
exports.getProductCategories = getProductCategories;
|
|
8
|
+
const http_1 = require("./http");
|
|
7
9
|
async function getPipelines() {
|
|
8
10
|
var _a;
|
|
9
11
|
const creds = await this.getCredentials('didarApi');
|
|
@@ -99,3 +101,14 @@ async function getActivityTypes() {
|
|
|
99
101
|
.filter((x) => (x === null || x === void 0 ? void 0 : x.Id) && (x === null || x === void 0 ? void 0 : x.Title))
|
|
100
102
|
.map((x) => ({ name: x.Title, value: x.Id }));
|
|
101
103
|
}
|
|
104
|
+
async function getProductCategories() {
|
|
105
|
+
const resp = await http_1.didarRequest(this, 0, { method: 'POST', path: '/api/product/categories' });
|
|
106
|
+
const list = Array.isArray(resp === null || resp === void 0 ? void 0 : resp.Response) ? resp.Response : resp; // در بعضی APIها Response دارند
|
|
107
|
+
return (list || []).map((cat) => {
|
|
108
|
+
var _a, _b;
|
|
109
|
+
return ({
|
|
110
|
+
name: (_b = (_a = cat.Title) !== null && _a !== void 0 ? _a : cat.Name) !== null && _b !== void 0 ? _b : cat.Id,
|
|
111
|
+
value: cat.Id,
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
}
|
|
@@ -6,6 +6,7 @@ export declare class DidarCrm implements INodeType {
|
|
|
6
6
|
getStagesForPipeline: (this: ILoadOptionsFunctions) => Promise<INodePropertyOptions[]>;
|
|
7
7
|
getUsers: (this: ILoadOptionsFunctions) => Promise<INodePropertyOptions[]>;
|
|
8
8
|
getActivityTypes: (this: ILoadOptionsFunctions) => Promise<INodePropertyOptions[]>;
|
|
9
|
+
getProductCategories: (this: ILoadOptionsFunctions) => Promise<INodePropertyOptions[]>;
|
|
9
10
|
};
|
|
10
11
|
};
|
|
11
12
|
description: INodeTypeDescription;
|
|
@@ -47,6 +47,8 @@ const NoteOps = __importStar(require("./note"));
|
|
|
47
47
|
const note_1 = require("./note");
|
|
48
48
|
const CaseOps = __importStar(require("./case"));
|
|
49
49
|
const case_1 = require("./case");
|
|
50
|
+
const ProductOps = __importStar(require("./product"));
|
|
51
|
+
const product_1 = require("./product");
|
|
50
52
|
class DidarCrm {
|
|
51
53
|
constructor() {
|
|
52
54
|
this.methods = {
|
|
@@ -55,6 +57,7 @@ class DidarCrm {
|
|
|
55
57
|
getStagesForPipeline: Load.getStagesForPipeline,
|
|
56
58
|
getUsers: Load.getUsers,
|
|
57
59
|
getActivityTypes: Load.getActivityTypes,
|
|
60
|
+
getProductCategories: Load.getProductCategories,
|
|
58
61
|
},
|
|
59
62
|
};
|
|
60
63
|
this.description = {
|
|
@@ -81,6 +84,7 @@ class DidarCrm {
|
|
|
81
84
|
{ name: 'Activity', value: 'activity' },
|
|
82
85
|
{ name: 'Note', value: 'note' },
|
|
83
86
|
{ name: 'Case', value: 'case' },
|
|
87
|
+
{ name: 'Product', value: 'product' },
|
|
84
88
|
],
|
|
85
89
|
default: 'deal',
|
|
86
90
|
description: 'Choose the entity to act on.',
|
|
@@ -160,6 +164,18 @@ class DidarCrm {
|
|
|
160
164
|
default: 'create',
|
|
161
165
|
description: 'Select the action to perform on the selected resource.',
|
|
162
166
|
},
|
|
167
|
+
{
|
|
168
|
+
displayName: 'Operation',
|
|
169
|
+
name: 'operation',
|
|
170
|
+
type: 'options',
|
|
171
|
+
displayOptions: { show: { resource: ['product'] } },
|
|
172
|
+
options: [
|
|
173
|
+
{ name: 'Create', value: 'create', action: 'Create a product' },
|
|
174
|
+
{ name: 'Update', value: 'update', action: 'Update a product by ID' },
|
|
175
|
+
],
|
|
176
|
+
default: 'create',
|
|
177
|
+
description: 'Select the action to perform on the selected resource.',
|
|
178
|
+
},
|
|
163
179
|
// Deal properties (imported)
|
|
164
180
|
...deal_1.dealCreateProperties,
|
|
165
181
|
...deal_1.dealUpdateProperties,
|
|
@@ -181,6 +197,9 @@ class DidarCrm {
|
|
|
181
197
|
// Case properties (imported)
|
|
182
198
|
...case_1.caseCreateProperties,
|
|
183
199
|
...case_1.caseUpdateProperties,
|
|
200
|
+
// Product properties (imported)
|
|
201
|
+
...product_1.productCreateProperties,
|
|
202
|
+
...product_1.productUpdateProperties,
|
|
184
203
|
],
|
|
185
204
|
};
|
|
186
205
|
}
|
|
@@ -262,6 +281,16 @@ class DidarCrm {
|
|
|
262
281
|
continue;
|
|
263
282
|
}
|
|
264
283
|
}
|
|
284
|
+
if (resource === 'product') {
|
|
285
|
+
if (operation === 'create') {
|
|
286
|
+
await ProductOps.productCreate.call(this, i, returnData);
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
if (operation === 'update') {
|
|
290
|
+
await ProductOps.productUpdate.call(this, i, returnData);
|
|
291
|
+
continue;
|
|
292
|
+
} // NEW
|
|
293
|
+
}
|
|
265
294
|
}
|
|
266
295
|
return [returnData];
|
|
267
296
|
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.productCreate = productCreate;
|
|
4
|
+
const http_1 = require("../../lib/http");
|
|
5
|
+
async function productCreate(i, returnData) {
|
|
6
|
+
var _a;
|
|
7
|
+
// 1) Read main params
|
|
8
|
+
const title = this.getNodeParameter('Title', i, '');
|
|
9
|
+
if (!(title === null || title === void 0 ? void 0 : title.trim()))
|
|
10
|
+
throw new Error('Title is required.');
|
|
11
|
+
const code = this.getNodeParameter('Code', i, '');
|
|
12
|
+
const unit = this.getNodeParameter('Unit', i, '');
|
|
13
|
+
const unitPrice = this.getNodeParameter('UnitPrice', i, 0);
|
|
14
|
+
const productCategoryId = this.getNodeParameter('ProductCategoryId', i, '');
|
|
15
|
+
const isActive = this.getNodeParameter('IsActive', i, true);
|
|
16
|
+
const description = this.getNodeParameter('Description', i, '');
|
|
17
|
+
// 2) Variants (optional)
|
|
18
|
+
// const variantsUi = (this.getNodeParameter('Variants', i, {}) as IDataObject) || {};
|
|
19
|
+
// let variants: IDataObject[] | undefined;
|
|
20
|
+
// if (variantsUi && typeof variantsUi === 'object' && Array.isArray((variantsUi as any).Variant)) {
|
|
21
|
+
// variants = ((variantsUi as any).Variant as IDataObject[])
|
|
22
|
+
// .filter(v => v && typeof v === 'object')
|
|
23
|
+
// .map(v => {
|
|
24
|
+
// const vTitle = (v.Title as string) ?? '';
|
|
25
|
+
// if (!vTitle?.trim()) throw new Error('Each Variant requires a Title.');
|
|
26
|
+
// const vCode = (v.VariantCode as string) ?? '';
|
|
27
|
+
// const vPrice = (typeof v.UnitPrice === 'number') ? (v.UnitPrice as number) : 0;
|
|
28
|
+
// return {
|
|
29
|
+
// Title: vTitle,
|
|
30
|
+
// TitleForInvoice: vTitle, // hidden rule
|
|
31
|
+
// IsDeleted: false, // hidden rule
|
|
32
|
+
// IsDefault: true, // hidden rule
|
|
33
|
+
// UnitPrice: vPrice,
|
|
34
|
+
// VariantCode: vCode,
|
|
35
|
+
// } as IDataObject;
|
|
36
|
+
// });
|
|
37
|
+
// if (!variants.length) variants = undefined;
|
|
38
|
+
// }
|
|
39
|
+
// 2) Variants (dynamic JSON)
|
|
40
|
+
let variants;
|
|
41
|
+
const variantsUi = this.getNodeParameter('Variants', i, '[]');
|
|
42
|
+
// نرمالسازی: هم رشتهٔ JSON قبول کن، هم آبجکت/آرایه (اگر از expression آمده باشد)
|
|
43
|
+
let parsed;
|
|
44
|
+
if (typeof variantsUi === 'string') {
|
|
45
|
+
const trimmed = variantsUi.trim();
|
|
46
|
+
if (trimmed) {
|
|
47
|
+
try {
|
|
48
|
+
parsed = JSON.parse(trimmed);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
throw new Error('Invalid JSON in "Variants". It must be a JSON array of objects.');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
parsed = [];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
parsed = variantsUi;
|
|
60
|
+
}
|
|
61
|
+
// باید آرایهٔ آبجکت باشد
|
|
62
|
+
if (parsed != null) {
|
|
63
|
+
if (!Array.isArray(parsed))
|
|
64
|
+
throw new Error('"Variants" must be an array.');
|
|
65
|
+
// Map و validate
|
|
66
|
+
variants = parsed.map((v, idx) => {
|
|
67
|
+
var _a, _b, _c;
|
|
68
|
+
if (typeof v !== 'object' || v == null) {
|
|
69
|
+
throw new Error(`"Variants[${idx}]" must be an object.`);
|
|
70
|
+
}
|
|
71
|
+
const vTitle = ((_a = v.Title) !== null && _a !== void 0 ? _a : '').toString();
|
|
72
|
+
if (!vTitle.trim())
|
|
73
|
+
throw new Error(`"Variants[${idx}].Title" is required.`);
|
|
74
|
+
const vCode = ((_b = v.VariantCode) !== null && _b !== void 0 ? _b : '').toString();
|
|
75
|
+
const vPrice = typeof v.UnitPrice === 'number' ? v.UnitPrice : Number((_c = v.UnitPrice) !== null && _c !== void 0 ? _c : 0) || 0;
|
|
76
|
+
return {
|
|
77
|
+
Title: vTitle,
|
|
78
|
+
TitleForInvoice: vTitle, // hidden rule
|
|
79
|
+
IsDeleted: false, // hidden rule
|
|
80
|
+
IsDefault: true, // hidden rule
|
|
81
|
+
UnitPrice: vPrice,
|
|
82
|
+
VariantCode: vCode,
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
if (!variants.length)
|
|
86
|
+
variants = undefined;
|
|
87
|
+
}
|
|
88
|
+
// 3) Fields (JSON)
|
|
89
|
+
let fields;
|
|
90
|
+
const fieldsUi = this.getNodeParameter('Fields', i, '');
|
|
91
|
+
if (typeof fieldsUi === 'string' && fieldsUi.trim()) {
|
|
92
|
+
try {
|
|
93
|
+
fields = JSON.parse(fieldsUi);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
throw new Error('Invalid JSON in "Custom Fields (JSON)".');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
else if (typeof fieldsUi === 'object' && fieldsUi) {
|
|
100
|
+
fields = fieldsUi;
|
|
101
|
+
}
|
|
102
|
+
// 4) Build payload
|
|
103
|
+
const product = {
|
|
104
|
+
Title: title,
|
|
105
|
+
Code: code,
|
|
106
|
+
Unit: unit,
|
|
107
|
+
UnitPrice: typeof unitPrice === 'number' ? unitPrice : Number(unitPrice) || 0,
|
|
108
|
+
Description: description,
|
|
109
|
+
IsActive: !!isActive,
|
|
110
|
+
};
|
|
111
|
+
if (productCategoryId)
|
|
112
|
+
product['ProductCategoryId'] = productCategoryId;
|
|
113
|
+
if (variants)
|
|
114
|
+
product['Variants'] = variants;
|
|
115
|
+
if (fields)
|
|
116
|
+
product['Fields'] = fields;
|
|
117
|
+
const body = { Product: product };
|
|
118
|
+
// 5) Request
|
|
119
|
+
const resp = await (0, http_1.didarRequest)(this, i, {
|
|
120
|
+
method: 'POST',
|
|
121
|
+
path: '/api/product/save',
|
|
122
|
+
body,
|
|
123
|
+
});
|
|
124
|
+
returnData.push({ json: ((_a = resp === null || resp === void 0 ? void 0 : resp.Response) !== null && _a !== void 0 ? _a : resp) });
|
|
125
|
+
return returnData;
|
|
126
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.productCreateProperties = void 0;
|
|
4
|
+
const showForProductCreate = { show: { resource: ['product'], operation: ['create'] } };
|
|
5
|
+
exports.productCreateProperties = [
|
|
6
|
+
// ===== Main (ordered) =====
|
|
7
|
+
{
|
|
8
|
+
displayName: 'Title',
|
|
9
|
+
name: 'Title',
|
|
10
|
+
type: 'string',
|
|
11
|
+
default: '',
|
|
12
|
+
required: true,
|
|
13
|
+
displayOptions: showForProductCreate,
|
|
14
|
+
description: 'Product title. Required.',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
displayName: 'Code',
|
|
18
|
+
name: 'Code',
|
|
19
|
+
type: 'string',
|
|
20
|
+
default: '',
|
|
21
|
+
displayOptions: showForProductCreate,
|
|
22
|
+
description: 'Internal product code (optional).',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
displayName: 'Product Category',
|
|
26
|
+
name: 'ProductCategoryId',
|
|
27
|
+
type: 'options',
|
|
28
|
+
typeOptions: { loadOptionsMethod: 'getProductCategories' },
|
|
29
|
+
default: '',
|
|
30
|
+
displayOptions: showForProductCreate,
|
|
31
|
+
description: 'Select a product category (optional).',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
displayName: 'Unit',
|
|
35
|
+
name: 'Unit',
|
|
36
|
+
type: 'string',
|
|
37
|
+
default: '',
|
|
38
|
+
displayOptions: showForProductCreate,
|
|
39
|
+
description: 'Unit name (e.g., USD, item, box).',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
displayName: 'Unit Price',
|
|
43
|
+
name: 'UnitPrice',
|
|
44
|
+
type: 'number',
|
|
45
|
+
typeOptions: { numberPrecision: 10 },
|
|
46
|
+
default: 0,
|
|
47
|
+
displayOptions: showForProductCreate,
|
|
48
|
+
description: 'Base price for the product.',
|
|
49
|
+
},
|
|
50
|
+
// Variants (optional, list)
|
|
51
|
+
// {
|
|
52
|
+
// displayName: 'Variants',
|
|
53
|
+
// name: 'Variants',
|
|
54
|
+
// type: 'fixedCollection',
|
|
55
|
+
// typeOptions: { multipleValues: true },
|
|
56
|
+
// default: {},
|
|
57
|
+
// displayOptions: showForProductCreate,
|
|
58
|
+
// options: [
|
|
59
|
+
// {
|
|
60
|
+
// name: 'Variant',
|
|
61
|
+
// displayName: 'Variant',
|
|
62
|
+
// values: [
|
|
63
|
+
// {
|
|
64
|
+
// displayName: 'Title',
|
|
65
|
+
// name: 'Title',
|
|
66
|
+
// type: 'string',
|
|
67
|
+
// default: '',
|
|
68
|
+
// description: 'Variant title. Required.',
|
|
69
|
+
// },
|
|
70
|
+
// {
|
|
71
|
+
// displayName: 'Variant Code',
|
|
72
|
+
// name: 'VariantCode',
|
|
73
|
+
// type: 'string',
|
|
74
|
+
// default: '',
|
|
75
|
+
// description: 'Variant code (optional).',
|
|
76
|
+
// },
|
|
77
|
+
// {
|
|
78
|
+
// displayName: 'Unit Price',
|
|
79
|
+
// name: 'UnitPrice',
|
|
80
|
+
// type: 'number',
|
|
81
|
+
// typeOptions: { numberPrecision: 10 },
|
|
82
|
+
// default: 0,
|
|
83
|
+
// description: 'Variant price (optional; defaults to 0).',
|
|
84
|
+
// },
|
|
85
|
+
// // نکته: TitleForInvoice, IsDeleted, IsDefault در UI نمایش داده نمیشوند — در operation ست میکنیم.
|
|
86
|
+
// ],
|
|
87
|
+
// },
|
|
88
|
+
// ],
|
|
89
|
+
// description: 'Optional list of variants.',
|
|
90
|
+
// },
|
|
91
|
+
{
|
|
92
|
+
displayName: 'Variants',
|
|
93
|
+
name: 'Variants',
|
|
94
|
+
type: 'json',
|
|
95
|
+
default: '[]',
|
|
96
|
+
displayOptions: showForProductCreate,
|
|
97
|
+
description: 'JSON array of variant objects. Example: ' +
|
|
98
|
+
'[{"Title":"V1","VariantCode":"A1","UnitPrice":1000},{"Title":"V2","VariantCode":"A2", "UnitPrice":0}]',
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
displayName: 'Active',
|
|
102
|
+
name: 'IsActive',
|
|
103
|
+
type: 'boolean',
|
|
104
|
+
default: true,
|
|
105
|
+
displayOptions: showForProductCreate,
|
|
106
|
+
description: 'Whether the product is active.',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
displayName: 'Description',
|
|
110
|
+
name: 'Description',
|
|
111
|
+
type: 'string',
|
|
112
|
+
default: '',
|
|
113
|
+
displayOptions: showForProductCreate,
|
|
114
|
+
description: 'Optional description.',
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
displayName: 'Custom Fields (JSON)',
|
|
118
|
+
name: 'Fields',
|
|
119
|
+
type: 'json',
|
|
120
|
+
default: '',
|
|
121
|
+
placeholder: '{ "Field_6_0_26": "value" }',
|
|
122
|
+
displayOptions: showForProductCreate,
|
|
123
|
+
description: 'JSON object of custom fields.',
|
|
124
|
+
},
|
|
125
|
+
];
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.productUpdateProperties = exports.productUpdate = exports.productCreateProperties = exports.productCreate = void 0;
|
|
4
|
+
// nodes/product/index.ts
|
|
5
|
+
var create_operation_1 = require("./create.operation");
|
|
6
|
+
Object.defineProperty(exports, "productCreate", { enumerable: true, get: function () { return create_operation_1.productCreate; } });
|
|
7
|
+
var create_properties_1 = require("./create.properties");
|
|
8
|
+
Object.defineProperty(exports, "productCreateProperties", { enumerable: true, get: function () { return create_properties_1.productCreateProperties; } });
|
|
9
|
+
var update_operation_1 = require("./update.operation");
|
|
10
|
+
Object.defineProperty(exports, "productUpdate", { enumerable: true, get: function () { return update_operation_1.productUpdate; } });
|
|
11
|
+
var update_properties_1 = require("./update.properties");
|
|
12
|
+
Object.defineProperty(exports, "productUpdateProperties", { enumerable: true, get: function () { return update_properties_1.productUpdateProperties; } });
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.productUpdate = productUpdate;
|
|
4
|
+
const http_1 = require("../../lib/http");
|
|
5
|
+
async function productUpdate(i, returnData) {
|
|
6
|
+
var _a;
|
|
7
|
+
// 1) Main params
|
|
8
|
+
const id = this.getNodeParameter('Id', i, '');
|
|
9
|
+
if (!(id === null || id === void 0 ? void 0 : id.trim()))
|
|
10
|
+
throw new Error('Product ID is required.');
|
|
11
|
+
const title = this.getNodeParameter('Title', i, '');
|
|
12
|
+
if (!(title === null || title === void 0 ? void 0 : title.trim()))
|
|
13
|
+
throw new Error('Title is required.');
|
|
14
|
+
const code = this.getNodeParameter('Code', i, '');
|
|
15
|
+
const unit = this.getNodeParameter('Unit', i, '');
|
|
16
|
+
const unitPrice = this.getNodeParameter('UnitPrice', i, 0);
|
|
17
|
+
const productCategoryId = this.getNodeParameter('ProductCategoryId', i, '');
|
|
18
|
+
const isActive = this.getNodeParameter('IsActive', i, true);
|
|
19
|
+
const description = this.getNodeParameter('Description', i, '');
|
|
20
|
+
// 2) Variants (dynamic JSON, each may include Id)
|
|
21
|
+
let variants;
|
|
22
|
+
const variantsUi = this.getNodeParameter('Variants', i, '[]');
|
|
23
|
+
let parsed;
|
|
24
|
+
if (typeof variantsUi === 'string') {
|
|
25
|
+
const trimmed = variantsUi.trim();
|
|
26
|
+
if (trimmed) {
|
|
27
|
+
try {
|
|
28
|
+
parsed = JSON.parse(trimmed);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
throw new Error('Invalid JSON in "Variants". It must be a JSON array of objects.');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
parsed = [];
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
parsed = variantsUi;
|
|
40
|
+
}
|
|
41
|
+
if (parsed != null) {
|
|
42
|
+
if (!Array.isArray(parsed))
|
|
43
|
+
throw new Error('"Variants" must be an array.');
|
|
44
|
+
variants = parsed.map((v, idx) => {
|
|
45
|
+
var _a, _b, _c;
|
|
46
|
+
if (typeof v !== 'object' || v == null) {
|
|
47
|
+
throw new Error(`"Variants[${idx}]" must be an object.`);
|
|
48
|
+
}
|
|
49
|
+
const vTitle = ((_a = v.Title) !== null && _a !== void 0 ? _a : '').toString();
|
|
50
|
+
if (!vTitle.trim())
|
|
51
|
+
throw new Error(`"Variants[${idx}].Title" is required.`);
|
|
52
|
+
const vCode = ((_b = v.VariantCode) !== null && _b !== void 0 ? _b : '').toString();
|
|
53
|
+
const vPrice = typeof v.UnitPrice === 'number' ? v.UnitPrice : Number((_c = v.UnitPrice) !== null && _c !== void 0 ? _c : 0) || 0;
|
|
54
|
+
const variant = {
|
|
55
|
+
Title: vTitle,
|
|
56
|
+
TitleForInvoice: vTitle, // hidden rule (same as create)
|
|
57
|
+
IsDeleted: false, // hidden rule
|
|
58
|
+
IsDefault: true, // hidden rule
|
|
59
|
+
UnitPrice: vPrice,
|
|
60
|
+
VariantCode: vCode,
|
|
61
|
+
};
|
|
62
|
+
// If variant Id provided (update existing variant)
|
|
63
|
+
if (typeof v.Id === 'string' && v.Id.trim()) {
|
|
64
|
+
variant['Id'] = v.Id.trim();
|
|
65
|
+
}
|
|
66
|
+
return variant;
|
|
67
|
+
});
|
|
68
|
+
if (!variants.length)
|
|
69
|
+
variants = undefined;
|
|
70
|
+
}
|
|
71
|
+
// 3) Fields (JSON)
|
|
72
|
+
let fields;
|
|
73
|
+
const fieldsUi = this.getNodeParameter('Fields', i, '');
|
|
74
|
+
if (typeof fieldsUi === 'string' && fieldsUi.trim()) {
|
|
75
|
+
try {
|
|
76
|
+
fields = JSON.parse(fieldsUi);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
throw new Error('Invalid JSON in "Custom Fields (JSON)".');
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
else if (typeof fieldsUi === 'object' && fieldsUi) {
|
|
83
|
+
fields = fieldsUi;
|
|
84
|
+
}
|
|
85
|
+
// 4) Build payload
|
|
86
|
+
const product = {
|
|
87
|
+
Id: id,
|
|
88
|
+
Title: title,
|
|
89
|
+
Code: code,
|
|
90
|
+
Unit: unit,
|
|
91
|
+
UnitPrice: typeof unitPrice === 'number' ? unitPrice : Number(unitPrice) || 0,
|
|
92
|
+
Description: description,
|
|
93
|
+
IsActive: !!isActive,
|
|
94
|
+
};
|
|
95
|
+
if (productCategoryId)
|
|
96
|
+
product['ProductCategoryId'] = productCategoryId;
|
|
97
|
+
if (variants)
|
|
98
|
+
product['Variants'] = variants;
|
|
99
|
+
if (fields)
|
|
100
|
+
product['Fields'] = fields;
|
|
101
|
+
const body = { Product: product };
|
|
102
|
+
// 5) Request
|
|
103
|
+
const resp = await (0, http_1.didarRequest)(this, i, {
|
|
104
|
+
method: 'POST',
|
|
105
|
+
path: '/api/product/save',
|
|
106
|
+
body,
|
|
107
|
+
});
|
|
108
|
+
returnData.push({ json: ((_a = resp === null || resp === void 0 ? void 0 : resp.Response) !== null && _a !== void 0 ? _a : resp) });
|
|
109
|
+
return returnData;
|
|
110
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.productUpdateProperties = void 0;
|
|
4
|
+
const showForProductUpdate = { show: { resource: ['product'], operation: ['update'] } };
|
|
5
|
+
exports.productUpdateProperties = [
|
|
6
|
+
// ===== Main (ordered) =====
|
|
7
|
+
{
|
|
8
|
+
displayName: 'Product ID',
|
|
9
|
+
name: 'Id',
|
|
10
|
+
type: 'string',
|
|
11
|
+
default: '',
|
|
12
|
+
required: true,
|
|
13
|
+
displayOptions: showForProductUpdate,
|
|
14
|
+
description: 'The ID of the product to update. Required.',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
displayName: 'Title',
|
|
18
|
+
name: 'Title',
|
|
19
|
+
type: 'string',
|
|
20
|
+
default: '',
|
|
21
|
+
required: true,
|
|
22
|
+
displayOptions: showForProductUpdate,
|
|
23
|
+
description: 'Product title. Required.',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
displayName: 'Code',
|
|
27
|
+
name: 'Code',
|
|
28
|
+
type: 'string',
|
|
29
|
+
default: '',
|
|
30
|
+
displayOptions: showForProductUpdate,
|
|
31
|
+
description: 'Internal product code (optional).',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
displayName: 'Product Category',
|
|
35
|
+
name: 'ProductCategoryId',
|
|
36
|
+
type: 'options',
|
|
37
|
+
typeOptions: { loadOptionsMethod: 'getProductCategories' },
|
|
38
|
+
default: '',
|
|
39
|
+
displayOptions: showForProductUpdate,
|
|
40
|
+
description: 'Select a product category (optional).',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
displayName: 'Unit',
|
|
44
|
+
name: 'Unit',
|
|
45
|
+
type: 'string',
|
|
46
|
+
default: '',
|
|
47
|
+
displayOptions: showForProductUpdate,
|
|
48
|
+
description: 'Unit name (e.g., USD, item, box).',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
displayName: 'Unit Price',
|
|
52
|
+
name: 'UnitPrice',
|
|
53
|
+
type: 'number',
|
|
54
|
+
typeOptions: { numberPrecision: 10 },
|
|
55
|
+
default: 0,
|
|
56
|
+
displayOptions: showForProductUpdate,
|
|
57
|
+
description: 'Base price for the product.',
|
|
58
|
+
},
|
|
59
|
+
// Variants as dynamic JSON (each item may include Id on update)
|
|
60
|
+
{
|
|
61
|
+
displayName: 'Variants',
|
|
62
|
+
name: 'Variants',
|
|
63
|
+
type: 'json',
|
|
64
|
+
default: '[]',
|
|
65
|
+
displayOptions: showForProductUpdate,
|
|
66
|
+
description: 'JSON array of variant objects. For update, each item may include "Id". ' +
|
|
67
|
+
'Example: ' +
|
|
68
|
+
'[{"Id":"<GUID>","Title":"V1","VariantCode":"A1","UnitPrice":1000},' +
|
|
69
|
+
'{"Id":"<GUID>","Title":"V2","VariantCode":"A2","UnitPrice":0}]',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
displayName: 'Active',
|
|
73
|
+
name: 'IsActive',
|
|
74
|
+
type: 'boolean',
|
|
75
|
+
default: true,
|
|
76
|
+
displayOptions: showForProductUpdate,
|
|
77
|
+
description: 'Whether the product is active.',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
displayName: 'Description',
|
|
81
|
+
name: 'Description',
|
|
82
|
+
type: 'string',
|
|
83
|
+
default: '',
|
|
84
|
+
displayOptions: showForProductUpdate,
|
|
85
|
+
description: 'Optional description.',
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
displayName: 'Custom Fields (JSON)',
|
|
89
|
+
name: 'Fields',
|
|
90
|
+
type: 'json',
|
|
91
|
+
default: '',
|
|
92
|
+
placeholder: '{ "Field_6_0_26": "value" }',
|
|
93
|
+
displayOptions: showForProductUpdate,
|
|
94
|
+
description: 'JSON object of custom fields.',
|
|
95
|
+
},
|
|
96
|
+
];
|