From 7a3e1219427ce557b49181b0049f02df30d65902 Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Thu, 28 Mar 2024 00:05:02 +0200 Subject: [PATCH] feat: import customers/vendors --- packages/server/resources/locales/en.json | 12 +- .../src/api/controllers/Import/_utils.ts | 3 +- packages/server/src/interfaces/Model.ts | 37 ++-- .../server/src/models/Customer.Settings.ts | 26 ++- packages/server/src/models/Item.Settings.ts | 59 ++++--- packages/server/src/models/Vendor.Settings.ts | 15 +- .../Contacts/Customers/CustomersImportable.ts | 8 + .../Contacts/Customers/_SampleData.ts | 158 ++++++++++++++++++ .../Contacts/Vendors/VendorsImportable.ts | 8 + .../services/Contacts/Vendors/_SampleData.ts | 122 ++++++++++++++ packages/server/src/services/Import/_utils.ts | 15 +- .../Import/ImportFileUploadForm.tsx | 22 ++- 12 files changed, 437 insertions(+), 48 deletions(-) create mode 100644 packages/server/src/services/Contacts/Customers/_SampleData.ts create mode 100644 packages/server/src/services/Contacts/Vendors/_SampleData.ts diff --git a/packages/server/resources/locales/en.json b/packages/server/resources/locales/en.json index 120aed816..d63edebaf 100644 --- a/packages/server/resources/locales/en.json +++ b/packages/server/resources/locales/en.json @@ -376,8 +376,8 @@ "customer.field.last_name": "Last name", "customer.field.display_name": "Display name", "customer.field.email": "Email", - "customer.field.work_phone": "Work phone", - "customer.field.personal_phone": "Personal phone", + "customer.field.work_phone": "Work Phone Number", + "customer.field.personal_phone": "Personal Phone Number", "customer.field.company_name": "Company name", "customer.field.website": "Website", "customer.field.opening_balance_at": "Opening balance at", @@ -385,7 +385,7 @@ "customer.field.created_at": "Created at", "customer.field.balance": "Balance", "customer.field.status": "Status", - "customer.field.currency": "Curreny", + "customer.field.currency": "Currency", "customer.field.status.active": "Active", "customer.field.status.inactive": "Inactive", "customer.field.status.overdue": "Overdue", @@ -394,8 +394,8 @@ "vendor.field.last_name": "Last name", "vendor.field.display_name": "Display name", "vendor.field.email": "Email", - "vendor.field.work_phone": "Work phone", - "vendor.field.personal_phone": "Personal phone", + "vendor.field.work_phone": "Work Phone Number", + "vendor.field.personal_phone": "Personal Phone Number", "vendor.field.company_name": "Company name", "vendor.field.website": "Website", "vendor.field.opening_balance_at": "Opening balance at", @@ -403,7 +403,7 @@ "vendor.field.created_at": "Created at", "vendor.field.balance": "Balance", "vendor.field.status": "Status", - "vendor.field.currency": "Curreny", + "vendor.field.currency": "Currency", "vendor.field.status.active": "Active", "vendor.field.status.inactive": "Inactive", "vendor.field.status.overdue": "Overdue", diff --git a/packages/server/src/api/controllers/Import/_utils.ts b/packages/server/src/api/controllers/Import/_utils.ts index 333e280fe..0621ba999 100644 --- a/packages/server/src/api/controllers/Import/_utils.ts +++ b/packages/server/src/api/controllers/Import/_utils.ts @@ -4,7 +4,8 @@ import { ServiceError } from '@/exceptions'; export function allowSheetExtensions(req, file, cb) { if ( file.mimetype !== 'text/csv' && - file.mimetype !== 'application/vnd.ms-excel' + file.mimetype !== 'application/vnd.ms-excel' && + file.mimetype !== 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ) { cb(new ServiceError('IMPORTED_FILE_EXTENSION_INVALID')); diff --git a/packages/server/src/interfaces/Model.ts b/packages/server/src/interfaces/Model.ts index 96ba461c0..49b875c2c 100644 --- a/packages/server/src/interfaces/Model.ts +++ b/packages/server/src/interfaces/Model.ts @@ -1,4 +1,3 @@ - export interface IModel { name: string; tableName: string; @@ -40,18 +39,35 @@ export interface IModelMetaFieldCommon { order?: number; } -export interface IModelMetaFieldNumber { - fieldType: 'number'; +export interface IModelMetaFieldText { + fieldType: 'text'; minLength?: number; maxLength?: number; } - -export interface IModelMetaFieldOther { - fieldType: 'text' | 'boolean'; +export interface IModelMetaFieldBoolean { + fieldType: 'boolean'; +} +export interface IModelMetaFieldNumber { + fieldType: 'number'; + min?: number; + max?: number; +} +export interface IModelMetaFieldDate { + fieldType: 'date'; +} +export interface IModelMetaFieldUrl { + fieldType: 'url'; } - export type IModelMetaField = IModelMetaFieldCommon & - (IModelMetaFieldOther | IModelMetaEnumerationField | IModelMetaRelationField); + ( + | IModelMetaFieldText + | IModelMetaFieldNumber + | IModelMetaFieldBoolean + | IModelMetaFieldDate + | IModelMetaFieldUrl + | IModelMetaEnumerationField + | IModelMetaRelationField + ); export interface IModelMetaEnumerationOption { key: string; @@ -74,9 +90,8 @@ export interface IModelMetaRelationEnumerationField { relationEntityKey: string; } -export type IModelMetaRelationField = IModelMetaRelationFieldCommon & ( - IModelMetaRelationEnumerationField -); +export type IModelMetaRelationField = IModelMetaRelationFieldCommon & + IModelMetaRelationEnumerationField; export interface IModelMeta { defaultFilterField: string; diff --git a/packages/server/src/models/Customer.Settings.ts b/packages/server/src/models/Customer.Settings.ts index 53cf83296..b789c9adf 100644 --- a/packages/server/src/models/Customer.Settings.ts +++ b/packages/server/src/models/Customer.Settings.ts @@ -6,6 +6,17 @@ export default { sortField: 'createdAt', }, fields: { + customerType: { + name: 'Customer Type', + column: 'contact_type', + fieldType: 'enumeration', + options: [ + { key: 'business', label: 'Business' }, + { key: 'individual', label: 'Individual' }, + ], + importable: true, + required: true, + }, firstName: { name: 'customer.field.first_name', column: 'first_name', @@ -52,7 +63,7 @@ export default { website: { name: 'customer.field.website', column: 'website', - fieldType: 'text', + fieldType: 'url', importable: true, }, balance: { @@ -85,6 +96,18 @@ export default { fieldType: 'text', importable: true, }, + note: { + name: 'Note', + column: 'note', + fieldType: 'text', + importable: true, + }, + active: { + name: 'Active', + column: 'active', + fieldType: 'boolean', + importable: true, + }, status: { name: 'customer.field.status', fieldType: 'enumeration', @@ -95,7 +118,6 @@ export default { { key: 'unpaid', label: 'customer.field.status.unpaid' }, ], filterCustomQuery: statusFieldFilterQuery, - importable: true, }, // Billing Address billingAddress1: { diff --git a/packages/server/src/models/Item.Settings.ts b/packages/server/src/models/Item.Settings.ts index b5509a0a4..3ff5b5613 100644 --- a/packages/server/src/models/Item.Settings.ts +++ b/packages/server/src/models/Item.Settings.ts @@ -1,51 +1,59 @@ export default { + importable: true, defaultFilterField: 'name', defaultSort: { sortField: 'name', sortOrder: 'DESC', }, fields: { - 'type': { + type: { name: 'item.field.type', column: 'type', fieldType: 'enumeration', options: [ - { key: 'inventory', label: 'item.field.type.inventory', }, + { key: 'inventory', label: 'item.field.type.inventory' }, { key: 'service', label: 'item.field.type.service' }, - { key: 'non-inventory', label: 'item.field.type.non-inventory', }, + { key: 'non-inventory', label: 'item.field.type.non-inventory' }, ], + importable: true, }, - 'name': { + name: { name: 'item.field.name', column: 'name', fieldType: 'text', + importable: true, }, - 'code': { + code: { name: 'item.field.code', column: 'code', fieldType: 'text', + importable: true, }, - 'sellable': { + sellable: { name: 'item.field.sellable', column: 'sellable', fieldType: 'boolean', + importable: true, }, - 'purchasable': { + purchasable: { name: 'item.field.purchasable', column: 'purchasable', fieldType: 'boolean', + importable: true, }, - 'sell_price': { + sellPrice: { name: 'item.field.cost_price', column: 'sell_price', fieldType: 'number', + importable: true, }, - 'cost_price': { + costPrice: { name: 'item.field.cost_account', column: 'cost_price', fieldType: 'number', + importable: true, }, - 'cost_account': { + costAccount: { name: 'item.field.sell_account', column: 'cost_account_id', fieldType: 'relation', @@ -55,8 +63,10 @@ export default { relationEntityLabel: 'name', relationEntityKey: 'slug', + + importable: true, }, - 'sell_account': { + sellAccount: { name: 'item.field.sell_description', column: 'sell_account_id', fieldType: 'relation', @@ -66,8 +76,10 @@ export default { relationEntityLabel: 'name', relationEntityKey: 'slug', + + importable: true, }, - 'inventory_account': { + inventoryAccount: { name: 'item.field.inventory_account', column: 'inventory_account_id', @@ -76,28 +88,34 @@ export default { relationEntityLabel: 'name', relationEntityKey: 'slug', + + importable: true, }, - 'sell_description': { + sellDescription: { name: 'Sell description', column: 'sell_description', fieldType: 'text', + importable: true, }, - 'purchase_description': { + purchaseDescription: { name: 'Purchase description', column: 'purchase_description', fieldType: 'text', + importable: true, }, - 'quantity_on_hand': { + quantityOnHand: { name: 'item.field.quantity_on_hand', column: 'quantity_on_hand', fieldType: 'number', + importable: true, }, - 'note': { + note: { name: 'item.field.note', column: 'note', fieldType: 'text', + importable: true, }, - 'category': { + category: { name: 'item.field.category', column: 'category_id', @@ -106,14 +124,15 @@ export default { relationEntityLabel: 'name', relationEntityKey: 'id', + importable: true, }, - 'active': { + active: { name: 'item.field.active', column: 'active', fieldType: 'boolean', - filterable: false, + importable: true, }, - 'created_at': { + createdAt: { name: 'item.field.created_at', column: 'created_at', columnType: 'date', diff --git a/packages/server/src/models/Vendor.Settings.ts b/packages/server/src/models/Vendor.Settings.ts index a1792ff0f..0317d43c5 100644 --- a/packages/server/src/models/Vendor.Settings.ts +++ b/packages/server/src/models/Vendor.Settings.ts @@ -38,7 +38,7 @@ export default { importable: true, }, personalPhone: { - name: 'vendor.field.personal_pone', + name: 'vendor.field.personal_phone', column: 'personal_phone', fieldType: 'text', importable: true, @@ -84,6 +84,18 @@ export default { fieldType: 'text', importable: true, }, + note: { + name: 'Note', + column: 'note', + fieldType: 'text', + importable: true, + }, + active: { + name: 'Active', + column: 'active', + fieldType: 'boolean', + importable: true, + }, status: { name: 'vendor.field.status', type: 'enumeration', @@ -101,7 +113,6 @@ export default { break; } }, - importable: true, }, // Billing Address billingAddress1: { diff --git a/packages/server/src/services/Contacts/Customers/CustomersImportable.ts b/packages/server/src/services/Contacts/Customers/CustomersImportable.ts index bb9d73ecc..599cfaf83 100644 --- a/packages/server/src/services/Contacts/Customers/CustomersImportable.ts +++ b/packages/server/src/services/Contacts/Customers/CustomersImportable.ts @@ -3,6 +3,7 @@ import { Importable } from '@/services/Import/Importable'; import { CreateCustomer } from './CRUD/CreateCustomer'; import { Knex } from 'knex'; import { ICustomer, ICustomerNewDTO } from '@/interfaces'; +import { CustomersSampleData } from './_SampleData'; @Service() export class CustomersImportable extends Importable { @@ -23,4 +24,11 @@ export class CustomersImportable extends Importable { ): Promise { await this.createCustomerService.createCustomer(tenantId, createDTO, trx); } + + /** + * Retrieves the sample data of customers used to download sample sheet. + */ + public sampleData(): any[] { + return CustomersSampleData; + } } diff --git a/packages/server/src/services/Contacts/Customers/_SampleData.ts b/packages/server/src/services/Contacts/Customers/_SampleData.ts new file mode 100644 index 000000000..601d845d5 --- /dev/null +++ b/packages/server/src/services/Contacts/Customers/_SampleData.ts @@ -0,0 +1,158 @@ + +export const CustomersSampleData = [ + { + "Customer Type": "Business", + "First Name": "Nicolette", + "Last Name": "Schamberger", + "Company Name": "Homenick - Hane", + "Display Name": "Rowland Rowe", + "Email": "cicero86@yahoo.com", + "Personal Phone Number": "811-603-2235", + "Work Phone Number": "906-993-5190", + "Website": "http://google.com", + "Opening Balance": 54302.23, + "Opening Balance At": "2022-02-02", + "Opening Balance Ex. Rate": 2, + "Currency": "LYD", + "Active": "F", + "Note": "Doloribus autem optio temporibus dolores mollitia sit.", + "Billing Address 1": "862 Jessika Well", + "Billing Address 2": "1091 Dorthy Mount", + "Billing Address City": "Deckowfort", + "Billing Address Country": "Ghana", + "Billing Address Phone": "825-011-5207", + "Billing Address Postcode": "38228", + "Billing Address State": "Oregon", + "Shipping Address 1": "37626 Thiel Villages", + "Shipping Address 2": "132 Batz Avenue", + "Shipping Address City": "Pagacburgh", + "Shipping Address Country": "Albania", + "Shipping Address Phone": "171-546-3701", + "Shipping Address Postcode": "13709", + "Shipping Address State": "Georgia" + }, + { + "Customer Type": "Business", + "First Name": "Hermann", + "Last Name": "Crooks", + "Company Name": "Veum - Schaefer", + "Display Name": "Harley Veum", + "Email": "immanuel56@hotmail.com", + "Personal Phone Number": "449-780-9999", + "Work Phone Number": "970-473-5785", + "Website": "http://google.com", + "Opening Balance": 54302.23, + "Opening Balance At": "2022-02-02", + "Opening Balance Ex. Rate": 2, + "Currency": "LYD", + "Active": "T", + "Note": "Doloribus dolore dolor dicta vitae in fugit nisi quibusdam.", + "Billing Address 1": "532 Simonis Spring", + "Billing Address 2": "3122 Nicolas Inlet", + "Billing Address City": "East Matteofort", + "Billing Address Country": "Holy See (Vatican City State)", + "Billing Address Phone": "366-084-8629", + "Billing Address Postcode": "41607", + "Billing Address State": "Montana", + "Shipping Address 1": "2889 Tremblay Plaza", + "Shipping Address 2": "71355 Kutch Isle", + "Shipping Address City": "D'Amorehaven", + "Shipping Address Country": "Monaco", + "Shipping Address Phone": "614-189-3328", + "Shipping Address Postcode": "09634-0435", + "Shipping Address State": "Nevada" + }, + { + "Customer Type": "Business", + "First Name": "Nellie", + "Last Name": "Gulgowski", + "Company Name": "Boyle, Heller and Jones", + "Display Name": "Randall Kohler", + "Email": "anibal_frami@yahoo.com", + "Personal Phone Number": "498-578-0740", + "Work Phone Number": "394-550-6827", + "Website": "http://google.com", + "Opening Balance": 54302.23, + "Opening Balance At": "2022-02-02", + "Opening Balance Ex. Rate": 2, + "Currency": "LYD", + "Active": "T", + "Note": "Vero quibusdam rem fugit aperiam est modi.", + "Billing Address 1": "214 Sauer Villages", + "Billing Address 2": "30687 Kacey Square", + "Billing Address City": "Jayceborough", + "Billing Address Country": "Benin", + "Billing Address Phone": "332-820-1127", + "Billing Address Postcode": "16425-3887", + "Billing Address State": "Mississippi", + "Shipping Address 1": "562 Diamond Loaf", + "Shipping Address 2": "9595 Satterfield Trafficway", + "Shipping Address City": "Alexandrinefort", + "Shipping Address Country": "Puerto Rico", + "Shipping Address Phone": "776-500-8456", + "Shipping Address Postcode": "30258", + "Shipping Address State": "South Dakota" + }, + { + "Customer Type": "Business", + "First Name": "Stone", + "Last Name": "Jerde", + "Company Name": "Cassin, Casper and Maggio", + "Display Name": "Clint McLaughlin", + "Email": "nathanael22@yahoo.com", + "Personal Phone Number": "562-790-6059", + "Work Phone Number": "686-838-0027", + "Website": "http://google.com", + "Opening Balance": 54302.23, + "Opening Balance At": "2022-02-02", + "Opening Balance Ex. Rate": 2, + "Currency": "LYD", + "Active": "F", + "Note": "Quis cumque molestias rerum.", + "Billing Address 1": "22590 Cathy Harbor", + "Billing Address 2": "24493 Brycen Brooks", + "Billing Address City": "Elnorashire", + "Billing Address Country": "Andorra", + "Billing Address Phone": "701-852-8005", + "Billing Address Postcode": "5680", + "Billing Address State": "Nevada", + "Shipping Address 1": "5355 Erdman Bridge", + "Shipping Address 2": "421 Jeanette Camp", + "Shipping Address City": "East Philip", + "Shipping Address Country": "Venezuela", + "Shipping Address Phone": "426-119-0858", + "Shipping Address Postcode": "34929-0501", + "Shipping Address State": "Tennessee" + }, + { + "Customer Type": "Individual", + "First Name": "Lempi", + "Last Name": "Kling", + "Company Name": "Schamberger, O'Connell and Bechtelar", + "Display Name": "Alexie Barton", + "Email": "eulah.kreiger@hotmail.com", + "Personal Phone Number": "745-756-1063", + "Work Phone Number": "965-150-1945", + "Website": "http://google.com", + "Opening Balance": 54302.23, + "Opening Balance At": "2022-02-02", + "Opening Balance Ex. Rate": 2, + "Currency": "LYD", + "Active": "F", + "Note": "Maxime laboriosam hic voluptate maiores est officia.", + "Billing Address 1": "0851 Jones Flat", + "Billing Address 2": "845 Bailee Drives", + "Billing Address City": "Kamrenport", + "Billing Address Country": "Niger", + "Billing Address Phone": "220-125-0608", + "Billing Address Postcode": "30311", + "Billing Address State": "Delaware", + "Shipping Address 1": "929 Ferry Row", + "Shipping Address 2": "020 Adam Plaza", + "Shipping Address City": "West Carmellaside", + "Shipping Address Country": "Ghana", + "Shipping Address Phone": "053-333-6679", + "Shipping Address Postcode": "79221-4681", + "Shipping Address State": "Illinois" + } +] diff --git a/packages/server/src/services/Contacts/Vendors/VendorsImportable.ts b/packages/server/src/services/Contacts/Vendors/VendorsImportable.ts index ce72b1ac7..67b4a57af 100644 --- a/packages/server/src/services/Contacts/Vendors/VendorsImportable.ts +++ b/packages/server/src/services/Contacts/Vendors/VendorsImportable.ts @@ -2,6 +2,7 @@ import { Importable } from '@/services/Import/Importable'; import { CreateVendor } from './CRUD/CreateVendor'; import { Knex } from 'knex'; import { Inject, Service } from 'typedi'; +import { VendorsSampleData } from './_SampleData'; @Service() export class VendorsImportable extends Importable { @@ -21,4 +22,11 @@ export class VendorsImportable extends Importable { ): Promise { await this.createVendorService.createVendor(tenantId, createDTO, trx); } + + /** + * Retrieves the sample data of vendors sample sheet. + */ + public sampleData(): any[] { + return VendorsSampleData; + } } diff --git a/packages/server/src/services/Contacts/Vendors/_SampleData.ts b/packages/server/src/services/Contacts/Vendors/_SampleData.ts new file mode 100644 index 000000000..dc88d71f9 --- /dev/null +++ b/packages/server/src/services/Contacts/Vendors/_SampleData.ts @@ -0,0 +1,122 @@ +export const VendorsSampleData = [ + { + "First Name": "Nicolette", + "Last Name": "Schamberger", + "Company Name": "Homenick - Hane", + "Display Name": "Rowland Rowe", + "Email": "cicero86@yahoo.com", + "Personal Phone Number": "811-603-2235", + "Work Phone Number": "906-993-5190", + "Website": "http://google.com", + "Opening Balance": 54302.23, + "Opening Balance At": "2022-02-02", + "Opening Balance Ex. Rate": 2, + "Currency": "LYD", + "Active": "F", + "Note": "Doloribus autem optio temporibus dolores mollitia sit.", + "Billing Address 1": "862 Jessika Well", + "Billing Address 2": "1091 Dorthy Mount", + "Billing Address City": "Deckowfort", + "Billing Address Country": "Ghana", + "Billing Address Phone": "825-011-5207", + "Billing Address Postcode": "38228", + "Billing Address State": "Oregon", + "Shipping Address 1": "37626 Thiel Villages", + "Shipping Address 2": "132 Batz Avenue", + "Shipping Address City": "Pagacburgh", + "Shipping Address Country": "Albania", + "Shipping Address Phone": "171-546-3701", + "Shipping Address Postcode": "13709", + "Shipping Address State": "Georgia" + }, + { + "First Name": "Hermann", + "Last Name": "Crooks", + "Company Name": "Veum - Schaefer", + "Display Name": "Harley Veum", + "Email": "immanuel56@hotmail.com", + "Personal Phone Number": "449-780-9999", + "Work Phone Number": "970-473-5785", + "Website": "http://google.com", + "Opening Balance": 54302.23, + "Opening Balance At": "2022-02-02", + "Opening Balance Ex. Rate": 2, + "Currency": "LYD", + "Active": "F", + "Note": "Doloribus dolore dolor dicta vitae in fugit nisi quibusdam.", + "Billing Address 1": "532 Simonis Spring", + "Billing Address 2": "3122 Nicolas Inlet", + "Billing Address City": "East Matteofort", + "Billing Address Country": "Holy See (Vatican City State)", + "Billing Address Phone": "366-084-8629", + "Billing Address Postcode": "41607", + "Billing Address State": "Montana", + "Shipping Address 1": "2889 Tremblay Plaza", + "Shipping Address 2": "71355 Kutch Isle", + "Shipping Address City": "D'Amorehaven", + "Shipping Address Country": "Monaco", + "Shipping Address Phone": "614-189-3328", + "Shipping Address Postcode": "09634-0435", + "Shipping Address State": "Nevada" + }, + { + "First Name": "Nellie", + "Last Name": "Gulgowski", + "Company Name": "Boyle, Heller and Jones", + "Display Name": "Randall Kohler", + "Email": "anibal_frami@yahoo.com", + "Personal Phone Number": "498-578-0740", + "Work Phone Number": "394-550-6827", + "Website": "http://google.com", + "Opening Balance": 54302.23, + "Opening Balance At": "2022-02-02", + "Opening Balance Ex. Rate": 2, + "Currency": "LYD", + "Active": "F", + "Note": "Vero quibusdam rem fugit aperiam est modi.", + "Billing Address 1": "214 Sauer Villages", + "Billing Address 2": "30687 Kacey Square", + "Billing Address City": "Jayceborough", + "Billing Address Country": "Benin", + "Billing Address Phone": "332-820-1127", + "Billing Address Postcode": "16425-3887", + "Billing Address State": "Mississippi", + "Shipping Address 1": "562 Diamond Loaf", + "Shipping Address 2": "9595 Satterfield Trafficway", + "Shipping Address City": "Alexandrinefort", + "Shipping Address Country": "Puerto Rico", + "Shipping Address Phone": "776-500-8456", + "Shipping Address Postcode": "30258", + "Shipping Address State": "South Dakota" + }, + { + "First Name": "Stone", + "Last Name": "Jerde", + "Company Name": "Cassin, Casper and Maggio", + "Display Name": "Clint McLaughlin", + "Email": "nathanael22@yahoo.com", + "Personal Phone Number": "562-790-6059", + "Work Phone Number": "686-838-0027", + "Website": "http://google.com", + "Opening Balance": 54302.23, + "Opening Balance At": "2022-02-02", + "Opening Balance Ex. Rate": 2, + "Currency": "LYD", + "Active": "F", + "Note": "Quis cumque molestias rerum.", + "Billing Address 1": "22590 Cathy Harbor", + "Billing Address 2": "24493 Brycen Brooks", + "Billing Address City": "Elnorashire", + "Billing Address Country": "Andorra", + "Billing Address Phone": "701-852-8005", + "Billing Address Postcode": "5680", + "Billing Address State": "Nevada", + "Shipping Address 1": "5355 Erdman Bridge", + "Shipping Address 2": "421 Jeanette Camp", + "Shipping Address City": "East Philip", + "Shipping Address Country": "Venezuela", + "Shipping Address Phone": "426-119-0858", + "Shipping Address Postcode": "34929-0501", + "Shipping Address State": "Tennessee" + } +] diff --git a/packages/server/src/services/Import/_utils.ts b/packages/server/src/services/Import/_utils.ts index 5e2e3a21c..b0de7885c 100644 --- a/packages/server/src/services/Import/_utils.ts +++ b/packages/server/src/services/Import/_utils.ts @@ -1,5 +1,5 @@ import * as Yup from 'yup'; -import { upperFirst, camelCase, first } from 'lodash'; +import { upperFirst, camelCase, first, isUndefined } from 'lodash'; import pluralize from 'pluralize'; import { ResourceMetaFieldsMap } from './interfaces'; import { IModelMetaField } from '@/interfaces'; @@ -36,13 +36,13 @@ export const convertFieldsToYupValidation = (fields: ResourceMetaFieldsMap) => { fieldSchema = Yup.string().label(field.name); if (field.fieldType === 'text') { - if (field.minLength) { + if (!isUndefined(field.minLength)) { fieldSchema = fieldSchema.min( field.minLength, `Minimum length is ${field.minLength} characters` ); } - if (field.maxLength) { + if (!isUndefined(field.maxLength)) { fieldSchema = fieldSchema.max( field.maxLength, `Maximum length is ${field.maxLength} characters` @@ -50,6 +50,13 @@ export const convertFieldsToYupValidation = (fields: ResourceMetaFieldsMap) => { } } else if (field.fieldType === 'number') { fieldSchema = Yup.number().label(field.name); + + if (!isUndefined(field.max)) { + fieldSchema = fieldSchema.max(field.max); + } + if (!isUndefined(field.min)) { + fieldSchema = fieldSchema.min(field.min); + } } else if (field.fieldType === 'boolean') { fieldSchema = Yup.boolean().label(field.name); } else if (field.fieldType === 'enumeration') { @@ -70,6 +77,8 @@ export const convertFieldsToYupValidation = (fields: ResourceMetaFieldsMap) => { return moment(val, 'YYYY-MM-DD', true).isValid(); } ); + } else if (field.fieldType === 'url') { + fieldSchema = fieldSchema.url(); } if (field.required) { fieldSchema = fieldSchema.required(); diff --git a/packages/webapp/src/containers/Import/ImportFileUploadForm.tsx b/packages/webapp/src/containers/Import/ImportFileUploadForm.tsx index 5ddf81bc5..bc0a7e1b5 100644 --- a/packages/webapp/src/containers/Import/ImportFileUploadForm.tsx +++ b/packages/webapp/src/containers/Import/ImportFileUploadForm.tsx @@ -29,8 +29,14 @@ export function ImportFileUploadForm({ formProps, }: ImportFileUploadFormProps) { const { mutateAsync: uploadImportFile } = useImportFileUpload(); - const { resource, params, setStep, setSheetColumns, setEntityColumns, setImportId } = - useImportFileContext(); + const { + resource, + params, + setStep, + setSheetColumns, + setEntityColumns, + setImportId, + } = useImportFileContext(); const handleSubmit = ( values: ImportFileUploadValues, @@ -52,7 +58,17 @@ export function ImportFileUploadForm({ setStep(ImportStepperStep.Mapping); setSubmitting(false); }) - .catch((error) => { + .catch(({ response: { data } }) => { + if ( + data.errors.find( + (er) => er.type === 'IMPORTED_FILE_EXTENSION_INVALID', + ) + ) { + AppToaster.show({ + intent: Intent.DANGER, + message: 'The extenstion of uploaded file is not supported.', + }); + } setSubmitting(false); }); };