n8n-nodes-didar-crm 0.0.14 → 0.0.16

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.
@@ -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>;
@@ -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.',
@@ -118,8 +122,8 @@ class DidarCrm {
118
122
  displayOptions: { show: { resource: ['company'] } },
119
123
  options: [
120
124
  { name: 'Create', value: 'create', action: 'Create a company' },
121
- { name: 'Update', value: 'update', action: 'Update a company by Id' }, // NEW
122
- { name: 'Get', value: 'get', action: 'Get a company by Id' }, // NEW
125
+ { name: 'Update', value: 'update', action: 'Update a company by Id' },
126
+ { name: 'Get', value: 'get', action: 'Get a company by Id' },
123
127
  ],
124
128
  default: 'create',
125
129
  description: 'Select the action to perform on the selected resource.',
@@ -131,7 +135,7 @@ class DidarCrm {
131
135
  displayOptions: { show: { resource: ['activity'] } },
132
136
  options: [
133
137
  { name: 'Create', value: 'create', action: 'Create an activity' },
134
- { name: 'Update', value: 'update', action: 'Update an activity by Id' }, // NEW
138
+ { name: 'Update', value: 'update', action: 'Update an activity by Id' },
135
139
  ],
136
140
  default: 'create',
137
141
  description: 'Select the action to perform on the selected resource.',
@@ -160,6 +164,19 @@ 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
+ { name: 'Get by Codes', value: 'getByCodes', action: 'Get products by list of codes' },
176
+ ],
177
+ default: 'create',
178
+ description: 'Select the action to perform on the selected resource.',
179
+ },
163
180
  // Deal properties (imported)
164
181
  ...deal_1.dealCreateProperties,
165
182
  ...deal_1.dealUpdateProperties,
@@ -181,6 +198,10 @@ class DidarCrm {
181
198
  // Case properties (imported)
182
199
  ...case_1.caseCreateProperties,
183
200
  ...case_1.caseUpdateProperties,
201
+ // Product properties (imported)
202
+ ...product_1.productCreateProperties,
203
+ ...product_1.productUpdateProperties,
204
+ ...product_1.productGetByCodesProperties,
184
205
  ],
185
206
  };
186
207
  }
@@ -226,11 +247,11 @@ class DidarCrm {
226
247
  if (operation === 'update') {
227
248
  await CompanyOps.companyUpdate.call(this, i, returnData);
228
249
  continue;
229
- } // NEW
250
+ }
230
251
  if (operation === 'get') {
231
252
  await CompanyOps.companyGet.call(this, i, returnData);
232
253
  continue;
233
- } // NEW
254
+ }
234
255
  }
235
256
  if (resource === 'activity') {
236
257
  if (operation === 'create') {
@@ -240,7 +261,7 @@ class DidarCrm {
240
261
  if (operation === 'update') {
241
262
  await ActivityOps.activityUpdate.call(this, i, returnData);
242
263
  continue;
243
- } // NEW
264
+ }
244
265
  }
245
266
  if (resource === 'note') {
246
267
  if (operation === 'create') {
@@ -262,6 +283,20 @@ class DidarCrm {
262
283
  continue;
263
284
  }
264
285
  }
286
+ if (resource === 'product') {
287
+ if (operation === 'create') {
288
+ await ProductOps.productCreate.call(this, i, returnData);
289
+ continue;
290
+ }
291
+ if (operation === 'update') {
292
+ await ProductOps.productUpdate.call(this, i, returnData);
293
+ continue;
294
+ }
295
+ if (operation === 'getByCodes') {
296
+ await ProductOps.productGetByCodes.call(this, i, returnData);
297
+ continue;
298
+ }
299
+ }
265
300
  }
266
301
  return [returnData];
267
302
  }
@@ -5,7 +5,7 @@ var create_operation_1 = require("./create.operation");
5
5
  Object.defineProperty(exports, "activityCreate", { enumerable: true, get: function () { return create_operation_1.activityCreate; } });
6
6
  var create_properties_1 = require("./create.properties");
7
7
  Object.defineProperty(exports, "activityCreateProperties", { enumerable: true, get: function () { return create_properties_1.activityCreateProperties; } });
8
- var update_operation_1 = require("./update.operation"); // NEW
8
+ var update_operation_1 = require("./update.operation");
9
9
  Object.defineProperty(exports, "activityUpdate", { enumerable: true, get: function () { return update_operation_1.activityUpdate; } });
10
- var update_properties_1 = require("./update.properties"); // NEW
10
+ var update_properties_1 = require("./update.properties");
11
11
  Object.defineProperty(exports, "activityUpdateProperties", { enumerable: true, get: function () { return update_properties_1.activityUpdateProperties; } });
@@ -9,7 +9,7 @@ var update_operation_1 = require("./update.operation");
9
9
  Object.defineProperty(exports, "companyUpdate", { enumerable: true, get: function () { return update_operation_1.companyUpdate; } });
