n8n-nodes-livo
Version:
n8n Livo App integration with triggers and actions for orders, products, customers, and repairs
279 lines (278 loc) • 13.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LivoProductEvents = void 0;
const n8n_workflow_1 = require("n8n-workflow");
class LivoProductEvents {
constructor() {
this.description = {
displayName: 'Livo Product Events',
name: 'livoProductEvents',
icon: 'file:product.svg',
group: ['trigger'],
version: 1,
subtitle: '={{$parameter["eventType"]}}',
description: 'Lắng nghe các sự kiện sản phẩm từ ứng dụng Livo',
defaults: {
name: 'Livo Product Events',
},
inputs: [],
outputs: ['main'],
webhooks: [
{
name: 'default',
httpMethod: 'POST',
responseMode: 'onReceived',
path: 'webhook',
},
],
properties: [
{
displayName: 'Event Type',
name: 'eventType',
type: 'options',
options: [
{
name: 'Lấy danh sách sản phẩm',
value: 'product.list',
description: 'Trigger khi lấy danh sách sản phẩm',
},
{
name: 'Chi tiết sản phẩm',
value: 'product.detail',
description: 'Trigger khi xem chi tiết sản phẩm',
},
{
name: 'Tạo sản phẩm',
value: 'product.created',
description: 'Trigger khi tạo mới sản phẩm',
},
{
name: 'Cập nhật sản phẩm',
value: 'product.updated',
description: 'Trigger khi cập nhật sản phẩm',
},
{
name: 'Xóa sản phẩm',
value: 'product.deleted',
description: 'Trigger khi xóa sản phẩm',
},
{
name: 'Nhập kho',
value: 'product.stock_in',
description: 'Trigger khi nhập hàng vào kho',
},
{
name: 'Xuất kho',
value: 'product.stock_out',
description: 'Trigger khi xuất hàng khỏi kho',
},
],
default: 'product.created',
required: true,
},
{
displayName: 'Advanced Filters',
name: 'advancedFilters',
type: 'collection',
placeholder: 'Add Filter',
default: {},
options: [
{
displayName: 'Category',
name: 'category',
type: 'string',
default: '',
description: 'Lọc theo danh mục sản phẩm',
},
{
displayName: 'Brand',
name: 'brand',
type: 'string',
default: '',
description: 'Lọc theo thương hiệu',
},
{
displayName: 'Min Price',
name: 'minPrice',
type: 'number',
default: 0,
description: 'Giá sản phẩm tối thiểu',
},
{
displayName: 'Max Price',
name: 'maxPrice',
type: 'number',
default: 0,
description: 'Giá sản phẩm tối đa (0 = không giới hạn)',
},
{
displayName: 'Stock Threshold',
name: 'stockThreshold',
type: 'number',
default: 0,
description: 'Ngưỡng tồn kho để lọc',
},
{
displayName: 'Assigned Staff',
name: 'assignedStaff',
type: 'string',
default: '',
description: 'Lọc theo nhân viên phụ trách',
},
{
displayName: 'Branch',
name: 'branch',
type: 'string',
default: '',
description: 'Lọc theo chi nhánh',
},
],
},
{
displayName: 'Authentication',
name: 'authentication',
type: 'collection',
placeholder: 'Add Authentication',
default: {},
options: [
{
displayName: 'Secret Token',
name: 'secretToken',
type: 'string',
typeOptions: {
password: true,
},
default: '',
description: 'Token bí mật để xác thực webhook',
},
{
displayName: 'Header Name',
name: 'headerName',
type: 'string',
default: 'X-Webhook-Secret',
description: 'Tên header chứa token xác thực',
},
],
},
],
};
}
async webhook() {
const bodyData = this.getBodyData();
const headers = this.getHeaderData();
const query = this.getQueryData();
const req = this.getRequestObject();
const expectedEventType = this.getNodeParameter('eventType');
const advancedFilters = this.getNodeParameter('advancedFilters', {});
const authentication = this.getNodeParameter('authentication', {});
if (authentication.secretToken) {
const headerName = authentication.headerName || 'X-Webhook-Secret';
const receivedToken = headers[headerName.toLowerCase()] || headers[headerName];
if (!receivedToken || receivedToken !== authentication.secretToken) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Xác thực webhook thất bại: Token không hợp lệ');
}
}
if (!bodyData || typeof bodyData !== 'object') {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Dữ liệu webhook không hợp lệ');
}
const eventData = bodyData;
const receivedEvent = eventData.event || headers['x-event-type'];
if (receivedEvent !== expectedEventType) {
return {
noWebhookResponse: true,
};
}
if (advancedFilters.category && eventData.category !== advancedFilters.category) {
return { noWebhookResponse: true };
}
if (advancedFilters.brand && eventData.brand !== advancedFilters.brand) {
return { noWebhookResponse: true };
}
if (advancedFilters.minPrice && (eventData.unit_price || 0) < advancedFilters.minPrice) {
return { noWebhookResponse: true };
}
if (advancedFilters.maxPrice && advancedFilters.maxPrice > 0 &&
(eventData.unit_price || 0) > advancedFilters.maxPrice) {
return { noWebhookResponse: true };
}
if (advancedFilters.stockThreshold &&
(eventData.stock_quantity || 0) < advancedFilters.stockThreshold) {
return { noWebhookResponse: true };
}
if (advancedFilters.assignedStaff && eventData.assigned_staff !== advancedFilters.assignedStaff) {
return { noWebhookResponse: true };
}
if (advancedFilters.branch && eventData.branch !== advancedFilters.branch) {
return { noWebhookResponse: true };
}
const outputData = {
app_name: 'Livo',
event: receivedEvent,
event_time: new Date().toISOString(),
event_category: 'product',
id: eventData.id || eventData.product_id,
code: eventData.code || eventData.product_code,
status: eventData.status || eventData.trang_thai,
created_date: eventData.created_date || eventData.ngay_tao,
updated_date: eventData.updated_date || eventData.ngay_cap_nhat,
assigned_staff: eventData.assigned_staff || eventData.nhan_vien_phu_trach,
branch: eventData.branch || eventData.chi_nhanh,
notes: eventData.notes || eventData.ghi_chu,
product_id: eventData.product_id || eventData.ma_san_pham,
product_name: eventData.product_name || eventData.ten_san_pham,
product_code: eventData.product_code || eventData.ma_san_pham,
sku: eventData.sku || eventData.ma_sku,
barcode: eventData.barcode || eventData.ma_vach,
category: eventData.category || eventData.danh_muc,
subcategory: eventData.subcategory || eventData.danh_muc_con,
brand: eventData.brand || eventData.thuong_hieu,
model: eventData.model || eventData.model,
variant: eventData.variant || eventData.bien_the,
description: eventData.description || eventData.mo_ta,
short_description: eventData.short_description || eventData.mo_ta_ngan,
specifications: eventData.specifications || eventData.thong_so_ky_thuat || {},
features: eventData.features || eventData.tinh_nang || [],
unit_price: eventData.unit_price || eventData.gia_ban,
cost_price: eventData.cost_price || eventData.gia_von,
wholesale_price: eventData.wholesale_price || eventData.gia_si,
retail_price: eventData.retail_price || eventData.gia_le,
discount_price: eventData.discount_price || eventData.gia_khuyen_mai,
stock_quantity: eventData.stock_quantity || eventData.ton_kho,
min_stock_level: eventData.min_stock_level || eventData.ton_kho_toi_thieu,
max_stock_level: eventData.max_stock_level || eventData.ton_kho_toi_da,
reorder_point: eventData.reorder_point || eventData.diem_dat_hang_lai,
weight: eventData.weight || eventData.trong_luong,
dimensions: eventData.dimensions || eventData.kich_thuoc,
color: eventData.color || eventData.mau_sac,
size: eventData.size || eventData.kich_co,
material: eventData.material || eventData.chat_lieu,
is_active: eventData.is_active || eventData.dang_hoat_dong,
is_featured: eventData.is_featured || eventData.san_pham_noi_bat,
sales_count: eventData.sales_count || eventData.so_luong_ban,
view_count: eventData.view_count || eventData.luot_xem,
rating: eventData.rating || eventData.danh_gia,
review_count: eventData.review_count || eventData.so_binh_luan,
meta_title: eventData.meta_title || eventData.tieu_de_seo,
meta_description: eventData.meta_description || eventData.mo_ta_seo,
keywords: eventData.keywords || eventData.tu_khoa || [],
tags: eventData.tags || eventData.the_bai || [],
images: eventData.images || eventData.hinh_anh || [],
thumbnail: eventData.thumbnail || eventData.hinh_dai_dien,
gallery: eventData.gallery || eventData.thu_vien_anh || [],
raw_data: eventData,
headers: headers,
query: query,
webhook_url: req.url,
};
return {
workflowData: [
[
{
json: outputData,
},
],
],
};
}
}
exports.LivoProductEvents = LivoProductEvents;