10
10
  var update_properties_1 = require("./update.properties");
11
11
  Object.defineProperty(exports, "companyUpdateProperties", { enumerable: true, get: function () { return update_properties_1.companyUpdateProperties; } });
12
- var get_operation_1 = require("./get.operation"); // NEW
12
+ var get_operation_1 = require("./get.operation");
13
13
  Object.defineProperty(exports, "companyGet", { enumerable: true, get: function () { return get_operation_1.companyGet; } });
14
- var get_properties_1 = require("./get.properties"); // NEW
14
+ var get_properties_1 = require("./get.properties");
15
15
  Object.defineProperty(exports, "companyGetProperties", { enumerable: true, get: function () { return get_properties_1.companyGetProperties; } });
@@ -0,0 +1,2 @@
1
+ import type { IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
2
+ export declare function productCreate(this: IExecuteFunctions, i: number, returnData: INodeExecutionData[]): Promise<INodeExecutionData[]>;
@@ -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,2 @@
1
+ import type { INodeProperties } from 'n8n-workflow';
2
+ export declare const productCreateProperties: INodeProperties[];
@@ -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,2 @@
1
+ import type { IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
2
+ export declare function productGetByCodes(this: IExecuteFunctions, i: number, returnData: INodeExecutionData[]): Promise<INodeExecutionData[]>;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.productGetByCodes = productGetByCodes;
4
+ const http_1 = require("../../lib/http");
5
+ async function productGetByCodes(i, returnData) {
6
+ var _a;
7
+ // Read & normalize codes
8
+ const raw = this.getNodeParameter('Code', i, []);
9
+ const toArray = (v) => Array.isArray(v) ? v : (typeof v === 'string' && v ? [v] : []);
10
+ const codes = toArray(raw).map(s => (s !== null && s !== void 0 ? s : '').toString().trim()).filter(Boolean);
11
+ if (!codes.length)
12
+ throw new Error('At least one product code is required.');
13
+ const body = { Code: codes };
14
+ const resp = await (0, http_1.didarRequest)(this, i, {
15
+ method: 'POST',
16
+ path: '/api/product/getproductbycodes',
17
+ body,
18
+ });
19
+ // API returns { Response: { Total, Products: [...] } }
20
+ const out = ((_a = resp === null || resp === void 0 ? void 0 : resp.Response) !== null && _a !== void 0 ? _a : resp);
21
+ returnData.push({ json: out });
22
+ return returnData;
23
+ }
@@ -0,0 +1,2 @@
1
+ import type { INodeProperties } from 'n8n-workflow';
2
+ export declare const productGetByCodesProperties: INodeProperties[];
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.productGetByCodesProperties = void 0;
4
+ const showForProductGetByCodes = { show: { resource: ['product'], operation: ['getByCodes'] } };
5
+ exports.productGetByCodesProperties = [
6
+ {
7
+ displayName: 'Codes',
8
+ name: 'Code',
9
+ type: 'string',
10
+ typeOptions: { multipleValues: true }, // n8n → string[]
11
+ default: [],
12
+ required: true,
13
+ displayOptions: showForProductGetByCodes,
14
+ description: 'List of product codes (at least one).',
15
+ },
16
+ ];
@@ -0,0 +1,6 @@
1
+ export { productCreate } from './create.operation';
2
+ export { productCreateProperties } from './create.properties';
3
+ export { productUpdate } from './update.operation';
4
+ export { productUpdateProperties } from './update.properties';
5
+ export { productGetByCodes } from './getByCodes.operation';
6
+ export { productGetByCodesProperties } from './getByCodes.properties';
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.productGetByCodesProperties = exports.productGetByCodes = 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; } });
13
+ var getByCodes_operation_1 = require("./getByCodes.operation");
14
+ Object.defineProperty(exports, "productGetByCodes", { enumerable: true, get: function () { return getByCodes_operation_1.productGetByCodes; } });
15
+ var getByCodes_properties_1 = require("./getByCodes.properties");
16
+ Object.defineProperty(exports, "productGetByCodesProperties", { enumerable: true, get: function () { return getByCodes_properties_1.productGetByCodesProperties; } });
@@ -0,0 +1,2 @@
1
+ import type { IExecuteFunctions, INodeExecutionData } from 'n8n-workflow';
2
+ export declare function productUpdate(this: IExecuteFunctions, i: number, returnData: INodeExecutionData[]): Promise<INodeExecutionData[]>;
@@ -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,2 @@
1
+ import type { INodeProperties } from 'n8n-workflow';
2
+ export declare const productUpdateProperties: INodeProperties[];
@@ -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
+ ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-didar-crm",
3
- "version": "0.0.14",
3
+ "version": "0.0.16",
4
4
  "description": "Didar CRM nodes for n8n (Trigger + Deal.create)",
5
5
  "author": "You",
6
6
  "license": "MIT",