Repository: idurar/idurar-erp-crm Branch: master Commit: 82ff5d1bcb8a Files: 429 Total size: 851.9 KB Directory structure: gitextract_uk7xy8q9/ ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.md │ │ ├── custom.md │ │ └── feature_request.md │ ├── pull_request_template.md │ └── workflows/ │ ├── CODEOWNERS │ ├── codesee-arch-diagram.yml │ └── github-repo-stats.yml ├── CODE-OF-CONDUCT.md ├── CONTRIBUTING.md ├── INSTALLATION-INSTRUCTIONS.md ├── LICENSE ├── README.md ├── SECURITY.md ├── backend/ │ ├── .eslintrc.js │ ├── .gitignore │ ├── .prettierignore │ ├── .prettierrc │ ├── .vscode/ │ │ └── settings.json │ ├── jsconfig.json │ ├── package.json │ └── src/ │ ├── app.js │ ├── controllers/ │ │ ├── appControllers/ │ │ │ ├── clientController/ │ │ │ │ ├── index.js │ │ │ │ └── summary.js │ │ │ ├── index.js │ │ │ ├── invoiceController/ │ │ │ │ ├── create.js │ │ │ │ ├── index.js │ │ │ │ ├── paginatedList.js │ │ │ │ ├── read.js │ │ │ │ ├── remove.js │ │ │ │ ├── schemaValidate.js │ │ │ │ ├── sendMail.js │ │ │ │ ├── summary.js │ │ │ │ └── update.js │ │ │ └── paymentController/ │ │ │ ├── create.js │ │ │ ├── index.js │ │ │ ├── remove.js │ │ │ ├── sendMail.js │ │ │ ├── summary.js │ │ │ └── update.js │ │ ├── coreControllers/ │ │ │ ├── adminAuth/ │ │ │ │ └── index.js │ │ │ ├── adminController/ │ │ │ │ └── index.js │ │ │ ├── settingController/ │ │ │ │ ├── index.js │ │ │ │ ├── listAll.js │ │ │ │ ├── listBySettingKey.js │ │ │ │ ├── readBySettingKey.js │ │ │ │ ├── updateBySettingKey.js │ │ │ │ └── updateManySetting.js │ │ │ └── setup.js │ │ ├── middlewaresControllers/ │ │ │ ├── createAuthMiddleware/ │ │ │ │ ├── authUser.js │ │ │ │ ├── checkAndCorrectURL.js │ │ │ │ ├── forgetPassword.js │ │ │ │ ├── index.js │ │ │ │ ├── isValidAuthToken.js │ │ │ │ ├── login.js │ │ │ │ ├── logout.js │ │ │ │ ├── resetPassword.js │ │ │ │ └── sendMail.js │ │ │ ├── createCRUDController/ │ │ │ │ ├── create.js │ │ │ │ ├── filter.js │ │ │ │ ├── index.js │ │ │ │ ├── listAll.js │ │ │ │ ├── paginatedList.js │ │ │ │ ├── read.js │ │ │ │ ├── remove.js │ │ │ │ ├── search.js │ │ │ │ ├── summary.js │ │ │ │ └── update.js │ │ │ └── createUserController/ │ │ │ ├── index.js │ │ │ ├── read.js │ │ │ ├── updatePassword.js │ │ │ ├── updateProfile.js │ │ │ └── updateProfilePassword.js │ │ └── pdfController/ │ │ └── index.js │ ├── emailTemplate/ │ │ ├── SendEmailTemplate.js │ │ └── emailVerfication.js │ ├── handlers/ │ │ ├── downloadHandler/ │ │ │ └── downloadPdf.js │ │ └── errorHandlers.js │ ├── helpers.js │ ├── locale/ │ │ ├── languages.js │ │ ├── translation/ │ │ │ └── en_us.js │ │ └── useLanguage.js │ ├── middlewares/ │ │ ├── inventory/ │ │ │ ├── generateUniqueNumber.js │ │ │ └── index.js │ │ ├── serverData.js │ │ ├── settings/ │ │ │ ├── increaseBySettingKey.js │ │ │ ├── index.js │ │ │ ├── listAllSettings.js │ │ │ ├── listBySettingKey.js │ │ │ ├── loadSettings.js │ │ │ ├── readBySettingKey.js │ │ │ └── updateBySettingKey.js │ │ └── uploadMiddleware/ │ │ ├── DoSingleStorage.js │ │ ├── LocalSingleStorage.js │ │ ├── index.js │ │ ├── singleStorageUpload.js │ │ └── utils/ │ │ ├── LocalfileFilter.js │ │ └── fileFilterMiddleware.js │ ├── models/ │ │ ├── .gitkeep │ │ ├── appModels/ │ │ │ ├── Client.js │ │ │ ├── Invoice.js │ │ │ └── Payment.js │ │ ├── coreModels/ │ │ │ ├── Admin.js │ │ │ ├── AdminPassword.js │ │ │ ├── Setting.js │ │ │ └── Upload.js │ │ └── utils/ │ │ └── index.js │ ├── pdf/ │ │ ├── Invoice.pug │ │ ├── Offer.pug │ │ ├── Payment.pug │ │ └── Quote.pug │ ├── routes/ │ │ ├── appRoutes/ │ │ │ └── appApi.js │ │ └── coreRoutes/ │ │ ├── coreApi.js │ │ ├── coreAuth.js │ │ ├── coreDownloadRouter.js │ │ └── corePublicRouter.js │ ├── server.js │ ├── settings/ │ │ ├── index.js │ │ ├── useAppSettings.js │ │ ├── useDate.js │ │ └── useMoney.js │ ├── setup/ │ │ ├── defaultSettings/ │ │ │ ├── appSettings.json │ │ │ ├── clientSettings.json │ │ │ ├── companySettings.json │ │ │ ├── financeSettings.json │ │ │ ├── invoiceSettings.json │ │ │ ├── moneyFormatSettings.json │ │ │ └── quoteSettings.json │ │ ├── reset.js │ │ ├── setup.js │ │ └── setupConfig.json │ └── utils/ │ ├── countryList.js │ ├── currency.js │ ├── currencyList.js │ └── is-path-inside.js ├── doc/ │ ├── README.fr.md │ └── README.sp.md ├── features/ │ ├── ar_eg_ملف_مفتوح_المصدر_مجاني_للبرمجيات_ERP_CRM.md │ ├── bg_bg_свободен_отворен_източник_erp_crm_софтуер.md │ ├── bn_bd_ফ্রি_ওপেন_সোর্স_ইআরপি_সিআরএম_সফটওয়্যার.md │ ├── ca_es_software_erp_crm_de_codi_obert_gratuït.md │ ├── cs_cz_volný_otevřený_zdroj_erp_crm_software.md │ ├── da_dk_gratis_åben_kilde_erp_crm_software.md │ ├── de_de_frei_offene_quelle_erp_crm_software.md │ ├── el_gr_ελεύθερο_ανοικτο_πηγαίο_erp_crm_λογισμικό.md │ ├── en_us_free_open_source_erp_crm_software.md │ ├── es_es_software_erp_crm_de_código_abierto_y_gratis.md │ ├── et_ee_tasuta_avatud_lähtekoodiga_erp_crm_tarkvara.md │ ├── fa_ir_رایگان_منبع_باز_نرم‌افزار_مدیریت_مالی_و_ارتباطات.md │ ├── fi_fi_ilmainen_avoin_lähdekoodi_erp_crm_ohjelmisto.md │ ├── fr_fr_gratuit_logiciel_erp_crm_open_source.md │ ├── hi_in_मुफ्त_खुला_स्रोत_ईआरपी_सीआरएम_सॉफ़्टवेयर.md │ ├── hr_hr_besplatni_otvoreni_izvor_erp_crm_softver.md │ ├── hu_hu_ingyenes_nyílt_forráskódú_erp_crm_szoftver.md │ ├── id_id_perangkat_lunak_erp_crm_sumber_terbuka_gratis.md │ ├── it_it_software_erp_crm_open_source_gratuito.md │ ├── ja_jp_フリーオープンソースERP CRMソフトウェア.md │ ├── ko_kr_자유_오픈_소스_ERP_CRM_소프트웨어.md │ ├── lt_lt_nemokamas_atviras_kodo_erp_crm_programinė_įranga.md │ ├── lv_lv_bezmaksas_atvērtā_koda_erp_crm_programmatūra.md │ ├── mk_mk_фрее_опен_сорсе_ерп_црм_софтвер.md │ ├── ms_my_fail_terbuka_sumber_erp_crm_perisian.md │ ├── nb_no_gratis_åpen_kilde_erp_crm_programvare.md │ ├── nl_nl_vrije_open_source_erp_crm_software.md │ ├── pl_pl_bezpłatne_otwarte_źródło_erp_crm_oprogramowanie.md │ ├── pt_br_software_de_erp_e_crm_de_código_aberto_gratuito.md │ ├── pt_pt_software_de_erp_crm_de_código_aberto_gratuito.md │ ├── ro_ro_software_erp_crm_open_source_gratuit.md │ ├── ru_ru_бесплатное_открытое_программное_обеспечение_erp_crm.md │ ├── sk_sk_zdarma_otvorene_zdrojove_erp_crm_software.md │ ├── sl_si_brezplačni_odprtokodni_erp_crm_programski_oprema.md │ ├── sr_rs_besplatni_otvoreni_izvor_erp_crm_softver.md │ ├── sv_se_fri_öppen_källkods_erp_crm_programvara.md │ ├── th_th_ฟรี_โปรแกรม_ตัวจัดการแหล่งข้อมูลโปรแกรม_ERP_CRM.md │ ├── tr_tr_ücretsiz_açık_kaynak_erp_crm_yazılımı.md │ ├── uk_ua_безкоштовне_відкрите_джерело_erp_crm_програмне_забезпечення.md │ ├── ur_pk_مفت_کھولیں_سورس_erp_crm_سافٹ ویئر.md │ ├── vi_vn_chương_trình_quản_lý_doanh_nghiệp_crm_nguồn_mở_miễn_phí.md │ └── zh_cn_免费开源ERP CRM软件.md └── frontend/ ├── .eslintrc.js ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .vscode/ │ └── settings.json ├── README.md ├── index.html ├── jsconfig.json ├── package.json ├── public/ │ └── robots.txt ├── rollup.config.js ├── src/ │ ├── RootApp.jsx │ ├── apps/ │ │ ├── ErpApp.jsx │ │ ├── Header/ │ │ │ ├── HeaderContainer.jsx │ │ │ └── UpgradeButton.jsx │ │ ├── IdurarOs.jsx │ │ └── Navigation/ │ │ └── NavigationContainer.jsx │ ├── auth/ │ │ ├── auth.service.js │ │ └── index.js │ ├── components/ │ │ ├── AutoCompleteAsync/ │ │ │ └── index.jsx │ │ ├── CollapseBox/ │ │ │ └── index.jsx │ │ ├── CreateForm/ │ │ │ └── index.jsx │ │ ├── CrudModal/ │ │ │ └── index.jsx │ │ ├── DataTable/ │ │ │ └── DataTable.jsx │ │ ├── DeleteModal/ │ │ │ └── index.jsx │ │ ├── IconMenu/ │ │ │ └── index.jsx │ │ ├── Loading/ │ │ │ └── index.jsx │ │ ├── MoneyInputFormItem/ │ │ │ └── index.jsx │ │ ├── MultiStepSelectAsync/ │ │ │ └── index.jsx │ │ ├── NotFound/ │ │ │ └── index.jsx │ │ ├── Notification/ │ │ │ └── index.jsx │ │ ├── PageLoader/ │ │ │ └── index.jsx │ │ ├── ReadItem/ │ │ │ └── index.jsx │ │ ├── SearchItem/ │ │ │ └── index.jsx │ │ ├── SelectAsync/ │ │ │ └── index.jsx │ │ ├── SelectTag/ │ │ │ └── index.jsx │ │ ├── SidePanel/ │ │ │ └── index.jsx │ │ ├── TabsContent/ │ │ │ └── TabsContent.jsx │ │ ├── Tag/ │ │ │ └── index.jsx │ │ ├── UpdateForm/ │ │ │ └── index.jsx │ │ ├── Visibility/ │ │ │ └── index.jsx │ │ └── outsideClick.js/ │ │ ├── demo.js │ │ └── index.js │ ├── config/ │ │ └── serverApiConfig.js │ ├── context/ │ │ ├── adavancedCrud/ │ │ │ ├── actions.jsx │ │ │ ├── index.jsx │ │ │ ├── reducer.jsx │ │ │ ├── selectors.jsx │ │ │ └── types.jsx │ │ ├── appContext/ │ │ │ ├── actions.jsx │ │ │ ├── index.jsx │ │ │ ├── reducer.jsx │ │ │ └── types.jsx │ │ ├── crud/ │ │ │ ├── actions.jsx │ │ │ ├── index.jsx │ │ │ ├── reducer.jsx │ │ │ ├── selectors.jsx │ │ │ └── types.jsx │ │ ├── erp/ │ │ │ ├── actions.jsx │ │ │ ├── index.jsx │ │ │ ├── reducer.jsx │ │ │ ├── selectors.jsx │ │ │ └── types.jsx │ │ └── profileContext/ │ │ ├── actions.jsx │ │ ├── index.jsx │ │ ├── reducer.jsx │ │ ├── selectors.jsx │ │ └── types.jsx │ ├── forms/ │ │ ├── AdminForm.jsx │ │ ├── AdvancedSettingsForm.jsx │ │ ├── CurrencyForm.jsx │ │ ├── CustomerForm.jsx │ │ ├── DynamicForm/ │ │ │ └── index.jsx │ │ ├── EmployeeForm.jsx │ │ ├── ForgetPasswordForm.jsx │ │ ├── InventoryForm.jsx │ │ ├── LeadForm.jsx │ │ ├── LoginForm.jsx │ │ ├── OrderForm.jsx │ │ ├── PaymentForm.jsx │ │ ├── PaymentModeForm.jsx │ │ ├── RegisterForm.jsx │ │ ├── ResetPasswordForm.jsx │ │ ├── TaxForm.jsx │ │ └── UpdateEmail.jsx │ ├── hooks/ │ │ ├── useDebounce.jsx │ │ ├── useFetch.jsx │ │ ├── useMail.jsx │ │ ├── useNetwork.jsx │ │ ├── useOnFetch.jsx │ │ ├── useResponsive.jsx │ │ └── useTimeoutFn.jsx │ ├── layout/ │ │ ├── AuthLayout/ │ │ │ └── index.jsx │ │ ├── CrudLayout/ │ │ │ └── index.jsx │ │ ├── DashboardLayout/ │ │ │ └── index.jsx │ │ ├── DefaultLayout/ │ │ │ └── index.jsx │ │ ├── ErpLayout/ │ │ │ └── index.jsx │ │ ├── Footer/ │ │ │ └── index.jsx │ │ ├── ProfileLayout/ │ │ │ └── index.jsx │ │ ├── SettingsLayout/ │ │ │ └── index.jsx │ │ └── index.jsx │ ├── locale/ │ │ ├── Localization.jsx │ │ ├── antdLocale.js │ │ ├── coreTranslation.js │ │ ├── translation/ │ │ │ ├── en_us.js │ │ │ ├── otherTranslation.js │ │ │ └── translation.js │ │ └── useLanguage.jsx │ ├── main.jsx │ ├── modules/ │ │ ├── AuthModule/ │ │ │ ├── SideContent.jsx │ │ │ └── index.jsx │ │ ├── CrudModule/ │ │ │ └── CrudModule.jsx │ │ ├── DashboardModule/ │ │ │ ├── components/ │ │ │ │ ├── CustomerPreviewCard.jsx │ │ │ │ ├── PreviewCard.jsx │ │ │ │ ├── RecentTable/ │ │ │ │ │ └── index.jsx │ │ │ │ └── SummaryCard.jsx │ │ │ └── index.jsx │ │ ├── ErpPanelModule/ │ │ │ ├── CreateItem.jsx │ │ │ ├── DataTable.jsx │ │ │ ├── DeleteItem.jsx │ │ │ ├── ItemRow.jsx │ │ │ ├── ReadItem.jsx │ │ │ ├── SearchItem.jsx │ │ │ ├── UpdateItem.jsx │ │ │ └── index.jsx │ │ ├── InvoiceModule/ │ │ │ ├── CreateInvoiceModule/ │ │ │ │ └── index.jsx │ │ │ ├── Forms/ │ │ │ │ └── InvoiceForm.jsx │ │ │ ├── InvoiceDataTableModule/ │ │ │ │ └── index.jsx │ │ │ ├── ReadInvoiceModule/ │ │ │ │ └── index.jsx │ │ │ ├── RecordPaymentModule/ │ │ │ │ ├── components/ │ │ │ │ │ ├── Payment.jsx │ │ │ │ │ └── RecordPayment.jsx │ │ │ │ └── index.jsx │ │ │ └── UpdateInvoiceModule/ │ │ │ └── index.jsx │ │ ├── PaymentModule/ │ │ │ ├── PaymentDataTableModule/ │ │ │ │ └── index.jsx │ │ │ ├── ReadPaymentModule/ │ │ │ │ ├── components/ │ │ │ │ │ └── ReadItem.jsx │ │ │ │ └── index.jsx │ │ │ └── UpdatePaymentModule/ │ │ │ ├── components/ │ │ │ │ ├── Payment.jsx │ │ │ │ └── UpdatePayment.jsx │ │ │ └── index.jsx │ │ ├── ProfileModule/ │ │ │ ├── components/ │ │ │ │ ├── AdminInfo.jsx │ │ │ │ ├── PasswordModal.jsx │ │ │ │ ├── Profile.jsx │ │ │ │ ├── ProfileAdminForm.jsx │ │ │ │ ├── UpdateAdmin.jsx │ │ │ │ └── UploadImg.jsx │ │ │ └── index.jsx │ │ ├── QuoteModule/ │ │ │ ├── CreateQuoteModule/ │ │ │ │ └── index.jsx │ │ │ ├── Forms/ │ │ │ │ └── QuoteForm.jsx │ │ │ ├── QuoteDataTableModule/ │ │ │ │ └── index.jsx │ │ │ ├── ReadQuoteModule/ │ │ │ │ └── index.jsx │ │ │ └── UpdateQuoteModule/ │ │ │ └── index.jsx │ │ └── SettingModule/ │ │ ├── CompanyLogoSettingsModule/ │ │ │ ├── forms/ │ │ │ │ └── AppSettingForm.jsx │ │ │ └── index.jsx │ │ ├── CompanySettingsModule/ │ │ │ ├── SettingsForm.jsx │ │ │ └── index.jsx │ │ ├── FinanceSettingsModule/ │ │ │ ├── SettingsForm.jsx │ │ │ └── index.jsx │ │ ├── GeneralSettingsModule/ │ │ │ ├── forms/ │ │ │ │ └── GeneralSettingForm.jsx │ │ │ └── index.jsx │ │ ├── MoneyFormatSettingsModule/ │ │ │ ├── SettingsForm.jsx │ │ │ └── index.jsx │ │ └── components/ │ │ ├── SetingsSection.jsx │ │ ├── UpdateSettingForm.jsx │ │ └── UpdateSettingModule.jsx │ ├── pages/ │ │ ├── About.jsx │ │ ├── Customer/ │ │ │ ├── config.js │ │ │ └── index.jsx │ │ ├── ForgetPassword.jsx │ │ ├── Invoice/ │ │ │ ├── InvoiceCreate.jsx │ │ │ ├── InvoiceRead.jsx │ │ │ ├── InvoiceRecordPayment.jsx │ │ │ ├── InvoiceUpdate.jsx │ │ │ └── index.jsx │ │ ├── Login.jsx │ │ ├── Logout.jsx │ │ ├── NotFound.jsx │ │ ├── Payment/ │ │ │ ├── PaymentRead.jsx │ │ │ ├── PaymentUpdate.jsx │ │ │ └── index.jsx │ │ ├── Profile.jsx │ │ ├── ResetPassword.jsx │ │ └── Settings/ │ │ ├── CompanyLogoSettings.jsx │ │ ├── CompanySettings.jsx │ │ ├── FinanceSettings.jsx │ │ ├── GeneralSettings.jsx │ │ ├── MoneyFormatSettings.jsx │ │ └── Settings.jsx │ ├── redux/ │ │ ├── adavancedCrud/ │ │ │ ├── actions.js │ │ │ ├── index.js │ │ │ ├── reducer.js │ │ │ ├── selectors.js │ │ │ └── types.js │ │ ├── auth/ │ │ │ ├── actions.js │ │ │ ├── index.js │ │ │ ├── reducer.js │ │ │ ├── selectors.js │ │ │ └── types.js │ │ ├── crud/ │ │ │ ├── actions.js │ │ │ ├── index.js │ │ │ ├── reducer.js │ │ │ ├── selectors.js │ │ │ └── types.js │ │ ├── erp/ │ │ │ ├── actions.js │ │ │ ├── index.js │ │ │ ├── reducer.js │ │ │ ├── selectors.js │ │ │ └── types.js │ │ ├── rootReducer.js │ │ ├── settings/ │ │ │ ├── actions.js │ │ │ ├── index.js │ │ │ ├── reducer.js │ │ │ ├── selectors.js │ │ │ └── types.js │ │ ├── store.js │ │ └── storePersist.js │ ├── request/ │ │ ├── checkImage.js │ │ ├── codeMessage.js │ │ ├── errorHandler.js │ │ ├── index.js │ │ ├── request.js │ │ └── successHandler.js │ ├── router/ │ │ ├── AppRouter.jsx │ │ ├── AuthRouter.jsx │ │ └── routes.jsx │ ├── settings/ │ │ ├── index.jsx │ │ ├── useDate.jsx │ │ └── useMoney.jsx │ ├── style/ │ │ ├── app.css │ │ └── partials/ │ │ ├── auth.css │ │ ├── collapseBox.css │ │ ├── core.css │ │ ├── customAntd.css │ │ ├── erp.css │ │ ├── header.css │ │ ├── layout.css │ │ ├── navigation.css │ │ ├── rest.css │ │ ├── sidePanel.css │ │ └── transition.css │ └── utils/ │ ├── calculate.js │ ├── color.js │ ├── countryList.js │ ├── currencyList.js │ ├── dataStructure.jsx │ ├── helpers.js │ ├── isBrowser.js │ ├── statusTagColor.js │ ├── tagColor.js │ └── valueType.js ├── temp.env └── vite.config.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.md ================================================ --- name: Bug report about: Create a report to help us improve title: '' labels: '' assignees: '' --- **Describe the bug** A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error **Expected behavior** A clear and concise description of what you expected to happen. **Screenshots** If applicable, add screenshots to help explain your problem. **Desktop (please complete the following information):** - OS: [e.g. iOS] - Browser [e.g. chrome, safari] - Version [e.g. 22] **Smartphone (please complete the following information):** - Device: [e.g. iPhone6] - OS: [e.g. iOS8.1] - Browser [e.g. stock browser, safari] - Version [e.g. 22] **Additional context** Add any other context about the problem here. ================================================ FILE: .github/ISSUE_TEMPLATE/custom.md ================================================ --- name: Custom issue template about: Describe this issue template's purpose here. title: '' labels: '' assignees: '' --- ================================================ FILE: .github/ISSUE_TEMPLATE/feature_request.md ================================================ --- name: Feature request about: Suggest an idea for this project title: '' labels: '' assignees: '' --- **Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] **Describe the solution you'd like** A clear and concise description of what you want to happen. **Describe alternatives you've considered** A clear and concise description of any alternative solutions or features you've considered. **Additional context** Add any other context or screenshots about the feature request here. ================================================ FILE: .github/pull_request_template.md ================================================ ## Description Please provide a brief description of the changes or additions made in this pull request. ## Related Issues If this pull request is related to any issue(s), please list them here. ## Steps to Test Provide steps on how to test the changes introduced in this pull request. ## Screenshots (if applicable) If your changes include visual updates, it would be helpful to provide screenshots of the before and after. ## Checklist - [ ] I have tested these changes - [ ] I have updated the relevant documentation - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the codebase - [ ] My changes generate no new warnings or errors - [ ] The title of my pull request is clear and descriptive ================================================ FILE: .github/workflows/CODEOWNERS ================================================ # Default reviewers * @salahlalami @polymahh @onfranciis @Ando22 @Fernando7181 ================================================ FILE: .github/workflows/codesee-arch-diagram.yml ================================================ # This workflow was added by CodeSee. Learn more at https://codesee.io/ # This is v2.0 of this workflow file on: push: branches: - master pull_request_target: types: [opened, synchronize, reopened] name: CodeSee permissions: read-all jobs: codesee: runs-on: ubuntu-latest continue-on-error: true name: Analyze the repo with CodeSee steps: - uses: Codesee-io/codesee-action@v2 with: codesee-token: ${{ secrets.CODESEE_ARCH_DIAG_API_TOKEN }} codesee-url: https://app.codesee.io ================================================ FILE: .github/workflows/github-repo-stats.yml ================================================ name: github-repo-stats on: schedule: # Run this once per day, towards the end of the day for keeping the most # recent data point most meaningful (hours are interpreted in UTC). - cron: "50 23 * * *" workflow_dispatch: # Allow for running this manually. jobs: j1: name: github-repo-stats runs-on: ubuntu-latest steps: - name: run-ghrs # Use latest release. uses: jgehrcke/github-repo-stats@RELEASE with: ghtoken: ${{ secrets.ghrs_github_api_token }} ================================================ FILE: CODE-OF-CONDUCT.md ================================================ # Contributor Covenant Code of Conduct ## Our Pledge We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. ## Our Standards Examples of behavior that contributes to a positive environment for our community include: * Demonstrating empathy and kindness toward other people * Being respectful of differing opinions, viewpoints, and experiences * Giving and gracefully accepting constructive feedback * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience * Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: * The use of sexualized language or imagery, and sexual attention or advances of any kind * Trolling, insulting or derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or email address, without their explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. ## Scope This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at 50052356+idurar@users.noreply.github.com. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident. ## Enforcement Guidelines Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: ### 1. Correction **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. ### 2. Warning **Community Impact**: A violation through a single incident or series of actions. **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. ### 3. Temporary Ban **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. ### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within the community. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations. ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing Guidelines Welcome to the [idurar-erp-crm](<[idurar-erp-crm](https://github.com/idurar/idurar-erp-crm)>) repository! We're excited that you're interested in contributing. Please take a moment to review this document to ensure a smooth collaboration process. ## How to Contribute ### Reporting Issues If you find a bug or have a suggestion for an enhancement : - please make sure it was not asked before here [issues](https://github.com/idurar/idurar-erp-crm/issues). - make sure it is not work in progress here [pull requests](https://github.com/idurar/idurar-erp-crm/pulls). - you can then [create an issue](https://github.com/idurar/idurar-erp-crm/issues/new/choose) with the following information: - a short but descriptive title. - a detailed description of the issue or suggestion (if it is a bug include the steps to reproduce it). ### working on issues - comment on issues you want to work on and we will assign you to it. - we do accept pull requests even if you are not assigned to an issue but we prefer you to comment on the issue first. ### Submitting Pull Requests 1. Fork the repository and create your own branch from `dev` branch. 2. follow this format for naming branches: - `features/new-profile-page` - `issues/fix-authentication-issue` 3. Make sure your code follows our [Coding Guidelines](#coding-guidelines). 4. Commit your changes using clear and descriptive commit messages . 5. Push your changes to your forked repository. 6. Submit a pull request to the `dev` branch of this repository. Please include a detailed description of your changes. We'll review your pull request as soon as possible. Feedback and suggestions are always welcome. ### Commit Guidelines Commits should be as small as possible, while ensuring that each commit is correct independently (i.e., each commit should compile and pass tests). Please follow this commit format for your commit messages: - `feat: add new profile page` - `fix: resolve authentication issue` ### Coding Guidelines - Use consistent coding style and follow best practices for readability. - Write clear and concise code comments. - Don't update dependencies (antd, redux, craco ... ) as it might break the project( we will update all dependencies soon ). - Do not include changes that are not related to the issue at hand. - Ensure your code has no conflicts and follows existing patterns. ### Questions If you have any questions, feel free to reach out by creating an issue. Thank you for contributing to [idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) dont forget to give us a :star: ! ================================================ FILE: INSTALLATION-INSTRUCTIONS.md ================================================ ## Getting started #### Step 1: Clone the repository ```bash git clone https://github.com/idurar/idurar-erp-crm.git ``` ```bash cd idurar-erp-crm ``` #### Step 2: Create Your MongoDB Account and Database Cluster - Create your own MongoDB account by visiting the MongoDB website and signing up for a new account. - Create a new database or cluster by following the instructions provided in the MongoDB documentation. Remember to note down the "Connect to your application URI" for the database, as you will need it later. Also, make sure to change `` with your own password - add your current IP address to the MongoDB database's IP whitelist to allow connections (this is needed whenever your ip changes) #### Step 3: Edit the Environment File - Check a file named .env in the /backend directory. This file will store environment variables for the project to run. #### Step 4: Update MongoDB URI In the .env file, find the line that reads: `DATABASE="your-mongodb-uri"` Replace "your-mongodb-uri" with the actual URI of your MongoDB database. #### Step 5: Install Backend Dependencies In your terminal, navigate to the /backend directory ```bash cd backend ``` the urn the following command to install the backend dependencies: ```bash npm install ``` This command will install all the required packages specified in the package.json file. #### Step 6: Run Setup Script While still in the /backend directory of the project, execute the following command to run the setup script: ```bash npm run setup ``` This setup script may perform necessary database migrations or any other initialization tasks required for the project. #### Step 7: Run the Backend Server In the same terminal, run the following command to start the backend server: ```bash npm run dev ``` This command will start the backend server, and it will listen for incoming requests. #### Step 8: Install Frontend Dependencies Open a new terminal window , and run the following command to install the frontend dependencies: ```bash cd frontend ``` ```bash npm install ``` #### Step 9: Run the Frontend Server After installing the frontend dependencies, run the following command in the same terminal to start the frontend server: ```bash npm run dev ``` This command will start the frontend server, and you'll be able to access the website on localhost:3000 in your web browser. :exclamation: :warning:` If you encounter an OpenSSL error while running the frontend server, follow these additional steps:` Reason behind error: This is caused by the node.js V17 compatible issues with OpenSSL, see [this](https://github.com/nodejs/node/issues/40547) and [this](https://github.com/webpack/webpack/issues/14532) issue on GitHub. Try one of these and error will be solved - > upgrade to Node.js v20. - > Enable legacy OpenSSL provider Here is how you can enable legacy OpenSSL provider - On Unix-like (Linux, macOS, Git bash, etc.) ```bash export NODE_OPTIONS=--openssl-legacy-provider ``` - On Windows command prompt: ```bash set NODE_OPTIONS=--openssl-legacy-provider ``` - On PowerShell: ```bash $env:NODE_OPTIONS = "--openssl-legacy-provider" ``` Here is [reference](https://github.com/webpack/webpack/issues/14532#issuecomment-947012063) about enabling legacy OpenSSL provider After trying above solutions, run below command ```bash npm run dev ``` > If you still facing issue, then follow [this stackoverflow thread](https://stackoverflow.com/questions/69692842/error-message-error0308010cdigital-envelope-routinesunsupported). It has so many different types of opinions. You definitely have solution after going through the thread. ================================================ FILE: LICENSE ================================================ GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU Affero General Public License is a free, copyleft license for software and other kinds of works, specifically designed to ensure cooperation with the community in the case of network server software. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, our General Public Licenses are intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. Developers that use our General Public Licenses protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License which gives you legal permission to copy, distribute and/or modify the software. A secondary benefit of defending all users' freedom is that improvements made in alternate versions of the program, if they receive widespread use, become available for other developers to incorporate. Many developers of free software are heartened and encouraged by the resulting cooperation. However, in the case of software used on network servers, this result may fail to come about. The GNU General Public License permits making a modified version and letting the public access it on a server without ever releasing its source code to the public. The GNU Affero General Public License is designed specifically to ensure that, in such cases, the modified source code becomes available to the community. It requires the operator of a network server to provide the source code of the modified version running there to the users of that server. Therefore, public use of a modified version, on a publicly accessible server, gives the public access to the source code of the modified version. An older license, called the Affero General Public License and published by Affero, was designed to accomplish similar goals. This is a different license, not a version of the Affero GPL, but Affero has released a new version of the Affero GPL which permits relicensing under this license. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU Affero General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Remote Network Interaction; Use with the GNU General Public License. Notwithstanding any other provision of this License, if you modify the Program, your modified version must prominently offer all users interacting with it remotely through a computer network (if your version supports such interaction) an opportunity to receive the Corresponding Source of your version by providing access to the Corresponding Source from a network server at no charge, through some standard or customary means of facilitating copying of software. This Corresponding Source shall include the Corresponding Source for any work covered by version 3 of the GNU General Public License that is incorporated pursuant to the following paragraph. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the work with which it is combined will remain governed by version 3 of the GNU General Public License. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU Affero General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU Affero General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU Affero General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU Affero General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If your software can interact with users remotely through a computer network, you should also make sure that it provides a way for users to get its source. For example, if your program is a web application, its interface could display a "Source" link that leads users to an archive of the code. There are many ways you could offer source, and different solutions will be better for different programs; see section 13 for the specific requirements. You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU AGPL, see . ================================================ FILE: README.md ================================================

Open Source ERP / CRM Accounting Invoice Quote

IDURAR ERP CRM | Simple To Use

``` Give a Star ⭐️ & Fork to this project ... Happy coding! 🤩` ``` IDURAR is Open Source ERP / CRM (Invoice / Quote / Accounting ) Based on Advanced Mern Stack (Node.js / Express.js / MongoDb / React.js ) with Ant Design (AntD) and Redux
**🚀 Self-hosted Entreprise Version** : [https://cloud.idurarapp.com](https://cloud.idurarapp.com) ## Features : Invoice Management Payment Management Quote Management Customer Management Ant Design Framework(AntD) 🐜 Based on Mern Stack (Node.js / Express.js / MongoDb / React.js ) 👨‍💻 ### May i can use IDURAR for Commercial use : - Yes You can use IDURAR for free for personal or Commercial use. ## Our Sponsors # Open Source ERP CRM ## Free Open Source ERP / CRM App IDURAR is Open "Fair-Code" Source ERP / CRM (Invoice / Inventory / Accounting / HR) Based on Mern Stack (Node.js / Express.js / MongoDb / React.js ) with Ant Design (AntD) and Redux ## Getting started 1.[Clone the repository](INSTALLATION-INSTRUCTIONS.md#step-1-clone-the-repository) 2.[Create Your MongoDB Account and Database Cluster](INSTALLATION-INSTRUCTIONS.md#Step-2-Create-Your-MongoDB-Account-and-Database-Cluster) 3.[Edit the Environment File](INSTALLATION-INSTRUCTIONS.md#Step-3-Edit-the-Environment-File) 4.[Update MongoDB URI](INSTALLATION-INSTRUCTIONS.md#Step-4-Update-MongoDB-URI) 5.[Install Backend Dependencies](INSTALLATION-INSTRUCTIONS.md#Step-5-Install-Backend-Dependencies) 6.[Run Setup Script](INSTALLATION-INSTRUCTIONS.md#Step-6-Run-Setup-Script) 7.[Run the Backend Server](INSTALLATION-INSTRUCTIONS.md#Step-7-Run-the-Backend-Server) 8.[Install Frontend Dependencies](INSTALLATION-INSTRUCTIONS.md#Step-8-Install-Frontend-Dependencies) 9.[Run the Frontend Server](INSTALLATION-INSTRUCTIONS.md#Step-9-Run-the-Frontend-Server) ## Contributing 1.[How to contribute](https://github.com/idurar/idurar-erp-crm/blob/master/CONTRIBUTING.md#how-to-contribute) 2.[Reporting issues](https://github.com/idurar/idurar-erp-crm/blob/master/CONTRIBUTING.md#reporting-issues) 3.[Working on issues ](https://github.com/idurar/idurar-erp-crm/blob/master/CONTRIBUTING.md#working-on-issues) 4.[Submitting pull requests](https://github.com/idurar/idurar-erp-crm/blob/master/CONTRIBUTING.md#submitting-pull-requests) 5.[Commit Guidelines](https://github.com/idurar/idurar-erp-crm/blob/master/CONTRIBUTING.md#commit-guidelines) 6.[Coding Guidelines](https://github.com/idurar/idurar-erp-crm/blob/master/CONTRIBUTING.md#coding-guidelines) 7.[Questions](https://github.com/idurar/idurar-erp-crm/blob/master/CONTRIBUTING.md#questions) ## Show your support Dont forget to give a ⭐️ to this project ... Happy coding! **🚀 Self-hosted Entreprise Version** : [https://cloud.idurarapp.com](https://cloud.idurarapp.com) ## License IDURAR is Free Open Source Released under the GNU Affero General Public License v3.0. ================================================ FILE: SECURITY.md ================================================ # Security Policy ## Supported Releases | Version | Supported | | ------- | ------------------ | | 2.0.1 | :white_check_mark: | | 2.0.0 | :white_check_mark: | ## Reporting a Vulnerability Please do not open public github issues or pull requests on this repository for security-related matters. Instead, follow the responsible disclosure process outlined below. ### Scope This security policy covers the security of this repository and its code. If you discover a security vulnerability related to this repository, please report it responsibly. ### Responsible Disclosure Process #### Option 1: Reporting via Github Security Advisors 1. **Contact Us**: Submit your report to [https://github.com/idurar/idurar-erp-crm/security](https://github.com/idurar/idurar-erp-crm/security) with details of the vulnerability. Please provide a clear and concise description of the issue, any potential impact, and a step-by-step demonstration if possible. Please do not include sensitive information in your initial email. 2. **Confirmation**: We will acknowledge receipt of your report within [X] business days and provide an estimated timeline for when you can expect a response. 3. **Investigation**: We will investigate the issue, which may involve reproducing the vulnerability or seeking further information from you. 4. **Resolution**: Once the vulnerability is confirmed, we will work to address it promptly and develop a fix. 5. **Disclosure**: We will coordinate with you regarding the public disclosure of the vulnerability. We aim to release a security advisory with information about the issue and the fix. ### Safe Harbor We consider security research conducted under this policy to be: - Authorized concerning any applicable anti-hacking laws, and we won't initiate legal action against researchers for their findings. - Subject to responsible disclosure, where we work with researchers to understand and address reported vulnerabilities before public disclosure. We appreciate your contributions to the security of this project and community. Thank you! ================================================ FILE: backend/.eslintrc.js ================================================ module.exports = { env: { browser: true, es2020: true, node: true, }, extends: 'eslint:recommended', parserOptions: { ecmaVersion: 12, sourceType: 'module', }, rules: { 'no-console': 0, }, }; ================================================ FILE: backend/.gitignore ================================================ node_modules/ *.zip .DS_Store .idea notes.md .env.local *.pdf ================================================ FILE: backend/.prettierignore ================================================ # Ignore artifacts: build coverage node_modules ================================================ FILE: backend/.prettierrc ================================================ { "printWidth": 100, "trailingComma": "es5", "tabWidth": 2, "semi": true, "singleQuote": true } ================================================ FILE: backend/.vscode/settings.json ================================================ { "editor.formatOnPaste": true, "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode", "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, "[jsonc]": { "editor.defaultFormatter": "esbenp.prettier-vscode" } } ================================================ FILE: backend/jsconfig.json ================================================ { "compilerOptions": { "baseUrl": "src", "paths": { "@/*": ["./*"] } }, "exclude": ["node_modules"] } ================================================ FILE: backend/package.json ================================================ { "name": "idurar-erp-crm", "version": "4.1.0", "engines": { "npm": "10.2.4", "node": "20.9.0" }, "scripts": { "start": "node src/server.js", "dev": "nodemon src/server.js --ignore public/", "production": "NODE_ENV=production", "setup": "node src/setup/setup.js", "upgrade": "node src/setup/upgrade.js", "reset": "node src/setup/reset.js" }, "dependencies": { "@aws-sdk/client-s3": "^3.509.0", "bcryptjs": "^2.4.3", "compression": "^1.7.4", "cookie-parser": "^1.4.6", "cors": "^2.8.5", "currency.js": "2.0.4", "dotenv": "16.3.1", "express": "^4.18.2", "express-fileupload": "^1.4.3", "express-rate-limit": "^7.1.5", "glob": "10.3.10", "html-pdf": "^3.0.1", "joi": "^17.11.0", "jsonwebtoken": "^9.0.2", "lodash": "^4.17.21", "module-alias": "^2.2.3", "moment": "^2.30.1", "mongoose": "^8.1.1", "mongoose-autopopulate": "^1.1.0", "multer": "^1.4.4", "node-cache": "^5.1.2", "openai": "^4.27.0", "pug": "^3.0.2", "resend": "^2.0.0", "shortid": "^2.2.16", "transliteration": "^2.3.5" }, "devDependencies": { "nodemon": "3.0.1" }, "_moduleAliases": { "@": "src" }, "main": "server.js", "author": "IDURAR", "email": "hello@idurarapp.com", "license": "Fair-code License", "repository": { "type": "git", "url": "git+https://github.com/idurar/idurar-erp-crm/.git" }, "bugs": { "url": "https://github.com/idurar/idurar-erp-crm//issues" }, "homepage": "https://github.com/idurar/idurar-erp-crm/#readme" } ================================================ FILE: backend/src/app.js ================================================ const express = require('express'); const cors = require('cors'); const compression = require('compression'); const cookieParser = require('cookie-parser'); const coreAuthRouter = require('./routes/coreRoutes/coreAuth'); const coreApiRouter = require('./routes/coreRoutes/coreApi'); const coreDownloadRouter = require('./routes/coreRoutes/coreDownloadRouter'); const corePublicRouter = require('./routes/coreRoutes/corePublicRouter'); const adminAuth = require('./controllers/coreControllers/adminAuth'); const errorHandlers = require('./handlers/errorHandlers'); const erpApiRouter = require('./routes/appRoutes/appApi'); const fileUpload = require('express-fileupload'); // create our Express app const app = express(); app.use( cors({ origin: true, credentials: true, }) ); app.use(cookieParser()); app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.use(compression()); // // default options // app.use(fileUpload()); // Here our API Routes app.use('/api', coreAuthRouter); app.use('/api', adminAuth.isValidAuthToken, coreApiRouter); app.use('/api', adminAuth.isValidAuthToken, erpApiRouter); app.use('/download', coreDownloadRouter); app.use('/public', corePublicRouter); // If that above routes didnt work, we 404 them and forward to error handler app.use(errorHandlers.notFound); // production error handler app.use(errorHandlers.productionErrors); // done! we export it so we can start the site in start.js module.exports = app; ================================================ FILE: backend/src/controllers/appControllers/clientController/index.js ================================================ const mongoose = require('mongoose'); const createCRUDController = require('@/controllers/middlewaresControllers/createCRUDController'); const summary = require('./summary'); function modelController() { const Model = mongoose.model('Client'); const methods = createCRUDController('Client'); methods.summary = (req, res) => summary(Model, req, res); return methods; } module.exports = modelController(); ================================================ FILE: backend/src/controllers/appControllers/clientController/summary.js ================================================ const mongoose = require('mongoose'); const moment = require('moment'); const InvoiceModel = mongoose.model('Invoice'); const summary = async (Model, req, res) => { let defaultType = 'month'; const { type } = req.query; if (type && ['week', 'month', 'year'].includes(type)) { defaultType = type; } else if (type) { return res.status(400).json({ success: false, result: null, message: 'Invalid type', }); } const currentDate = moment(); let startDate = currentDate.clone().startOf(defaultType); let endDate = currentDate.clone().endOf(defaultType); const pipeline = [ { $facet: { totalClients: [ { $match: { removed: false, enabled: true, }, }, { $count: 'count', }, ], newClients: [ { $match: { removed: false, created: { $gte: startDate.toDate(), $lte: endDate.toDate() }, enabled: true, }, }, { $count: 'count', }, ], activeClients: [ { $lookup: { from: InvoiceModel.collection.name, localField: '_id', // Match _id from ClientModel foreignField: 'client', // Match client field in InvoiceModel as: 'invoice', }, }, { $match: { 'invoice.removed': false, }, }, { $group: { _id: '$_id', }, }, { $count: 'count', }, ], }, }, ]; const aggregationResult = await Model.aggregate(pipeline); const result = aggregationResult[0]; const totalClients = result.totalClients[0] ? result.totalClients[0].count : 0; const totalNewClients = result.newClients[0] ? result.newClients[0].count : 0; const activeClients = result.activeClients[0] ? result.activeClients[0].count : 0; const totalActiveClientsPercentage = totalClients > 0 ? (activeClients / totalClients) * 100 : 0; const totalNewClientsPercentage = totalClients > 0 ? (totalNewClients / totalClients) * 100 : 0; return res.status(200).json({ success: true, result: { new: Math.round(totalNewClientsPercentage), active: Math.round(totalActiveClientsPercentage), }, message: 'Successfully get summary of new clients', }); }; module.exports = summary; ================================================ FILE: backend/src/controllers/appControllers/index.js ================================================ const createCRUDController = require('@/controllers/middlewaresControllers/createCRUDController'); const { routesList } = require('@/models/utils'); const { globSync } = require('glob'); const path = require('path'); const pattern = './src/controllers/appControllers/*/**/'; const controllerDirectories = globSync(pattern).map((filePath) => { return path.basename(filePath); }); const appControllers = () => { const controllers = {}; const hasCustomControllers = []; controllerDirectories.forEach((controllerName) => { try { const customController = require('@/controllers/appControllers/' + controllerName); if (customController) { hasCustomControllers.push(controllerName); controllers[controllerName] = customController; } } catch (err) { throw new Error(err.message); } }); routesList.forEach(({ modelName, controllerName }) => { if (!hasCustomControllers.includes(controllerName)) { controllers[controllerName] = createCRUDController(modelName); } }); return controllers; }; module.exports = appControllers(); ================================================ FILE: backend/src/controllers/appControllers/invoiceController/create.js ================================================ const mongoose = require('mongoose'); const Model = mongoose.model('Invoice'); const { calculate } = require('@/helpers'); const { increaseBySettingKey } = require('@/middlewares/settings'); const schema = require('./schemaValidate'); const create = async (req, res) => { let body = req.body; const { error, value } = schema.validate(body); if (error) { const { details } = error; return res.status(400).json({ success: false, result: null, message: details[0]?.message, }); } const { items = [], taxRate = 0, discount = 0 } = value; // default let subTotal = 0; let taxTotal = 0; let total = 0; //Calculate the items array with subTotal, total, taxTotal items.map((item) => { let total = calculate.multiply(item['quantity'], item['price']); //sub total subTotal = calculate.add(subTotal, total); //item total item['total'] = total; }); taxTotal = calculate.multiply(subTotal, taxRate / 100); total = calculate.add(subTotal, taxTotal); body['subTotal'] = subTotal; body['taxTotal'] = taxTotal; body['total'] = total; body['items'] = items; let paymentStatus = calculate.sub(total, discount) === 0 ? 'paid' : 'unpaid'; body['paymentStatus'] = paymentStatus; body['createdBy'] = req.admin._id; // Creating a new document in the collection const result = await new Model(body).save(); const fileId = 'invoice-' + result._id + '.pdf'; const updateResult = await Model.findOneAndUpdate( { _id: result._id }, { pdf: fileId }, { new: true, } ).exec(); // Returning successfull response increaseBySettingKey({ settingKey: 'last_invoice_number', }); // Returning successfull response return res.status(200).json({ success: true, result: updateResult, message: 'Invoice created successfully', }); }; module.exports = create; ================================================ FILE: backend/src/controllers/appControllers/invoiceController/index.js ================================================ const createCRUDController = require('@/controllers/middlewaresControllers/createCRUDController'); const methods = createCRUDController('Invoice'); const sendMail = require('./sendMail'); const create = require('./create'); const summary = require('./summary'); const update = require('./update'); const remove = require('./remove'); const paginatedList = require('./paginatedList'); const read = require('./read'); methods.mail = sendMail; methods.create = create; methods.update = update; methods.delete = remove; methods.summary = summary; methods.list = paginatedList; methods.read = read; module.exports = methods; ================================================ FILE: backend/src/controllers/appControllers/invoiceController/paginatedList.js ================================================ const mongoose = require('mongoose'); const Model = mongoose.model('Invoice'); const paginatedList = async (req, res) => { const page = req.query.page || 1; const limit = parseInt(req.query.items) || 10; const skip = page * limit - limit; const { sortBy = 'enabled', sortValue = -1, filter, equal } = req.query; const fieldsArray = req.query.fields ? req.query.fields.split(',') : []; let fields; fields = fieldsArray.length === 0 ? {} : { $or: [] }; for (const field of fieldsArray) { fields.$or.push({ [field]: { $regex: new RegExp(req.query.q, 'i') } }); } // Query the database for a list of all results const resultsPromise = Model.find({ removed: false, [filter]: equal, ...fields, }) .skip(skip) .limit(limit) .sort({ [sortBy]: sortValue }) .populate('createdBy', 'name') .exec(); // Counting the total documents const countPromise = Model.countDocuments({ removed: false, [filter]: equal, ...fields, }); // Resolving both promises const [result, count] = await Promise.all([resultsPromise, countPromise]); // Calculating total pages const pages = Math.ceil(count / limit); // Getting Pagination Object const pagination = { page, pages, count }; if (count > 0) { return res.status(200).json({ success: true, result, pagination, message: 'Successfully found all documents', }); } else { return res.status(203).json({ success: true, result: [], pagination, message: 'Collection is Empty', }); } }; module.exports = paginatedList; ================================================ FILE: backend/src/controllers/appControllers/invoiceController/read.js ================================================ const mongoose = require('mongoose'); const Model = mongoose.model('Invoice'); const read = async (req, res) => { // Find document by id const result = await Model.findOne({ _id: req.params.id, removed: false, }) .populate('createdBy', 'name') .exec(); // If no results found, return document not found if (!result) { return res.status(404).json({ success: false, result: null, message: 'No document found ', }); } else { // Return success resposne return res.status(200).json({ success: true, result, message: 'we found this document ', }); } }; module.exports = read; ================================================ FILE: backend/src/controllers/appControllers/invoiceController/remove.js ================================================ const mongoose = require('mongoose'); const Model = mongoose.model('Invoice'); const ModelPayment = mongoose.model('Payment'); const remove = async (req, res) => { const deletedInvoice = await Model.findOneAndUpdate( { _id: req.params.id, removed: false, }, { $set: { removed: true, }, } ).exec(); if (!deletedInvoice) { return res.status(404).json({ success: false, result: null, message: 'Invoice not found', }); } const paymentsInvoices = await ModelPayment.updateMany( { invoice: deletedInvoice._id }, { $set: { removed: true } } ); return res.status(200).json({ success: true, result: deletedInvoice, message: 'Invoice deleted successfully', }); }; module.exports = remove; ================================================ FILE: backend/src/controllers/appControllers/invoiceController/schemaValidate.js ================================================ const Joi = require('joi'); const schema = Joi.object({ client: Joi.alternatives().try(Joi.string(), Joi.object()).required(), number: Joi.number().required(), year: Joi.number().required(), status: Joi.string().required(), notes: Joi.string().allow(''), expiredDate: Joi.date().required(), date: Joi.date().required(), // array cannot be empty items: Joi.array() .items( Joi.object({ _id: Joi.string().allow('').optional(), itemName: Joi.string().required(), description: Joi.string().allow(''), quantity: Joi.number().required(), price: Joi.number().required(), total: Joi.number().required(), }).required() ) .required(), taxRate: Joi.alternatives().try(Joi.number(), Joi.string()).required(), }); module.exports = schema; ================================================ FILE: backend/src/controllers/appControllers/invoiceController/sendMail.js ================================================ const fs = require('fs'); const mongoose = require('mongoose'); const mail = async (req, res) => { return res.status(200).json({ success: true, result: null, message: 'Please Upgrade to Premium Version to have full features', }); }; module.exports = mail; ================================================ FILE: backend/src/controllers/appControllers/invoiceController/summary.js ================================================ const mongoose = require('mongoose'); const moment = require('moment'); const Model = mongoose.model('Invoice'); const { loadSettings } = require('@/middlewares/settings'); const summary = async (req, res) => { let defaultType = 'month'; const { type } = req.query; const settings = await loadSettings(); if (type) { if (['week', 'month', 'year'].includes(type)) { defaultType = type; } else { return res.status(400).json({ success: false, result: null, message: 'Invalid type', }); } } const currentDate = moment(); let startDate = currentDate.clone().startOf(defaultType); let endDate = currentDate.clone().endOf(defaultType); const statuses = ['draft', 'pending', 'overdue', 'paid', 'unpaid', 'partially']; const response = await Model.aggregate([ { $match: { removed: false, // date: { // $gte: startDate.toDate(), // $lte: endDate.toDate(), // }, }, }, { $facet: { totalInvoice: [ { $group: { _id: null, total: { $sum: '$total', }, count: { $sum: 1, }, }, }, { $project: { _id: 0, total: '$total', count: '$count', }, }, ], statusCounts: [ { $group: { _id: '$status', count: { $sum: 1, }, }, }, { $project: { _id: 0, status: '$_id', count: '$count', }, }, ], paymentStatusCounts: [ { $group: { _id: '$paymentStatus', count: { $sum: 1, }, }, }, { $project: { _id: 0, status: '$_id', count: '$count', }, }, ], overdueCounts: [ { $match: { expiredDate: { $lt: new Date(), }, }, }, { $group: { _id: '$status', count: { $sum: 1, }, }, }, { $project: { _id: 0, status: '$_id', count: '$count', }, }, ], }, }, ]); let result = []; const totalInvoices = response[0].totalInvoice ? response[0].totalInvoice[0] : 0; const statusResult = response[0].statusCounts || []; const paymentStatusResult = response[0].paymentStatusCounts || []; const overdueResult = response[0].overdueCounts || []; const statusResultMap = statusResult.map((item) => { return { ...item, percentage: Math.round((item.count / totalInvoices.count) * 100), }; }); const paymentStatusResultMap = paymentStatusResult.map((item) => { return { ...item, percentage: Math.round((item.count / totalInvoices.count) * 100), }; }); const overdueResultMap = overdueResult.map((item) => { return { ...item, status: 'overdue', percentage: Math.round((item.count / totalInvoices.count) * 100), }; }); statuses.forEach((status) => { const found = [...paymentStatusResultMap, ...statusResultMap, ...overdueResultMap].find( (item) => item.status === status ); if (found) { result.push(found); } }); const unpaid = await Model.aggregate([ { $match: { removed: false, // date: { // $gte: startDate.toDate(), // $lte: endDate.toDate(), // }, paymentStatus: { $in: ['unpaid', 'partially'], }, }, }, { $group: { _id: null, total_amount: { $sum: { $subtract: ['$total', '$credit'], }, }, }, }, { $project: { _id: 0, total_amount: '$total_amount', }, }, ]); const finalResult = { total: totalInvoices?.total, total_undue: unpaid.length > 0 ? unpaid[0].total_amount : 0, type, performance: result, }; return res.status(200).json({ success: true, result: finalResult, message: `Successfully found all invoices for the last ${defaultType}`, }); }; module.exports = summary; ================================================ FILE: backend/src/controllers/appControllers/invoiceController/update.js ================================================ const mongoose = require('mongoose'); const Model = mongoose.model('Invoice'); const custom = require('@/controllers/pdfController'); const { calculate } = require('@/helpers'); const schema = require('./schemaValidate'); const update = async (req, res) => { let body = req.body; const { error, value } = schema.validate(body); if (error) { const { details } = error; return res.status(400).json({ success: false, result: null, message: details[0]?.message, }); } const previousInvoice = await Model.findOne({ _id: req.params.id, removed: false, }); const { credit } = previousInvoice; const { items = [], taxRate = 0, discount = 0 } = req.body; if (items.length === 0) { return res.status(400).json({ success: false, result: null, message: 'Items cannot be empty', }); } // default let subTotal = 0; let taxTotal = 0; let total = 0; //Calculate the items array with subTotal, total, taxTotal items.map((item) => { let total = calculate.multiply(item['quantity'], item['price']); //sub total subTotal = calculate.add(subTotal, total); //item total item['total'] = total; }); taxTotal = calculate.multiply(subTotal, taxRate / 100); total = calculate.add(subTotal, taxTotal); body['subTotal'] = subTotal; body['taxTotal'] = taxTotal; body['total'] = total; body['items'] = items; body['pdf'] = 'invoice-' + req.params.id + '.pdf'; if (body.hasOwnProperty('currency')) { delete body.currency; } // Find document by id and updates with the required fields let paymentStatus = calculate.sub(total, discount) === credit ? 'paid' : credit > 0 ? 'partially' : 'unpaid'; body['paymentStatus'] = paymentStatus; const result = await Model.findOneAndUpdate({ _id: req.params.id, removed: false }, body, { new: true, // return the new result instead of the old one }).exec(); // Returning successfull response return res.status(200).json({ success: true, result, message: 'we update this document ', }); }; module.exports = update; ================================================ FILE: backend/src/controllers/appControllers/paymentController/create.js ================================================ const mongoose = require('mongoose'); const Model = mongoose.model('Payment'); const Invoice = mongoose.model('Invoice'); const custom = require('@/controllers/pdfController'); const { calculate } = require('@/helpers'); const create = async (req, res) => { // Creating a new document in the collection if (req.body.amount === 0) { return res.status(202).json({ success: false, result: null, message: `The Minimum Amount couldn't be 0`, }); } const currentInvoice = await Invoice.findOne({ _id: req.body.invoice, removed: false, }); const { total: previousTotal, discount: previousDiscount, credit: previousCredit, } = currentInvoice; const maxAmount = calculate.sub(calculate.sub(previousTotal, previousDiscount), previousCredit); if (req.body.amount > maxAmount) { return res.status(202).json({ success: false, result: null, message: `The Max Amount you can add is ${maxAmount}`, }); } req.body['createdBy'] = req.admin._id; const result = await Model.create(req.body); const fileId = 'payment-' + result._id + '.pdf'; const updatePath = await Model.findOneAndUpdate( { _id: result._id.toString(), removed: false, }, { pdf: fileId }, { new: true, } ).exec(); // Returning successfull response const { _id: paymentId, amount } = result; const { id: invoiceId, total, discount, credit } = currentInvoice; let paymentStatus = calculate.sub(total, discount) === calculate.add(credit, amount) ? 'paid' : calculate.add(credit, amount) > 0 ? 'partially' : 'unpaid'; const invoiceUpdate = await Invoice.findOneAndUpdate( { _id: req.body.invoice }, { $push: { payment: paymentId.toString() }, $inc: { credit: amount }, $set: { paymentStatus: paymentStatus }, }, { new: true, // return the new result instead of the old one runValidators: true, } ).exec(); return res.status(200).json({ success: true, result: updatePath, message: 'Payment Invoice created successfully', }); }; module.exports = create; ================================================ FILE: backend/src/controllers/appControllers/paymentController/index.js ================================================ const createCRUDController = require('@/controllers/middlewaresControllers/createCRUDController'); const methods = createCRUDController('Payment'); const create = require('./create'); const summary = require('./summary'); const update = require('./update'); const remove = require('./remove'); const sendMail = require('./sendMail'); methods.mail = sendMail; methods.create = create; methods.update = update; methods.delete = remove; methods.summary = summary; module.exports = methods; ================================================ FILE: backend/src/controllers/appControllers/paymentController/remove.js ================================================ const mongoose = require('mongoose'); const Model = mongoose.model('Payment'); const Invoice = mongoose.model('Invoice'); const remove = async (req, res) => { // Find document by id and updates with the required fields const previousPayment = await Model.findOne({ _id: req.params.id, removed: false, }); if (!previousPayment) { return res.status(404).json({ success: false, result: null, message: 'No document found ', }); } const { _id: paymentId, amount: previousAmount } = previousPayment; const { id: invoiceId, total, discount, credit: previousCredit } = previousPayment.invoice; // Find the document by id and delete it let updates = { removed: true, }; // Find the document by id and delete it const result = await Model.findOneAndUpdate( { _id: req.params.id, removed: false }, { $set: updates }, { new: true, // return the new result instead of the old one } ).exec(); // If no results found, return document not found let paymentStatus = total - discount === previousCredit - previousAmount ? 'paid' : previousCredit - previousAmount > 0 ? 'partially' : 'unpaid'; const updateInvoice = await Invoice.findOneAndUpdate( { _id: invoiceId }, { $pull: { payment: paymentId, }, $inc: { credit: -previousAmount }, $set: { paymentStatus: paymentStatus, }, }, { new: true, // return the new result instead of the old one } ).exec(); return res.status(200).json({ success: true, result, message: 'Successfully Deleted the document ', }); }; module.exports = remove; ================================================ FILE: backend/src/controllers/appControllers/paymentController/sendMail.js ================================================ const mail = async (req, res) => { return res.status(200).json({ success: true, result: null, message: 'Please Upgrade to Premium Version to have full features', }); }; module.exports = mail; ================================================ FILE: backend/src/controllers/appControllers/paymentController/summary.js ================================================ const mongoose = require('mongoose'); const moment = require('moment'); const Model = mongoose.model('Payment'); const { loadSettings } = require('@/middlewares/settings'); const summary = async (req, res) => { let defaultType = 'month'; const { type } = req.query; const settings = await loadSettings(); if (type) { if (['week', 'month', 'year'].includes(type)) { defaultType = type; } else { return res.status(400).json({ success: false, result: null, message: 'Invalid type', }); } } const currentDate = moment(); let startDate = currentDate.clone().startOf(defaultType); let endDate = currentDate.clone().endOf(defaultType); // get total amount of invoices const result = await Model.aggregate([ { $match: { removed: false, // date: { // $gte: startDate.toDate(), // $lte: endDate.toDate(), // }, }, }, { $group: { _id: null, // Group all documents into a single group count: { $sum: 1, }, total: { $sum: '$amount', }, }, }, { $project: { _id: 0, // Exclude _id from the result count: 1, total: 1, }, }, ]); return res.status(200).json({ success: true, result: result.length > 0 ? result[0] : { count: 0, total: 0 }, message: `Successfully fetched the summary of payment invoices for the last ${defaultType}`, }); }; module.exports = summary; ================================================ FILE: backend/src/controllers/appControllers/paymentController/update.js ================================================ const mongoose = require('mongoose'); const Model = mongoose.model('Payment'); const Invoice = mongoose.model('Invoice'); const custom = require('@/controllers/pdfController'); const { calculate } = require('@/helpers'); const update = async (req, res) => { if (req.body.amount === 0) { return res.status(202).json({ success: false, result: null, message: `The Minimum Amount couldn't be 0`, }); } // Find document by id and updates with the required fields const previousPayment = await Model.findOne({ _id: req.params.id, removed: false, }); const { amount: previousAmount } = previousPayment; const { id: invoiceId, total, discount, credit: previousCredit } = previousPayment.invoice; const { amount: currentAmount } = req.body; const changedAmount = calculate.sub(currentAmount, previousAmount); const maxAmount = calculate.sub(total, calculate.add(discount, previousCredit)); if (changedAmount > maxAmount) { return res.status(202).json({ success: false, result: null, message: `The Max Amount you can add is ${maxAmount + previousAmount}`, error: `The Max Amount you can add is ${maxAmount + previousAmount}`, }); } let paymentStatus = calculate.sub(total, discount) === calculate.add(previousCredit, changedAmount) ? 'paid' : calculate.add(previousCredit, changedAmount) > 0 ? 'partially' : 'unpaid'; const updatedDate = new Date(); const updates = { number: req.body.number, date: req.body.date, amount: req.body.amount, paymentMode: req.body.paymentMode, ref: req.body.ref, description: req.body.description, updated: updatedDate, }; const result = await Model.findOneAndUpdate( { _id: req.params.id, removed: false }, { $set: updates }, { new: true, // return the new result instead of the old one } ).exec(); const updateInvoice = await Invoice.findOneAndUpdate( { _id: result.invoice._id.toString() }, { $inc: { credit: changedAmount }, $set: { paymentStatus: paymentStatus, }, }, { new: true, // return the new result instead of the old one } ).exec(); return res.status(200).json({ success: true, result, message: 'Successfully updated the Payment ', }); }; module.exports = update; ================================================ FILE: backend/src/controllers/coreControllers/adminAuth/index.js ================================================ const createAuthMiddleware = require('@/controllers/middlewaresControllers/createAuthMiddleware'); module.exports = createAuthMiddleware('Admin'); ================================================ FILE: backend/src/controllers/coreControllers/adminController/index.js ================================================ const createUserController = require('@/controllers/middlewaresControllers/createUserController'); module.exports = createUserController('Admin'); ================================================ FILE: backend/src/controllers/coreControllers/settingController/index.js ================================================ const createCRUDController = require('@/controllers/middlewaresControllers/createCRUDController'); const crudController = createCRUDController('Setting'); const listBySettingKey = require('./listBySettingKey'); const readBySettingKey = require('./readBySettingKey'); const updateBySettingKey = require('./updateBySettingKey'); const updateManySetting = require('./updateManySetting'); const listAll = require('./listAll'); const settingMethods = { read: crudController.read, create: crudController.create, update: crudController.update, list: crudController.list, filter: crudController.filter, search: crudController.search, listAll: listAll, listBySettingKey, readBySettingKey, updateBySettingKey, updateManySetting, }; module.exports = settingMethods; ================================================ FILE: backend/src/controllers/coreControllers/settingController/listAll.js ================================================ const mongoose = require('mongoose'); const Model = mongoose.model('Setting'); const listAll = async (req, res) => { const sort = parseInt(req.query.sort) || 'desc'; // Query the database for a list of all results const result = await Model.find({ removed: false, isPrivate: false, }).sort({ created: sort }); if (result.length > 0) { return res.status(200).json({ success: true, result, message: 'Successfully found all documents', }); } else { return res.status(203).json({ success: false, result: [], message: 'Collection is Empty', }); } }; module.exports = listAll; ================================================ FILE: backend/src/controllers/coreControllers/settingController/listBySettingKey.js ================================================ const mongoose = require('mongoose'); const Model = mongoose.model('Setting'); const listBySettingKey = async (req, res) => { // Find document by id const settingKeyArray = req.query.settingKeyArray ? req.query.settingKeyArray.split(',') : []; const settingsToShow = { $or: [] }; if (settingKeyArray.length === 0) { return res .status(202) .json({ success: false, result: [], message: 'Please provide settings you need', }) .end(); } for (const settingKey of settingKeyArray) { settingsToShow.$or.push({ settingKey }); } let results = await Model.find({ ...settingsToShow, }).where('removed', false); // If no results found, return document not found if (results.length >= 1) { return res.status(200).json({ success: true, result: results, message: 'Successfully found all documents', }); } else { return res .status(202) .json({ success: false, result: [], message: 'No document found by this request', }) .end(); } }; module.exports = listBySettingKey; ================================================ FILE: backend/src/controllers/coreControllers/settingController/readBySettingKey.js ================================================ const mongoose = require('mongoose'); const Model = mongoose.model('Setting'); const readBySettingKey = async (req, res) => { // Find document by id const settingKey = req.params.settingKey || undefined; if (!settingKey) { return res.status(202).json({ success: false, result: null, message: 'No settingKey provided ', }); } const result = await Model.findOne({ settingKey, }); // If no results found, return document not found if (!result) { return res.status(404).json({ success: false, result: null, message: 'No document found by this settingKey: ' + settingKey, }); } else { // Return success resposne return res.status(200).json({ success: true, result, message: 'we found this document by this settingKey: ' + settingKey, }); } }; module.exports = readBySettingKey; ================================================ FILE: backend/src/controllers/coreControllers/settingController/updateBySettingKey.js ================================================ const mongoose = require('mongoose'); const Model = mongoose.model('Setting'); const updateBySettingKey = async (req, res) => { const settingKey = req.params.settingKey || undefined; if (!settingKey) { return res.status(202).json({ success: false, result: null, message: 'No settingKey provided ', }); } const { settingValue } = req.body; if (!settingValue) { return res.status(202).json({ success: false, result: null, message: 'No settingValue provided ', }); } const result = await Model.findOneAndUpdate( { settingKey }, { settingValue, }, { new: true, // return the new result instead of the old one runValidators: true, } ).exec(); if (!result) { return res.status(404).json({ success: false, result: null, message: 'No document found by this settingKey: ' + settingKey, }); } else { return res.status(200).json({ success: true, result, message: 'we update this document by this settingKey: ' + settingKey, }); } }; module.exports = updateBySettingKey; ================================================ FILE: backend/src/controllers/coreControllers/settingController/updateManySetting.js ================================================ const mongoose = require('mongoose'); const Model = mongoose.model('Setting'); const updateManySetting = async (req, res) => { // req/body = [{settingKey:"",settingValue}] let settingsHasError = false; const updateDataArray = []; const { settings } = req.body; for (const setting of settings) { if (!setting.hasOwnProperty('settingKey') || !setting.hasOwnProperty('settingValue')) { settingsHasError = true; break; } const { settingKey, settingValue } = setting; updateDataArray.push({ updateOne: { filter: { settingKey: settingKey }, update: { settingValue: settingValue }, }, }); } if (updateDataArray.length === 0) { return res.status(202).json({ success: false, result: null, message: 'No settings provided ', }); } if (settingsHasError) { return res.status(202).json({ success: false, result: null, message: 'Settings provided has Error', }); } const result = await Model.bulkWrite(updateDataArray); if (!result || result.nMatched < 1) { return res.status(404).json({ success: false, result: null, message: 'No settings found by to update', }); } else { return res.status(200).json({ success: true, result: [], message: 'we update all settings', }); } }; module.exports = updateManySetting; ================================================ FILE: backend/src/controllers/coreControllers/setup.js ================================================ require('dotenv').config({ path: '.env' }); require('dotenv').config({ path: '.env.local' }); const { globSync } = require('glob'); const fs = require('fs'); const { generate: uniqueId } = require('shortid'); const mongoose = require('mongoose'); const setup = async (req, res) => { const Admin = mongoose.model('Admin'); const AdminPassword = mongoose.model('AdminPassword'); const Setting = mongoose.model('Setting'); const PaymentMode = mongoose.model('PaymentMode'); const Taxes = mongoose.model('Taxes'); const newAdminPassword = new AdminPassword(); const { name, email, password, language, timezone, country, config = {} } = req.body; const objectSchema = Joi.object({ name: Joi.string().required(), email: Joi.string() .email({ tlds: { allow: true } }) .required(), password: Joi.string().required(), }); const { error, value } = objectSchema.validate({ name, email, password }); if (error) { return res.status(409).json({ success: false, result: null, error: error, message: 'Invalid/Missing credentials.', errorMessage: error.message, }); } const salt = uniqueId(); const passwordHash = newAdminPassword.generateHash(salt, password); const accountOwnner = { email, name, role: 'owner', }; const result = await new Admin(accountOwnner).save(); const AdminPasswordData = { password: passwordHash, emailVerified: true, salt: salt, user: result._id, }; await new AdminPassword(AdminPasswordData).save(); const settingData = []; const settingsFiles = globSync('./src/setup/defaultSettings/**/*.json'); for (const filePath of settingsFiles) { const file = JSON.parse(fs.readFileSync(filePath, 'utf-8')); const settingsToUpdate = { idurar_app_email: email, idurar_app_company_email: email, idurar_app_timezone: timezone, idurar_app_country: country, idurar_app_language: language || 'en_us', }; const newSettings = file.map((x) => { const settingValue = settingsToUpdate[x.settingKey]; return settingValue ? { ...x, settingValue } : { ...x }; }); settingData.push(...newSettings); } await Setting.insertMany(settingData); await Taxes.insertMany([{ taxName: 'Tax 0%', taxValue: '0', isDefault: true }]); await PaymentMode.insertMany([ { name: 'Default Payment', description: 'Default Payment Mode (Cash , Wire Transfer)', isDefault: true, }, ]); return res.status(200).json({ success: true, result: {}, message: 'Successfully IDURAR App Setup', }); }; module.exports = setup; ================================================ FILE: backend/src/controllers/middlewaresControllers/createAuthMiddleware/authUser.js ================================================ const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken'); const authUser = async (req, res, { user, databasePassword, password, UserPasswordModel }) => { const isMatch = await bcrypt.compare(databasePassword.salt + password, databasePassword.password); if (!isMatch) return res.status(403).json({ success: false, result: null, message: 'Invalid credentials.', }); if (isMatch === true) { const token = jwt.sign( { id: user._id, }, process.env.JWT_SECRET, { expiresIn: req.body.remember ? 365 * 24 + 'h' : '24h' } ); await UserPasswordModel.findOneAndUpdate( { user: user._id }, { $push: { loggedSessions: token } }, { new: true, } ).exec(); // .cookie(`token_${user.cloud}`, token, { // maxAge: req.body.remember ? 365 * 24 * 60 * 60 * 1000 : null, // sameSite: 'None', // httpOnly: true, // secure: true, // domain: req.hostname, // path: '/', // Partitioned: true, // }) res.status(200).json({ success: true, result: { _id: user._id, name: user.name, surname: user.surname, role: user.role, email: user.email, photo: user.photo, token: token, maxAge: req.body.remember ? 365 : null, }, message: 'Successfully login user', }); } else { return res.status(403).json({ success: false, result: null, message: 'Invalid credentials.', }); } }; module.exports = authUser; ================================================ FILE: backend/src/controllers/middlewaresControllers/createAuthMiddleware/checkAndCorrectURL.js ================================================ function checkAndCorrectURL(url) { // detect if it has http or https: const hasHttps = url.startsWith('https://'); // Remove "http://" or "https://" if present url = url.replace(/^https?:\/\//i, ''); // Remove trailing slashes url = url.replace(/\/+$/, ''); const httpType = hasHttps ? 'https://' : 'http://'; return httpType + url; } module.exports = checkAndCorrectURL; ================================================ FILE: backend/src/controllers/middlewaresControllers/createAuthMiddleware/forgetPassword.js ================================================ const Joi = require('joi'); const mongoose = require('mongoose'); const checkAndCorrectURL = require('./checkAndCorrectURL'); const sendMail = require('./sendMail'); const shortid = require('shortid'); const { loadSettings } = require('@/middlewares/settings'); const { useAppSettings } = require('@/settings'); const forgetPassword = async (req, res, { userModel }) => { const UserPassword = mongoose.model(userModel + 'Password'); const User = mongoose.model(userModel); const { email } = req.body; // validate const objectSchema = Joi.object({ email: Joi.string() .email({ tlds: { allow: true } }) .required(), }); const { error, value } = objectSchema.validate({ email }); if (error) { return res.status(409).json({ success: false, result: null, error: error, message: 'Invalid email.', errorMessage: error.message, }); } const user = await User.findOne({ email: email, removed: false }); const databasePassword = await UserPassword.findOne({ user: user._id, removed: false }); // console.log(user); if (!user) return res.status(404).json({ success: false, result: null, message: 'No account with this email has been registered.', }); const resetToken = shortid.generate(); await UserPassword.findOneAndUpdate( { user: user._id }, { resetToken }, { new: true, } ).exec(); const settings = useAppSettings(); const idurar_app_email = settings['idurar_app_email']; const idurar_base_url = settings['idurar_base_url']; const url = checkAndCorrectURL(idurar_base_url); const link = url + '/resetpassword/' + user._id + '/' + resetToken; await sendMail({ email, name: user.name, link, subject: 'Reset your password | idurar', idurar_app_email, type: 'passwordVerfication', }); return res.status(200).json({ success: true, result: null, message: 'Check your email inbox , to reset your password', }); }; module.exports = forgetPassword; ================================================ FILE: backend/src/controllers/middlewaresControllers/createAuthMiddleware/index.js ================================================ const isValidAuthToken = require('./isValidAuthToken'); const login = require('./login'); const logout = require('./logout'); const forgetPassword = require('./forgetPassword'); const resetPassword = require('./resetPassword'); const createAuthMiddleware = (userModel) => { let authMethods = {}; authMethods.isValidAuthToken = (req, res, next) => isValidAuthToken(req, res, next, { userModel, }); authMethods.login = (req, res) => login(req, res, { userModel, }); authMethods.forgetPassword = (req, res) => forgetPassword(req, res, { userModel, }); authMethods.resetPassword = (req, res) => resetPassword(req, res, { userModel, }); authMethods.logout = (req, res) => logout(req, res, { userModel, }); return authMethods; }; module.exports = createAuthMiddleware; ================================================ FILE: backend/src/controllers/middlewaresControllers/createAuthMiddleware/isValidAuthToken.js ================================================ const jwt = require('jsonwebtoken'); const mongoose = require('mongoose'); const isValidAuthToken = async (req, res, next, { userModel, jwtSecret = 'JWT_SECRET' }) => { try { const UserPassword = mongoose.model(userModel + 'Password'); const User = mongoose.model(userModel); // const token = req.cookies[`token_${cloud._id}`]; const authHeader = req.headers['authorization']; const token = authHeader && authHeader.split(' ')[1]; // Extract the token if (!token) return res.status(401).json({ success: false, result: null, message: 'No authentication token, authorization denied.', jwtExpired: true, }); const verified = jwt.verify(token, process.env[jwtSecret]); if (!verified) return res.status(401).json({ success: false, result: null, message: 'Token verification failed, authorization denied.', jwtExpired: true, }); const userPasswordPromise = UserPassword.findOne({ user: verified.id, removed: false }); const userPromise = User.findOne({ _id: verified.id, removed: false }); const [user, userPassword] = await Promise.all([userPromise, userPasswordPromise]); if (!user) return res.status(401).json({ success: false, result: null, message: "User doens't Exist, authorization denied.", jwtExpired: true, }); const { loggedSessions } = userPassword; if (!loggedSessions.includes(token)) return res.status(401).json({ success: false, result: null, message: 'User is already logout try to login, authorization denied.', jwtExpired: true, }); else { const reqUserName = userModel.toLowerCase(); req[reqUserName] = user; next(); } } catch (error) { return res.status(500).json({ success: false, result: null, message: error.message, error: error, controller: 'isValidAuthToken', jwtExpired: true, }); } }; module.exports = isValidAuthToken; ================================================ FILE: backend/src/controllers/middlewaresControllers/createAuthMiddleware/login.js ================================================ const Joi = require('joi'); const mongoose = require('mongoose'); const authUser = require('./authUser'); const login = async (req, res, { userModel }) => { const UserPasswordModel = mongoose.model(userModel + 'Password'); const UserModel = mongoose.model(userModel); const { email, password } = req.body; // validate const objectSchema = Joi.object({ email: Joi.string() .email({ tlds: { allow: true } }) .required(), password: Joi.string().required(), }); const { error, value } = objectSchema.validate({ email, password }); if (error) { return res.status(409).json({ success: false, result: null, error: error, message: 'Invalid/Missing credentials.', errorMessage: error.message, }); } const user = await UserModel.findOne({ email: email, removed: false }); // console.log(user); if (!user) return res.status(404).json({ success: false, result: null, message: 'No account with this email has been registered.', }); const databasePassword = await UserPasswordModel.findOne({ user: user._id, removed: false }); if (!user.enabled) return res.status(409).json({ success: false, result: null, message: 'Your account is disabled, contact your account adminstrator', }); // authUser if your has correct password authUser(req, res, { user, databasePassword, password, UserPasswordModel, }); }; module.exports = login; ================================================ FILE: backend/src/controllers/middlewaresControllers/createAuthMiddleware/logout.js ================================================ const mongoose = require('mongoose'); const logout = async (req, res, { userModel }) => { const UserPassword = mongoose.model(userModel + 'Password'); // const token = req.cookies[`token_${cloud._id}`]; const authHeader = req.headers['authorization']; const token = authHeader && authHeader.split(' ')[1]; // Extract the token if (token) await UserPassword.findOneAndUpdate( { user: req.admin._id }, { $pull: { loggedSessions: token } }, { new: true, } ).exec(); else await UserPassword.findOneAndUpdate( { user: req.admin._id }, { loggedSessions: [] }, { new: true, } ).exec(); return res.json({ success: true, result: {}, message: 'Successfully logout', }); }; module.exports = logout; ================================================ FILE: backend/src/controllers/middlewaresControllers/createAuthMiddleware/resetPassword.js ================================================ const jwt = require('jsonwebtoken'); const bcrypt = require('bcryptjs'); const Joi = require('joi'); const mongoose = require('mongoose'); const shortid = require('shortid'); const resetPassword = async (req, res, { userModel }) => { const UserPassword = mongoose.model(userModel + 'Password'); const User = mongoose.model(userModel); const { password, userId, resetToken } = req.body; const databasePassword = await UserPassword.findOne({ user: userId, removed: false }); const user = await User.findOne({ _id: userId, removed: false }).exec(); if (!user.enabled) return res.status(409).json({ success: false, result: null, message: 'Your account is disabled, contact your account adminstrator', }); if (!databasePassword || !user) return res.status(404).json({ success: false, result: null, message: 'No account with this email has been registered.', }); const isMatch = resetToken === databasePassword.resetToken; if (!isMatch || databasePassword.resetToken === undefined || databasePassword.resetToken === null) return res.status(403).json({ success: false, result: null, message: 'Invalid reset token', }); // validate const objectSchema = Joi.object({ password: Joi.string().required(), userId: Joi.string().required(), resetToken: Joi.string().required(), }); const { error, value } = objectSchema.validate({ password, userId, resetToken }); if (error) { return res.status(409).json({ success: false, result: null, error: error, message: 'Invalid reset password object', errorMessage: error.message, }); } const salt = shortid.generate(); const hashedPassword = bcrypt.hashSync(salt + password); const emailToken = shortid.generate(); const token = jwt.sign( { id: userId, }, process.env.JWT_SECRET, { expiresIn: '24h' } ); await UserPassword.findOneAndUpdate( { user: userId }, { $push: { loggedSessions: token }, password: hashedPassword, salt: salt, emailToken: emailToken, resetToken: shortid.generate(), emailVerified: true, }, { new: true, } ).exec(); if ( resetToken === databasePassword.resetToken && databasePassword.resetToken !== undefined && databasePassword.resetToken !== null ) // .cookie(`token_${user.cloud}`, token, { // maxAge: 24 * 60 * 60 * 1000, // sameSite: 'None', // httpOnly: true, // secure: true, // domain: req.hostname, // path: '/', // Partitioned: true, // }) return res.status(200).json({ success: true, result: { _id: user._id, name: user.name, surname: user.surname, role: user.role, email: user.email, photo: user.photo, token: token, maxAge: req.body.remember ? 365 : null, }, message: 'Successfully resetPassword user', }); }; module.exports = resetPassword; ================================================ FILE: backend/src/controllers/middlewaresControllers/createAuthMiddleware/sendMail.js ================================================ const { passwordVerfication } = require('@/emailTemplate/emailVerfication'); const { Resend } = require('resend'); const sendMail = async ({ email, name, link, idurar_app_email, subject = 'Verify your email | idurar', type = 'emailVerfication', emailToken, }) => { const resend = new Resend(process.env.RESEND_API); const { data } = await resend.emails.send({ from: idurar_app_email, to: email, subject, html: passwordVerfication({ name, link }), }); return data; }; module.exports = sendMail; ================================================ FILE: backend/src/controllers/middlewaresControllers/createCRUDController/create.js ================================================ const create = async (Model, req, res) => { // Creating a new document in the collection req.body.removed = false; const result = await new Model({ ...req.body, }).save(); // Returning successfull response return res.status(200).json({ success: true, result, message: 'Successfully Created the document in Model ', }); }; module.exports = create; ================================================ FILE: backend/src/controllers/middlewaresControllers/createCRUDController/filter.js ================================================ const filter = async (Model, req, res) => { if (req.query.filter === undefined || req.query.equal === undefined) { return res.status(403).json({ success: false, result: null, message: 'filter not provided correctly', }); } const result = await Model.find({ removed: false, }) .where(req.query.filter) .equals(req.query.equal) .exec(); if (!result) { return res.status(404).json({ success: false, result: null, message: 'No document found ', }); } else { // Return success resposne return res.status(200).json({ success: true, result, message: 'Successfully found all documents ', }); } }; module.exports = filter; ================================================ FILE: backend/src/controllers/middlewaresControllers/createCRUDController/index.js ================================================ const { modelsFiles } = require('@/models/utils'); const mongoose = require('mongoose'); const create = require('./create'); const read = require('./read'); const update = require('./update'); const remove = require('./remove'); const search = require('./search'); const filter = require('./filter'); const summary = require('./summary'); const listAll = require('./listAll'); const paginatedList = require('./paginatedList'); const createCRUDController = (modelName) => { if (!modelsFiles.includes(modelName)) { throw new Error(`Model ${modelName} does not exist`); } const Model = mongoose.model(modelName); let crudMethods = { create: (req, res) => create(Model, req, res), read: (req, res) => read(Model, req, res), update: (req, res) => update(Model, req, res), delete: (req, res) => remove(Model, req, res), list: (req, res) => paginatedList(Model, req, res), listAll: (req, res) => listAll(Model, req, res), search: (req, res) => search(Model, req, res), filter: (req, res) => filter(Model, req, res), summary: (req, res) => summary(Model, req, res), }; return crudMethods; }; module.exports = createCRUDController; ================================================ FILE: backend/src/controllers/middlewaresControllers/createCRUDController/listAll.js ================================================ const listAll = async (Model, req, res) => { const sort = req.query.sort || 'desc'; const enabled = req.query.enabled || undefined; // Query the database for a list of all results let result; if (enabled === undefined) { result = await Model.find({ removed: false, }) .sort({ created: sort }) .populate() .exec(); } else { result = await Model.find({ removed: false, enabled: enabled, }) .sort({ created: sort }) .populate() .exec(); } if (result.length > 0) { return res.status(200).json({ success: true, result, message: 'Successfully found all documents', }); } else { return res.status(203).json({ success: false, result: [], message: 'Collection is Empty', }); } }; module.exports = listAll; ================================================ FILE: backend/src/controllers/middlewaresControllers/createCRUDController/paginatedList.js ================================================ const paginatedList = async (Model, req, res) => { const page = req.query.page || 1; const limit = parseInt(req.query.items) || 10; const skip = page * limit - limit; const { sortBy = 'enabled', sortValue = -1, filter, equal } = req.query; const fieldsArray = req.query.fields ? req.query.fields.split(',') : []; let fields; fields = fieldsArray.length === 0 ? {} : { $or: [] }; for (const field of fieldsArray) { fields.$or.push({ [field]: { $regex: new RegExp(req.query.q, 'i') } }); } // Build filter condition safely: reject MongoDB operators in values let filterCondition = {}; if (filter && equal !== undefined) { if (typeof equal === 'object') { return res.status(400).json({ success: false, result: [], message: 'Invalid filter value', }); } filterCondition = { [filter]: equal }; } // Query the database for a list of all results const resultsPromise = Model.find({ removed: false, ...filterCondition, ...fields, }) .skip(skip) .limit(limit) .sort({ [sortBy]: sortValue }) .populate() .exec(); // Counting the total documents const countPromise = Model.countDocuments({ removed: false, ...filterCondition, ...fields, }); // Resolving both promises const [result, count] = await Promise.all([resultsPromise, countPromise]); // Calculating total pages const pages = Math.ceil(count / limit); // Getting Pagination Object const pagination = { page, pages, count }; if (count > 0) { return res.status(200).json({ success: true, result, pagination, message: 'Successfully found all documents', }); } else { return res.status(203).json({ success: true, result: [], pagination, message: 'Collection is Empty', }); } }; module.exports = paginatedList; ================================================ FILE: backend/src/controllers/middlewaresControllers/createCRUDController/read.js ================================================ const read = async (Model, req, res) => { // Find document by id const result = await Model.findOne({ _id: req.params.id, removed: false, }).exec(); // If no results found, return document not found if (!result) { return res.status(404).json({ success: false, result: null, message: 'No document found ', }); } else { // Return success resposne return res.status(200).json({ success: true, result, message: 'we found this document ', }); } }; module.exports = read; ================================================ FILE: backend/src/controllers/middlewaresControllers/createCRUDController/remove.js ================================================ const remove = async (Model, req, res) => { // Find the document by id and delete it let updates = { removed: true, }; // Find the document by id and delete it const result = await Model.findOneAndUpdate( { _id: req.params.id, }, { $set: updates }, { new: true, // return the new result instead of the old one } ).exec(); // If no results found, return document not found if (!result) { return res.status(404).json({ success: false, result: null, message: 'No document found ', }); } else { return res.status(200).json({ success: true, result, message: 'Successfully Deleted the document ', }); } }; module.exports = remove; ================================================ FILE: backend/src/controllers/middlewaresControllers/createCRUDController/search.js ================================================ const search = async (Model, req, res) => { // console.log(req.query.fields) // if (req.query.q === undefined || req.query.q.trim() === '') { // return res // .status(202) // .json({ // success: false, // result: [], // message: 'No document found by this request', // }) // .end(); // } const fieldsArray = req.query.fields ? req.query.fields.split(',') : ['name']; const fields = { $or: [] }; for (const field of fieldsArray) { fields.$or.push({ [field]: { $regex: new RegExp(req.query.q, 'i') } }); } // console.log(fields) let results = await Model.find({ ...fields, }) .where('removed', false) .limit(20) .exec(); if (results.length >= 1) { return res.status(200).json({ success: true, result: results, message: 'Successfully found all documents', }); } else { return res .status(202) .json({ success: false, result: [], message: 'No document found by this request', }) .end(); } }; module.exports = search; ================================================ FILE: backend/src/controllers/middlewaresControllers/createCRUDController/summary.js ================================================ const summary = async (Model, req, res) => { // Query the database for a list of all results const countPromise = Model.countDocuments({ removed: false, }); const resultsPromise = await Model.countDocuments({ removed: false, }) .where(req.query.filter) .equals(req.query.equal) .exec(); // Resolving both promises const [countFilter, countAllDocs] = await Promise.all([resultsPromise, countPromise]); if (countAllDocs.length > 0) { return res.status(200).json({ success: true, result: { countFilter, countAllDocs }, message: 'Successfully count all documents', }); } else { return res.status(203).json({ success: false, result: [], message: 'Collection is Empty', }); } }; module.exports = summary; ================================================ FILE: backend/src/controllers/middlewaresControllers/createCRUDController/update.js ================================================ const update = async (Model, req, res) => { // Find document by id and updates with the required fields req.body.removed = false; const result = await Model.findOneAndUpdate( { _id: req.params.id, removed: false, }, req.body, { new: true, // return the new result instead of the old one runValidators: true, } ).exec(); if (!result) { return res.status(404).json({ success: false, result: null, message: 'No document found ', }); } else { return res.status(200).json({ success: true, result, message: 'we update this document ', }); } }; module.exports = update; ================================================ FILE: backend/src/controllers/middlewaresControllers/createUserController/index.js ================================================ const read = require('./read'); const updateProfile = require('./updateProfile'); const updatePassword = require('./updatePassword'); const updateProfilePassword = require('./updateProfilePassword'); const createUserController = (userModel) => { let userController = {}; userController.updateProfile = (req, res) => updateProfile(userModel, req, res); userController.updatePassword = (req, res) => updatePassword(userModel, req, res); userController.updateProfilePassword = (req, res) => updateProfilePassword(userModel, req, res); userController.read = (req, res) => read(userModel, req, res); return userController; }; module.exports = createUserController; ================================================ FILE: backend/src/controllers/middlewaresControllers/createUserController/read.js ================================================ const mongoose = require('mongoose'); const read = async (userModel, req, res) => { const User = mongoose.model(userModel); // Find document by id const tmpResult = await User.findOne({ _id: req.params.id, removed: false, }).exec(); // If no results found, return document not found if (!tmpResult) { return res.status(404).json({ success: false, result: null, message: 'No document found ', }); } else { // Return success resposne let result = { _id: tmpResult._id, enabled: tmpResult.enabled, email: tmpResult.email, name: tmpResult.name, surname: tmpResult.surname, photo: tmpResult.photo, role: tmpResult.role, }; return res.status(200).json({ success: true, result, message: 'we found this document ', }); } }; module.exports = read; ================================================ FILE: backend/src/controllers/middlewaresControllers/createUserController/updatePassword.js ================================================ const mongoose = require('mongoose'); const bcrypt = require('bcryptjs'); const { generate: uniqueId } = require('shortid'); const updatePassword = async (userModel, req, res) => { const UserPassword = mongoose.model(userModel + 'Password'); const reqUserName = userModel.toLowerCase(); const userProfile = req[reqUserName]; let { password } = req.body; if (password.length < 8) return res.status(400).json({ msg: 'The password needs to be at least 8 characters long.', }); // Find document by id and updates with the required fields if (userProfile.email === 'admin@admin.com') { return res.status(403).json({ success: false, result: null, message: "you couldn't update demo password", }); } const salt = uniqueId(); const passwordHash = bcrypt.hashSync(salt + password); const UserPasswordData = { password: passwordHash, salt: salt, }; const resultPassword = await UserPassword.findOneAndUpdate( { user: req.params.id, removed: false }, { $set: UserPasswordData }, { new: true, // return the new result instead of the old one } ).exec(); // Code to handle the successful response if (!resultPassword) { return res.status(403).json({ success: false, result: null, message: "User Password couldn't save correctly", }); } return res.status(200).json({ success: true, result: {}, message: 'we update the password by this id: ' + userProfile._id, }); }; module.exports = updatePassword; ================================================ FILE: backend/src/controllers/middlewaresControllers/createUserController/updateProfile.js ================================================ const mongoose = require('mongoose'); const updateProfile = async (userModel, req, res) => { const User = mongoose.model(userModel); const reqUserName = userModel.toLowerCase(); const userProfile = req[reqUserName]; // Get token from Authorization header const authHeader = req.headers['authorization']; const token = authHeader && authHeader.split(' ')[1]; if (userProfile.email === 'admin@demo.com') { return res.status(403).json({ success: false, result: null, message: "you couldn't update demo informations", }); } let updates = req.body.photo ? { email: req.body.email, name: req.body.name, surname: req.body.surname, photo: req.body.photo, } : { email: req.body.email, name: req.body.name, surname: req.body.surname, }; // Find document by id and updates with the required fields const result = await User.findOneAndUpdate( { _id: userProfile._id, removed: false }, { $set: updates }, { new: true, // return the new result instead of the old one } ).exec(); if (!result) { return res.status(404).json({ success: false, result: null, message: 'No profile found by this id: ' + userProfile._id, }); } return res.status(200).json({ success: true, result: { _id: result?._id, enabled: result?.enabled, email: result?.email, name: result?.name, surname: result?.surname, photo: result?.photo, role: result?.role, token }, message: 'we update this profile by this id: ' + userProfile._id, }); }; module.exports = updateProfile; ================================================ FILE: backend/src/controllers/middlewaresControllers/createUserController/updateProfilePassword.js ================================================ const mongoose = require('mongoose'); const bcrypt = require('bcryptjs'); const { generate: uniqueId } = require('shortid'); const updateProfilePassword = async (userModel, req, res) => { const UserPassword = mongoose.model(userModel + 'Password'); const reqUserName = userModel.toLowerCase(); const userProfile = req[reqUserName]; let { password, passwordCheck } = req.body; if (!password || !passwordCheck) return res.status(400).json({ msg: 'Not all fields have been entered.' }); if (password.length < 8) return res.status(400).json({ msg: 'The password needs to be at least 8 characters long.', }); if (password !== passwordCheck) return res.status(400).json({ msg: 'Enter the same password twice for verification.' }); // Find document by id and updates with the required fields const salt = uniqueId(); const passwordHash = bcrypt.hashSync(salt + password); const UserPasswordData = { password: passwordHash, salt: salt, }; if (userProfile.email === 'admin@admin.com') { return res.status(403).json({ success: false, result: null, message: "you couldn't update demo password", }); } const resultPassword = await UserPassword.findOneAndUpdate( { user: userProfile._id, removed: false }, { $set: UserPasswordData }, { new: true, // return the new result instead of the old one } ).exec(); if (!resultPassword) { return res.status(403).json({ success: false, result: null, message: "User Password couldn't save correctly", }); } return res.status(200).json({ success: true, result: {}, message: 'we update the password by this id: ' + userProfile._id, }); }; module.exports = updateProfilePassword; ================================================ FILE: backend/src/controllers/pdfController/index.js ================================================ const pug = require('pug'); const fs = require('fs'); const moment = require('moment'); let pdf = require('html-pdf'); const { listAllSettings, loadSettings } = require('@/middlewares/settings'); const { getData } = require('@/middlewares/serverData'); const useLanguage = require('@/locale/useLanguage'); const { useMoney, useDate } = require('@/settings'); const pugFiles = ['invoice', 'offer', 'quote', 'payment']; require('dotenv').config({ path: '.env' }); require('dotenv').config({ path: '.env.local' }); exports.generatePdf = async ( modelName, info = { filename: 'pdf_file', format: 'A5', targetLocation: '' }, result, callback ) => { try { const { targetLocation } = info; // if PDF already exists, then delete it and create a new PDF if (fs.existsSync(targetLocation)) { fs.unlinkSync(targetLocation); } // render pdf html if (pugFiles.includes(modelName.toLowerCase())) { // Compile Pug template const settings = await loadSettings(); const selectedLang = settings['idurar_app_language']; const translate = useLanguage({ selectedLang }); const { currency_symbol, currency_position, decimal_sep, thousand_sep, cent_precision, zero_format, } = settings; const { moneyFormatter } = useMoney({ settings: { currency_symbol, currency_position, decimal_sep, thousand_sep, cent_precision, zero_format, }, }); const { dateFormat } = useDate({ settings }); settings.public_server_file = process.env.PUBLIC_SERVER_FILE; const htmlContent = pug.renderFile('src/pdf/' + modelName + '.pug', { model: result, settings, translate, dateFormat, moneyFormatter, moment: moment, }); pdf .create(htmlContent, { format: info.format, orientation: 'portrait', border: '10mm', }) .toFile(targetLocation, function (error) { if (error) throw new Error(error); if (callback) callback(); }); } } catch (error) { throw new Error(error); } }; ================================================ FILE: backend/src/emailTemplate/SendEmailTemplate.js ================================================ exports.SendInvoice = ({ title = 'Invoice from Idurar', name = '', time = new Date() }) => { return `
${title}

${title}


Hello ${name},

Here's the invoice you requested at ${time}

`; }; exports.SendQuote = ({ title = 'Quote from Idurar', name = '', time = new Date() }) => { return `
${title}

${title}


Hello ${name},

Here's the quote you requested at ${time}

`; }; exports.SendOffer = ({ title = 'Offer from Idurar', name = '', time = new Date() }) => { return `
${title}

${title}


Hello ${name},

Here's the offer you requested at ${time}

`; }; exports.SendPaymentReceipt = ({ title = 'Payment Receipt from Idurar', name = '', time = new Date(), }) => { return `
${title}

${title}


Hello ${name},

Here's the Payment Receipt you requested at ${time}

`; }; ================================================ FILE: backend/src/emailTemplate/emailVerfication.js ================================================ exports.passwordVerfication = ({ title = 'Reset your Password', name = '', link = '', time = new Date(), }) => { return `
${title}

${title}


Hello ${name},

We have received a request to reset the password for your account on IDURAR. To proceed with the password reset, please click on the link provided below:

${link}

`; }; ================================================ FILE: backend/src/handlers/downloadHandler/downloadPdf.js ================================================ const custom = require('@/controllers/pdfController'); const mongoose = require('mongoose'); module.exports = downloadPdf = async (req, res, { directory, id }) => { try { const modelName = directory.slice(0, 1).toUpperCase() + directory.slice(1); if (mongoose.models[modelName]) { const Model = mongoose.model(modelName); const result = await Model.findOne({ _id: id, }).exec(); // Throw error if no result if (!result) { throw { name: 'ValidationError' }; } // Continue process if result is returned const fileId = modelName.toLowerCase() + '-' + result._id + '.pdf'; const folderPath = modelName.toLowerCase(); const targetLocation = `src/public/download/${folderPath}/${fileId}`; await custom.generatePdf( modelName, { filename: folderPath, format: 'A4', targetLocation }, result, async () => { return res.download(targetLocation, (error) => { if (error) return res.status(500).json({ success: false, result: null, message: "Couldn't find file", error: error.message, }); }); } ); } else { return res.status(404).json({ success: false, result: null, message: `Model '${modelName}' does not exist`, }); } } catch (error) { // If error is thrown by Mongoose due to required validations if (error.name == 'ValidationError') { return res.status(400).json({ success: false, result: null, error: error.message, message: 'Required fields are not supplied', }); } else if (error.name == 'BSONTypeError') { // If error is thrown by Mongoose due to invalid ID return res.status(400).json({ success: false, result: null, error: error.message, message: 'Invalid ID', }); } else { // Server Error return res.status(500).json({ success: false, result: null, error: error.message, message: error.message, controller: 'downloadPDF.js', }); } } }; ================================================ FILE: backend/src/handlers/errorHandlers.js ================================================ /* Catch Errors Handler With async/await, you need some way to catch errors Instead of using try{} catch(e) {} in each controller, we wrap the function in catchErrors(), catch any errors they throw, and pass it along to our express middleware with next() */ exports.catchErrors = (fn) => { return function (req, res, next) { return fn(req, res, next).catch((error) => { if (error.name == 'ValidationError') { return res.status(400).json({ success: false, result: null, message: 'Required fields are not supplied', controller: fn.name, error: error, }); } else { // Server Error return res.status(500).json({ success: false, result: null, message: error.message, controller: fn.name, error: error, }); } }); }; }; /* Not Found Error Handler If we hit a route that is not found, we mark it as 404 and pass it along to the next error handler to display */ exports.notFound = (req, res, next) => { return res.status(404).json({ success: false, message: "Api url doesn't exist ", }); }; /* Development Error Handler In development we show good error messages so if we hit a syntax error or any other previously un-handled error, we can show good info on what happened */ exports.developmentErrors = (error, req, res, next) => { error.stack = error.stack || ''; const errorDetails = { message: error.message, status: error.status, stackHighlighted: error.stack.replace(/[a-z_-\d]+.js:\d+:\d+/gi, '$&'), }; return res.status(500).json({ success: false, message: error.message, error: error, }); }; /* Production Error Handler No stacktraces are leaked to admin */ exports.productionErrors = (error, req, res, next) => { return res.status(500).json({ success: false, message: error.message, error: error, }); }; ================================================ FILE: backend/src/helpers.js ================================================ /* This is a file of data and helper functions that we can expose and use in our templating function */ // FS is a built in module to node that let's us read files from the system we're running on const fs = require('fs'); const currency = require('currency.js'); // moment.js is a handy library for displaying dates. We need this in our templates to display things like "Posted 5 minutes ago" exports.moment = require('moment'); // Making a static map is really long - this is a handy helper function to make one // inserting an SVG exports.icon = (name) => { try { return fs.readFileSync(`./public/images/icons/${name}.svg`); } catch (error) { return null; } }; exports.image = (name) => fs.readFileSync(`./public/images/photos/${name}.jpg`); // Some details about the site exports.siteName = `Express.js / MongoBD / Rest Api`; exports.timeRange = (start, end, format, interval) => { if (format == undefined) { format = 'HH:mm'; } if (interval == undefined) { interval = 60; } interval = interval > 0 ? interval : 60; const range = []; while (moment(start).isBefore(moment(end))) { range.push(moment(start).format(format)); start = moment(start).add(interval, 'minutes'); } return range; }; exports.calculate = { add: (firstValue, secondValue) => { return currency(firstValue).add(secondValue).value; }, sub: (firstValue, secondValue) => { return currency(firstValue).subtract(secondValue).value; }, multiply: (firstValue, secondValue) => { return currency(firstValue).multiply(secondValue).value; }, divide: (firstValue, secondValue) => { return currency(firstValue).divide(secondValue).value; }, }; ================================================ FILE: backend/src/locale/languages.js ================================================ module.exports = []; ================================================ FILE: backend/src/locale/translation/en_us.js ================================================ module.exports = { sign_up: 'Sign Up', manage_your_company_with: 'Manage Your Company With', all_in_one_tool: 'All In One Tool', run_and_scale_your_erp_crm_apps: 'Run And Scale Your Erp Crm Apps', easily_add_and_manage_your_services: 'Easily Add And Manage Your Services', it_brings_together_your_invoice_clients_and_leads: 'It Brings Together Your Invoice Clients And Leads', select_language: 'Select Language', register: 'Register', or: 'Or', already_have_account_login: 'Already Have Account Login', name: 'Name', email: 'Email', password: 'Password', country: 'Country', afghanistan: 'Afghanistan', albania: 'Albania', algeria: 'Algeria', andorra: 'Andorra', angola: 'Angola', anguilla: 'Anguilla', argentina: 'Argentina', armenia: 'Armenia', aruba: 'Aruba', australia: 'Australia', austria: 'Austria', azerbaijan: 'Azerbaijan', bahamas: 'Bahamas', bahrain: 'Bahrain', bangladesh: 'Bangladesh', barbados: 'Barbados', belarus: 'Belarus', belgium: 'Belgium', belize: 'Belize', benin: 'Benin', bermuda: 'Bermuda', bhutan: 'Bhutan', bolivia: 'Bolivia', bosnia_and_herzegovina: 'Bosnia And Herzegovina', botswana: 'Botswana', brazil: 'Brazil', brunei_darussalam: 'Brunei Darussalam', bulgaria: 'Bulgaria', burkina_faso: 'Burkina Faso', burundi: 'Burundi', cabo_verde: 'Cabo Verde', cambodia: 'Cambodia', cameroon: 'Cameroon', canada: 'Canada', central_african_republic: 'Central African Republic', chad: 'Chad', chile: 'Chile', china: 'China', colombia: 'Colombia', comoros: 'Comoros', congo: 'Congo', costa_rica: 'Costa Rica', croatia: 'Croatia', cuba: 'Cuba', cyprus: 'Cyprus', czechia: 'Czechia', cote_d_ivoire: 'Cote D Ivoire', denmark: 'Denmark', djibouti: 'Djibouti', dominica: 'Dominica', dominican_republic: 'Dominican Republic', ecuador: 'Ecuador', egypt: 'Egypt', el_salvador: 'El Salvador', eritrea: 'Eritrea', estonia: 'Estonia', eswatini: 'Eswatini', ethiopia: 'Ethiopia', fiji: 'Fiji', finland: 'Finland', france: 'France', gabon: 'Gabon', gambia: 'Gambia', georgia: 'Georgia', germany: 'Germany', ghana: 'Ghana', gibraltar: 'Gibraltar', greece: 'Greece', greenland: 'Greenland', guadeloupe: 'Guadeloupe', guam: 'Guam', guatemala: 'Guatemala', guernsey: 'Guernsey', guinea: 'Guinea', guinea_bissau: 'Guinea Bissau', guyana: 'Guyana', haiti: 'Haiti', honduras: 'Honduras', hong_kong: 'Hong Kong', hungary: 'Hungary', iceland: 'Iceland', india: 'India', indonesia: 'Indonesia', iran: 'Iran', iraq: 'Iraq', ireland: 'Ireland', israel: 'Israel', italy: 'Italy', jamaica: 'Jamaica', japan: 'Japan', jordan: 'Jordan', kazakhstan: 'Kazakhstan', kenya: 'Kenya', korea: 'Korea', kuwait: 'Kuwait', kyrgyzstan: 'Kyrgyzstan', latvia: 'Latvia', lebanon: 'Lebanon', lesotho: 'Lesotho', liberia: 'Liberia', libya: 'Libya', liechtenstein: 'Liechtenstein', lithuania: 'Lithuania', luxembourg: 'Luxembourg', madagascar: 'Madagascar', malawi: 'Malawi', malaysia: 'Malaysia', maldives: 'Maldives', mali: 'Mali', malta: 'Malta', martinique: 'Martinique', mauritania: 'Mauritania', mauritius: 'Mauritius', mexico: 'Mexico', moldova: 'Moldova', monaco: 'Monaco', mongolia: 'Mongolia', montenegro: 'Montenegro', montserrat: 'Montserrat', morocco: 'Morocco', mozambique: 'Mozambique', myanmar: 'Myanmar', namibia: 'Namibia', nepal: 'Nepal', netherlands: 'Netherlands', new_caledonia: 'New Caledonia', new_zealand: 'New Zealand', nicaragua: 'Nicaragua', niger: 'Niger', nigeria: 'Nigeria', norway: 'Norway', oman: 'Oman', pakistan: 'Pakistan', palestine: 'Palestine', panama: 'Panama', papua_new_guinea: 'Papua New Guinea', paraguay: 'Paraguay', peru: 'Peru', philippines: 'Philippines', poland: 'Poland', portugal: 'Portugal', puerto_rico: 'Puerto Rico', qatar: 'Qatar', macedonia: 'Macedonia', romania: 'Romania', russia: 'Russia', rwanda: 'Rwanda', r_union: 'R Union', saudi_arabia: 'Saudi Arabia', senegal: 'Senegal', serbia: 'Serbia', singapore: 'Singapore', slovakia: 'Slovakia', slovenia: 'Slovenia', somalia: 'Somalia', south_africa: 'South Africa', south_sudan: 'South Sudan', spain: 'Spain', sri_lanka: 'Sri Lanka', sudan: 'Sudan', suriname: 'Suriname', sweden: 'Sweden', switzerland: 'Switzerland', syria: 'Syria', taiwan: 'Taiwan', tajikistan: 'Tajikistan', tanzania: 'Tanzania', thailand: 'Thailand', timor_leste: 'Timor Leste', togo: 'Togo', tonga: 'Tonga', tunisia: 'Tunisia', turkey: 'Turkey', turkmenistan: 'Turkmenistan', uganda: 'Uganda', ukraine: 'Ukraine', united_arab_emirates: 'United Arab Emirates', united_kingdom: 'United Kingdom', united_states: 'United States', uruguay: 'Uruguay', uzbekistan: 'Uzbekistan', venezuela: 'Venezuela', vietnam: 'Vietnam', yemen: 'Yemen', zambia: 'Zambia', zimbabwe: 'Zimbabwe', verify_your_account: 'Verify Your Account', check_your_email_address_to_verify_your_account: 'Check Your Email Address To Verify Your Account', complete_verification_by_providing_the_code_that_you_received_by_email: 'Complete Verification By Providing The Code That You Received By Email', verify_now: 'Verify Now', dashboard: 'Dashboard', customer: 'Customer', people: 'People', company: 'Company', lead: 'Lead', offer: 'Offer', invoice: 'Invoice', quote: 'Quote', payment: 'Payment', product: 'Product', product_category: 'Product Category', expense: 'Expense', expenses_category: 'Expenses Category', settings: 'Settings', admin: 'Admin', currency: 'Currency', payment_mode: 'Payment Mode', taxes: 'Taxes', about: 'About', profile_settings: 'Profile Settings', app_settings: 'App Settings', logout: 'Logout', number: 'Number', client: 'Client', total: 'Total', status: 'Status', invoices_preview: 'Invoices Preview', quotes_preview: 'Quotes Preview', offers_preview: 'Offers Preview', payments_preview: 'Payments Preview', this_month: 'This Month', unpaid: 'Unpaid', not_paid: 'Not Paid', recent_invoices: 'Recent Invoices', recent_quotes: 'Recent Quotes', customer_preview: 'Customer Preview', show: 'Show', edit: 'Edit', download: 'Download', draft: 'Draft', pending: 'Pending', sent: 'Sent', declined: 'Declined', accepted: 'Accepted', expired: 'Expired', new_customer_this_month: 'New Customer This Month', active_customer: 'Active Customer', overdue: 'Overdue', partially: 'Partially', paid: 'Paid', sign_in: 'Sign In', log_in: 'Log In', register_now: 'Register Now', remember_me: 'Remember Me', forgot_password: 'Forgot Password', forget_password: 'Forget Password', request_new_password: 'Request New Password', password_reset_in_progress: 'Password Reset In Progress', check_your_email_address_to_reset_your_password: 'Check Your Email Address To Reset Your Password', login: 'Login', reset_password: 'Reset Password', update_password: 'Update Password', profile: 'Profile', first_name: 'First Name', last_name: 'Last Name', role: 'Role', close: 'Close', save: 'Save', photo: 'Photo', click_to_upload: 'Click To Upload', new_password: 'New Password', confirm_password: 'Confirm Password', general_settings: 'General Settings', company_settings: 'Company Settings', company_logo: 'Company Logo', currency_settings: 'Currency Settings', finance_settings: 'Finance Settings', settings_list: 'Settings List', add_new_settings: 'Add New Settings', update_your_app_configuration: 'Update Your App Configuration', language: 'Language', date_format: 'Date Format', update_your_company_informations: 'Update Your Company Informations', company_name: 'Company Name', company_address: 'Company Address', company_state: 'Company State', company_country: 'Company Country', company_email: 'Company Email', company_phone: 'Company Phone', company_cell: 'Company Cell', company_website: 'Company Website', company_tax_number: 'Company Tax Number', company_vat_number: 'Company Vat Number', company_reg_number: 'Company Reg Number', update_company_logo: 'Update Company Logo', money_format_settings: 'Money Format Settings', default_currency: 'Default Currency', select_default_currency: 'Select Default Currency', update_company_finance_settings: 'Update Company Finance Settings', last_invoice_number: 'Last Invoice Number', last_quote_number: 'Last Quote Number', last_offer_number: 'Last Offer Number', last_payment_number: 'Last Payment Number', client_list: 'Client List', add_new_client: 'Add New Client', delete: 'Delete', type: 'Type', phone: 'Phone', refresh: 'Refresh', are_you_sure_you_want_to_delete: 'Are You Sure You Want To Delete', delete_confirmation: 'Delete Confirmation', remove: 'Remove', cancel: 'Cancel', select_date: 'Select Date', add_new_person: 'Add New Person', add_new_company: 'Add New Company', submit: 'Submit', person: 'Person', people_list: 'People List', firstname: 'Firstname', lastname: 'Lastname', company_list: 'Company List', contact: 'Contact', website: 'Website', lead_list: 'Lead List', add_new_lead: 'Add New Lead', source: 'Source', notes: 'Notes', new: 'New', in_negociation: 'In Negociation', won: 'Won', loose: 'Loose', canceled: 'Canceled', assigned: 'Assigned', on_hold: 'On Hold', waiting: 'Waiting', linkedin: 'Linkedin', social_media: 'Social Media', advertising: 'Advertising', friend: 'Friend', professionals_network: 'Professionals Network', customer_referral: 'Customer Referral', sales: 'Sales', other: 'Other', add_new: 'Add New', date: 'Date', sub_total: 'Sub Total', note: 'Note', offer_list: 'Offer List', add_new_offer: 'Add New Offer', year: 'Year', expire_date: 'Expire Date', item: 'Item', description: 'Description', quantity: 'Quantity', price: 'Price', add_new_tax: 'Add New Tax', select_tax_value: 'Select Tax Value', add_field: 'Add Field', error_404: 'Error 404', sorry_the_page_you_requested_does_not_exist: 'Sorry The Page You Requested Does Not Exist', back: 'Back', download_pdf: 'Download Pdf', send_by_email: 'Send By Email', convert_to_invoice: 'Convert To Invoice', subtotal: 'Subtotal', address: 'Address', update: 'Update', expired_date: 'Expired Date', created_by: 'Created By', invoice_list: 'Invoice List', add_new_invoice: 'Add New Invoice', record_payment: 'Record Payment', tax_total: 'Tax Total', show_invoice: 'Show Invoice', payment_status: 'Payment Status', discount: 'Discount', amount: 'Amount', reference: 'Reference', add_payment_mode: 'Add Payment Mode', quote_list: 'Quote List', add_new_quote: 'Add New Quote', payment_list: 'Payment List', add_new_payment: 'Add New Payment', payment_information: 'Payment Information', total_paid: 'Total Paid', total_remaining: 'Total Remaining', product_list: 'Product List', add_new_product: 'Add New Product', ref: 'Ref', product_category_list: 'Product Category List', add_new_product_category: 'Add New Product Category', color: 'Color', enabled: 'Enabled', expense_list: 'Expense List', add_new_expense: 'Add New Expense', expense_category: 'Expense Category', expense_category_list: 'Expense Category List', add_new_expense_category: 'Add New Expense Category', admin_list: 'Admin List', add_new_admin: 'Add New Admin', admin_super_admin: 'Admin Super Admin', staff_admin_crud: 'Staff Admin Crud', staff_cru: 'Staff Cru', create_and_read_only: 'Create And Read Only', read_only: 'Read Only', currency_list: 'Currency List', add_new_currency: 'Add New Currency', currency_name: 'Currency Name', currency_code: 'Currency Code', currency_symbol: 'Currency Symbol', currency_position: 'Currency Position', decimal_separator: 'Decimal Separator', thousand_separator: 'Thousand Separator', cent_precision: 'Cent Precision', zero_format: 'Zero Format', default: 'Default', payment_mode_list: 'Payment Mode List', add_new_payment_mode: 'Add New Payment Mode', default_mode: 'Default Mode', value: 'Value', taxes_list: 'Taxes List', do_you_need_help_on_customize_of_this_app: 'Do You Need Help On Customize Of This App', contact_us: 'Contact Us', customers: 'Customers', peoples: 'Peoples', companies: 'Companies', leads: 'Leads', offer_leads: 'Offer Leads', invoices: 'Invoices', quotes: 'Quotes', payments: 'Payments', products: 'Products', products_category: 'Products Category', expenses: 'Expenses', currencies: 'Currencies', payments_mode: 'Payments Mode', account_owner: 'Account Owner', create_only: 'Create Only', enter_code: 'Enter Code', offers: 'Offers', proforma_invoices: 'quote', }; ================================================ FILE: backend/src/locale/useLanguage.js ================================================ const { readBySettingKey } = require('@/middlewares/settings'); const getLabel = (lang, key) => { try { const lowerCaseKey = key .toLowerCase() .replace(/[^a-zA-Z0-9]/g, '_') .replace(/ /g, '_'); if (lang[lowerCaseKey]) return lang[lowerCaseKey]; else { const remove_underscore_fromKey = lowerCaseKey.replace(/_/g, ' ').split(' '); const conversionOfAllFirstCharacterofEachWord = remove_underscore_fromKey.map( (word) => word[0].toUpperCase() + word.substring(1) ); const label = conversionOfAllFirstCharacterofEachWord.join(' '); return label; } } catch (error) { return 'No translate Found'; } }; const useSelector = () => { const defaultfilePath = `./translation/en_us`; const langFile = require(defaultfilePath); return langFile; }; const useLanguage = ({ selectedLang }) => { const lang = useSelector(); const translate = (value) => { const text = getLabel(lang, value); return text; }; return translate; }; module.exports = useLanguage; ================================================ FILE: backend/src/middlewares/inventory/generateUniqueNumber.js ================================================ function generateUniqueNumber(uniqueId, numberLength = 13) { const currentDate = new Date(); const year = (currentDate.getFullYear() % 100).toString().padStart(2, '0'); const month = (currentDate.getMonth() + 1).toString().padStart(2, '0'); const day = currentDate.getDate().toString().padStart(2, '0'); const randomNumber = Math.floor(Math.random() * 900) + 100; const number = (uniqueId + 1).toString().padStart(numberLength - 9, '0'); // numberLength - 9 , 9 is length day + month + year + randomNumber return day + month + year + randomNumber + number; } module.exports = generateUniqueNumber; ================================================ FILE: backend/src/middlewares/inventory/index.js ================================================ const generateUniqueNumber = require('../inventory/generateUniqueNumber'); module.exports = { generateUniqueNumber, }; ================================================ FILE: backend/src/middlewares/serverData.js ================================================ const mongoose = require('mongoose'); exports.getData = ({ model }) => { const Model = mongoose.model(model); const result = Model.find({ removed: false, enabled: true }); return result; }; exports.getOne = ({ model, id }) => { const Model = mongoose.model(model); const result = Model.findOne({ _id: id, removed: false }); return result; }; ================================================ FILE: backend/src/middlewares/settings/increaseBySettingKey.js ================================================ const mongoose = require('mongoose'); const Model = mongoose.model('Setting'); const increaseBySettingKey = async ({ settingKey }) => { try { if (!settingKey) { return null; } const result = await Model.findOneAndUpdate( { settingKey }, { $inc: { settingValue: 1 }, }, { new: true, // return the new result instead of the old one runValidators: true, } ).exec(); // If no results found, return document not found if (!result) { return null; } else { // Return success resposne return result; } } catch { return null; } }; module.exports = increaseBySettingKey; ================================================ FILE: backend/src/middlewares/settings/index.js ================================================ const listBySettingKey = require('./listBySettingKey'); const readBySettingKey = require('./readBySettingKey'); const listAllSettings = require('./listAllSettings'); const updateBySettingKey = require('./updateBySettingKey'); const increaseBySettingKey = require('./increaseBySettingKey'); const loadSettings = require('./loadSettings'); module.exports = { loadSettings, listAllSettings, listBySettingKey, readBySettingKey, updateBySettingKey, increaseBySettingKey, }; ================================================ FILE: backend/src/middlewares/settings/listAllSettings.js ================================================ const mongoose = require('mongoose'); const Model = mongoose.model('Setting'); const listAllSettings = async () => { try { // Query the database for a list of all results const result = await Model.find({ removed: false, }).exec(); if (result.length > 0) { return result; } else { return []; } } catch { return []; } }; module.exports = listAllSettings; ================================================ FILE: backend/src/middlewares/settings/listBySettingKey.js ================================================ const mongoose = require('mongoose'); const Model = mongoose.model('Setting'); const listBySettingKey = async ({ settingKeyArray = [] }) => { try { // Find document by id const settingsToShow = { $or: [] }; if (settingKeyArray.length === 0) { return []; } for (const settingKey of settingKeyArray) { settingsToShow.$or.push({ settingKey }); } let results = await Model.find({ ...settings }).where('removed', false); // If no results found, return document not found if (results.length >= 1) { return results; } else { return []; } } catch { return []; } }; module.exports = listBySettingKey; ================================================ FILE: backend/src/middlewares/settings/loadSettings.js ================================================ const listAllSettings = require('./listAllSettings'); const loadSettings = async () => { const allSettings = {}; const datas = await listAllSettings(); datas.forEach(({ settingKey, settingValue }) => { allSettings[settingKey] = settingValue; }); return allSettings; }; module.exports = loadSettings; ================================================ FILE: backend/src/middlewares/settings/readBySettingKey.js ================================================ const mongoose = require('mongoose'); const Model = mongoose.model('Setting'); const readBySettingKey = async ({ settingKey }) => { try { // Find document by id if (!settingKey) { return null; } const result = await Model.findOne({ settingKey }); // If no results found, return document not found if (!result) { return null; } else { // Return success resposne return result; } } catch { return null; } }; module.exports = readBySettingKey; ================================================ FILE: backend/src/middlewares/settings/updateBySettingKey.js ================================================ const mongoose = require('mongoose'); const Model = mongoose.model('Setting'); const updateBySettingKey = async ({ settingKey, settingValue }) => { try { if (!settingKey || !settingValue) { return null; } const result = await Model.findOneAndUpdate( { settingKey }, { settingValue, }, { new: true, // return the new result instead of the old one runValidators: true, } ).exec(); // If no results found, return document not found if (!result) { return null; } else { // Return success resposne return result; } } catch { return null; } }; module.exports = updateBySettingKey; ================================================ FILE: backend/src/middlewares/uploadMiddleware/DoSingleStorage.js ================================================ require('dotenv').config({ path: '.env' }); require('dotenv').config({ path: '.env.local' }); const path = require('path'); const { slugify } = require('transliteration'); const fileFilterMiddleware = require('./utils/fileFilterMiddleware'); const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3'); const secretAccessKey = process.env.DO_SPACES_SECRET; const accessKeyId = process.env.DO_SPACES_KEY; const endpoint = 'https://' + process.env.DO_SPACES_URL; const region = process.env.REGION; const clientParams = { endpoint: endpoint, region: region, credentials: { accessKeyId, secretAccessKey, }, }; const DoSingleStorage = ({ entity, fileType = 'default', uploadFieldName = 'file', fieldName = 'file', }) => { return async function (req, res, next) { if (!req.files || Object.keys(req.files)?.length === 0 || !req.files?.file) { req.body[fieldName] = null; next(); } else { const s3Client = new S3Client(clientParams); try { if (!fileFilterMiddleware({ type: fileType, mimetype: req.files.file.mimetype })) { // skip upload if File type not supported throw new Error('Uploaded file type not supported'); // next(); } let fileExtension = path.extname(req.files.file.name); const fileNameWithoutExt = path.parse(req.files.file.name).name; let uniqueFileID = Math.random().toString(36).slice(2, 7); // generates unique ID of length 5 let originalname = ''; if (req.body.seotitle) { originalname = slugify(req.body.seotitle.toLocaleLowerCase()); // convert any language to English characters } else { originalname = slugify(fileNameWithoutExt.toLocaleLowerCase()); // convert any language to English characters } let _fileName = `${originalname}-${uniqueFileID}${fileExtension}`; const filePath = `public/uploads/${entity}/${_fileName}`; let uploadParams = { Key: `${filePath}`, Bucket: process.env.DO_SPACES_NAME, ACL: 'public-read', Body: req.files.file.data, }; const command = new PutObjectCommand(uploadParams); const s3response = await s3Client.send(command); if (s3response.$metadata.httpStatusCode === 200) { // saving file name and extension in request upload object req.upload = { fileName: _fileName, fieldExt: fileExtension, entity: entity, fieldName: fieldName, fileType: fileType, filePath: filePath, }; req.body[fieldName] = filePath; next(); } } catch (error) { return res.status(403).json({ success: false, result: null, controller: 'DoSingleStorage.js', message: 'Error on uploading file', }); } } }; }; module.exports = DoSingleStorage; ================================================ FILE: backend/src/middlewares/uploadMiddleware/LocalSingleStorage.js ================================================ const multer = require('multer'); const path = require('path'); const { slugify } = require('transliteration'); const fileFilter = require('./utils/LocalfileFilter'); const singleStorageUpload = ({ entity, fileType = 'default', uploadFieldName = 'file', fieldName = 'file', }) => { var diskStorage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, `src/public/uploads/${entity}`); }, filename: function (req, file, cb) { try { // fetching the file extension of the uploaded file let fileExtension = path.extname(file.originalname); let uniqueFileID = Math.random().toString(36).slice(2, 7); // generates unique ID of length 5 let originalname = ''; if (req.body.seotitle) { originalname = slugify(req.body.seotitle.toLocaleLowerCase()); // convert any language to English characters } else { originalname = slugify(file.originalname.split('.')[0].toLocaleLowerCase()); // convert any language to English characters } let _fileName = `${originalname}-${uniqueFileID}${fileExtension}`; const filePath = `public/uploads/${entity}/${_fileName}`; // saving file name and extension in request upload object req.upload = { fileName: _fileName, fieldExt: fileExtension, entity: entity, fieldName: fieldName, fileType: fileType, filePath: filePath, }; req.body[fieldName] = filePath; cb(null, _fileName); } catch (error) { cb(error); // pass the error to the callback } }, }); let filterType = fileFilter(fileType); const multerStorage = multer({ storage: diskStorage, fileFilter: filterType }).single('file'); return multerStorage; }; module.exports = singleStorageUpload; ================================================ FILE: backend/src/middlewares/uploadMiddleware/index.js ================================================ const singleStorageUpload = require('./singleStorageUpload'); const LocalSingleStorage = require('./LocalSingleStorage'); module.exports = { singleStorageUpload, LocalSingleStorage, }; ================================================ FILE: backend/src/middlewares/uploadMiddleware/singleStorageUpload.js ================================================ const multer = require('multer'); const path = require('path'); const { slugify } = require('transliteration'); const fileFilter = require('./utils/LocalfileFilter'); const singleStorageUpload = ({ entity, fileType = 'default', uploadFieldName = 'file', fieldName = 'file', }) => { var diskStorage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, `src/public/uploads/${entity}`); }, filename: function (req, file, cb) { try { // fetching the file extension of the uploaded file let fileExtension = path.extname(file.originalname); let uniqueFileID = Math.random().toString(36).slice(2, 7); // generates unique ID of length 5 let originalname = ''; if (req.body.seotitle) { originalname = slugify(req.body.seotitle.toLocaleLowerCase()); // convert any language to English characters } else { originalname = slugify(file.originalname.split('.')[0].toLocaleLowerCase()); // convert any language to English characters } let _fileName = `${originalname}-${uniqueFileID}${fileExtension}`; const filePath = `public/uploads/${entity}/${_fileName}`; // saving file name and extension in request upload object req.upload = { fileName: _fileName, fieldExt: fileExtension, entity: entity, fieldName: fieldName, fileType: fileType, filePath: filePath, }; req.body[fieldName] = filePath; cb(null, _fileName); } catch (error) { cb(error); // pass the error to the callback } }, }); let filterType = fileFilter(fileType); const multerStorage = multer({ storage: diskStorage, fileFilter: filterType }).single('file'); return multerStorage; }; module.exports = singleStorageUpload; ================================================ FILE: backend/src/middlewares/uploadMiddleware/utils/LocalfileFilter.js ================================================ const fileFilter = (type = 'default') => (req, file, cb) => { // array containing all the possible file types const _fileType = [ 'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml', 'application/msword', 'text/plain', 'text/csv', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.ms-excel', 'application/pdf', 'application/zip', 'application/vnd.rar', 'video/mp4', 'video/x-msvideo', 'audio/mpeg', 'video/webm', ]; if (type === 'default') { return cb(null, true); } else { let _flag = _fileType.includes(file.mimetype); if (type === 'image') { if (!file.mimetype.startsWith('image/')) { _flag = false; } } else if (type === 'pdf') { if (!file.mimetype.startsWith('application/pdf')) { _flag = false; } } else if (type === 'video') { if (!file.mimetype.startsWith('video/')) { _flag = false; } } else if (type === 'audio') { if (!file.mimetype.startsWith('audio/')) { _flag = false; } } else if (type === 'text') { if ( !file.mimetype.startsWith('text/') && !file.mimetype.startsWith('application/vnd.ms-excel') && !file.mimetype.startsWith('application/msword') && !file.mimetype.startsWith( 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' ) ) { _flag = false; } } else if (type === 'excel') { if ( !file.mimetype.startsWith('application/vnd.ms-excel') && !file.mimetype.startsWith( 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ) ) { _flag = false; } } else if (type === 'compressed') { if ( !file.mimetype.startsWith('application/zip') && !file.mimetype.startsWith('application/x-zip-compressed') && !file.mimetype.startsWith('application/vnd.rar') ) { _flag = false; } } if (_flag) { return cb(null, true); } else { return cb(new Error(`${file.mimetype} File type not supported!`)); } } }; module.exports = fileFilter; ================================================ FILE: backend/src/middlewares/uploadMiddleware/utils/fileFilterMiddleware.js ================================================ const fileFilterMiddleware = ({ type = 'default', mimetype }) => { // array containing all the possible file types const _fileType = [ 'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml', 'application/msword', 'text/plain', 'text/csv', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/vnd.ms-excel', 'application/pdf', 'application/zip', 'application/vnd.rar', 'video/mp4', 'video/x-msvideo', 'audio/mpeg', 'video/webm', ]; if (type === 'default') { return true; } else { let _flag = _fileType.includes(mimetype); if (type === 'image') { if (!mimetype.startsWith('image/')) { _flag = false; } } else if (type === 'pdf') { if (!mimetype.startsWith('application/pdf')) { _flag = false; } } else if (type === 'video') { if (!mimetype.startsWith('video/')) { _flag = false; } } else if (type === 'audio') { if (!mimetype.startsWith('audio/')) { _flag = false; } } else if (type === 'text') { if ( !mimetype.startsWith('text/') && !mimetype.startsWith('application/vnd.ms-excel') && !mimetype.startsWith('application/msword') && !mimetype.startsWith( 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' ) ) { _flag = false; } } else if (type === 'excel') { if ( !mimetype.startsWith('application/vnd.ms-excel') && !mimetype.startsWith('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') ) { _flag = false; } } else if (type === 'compressed') { if ( !mimetype.startsWith('application/zip') && !mimetype.startsWith('application/x-zip-compressed') && !mimetype.startsWith('application/vnd.rar') ) { _flag = false; } } if (_flag) { return true; } else { return false; } } }; module.exports = fileFilterMiddleware; ================================================ FILE: backend/src/models/.gitkeep ================================================ ================================================ FILE: backend/src/models/appModels/Client.js ================================================ const mongoose = require('mongoose'); const schema = new mongoose.Schema({ removed: { type: Boolean, default: false, }, enabled: { type: Boolean, default: true, }, name: { type: String, required: true, }, phone: String, country: String, address: String, email: String, createdBy: { type: mongoose.Schema.ObjectId, ref: 'Admin' }, assigned: { type: mongoose.Schema.ObjectId, ref: 'Admin' }, created: { type: Date, default: Date.now, }, updated: { type: Date, default: Date.now, }, }); schema.plugin(require('mongoose-autopopulate')); module.exports = mongoose.model('Client', schema); ================================================ FILE: backend/src/models/appModels/Invoice.js ================================================ const mongoose = require('mongoose'); const invoiceSchema = new mongoose.Schema({ removed: { type: Boolean, default: false, }, createdBy: { type: mongoose.Schema.ObjectId, ref: 'Admin', required: true }, number: { type: Number, required: true, }, year: { type: Number, required: true, }, content: String, recurring: { type: String, enum: ['daily', 'weekly', 'monthly', 'annually', 'quarter'], }, date: { type: Date, required: true, }, expiredDate: { type: Date, required: true, }, client: { type: mongoose.Schema.ObjectId, ref: 'Client', required: true, autopopulate: true, }, converted: { from: { type: String, enum: ['quote', 'offer'], }, offer: { type: mongoose.Schema.ObjectId, ref: 'Offer', }, quote: { type: mongoose.Schema.ObjectId, ref: 'Quote', }, }, items: [ { // product: { // type: mongoose.Schema.ObjectId, // ref: 'Product', // // required: true, // }, itemName: { type: String, required: true, }, description: { type: String, }, quantity: { type: Number, default: 1, required: true, }, price: { type: Number, required: true, }, // discount: { // type: Number, // default: 0, // }, // taxRate: { // type: Number, // default: 0, // }, // subTotal: { // type: Number, // default: 0, // }, // taxTotal: { // type: Number, // default: 0, // }, total: { type: Number, required: true, }, }, ], taxRate: { type: Number, default: 0, }, subTotal: { type: Number, default: 0, }, taxTotal: { type: Number, default: 0, }, total: { type: Number, default: 0, }, currency: { type: String, default: 'NA', uppercase: true, required: true, }, credit: { type: Number, default: 0, }, discount: { type: Number, default: 0, }, payment: [ { type: mongoose.Schema.ObjectId, ref: 'Payment', }, ], paymentStatus: { type: String, default: 'unpaid', enum: ['unpaid', 'paid', 'partially'], }, isOverdue: { type: Boolean, default: false, }, approved: { type: Boolean, default: false, }, notes: { type: String, }, status: { type: String, enum: ['draft', 'pending', 'sent', 'refunded', 'cancelled', 'on hold'], default: 'draft', }, pdf: { type: String, }, files: [ { id: String, name: String, path: String, description: String, isPublic: { type: Boolean, default: true, }, }, ], updated: { type: Date, default: Date.now, }, created: { type: Date, default: Date.now, }, }); invoiceSchema.plugin(require('mongoose-autopopulate')); module.exports = mongoose.model('Invoice', invoiceSchema); ================================================ FILE: backend/src/models/appModels/Payment.js ================================================ const mongoose = require('mongoose'); const paymentSchema = new mongoose.Schema({ removed: { type: Boolean, default: false, }, createdBy: { type: mongoose.Schema.ObjectId, ref: 'Admin', autopopulate: true, required: true }, number: { type: Number, required: true, }, client: { type: mongoose.Schema.ObjectId, ref: 'Client', autopopulate: true, required: true, }, invoice: { type: mongoose.Schema.ObjectId, ref: 'Invoice', required: true, autopopulate: true, }, date: { type: Date, default: Date.now, required: true, }, amount: { type: Number, required: true, }, currency: { type: String, default: 'NA', uppercase: true, required: true, }, ref: { type: String, }, description: { type: String, }, updated: { type: Date, default: Date.now, }, created: { type: Date, default: Date.now, }, }); paymentSchema.plugin(require('mongoose-autopopulate')); module.exports = mongoose.model('Payment', paymentSchema); ================================================ FILE: backend/src/models/coreModels/Admin.js ================================================ const mongoose = require('mongoose'); const Schema = mongoose.Schema; const adminSchema = new Schema({ removed: { type: Boolean, default: false, }, enabled: { type: Boolean, default: false, }, email: { type: String, lowercase: true, trim: true, required: true, }, name: { type: String, required: true }, surname: { type: String }, photo: { type: String, trim: true, }, created: { type: Date, default: Date.now, }, role: { type: String, default: 'owner', enum: ['owner'], }, }); module.exports = mongoose.model('Admin', adminSchema); ================================================ FILE: backend/src/models/coreModels/AdminPassword.js ================================================ const mongoose = require('mongoose'); const Schema = mongoose.Schema; const bcrypt = require('bcryptjs'); const AdminPasswordSchema = new Schema({ removed: { type: Boolean, default: false, }, user: { type: mongoose.Schema.ObjectId, ref: 'Admin', required: true, unique: true }, password: { type: String, required: true, }, salt: { type: String, required: true, }, emailToken: String, resetToken: String, emailVerified: { type: Boolean, default: false, }, authType: { type: String, default: 'email', }, loggedSessions: { type: [String], default: [], }, }); // AdminPasswordSchema.index({ user: 1 }); // generating a hash AdminPasswordSchema.methods.generateHash = function (salt, password) { return bcrypt.hashSync(salt + password); }; // checking if password is valid AdminPasswordSchema.methods.validPassword = function (salt, userpassword) { return bcrypt.compareSync(salt + userpassword, this.password); }; module.exports = mongoose.model('AdminPassword', AdminPasswordSchema); ================================================ FILE: backend/src/models/coreModels/Setting.js ================================================ const mongoose = require('mongoose'); const settingSchema = new mongoose.Schema({ removed: { type: Boolean, default: false, }, enabled: { type: Boolean, default: true, }, settingCategory: { type: String, required: true, lowercase: true, }, settingKey: { type: String, lowercase: true, required: true, }, settingValue: { type: mongoose.Schema.Types.Mixed, }, valueType: { type: String, default: 'String', }, isPrivate: { type: Boolean, default: false, }, isCoreSetting: { type: Boolean, default: false, }, }); module.exports = mongoose.model('Setting', settingSchema); ================================================ FILE: backend/src/models/coreModels/Upload.js ================================================ const mongoose = require('mongoose'); const uploadSchema = new mongoose.Schema({ removed: { type: Boolean, default: false, }, enabled: { type: Boolean, default: true, }, modelName: { type: String, trim: true, }, fieldId: { type: String, required: true, }, fileName: { type: String, required: true, }, fileType: { type: String, enum: [ 'jpeg', 'jpg', 'png', 'gif', 'webp', 'doc', 'txt', 'csv', 'docx', 'xls', 'xlsx', 'pdf', 'zip', 'rar', 'mp4', 'mov', 'avi', 'mp3', 'm4a', 'webm', ], required: true, }, isPublic: { type: Boolean, required: true, }, userID: { type: mongoose.SchemaTypes.ObjectId, required: true, }, isSecure: { type: Boolean, required: true, }, path: { type: String, required: true, }, created: { type: Date, default: Date.now, }, }); module.exports = mongoose.model('Upload ', uploadSchema); ================================================ FILE: backend/src/models/utils/index.js ================================================ const { basename, extname } = require('path'); const { globSync } = require('glob'); const appModelsFiles = globSync('./src/models/appModels/**/*.js'); const pattern = './src/models/**/*.js'; const modelsFiles = globSync(pattern).map((filePath) => { const fileNameWithExtension = basename(filePath); const fileNameWithoutExtension = fileNameWithExtension.replace( extname(fileNameWithExtension), '' ); return fileNameWithoutExtension; }); const constrollersList = []; const appModelsList = []; const entityList = []; const routesList = []; for (const filePath of appModelsFiles) { const fileNameWithExtension = basename(filePath); const fileNameWithoutExtension = fileNameWithExtension.replace( extname(fileNameWithExtension), '' ); const firstChar = fileNameWithoutExtension.charAt(0); const modelName = fileNameWithoutExtension.replace(firstChar, firstChar.toUpperCase()); const fileNameLowerCaseFirstChar = fileNameWithoutExtension.replace( firstChar, firstChar.toLowerCase() ); const entity = fileNameWithoutExtension.toLowerCase(); controllerName = fileNameLowerCaseFirstChar + 'Controller'; constrollersList.push(controllerName); appModelsList.push(modelName); entityList.push(entity); const route = { entity: entity, modelName: modelName, controllerName: controllerName, }; routesList.push(route); } module.exports = { constrollersList, appModelsList, modelsFiles, entityList, routesList }; ================================================ FILE: backend/src/pdf/Invoice.pug ================================================ doctype html html head link(rel="shortcut icon" type="image/png" href="/images/icons/favicon.png") meta(name="viewport" content="width=device-width, initial-scale=1") style. .sheet { margin: 0; width: 100%; height: 297mm; } body{ width: 100%; margin: 0; padding: 0px ; background: #ffffff; font-family: sans-serif; font-size:12px; color:#222 } *, *:before, *:after { box-sizing: inherit; color:#222 } .clearfix { display: block; } //- .invoice-container { //- position: relative; //- margin: 0 auto; //- color: #001028; //- background: #fff; //- font-size: 10px; //- } .left{ float:left; } .right{ float:right; } .top-area { display: block; width:100%; } alignRight :{ text-align: right !important; } alignLeft :{ text-align: left; } .logo { width: 150px; } .company-info{ text-align: right; font-size:12px; } h1.invoice{ font-size:32px; color:#52008c; margin-top:0; } p.strong{ font-weight:700; } .billTo p { text-align: right !important; float:right; display:block; font-size:12px; width:100%; margin-top:0; margin-bottom:10px; } .tableHeader{ color:#52008c; } .clearfix { display: block; } .col { float:left; } .col-1 { width: 4.16667%; } .col-2 { width: 8.33333%; } .col-3 { width: 12.5%; } .col-4 { width: 16.66667%; } .col-5 { width: 20.83333%; } .col-6 { width: 25%; } .col-7 { width: 29.16667%; } .col-8 { width: 33.33333%; } .col-9 { width: 37.5%; } .col-10 { width: 41.66667%; } .col-11 { width: 45.83333%; } .col-12 { width: 50%; } .col-13 { width: 54.16667%; } .col-14 { width: 58.33333%; } .col-15 { width: 62.5%; } .col-16 { width: 66.66667%; } .col-17 { width: 70.83333%; } .col-18 { width: 75%; } .col-19 { width: 79.16667%; } .col-20 { width: 83.33333%; } .col-21 { width: 87.5%; } .col-22 { width: 91.66667%; } .col-23 { width: 95.83333%; } .col-24 { width: 100%; } .space { margin-top: 30px; margin-bottom: 40px; width:100%; } .top-area .number-invoice > h1 { font-weight: 500; } .about-invoice { padding: 0px 15px; margin-top: 10px; font-size: 13px; } .project-invoice { float: left; margin-bottom: 10px; } .project-invoice span { color: #5d6975; text-align: right; width: 52px; margin-right: 10px; display: inline-block; font-size: 0.8em; } .company-invoice { float: right; text-align: right; margin-bottom: 60px; } .project-invoice div, .company-invoice div { white-space: nowrap; margin: 5px auto; } .table-invoice { width: 100%; border-collapse: collapse; border-spacing: 0; margin-bottom: 20px; } .table-invoice tr:nth-child(2n-1) td { background: #fcfeff; } .table-invoice th, .table-invoice td { text-align: center; } .table-invoice th { padding: 8px 10px; border-bottom: 1px solid #c2e0f2; color:#52008c; white-space: nowrap; font-weight: 700; font-size: 12px; text-align: right; } tbody{ border-bottom: 1px solid #c2e0f2; } .table-invoice .service, .table-invoice .desc { text-align: left; } .table-invoice td { padding: 10px ; text-align: right; font-size: 11px; } .table-invoice td.service, .table-invoice td.desc { vertical-align: top; } .table-invoice td.unit, .table-invoice td.qty, .table-invoice td.total { } .table-invoice td.grand { border-top: 1px solid #5d6975; } .service span{ display:block; clear:both; width : 100%; color:#666; margin-top:5px; font-size:10px; } .notice-invoice { padding: 15px; } .notice-invoice .notice { color: #5d6975; } .footer-invoice { margin-top:30px color: #5d6975; width: 100%; position: absolute; bottom: 0; padding: 20px 0; text-align: center; } body header.clearfix .top-area img.logo.left(src=settings.public_server_file+settings.company_logo) .right.company-info p.strong #{settings.company_name} p #{settings.company_address} p #{settings.company_reg_number} .col.col-24 .space .left.col-14 h1.invoice | #{translate('invoice')} div .col.col-7 p.strong #{translate('Date')} : p #{moment(model.date).format(dateFormat)} .col.col-9 p.strong #{translate('Expired Date')} : p #{moment(model.expiredDate).format(dateFormat)} .col.col-8 p.strong #{translate('Number')} : p # #{model.number}/#{model.year || ""} .right.col-10 .billTo p #{translate('Client')} : p #{model.client.name} p #{model.client.address} p #{model.client.phone} p #{model.client.email} .col.col-24 .space main table.table-invoice thead tr.tableHeader th.service #{translate('item')} th #{translate('Quantity')} th #{translate('PRICE')} th #{translate('TOTAL')} tbody each item in model.items tr td.service #{item.itemName} span #{item.description} td.qty #{item.quantity} td.unit #{moneyFormatter({amount:item.price})} td.total #{moneyFormatter({amount:item.total})} tr td(colspan='3') #{translate('SUB TOTAL')} td.total #{moneyFormatter({amount:model.subTotal})} tr td(colspan='3') #{translate('TAX')} #{model.taxRate} % td.total #{moneyFormatter({amount:model.taxTotal})} tr td.grand.total(colspan='3') #{translate('TOTAL')} td.grand.total #{moneyFormatter({amount:model.total})} .col.col-24 .space footer.footer-invoice //- | Invoice was created on a computer and is valid without the signature and seal. ================================================ FILE: backend/src/pdf/Offer.pug ================================================ doctype html html head link(rel="shortcut icon" type="image/png" href="/images/icons/favicon.png") meta(name="viewport" content="width=device-width, initial-scale=1") style. .sheet { margin: 0; width: 100%; height: 297mm; } body{ width: 100%; margin: 0; padding: 0px ; background: #ffffff; font-family: sans-serif; font-size:12px; color:#222 } *, *:before, *:after { box-sizing: inherit; color:#222 } .clearfix { display: block; } //- .invoice-container { //- position: relative; //- margin: 0 auto; //- color: #001028; //- background: #fff; //- font-size: 10px; //- } .left{ float:left; } .right{ float:right; } .top-area { display: block; width:100%; } alignRight :{ text-align: right !important; } alignLeft :{ text-align: left; } .logo { width: 150px; } .company-info{ text-align: right; font-size:12px; } h1.invoice{ font-size:32px; color:#52008c; margin-top:0; } p.strong{ font-weight:700; } .billTo p { text-align: right !important; float:right; display:block; font-size:12px; width:100%; margin-top:0; margin-bottom:10px; } .tableHeader{ color:#52008c; } .clearfix { display: block; } .col { float:left; } .col-1 { width: 4.16667%; } .col-2 { width: 8.33333%; } .col-3 { width: 12.5%; } .col-4 { width: 16.66667%; } .col-5 { width: 20.83333%; } .col-6 { width: 25%; } .col-7 { width: 29.16667%; } .col-8 { width: 33.33333%; } .col-9 { width: 37.5%; } .col-10 { width: 41.66667%; } .col-11 { width: 45.83333%; } .col-12 { width: 50%; } .col-13 { width: 54.16667%; } .col-14 { width: 58.33333%; } .col-15 { width: 62.5%; } .col-16 { width: 66.66667%; } .col-17 { width: 70.83333%; } .col-18 { width: 75%; } .col-19 { width: 79.16667%; } .col-20 { width: 83.33333%; } .col-21 { width: 87.5%; } .col-22 { width: 91.66667%; } .col-23 { width: 95.83333%; } .col-24 { width: 100%; } .space { margin-top: 30px; margin-bottom: 40px; width:100%; } .top-area .number-invoice > h1 { font-weight: 500; } .about-invoice { padding: 0px 15px; margin-top: 10px; font-size: 13px; } .project-invoice { float: left; margin-bottom: 10px; } .project-invoice span { color: #5d6975; text-align: right; width: 52px; margin-right: 10px; display: inline-block; font-size: 0.8em; } .company-invoice { float: right; text-align: right; margin-bottom: 60px; } .project-invoice div, .company-invoice div { white-space: nowrap; margin: 5px auto; } .table-invoice { width: 100%; border-collapse: collapse; border-spacing: 0; margin-bottom: 20px; } .table-invoice tr:nth-child(2n-1) td { background: #fcfeff; } .table-invoice th, .table-invoice td { text-align: center; } .table-invoice th { padding: 8px 10px; border-bottom: 1px solid #c2e0f2; color:#52008c; white-space: nowrap; font-weight: 700; font-size: 12px; text-align: right; } tbody{ border-bottom: 1px solid #c2e0f2; } .table-invoice .service, .table-invoice .desc { text-align: left; } .table-invoice td { padding: 10px ; text-align: right; font-size: 11px; } .table-invoice td.service, .table-invoice td.desc { vertical-align: top; } .table-invoice td.unit, .table-invoice td.qty, .table-invoice td.total { } .table-invoice td.grand { border-top: 1px solid #5d6975; } .service span{ display:block; clear:both; width : 100%; color:#666; margin-top:5px; font-size:10px; } .notice-invoice { padding: 15px; } .notice-invoice .notice { color: #5d6975; } .footer-invoice { margin-top:30px color: #5d6975; width: 100%; position: absolute; bottom: 0; padding: 20px 0; text-align: center; } body header.clearfix .top-area img.logo.left(src=settings.public_server_file+settings.company_logo) .right.company-info p.strong #{settings.company_name} p #{settings.company_address} p #{settings.company_reg_number} .col.col-24 .space .left.col-14 h1.invoice | #{translate('offer')} div .col.col-7 p.strong #{translate('Date')} : p #{moment(model.date).format(dateFormat)} .col.col-9 p.strong #{translate('Expired Date')} : p #{moment(model.expiredDate).format(dateFormat)} .col.col-8 p.strong #{translate('Number')} : p # #{model.number}/#{model.year || ""} .right.col-10 .billTo p #{translate('Client')} : p #{model.lead.name} p #{model.lead.address} p #{model.lead.phone} p #{model.lead.email} .col.col-24 .space main table.table-invoice thead tr.tableHeader th.service #{translate('item')} th #{translate('Quantity')} th #{translate('PRICE')} th #{translate('TOTAL')} tbody each item in model.items tr td.service #{item.itemName} span #{item.description} td.qty #{item.quantity} td.unit #{moneyFormatter({amount:item.price})} td.total #{moneyFormatter({amount:item.total})} tr td(colspan='3') #{translate('SUB TOTAL')} td.total #{moneyFormatter({amount:model.subTotal})} tr td(colspan='3') #{translate('TAX')} #{model.taxRate} % td.total #{moneyFormatter({amount:model.taxTotal})} tr td.grand.total(colspan='3') #{translate('TOTAL')} td.grand.total #{moneyFormatter({amount:model.total})} .col.col-24 .space footer.footer-invoice //- | Invoice was created on a computer and is valid without the signature and seal. ================================================ FILE: backend/src/pdf/Payment.pug ================================================ doctype html html head link(rel="shortcut icon" type="image/png" href="/images/icons/favicon.png") meta(name="viewport" content="width=device-width, initial-scale=1") style. .sheet { margin: 0; width: 100%; height: 297mm; } body{ width: 100%; margin: 0; padding: 0px ; background: #ffffff; font-family: sans-serif; font-size:12px; color:#222 } *, *:before, *:after { box-sizing: inherit; color:#222 } .clearfix { display: block; } //- .invoice-container { //- position: relative; //- margin: 0 auto; //- color: #001028; //- background: #fff; //- font-size: 10px; //- } .left{ float:left; } .right{ float:right; } .top-area { display: block; width:100%; } alignRight :{ text-align: right !important; } alignLeft :{ text-align: left; } .logo { width: 150px; } .company-info{ text-align: right; font-size:12px; } h1.invoice{ font-size:32px; color:#52008c; margin-top:0; } p.strong{ font-weight:700; } .billTo p { text-align: right !important; float:right; display:block; font-size:12px; width:100%; margin-top:0; margin-bottom:10px; } .tableHeader{ color:#52008c; } .clearfix { display: block; } .col { float:left; } .col-1 { width: 4.16667%; } .col-2 { width: 8.33333%; } .col-3 { width: 12.5%; } .col-4 { width: 16.66667%; } .col-5 { width: 20.83333%; } .col-6 { width: 25%; } .col-7 { width: 29.16667%; } .col-8 { width: 33.33333%; } .col-9 { width: 37.5%; } .col-10 { width: 41.66667%; } .col-11 { width: 45.83333%; } .col-12 { width: 50%; } .col-13 { width: 54.16667%; } .col-14 { width: 58.33333%; } .col-15 { width: 62.5%; } .col-16 { width: 66.66667%; } .col-17 { width: 70.83333%; } .col-18 { width: 75%; } .col-19 { width: 79.16667%; } .col-20 { width: 83.33333%; } .col-21 { width: 87.5%; } .col-22 { width: 91.66667%; } .col-23 { width: 95.83333%; } .col-24 { width: 100%; } .space { margin-top: 30px; margin-bottom: 40px; width:100%; } .top-area .number-invoice > h1 { font-weight: 500; } .about-invoice { padding: 0px 15px; margin-top: 10px; font-size: 13px; } .project-invoice { float: left; margin-bottom: 10px; } .project-invoice span { color: #5d6975; text-align: right; width: 52px; margin-right: 10px; display: inline-block; font-size: 0.8em; } .company-invoice { float: right; text-align: right; margin-bottom: 60px; } .project-invoice div, .company-invoice div { white-space: nowrap; margin: 5px auto; } .table-invoice { width: 100%; border-collapse: collapse; border-spacing: 0; margin-bottom: 20px; } .table-invoice tr:nth-child(2n-1) td { background: #fcfeff; } .table-invoice th, .table-invoice td { text-align: center; } .table-invoice th { padding: 8px 10px; border-bottom: 1px solid #c2e0f2; color:#52008c; white-space: nowrap; font-weight: 700; font-size: 12px; text-align: right; } tbody{ border-bottom: 1px solid #c2e0f2; } .table-invoice .service, .table-invoice .desc { text-align: left; } .table-invoice td { padding: 10px ; text-align: right; font-size: 11px; } .table-invoice td.service, .table-invoice td.desc { vertical-align: top; } .table-invoice td.unit, .table-invoice td.qty, .table-invoice td.total { } .table-invoice td.grand { border-top: 1px solid #5d6975; } .service span{ display:block; clear:both; width : 100%; color:#666; margin-top:5px; font-size:10px; } .notice-invoice { padding: 15px; } .notice-invoice .notice { color: #5d6975; } .footer-invoice { margin-top:30px color: #5d6975; width: 100%; position: absolute; bottom: 0; padding: 20px 0; text-align: center; } .line{ width:100%; border-top: 1px solid #ccc; height: 5px; } body header.clearfix .top-area img.logo.left(src=settings.public_server_file+settings.company_logo) .right.company-info p.strong #{settings.company_name} p #{settings.company_address} p #{settings.company_reg_number} .col.col-24 .space .left.col-12 h1.invoice | #{translate('Payment Reciept')} div .col.col-8 p.strong #{translate('Date')} : p #{moment(model.date).format(dateFormat)} .col.col-9 p.strong #{translate('Reciept Number')}: p # #{model.number}/#{model.year || ""} .right.col-10 .billTo p #{translate('Client')} : p #{model.client.name} p #{model.client.address} p #{model.client.phone} p #{model.client.email} .col.col-24 .space main.clearfix .left.col-24 .line h3 #{translate('total paid')} : #{moneyFormatter({amount:model.amount})} .col.col-24 .space footer.footer-invoice //- | This Payment Reciept was created on a computer and is valid without the signature and seal. ================================================ FILE: backend/src/pdf/Quote.pug ================================================ doctype html html head link(rel="shortcut icon" type="image/png" href="/images/icons/favicon.png") meta(name="viewport" content="width=device-width, initial-scale=1") style. .sheet { margin: 0; width: 100%; height: 297mm; } body{ width: 100%; margin: 0; padding: 0px ; background: #ffffff; font-family: sans-serif; font-size:12px; color:#222 } *, *:before, *:after { box-sizing: inherit; color:#222 } .clearfix { display: block; } //- .invoice-container { //- position: relative; //- margin: 0 auto; //- color: #001028; //- background: #fff; //- font-size: 10px; //- } .left{ float:left; } .right{ float:right; } .top-area { display: block; width:100%; } alignRight :{ text-align: right !important; } alignLeft :{ text-align: left; } .logo { width: 150px; } .company-info{ text-align: right; font-size:12px; } h1.invoice{ font-size:32px; color:#52008c; margin-top:0; } p.strong{ font-weight:700; } .billTo p { text-align: right !important; float:right; display:block; font-size:12px; width:100%; margin-top:0; margin-bottom:10px; } .tableHeader{ color:#52008c; } .clearfix { display: block; } .col { float:left; } .col-1 { width: 4.16667%; } .col-2 { width: 8.33333%; } .col-3 { width: 12.5%; } .col-4 { width: 16.66667%; } .col-5 { width: 20.83333%; } .col-6 { width: 25%; } .col-7 { width: 29.16667%; } .col-8 { width: 33.33333%; } .col-9 { width: 37.5%; } .col-10 { width: 41.66667%; } .col-11 { width: 45.83333%; } .col-12 { width: 50%; } .col-13 { width: 54.16667%; } .col-14 { width: 58.33333%; } .col-15 { width: 62.5%; } .col-16 { width: 66.66667%; } .col-17 { width: 70.83333%; } .col-18 { width: 75%; } .col-19 { width: 79.16667%; } .col-20 { width: 83.33333%; } .col-21 { width: 87.5%; } .col-22 { width: 91.66667%; } .col-23 { width: 95.83333%; } .col-24 { width: 100%; } .space { margin-top: 30px; margin-bottom: 40px; width:100%; } .top-area .number-invoice > h1 { font-weight: 500; } .about-invoice { padding: 0px 15px; margin-top: 10px; font-size: 13px; } .project-invoice { float: left; margin-bottom: 10px; } .project-invoice span { color: #5d6975; text-align: right; width: 52px; margin-right: 10px; display: inline-block; font-size: 0.8em; } .company-invoice { float: right; text-align: right; margin-bottom: 60px; } .project-invoice div, .company-invoice div { white-space: nowrap; margin: 5px auto; } .table-invoice { width: 100%; border-collapse: collapse; border-spacing: 0; margin-bottom: 20px; } .table-invoice tr:nth-child(2n-1) td { background: #fcfeff; } .table-invoice th, .table-invoice td { text-align: center; } .table-invoice th { padding: 8px 10px; border-bottom: 1px solid #c2e0f2; color:#52008c; white-space: nowrap; font-weight: 700; font-size: 12px; text-align: right; } tbody{ border-bottom: 1px solid #c2e0f2; } .table-invoice .service, .table-invoice .desc { text-align: left; } .table-invoice td { padding: 10px ; text-align: right; font-size: 11px; } .table-invoice td.service, .table-invoice td.desc { vertical-align: top; } .table-invoice td.unit, .table-invoice td.qty, .table-invoice td.total { } .table-invoice td.grand { border-top: 1px solid #5d6975; } .service span{ display:block; clear:both; width : 100%; color:#666; margin-top:5px; font-size:10px; } .notice-invoice { padding: 15px; } .notice-invoice .notice { color: #5d6975; } .footer-invoice { margin-top:30px color: #5d6975; width: 100%; position: absolute; bottom: 0; padding: 20px 0; text-align: center; } body header.clearfix .top-area img.logo.left(src=settings.public_server_file+settings.company_logo) .right.company-info p.strong #{settings.company_name} p #{settings.company_address} p #{settings.company_reg_number} .col.col-24 .space .left.col-14 h1.invoice | #{translate('quote')} div .col.col-7 p.strong #{translate('Date')} : p #{moment(model.date).format(dateFormat)} .col.col-9 p.strong #{translate('Expired Date')} : p #{moment(model.expiredDate).format(dateFormat)} .col.col-8 p.strong #{translate('Number')} : p # #{model.number}/#{model.year || ""} .right.col-10 .billTo p #{translate('Client')} : p #{model.client.name} p #{model.client.address} p #{model.client.phone} p #{model.client.email} .col.col-24 .space main table.table-invoice thead tr.tableHeader th.service #{translate('item')} th #{translate('Quantity')} th #{translate('PRICE')} th #{translate('TOTAL')} tbody each item in model.items tr td.service #{item.itemName} span #{item.description} td.qty #{item.quantity} td.unit #{moneyFormatter({amount:item.price})} td.total #{moneyFormatter({amount:item.total})} tr td(colspan='3') #{translate('SUB TOTAL')} td.total #{moneyFormatter({amount:model.subTotal})} tr td(colspan='3') #{translate('TAX')} #{model.taxRate} % td.total #{moneyFormatter({amount:model.taxTotal})} tr td.grand.total(colspan='3') #{translate('TOTAL')} td.grand.total #{moneyFormatter({amount:model.total})} .col.col-24 .space footer.footer-invoice //- | Invoice was created on a computer and is valid without the signature and seal. ================================================ FILE: backend/src/routes/appRoutes/appApi.js ================================================ const express = require('express'); const { catchErrors } = require('@/handlers/errorHandlers'); const router = express.Router(); const appControllers = require('@/controllers/appControllers'); const { routesList } = require('@/models/utils'); const routerApp = (entity, controller) => { router.route(`/${entity}/create`).post(catchErrors(controller['create'])); router.route(`/${entity}/read/:id`).get(catchErrors(controller['read'])); router.route(`/${entity}/update/:id`).patch(catchErrors(controller['update'])); router.route(`/${entity}/delete/:id`).delete(catchErrors(controller['delete'])); router.route(`/${entity}/search`).get(catchErrors(controller['search'])); router.route(`/${entity}/list`).get(catchErrors(controller['list'])); router.route(`/${entity}/listAll`).get(catchErrors(controller['listAll'])); router.route(`/${entity}/filter`).get(catchErrors(controller['filter'])); router.route(`/${entity}/summary`).get(catchErrors(controller['summary'])); if (entity === 'invoice' || entity === 'quote' || entity === 'payment') { router.route(`/${entity}/mail`).post(catchErrors(controller['mail'])); } if (entity === 'quote') { router.route(`/${entity}/convert/:id`).get(catchErrors(controller['convert'])); } }; routesList.forEach(({ entity, controllerName }) => { const controller = appControllers[controllerName]; routerApp(entity, controller); }); module.exports = router; ================================================ FILE: backend/src/routes/coreRoutes/coreApi.js ================================================ const express = require('express'); const { catchErrors } = require('@/handlers/errorHandlers'); const router = express.Router(); const adminController = require('@/controllers/coreControllers/adminController'); const settingController = require('@/controllers/coreControllers/settingController'); const { singleStorageUpload } = require('@/middlewares/uploadMiddleware'); // //_______________________________ Admin management_______________________________ router.route('/admin/read/:id').get(catchErrors(adminController.read)); router.route('/admin/password-update/:id').patch(catchErrors(adminController.updatePassword)); //_______________________________ Admin Profile _______________________________ router.route('/admin/profile/password').patch(catchErrors(adminController.updateProfilePassword)); router .route('/admin/profile/update') .patch( singleStorageUpload({ entity: 'admin', fieldName: 'photo', fileType: 'image' }), catchErrors(adminController.updateProfile) ); // //____________________________________________ API for Global Setting _________________ router.route('/setting/create').post(catchErrors(settingController.create)); router.route('/setting/read/:id').get(catchErrors(settingController.read)); router.route('/setting/update/:id').patch(catchErrors(settingController.update)); //router.route('/setting/delete/:id).delete(catchErrors(settingController.delete)); router.route('/setting/search').get(catchErrors(settingController.search)); router.route('/setting/list').get(catchErrors(settingController.list)); router.route('/setting/listAll').get(catchErrors(settingController.listAll)); router.route('/setting/filter').get(catchErrors(settingController.filter)); router .route('/setting/readBySettingKey/:settingKey') .get(catchErrors(settingController.readBySettingKey)); router.route('/setting/listBySettingKey').get(catchErrors(settingController.listBySettingKey)); router .route('/setting/updateBySettingKey/:settingKey?') .patch(catchErrors(settingController.updateBySettingKey)); router .route('/setting/upload/:settingKey?') .patch( singleStorageUpload({ entity: 'setting', fieldName: 'settingValue', fileType: 'image' }), catchErrors(settingController.updateBySettingKey) ); router.route('/setting/updateManySetting').patch(catchErrors(settingController.updateManySetting)); module.exports = router; ================================================ FILE: backend/src/routes/coreRoutes/coreAuth.js ================================================ const express = require('express'); const router = express.Router(); const { catchErrors } = require('@/handlers/errorHandlers'); const adminAuth = require('@/controllers/coreControllers/adminAuth'); router.route('/login').post(catchErrors(adminAuth.login)); router.route('/forgetpassword').post(catchErrors(adminAuth.forgetPassword)); router.route('/resetpassword').post(catchErrors(adminAuth.resetPassword)); router.route('/logout').post(adminAuth.isValidAuthToken, catchErrors(adminAuth.logout)); module.exports = router; ================================================ FILE: backend/src/routes/coreRoutes/coreDownloadRouter.js ================================================ const downloadPdf = require('@/handlers/downloadHandler/downloadPdf'); const express = require('express'); const router = express.Router(); router.route('/:directory/:file').get(function (req, res) { try { const { directory, file } = req.params; const id = file.slice(directory.length + 1).slice(0, -4); // extract id from file name downloadPdf(req, res, { directory, id }); } catch (error) { return res.status(503).json({ success: false, result: null, message: error.message, error: error, }); } }); module.exports = router; ================================================ FILE: backend/src/routes/coreRoutes/corePublicRouter.js ================================================ const express = require('express'); const router = express.Router(); const path = require('path'); const { isPathInside } = require('../../utils/is-path-inside'); router.route('/:subPath/:directory/:file').get(function (req, res) { try { const { subPath, directory, file } = req.params; // Decode each parameter separately const decodedSubPath = decodeURIComponent(subPath); const decodedDirectory = decodeURIComponent(directory); const decodedFile = decodeURIComponent(file); // Define the trusted root directory const rootDir = path.join(__dirname, '../../public'); // Safely join the decoded path segments const relativePath = path.join(decodedSubPath, decodedDirectory, decodedFile); const absolutePath = path.join(rootDir, relativePath); // Check if the resulting path stays inside rootDir if (!isPathInside(absolutePath, rootDir)) { return res.status(400).json({ success: false, error: 'Invalid filepath', }); } return res.sendFile(absolutePath, (error) => { if (error) { return res.status(404).json({ success: false, result: null, message: 'we could not find : ' + file, }); } }); } catch (error) { return res.status(503).json({ success: false, result: null, message: error.message, error: error, }); } }); module.exports = router; ================================================ FILE: backend/src/server.js ================================================ require('module-alias/register'); const mongoose = require('mongoose'); const { globSync } = require('glob'); const path = require('path'); // Make sure we are running node 7.6+ const [major, minor] = process.versions.node.split('.').map(parseFloat); if (major < 20) { console.log('Please upgrade your node.js version at least 20 or greater. 👌\n '); process.exit(); } // import environmental variables from our variables.env file require('dotenv').config({ path: '.env' }); require('dotenv').config({ path: '.env.local' }); mongoose.connect(process.env.DATABASE); const OPENAI_API_KEY = process.env.OPENAI_API_KEY; mongoose.connection.on('error', (error) => { console.log( `1. 🔥 Common Error caused issue → : check your .env file first and add your mongodb url` ); console.error(`2. 🚫 Error → : ${error.message}`); }); const modelsFiles = globSync('./src/models/**/*.js'); for (const filePath of modelsFiles) { require(path.resolve(filePath)); } // Start our app! const app = require('./app'); app.set('port', process.env.PORT || 8888); const server = app.listen(app.get('port'), () => { console.log(`Express running → On PORT : ${server.address().port}`); }); ================================================ FILE: backend/src/settings/index.js ================================================ const useDate = require('./useDate'); const useMoney = require('./useMoney'); const useAppSettings = require('./useAppSettings'); module.exports = { useDate, useMoney, useAppSettings, }; ================================================ FILE: backend/src/settings/useAppSettings.js ================================================ const useAppSettings = () => { let settings = {}; settings['idurar_app_email'] = 'noreply@idurarapp.com'; settings['idurar_base_url'] = 'https://cloud.idurarapp.com'; return settings; }; module.exports = useAppSettings; ================================================ FILE: backend/src/settings/useDate.js ================================================ const useDate = ({ settings }) => { const { idurar_app_date_format } = settings; const dateFormat = idurar_app_date_format; return { dateFormat, }; }; module.exports = useDate; ================================================ FILE: backend/src/settings/useMoney.js ================================================ const currency = require('currency.js'); const useMoney = ({ settings }) => { const { currency_symbol, currency_position, decimal_sep, thousand_sep, cent_precision, zero_format, } = settings; function currencyFormat(amount) { return currency(amount).dollars() > 0 || !zero_format ? currency(amount, { separator: thousand_sep, decimal: decimal_sep, symbol: '', precision: cent_precision, }).format() : 0 + currency(amount, { separator: thousand_sep, decimal: decimal_sep, symbol: '', precision: cent_precision, }).format(); } function moneyFormatter({ amount = 0 }) { return currency_position === 'before' ? currency_symbol + ' ' + currencyFormat(amount) : currencyFormat(amount) + ' ' + currency_symbol; } function amountFormatter({ amount = 0 }) { return currencyFormat(amount); } return { moneyFormatter, amountFormatter, currency_symbol, currency_position, decimal_sep, thousand_sep, cent_precision, zero_format, }; }; module.exports = useMoney; ================================================ FILE: backend/src/setup/defaultSettings/appSettings.json ================================================ [ { "settingCategory": "app_settings", "settingKey": "idurar_app_date_format", "settingValue": "DD/MM/YYYY", "valueType": "string" }, { "settingCategory": "app_settings", "settingKey": "idurar_app_language", "settingValue": "en_us", "valueType": "string" }, { "settingCategory": "app_settings", "settingKey": "idurar_app_country", "settingValue": null, "valueType": "string" }, { "settingCategory": "app_settings", "settingKey": "idurar_app_timezone", "settingValue": null, "valueType": "string" }, { "settingCategory": "app_settings", "settingKey": "idurar_app_email", "settingValue": null, "valueType": "string" }, { "settingCategory": "app_settings", "settingKey": "idurar_app_company_email", "settingValue": null, "valueType": "string" }, { "settingCategory": "app_settings", "settingKey": "idurar_app_has_mutli_branch", "settingValue": false, "valueType": "boolean" }, { "settingCategory": "app_settings", "settingKey": "idurar_app_industry", "settingValue": "default", "valueType": "string" }, { "settingCategory": "app_settings", "settingKey": "idurar_app_early_access", "settingValue": "default", "valueType": "boolean", "isCoreSetting": false } ] ================================================ FILE: backend/src/setup/defaultSettings/clientSettings.json ================================================ [ { "settingCategory": "client_settings", "settingKey": "client_type", "settingValue": ["people", "company"], "valueType": "array" }, { "settingCategory": "client_settings", "settingKey": "client_status", "settingValue": ["active", "new", "premium", "unactive"], "valueType": "array" }, { "settingCategory": "client_settings", "settingKey": "client_source", "settingValue": [ "self checking", "sales lead", "recomendation", "facebook", "instagram", "tiktok", "youtube", "blog", "linkedin", "newsletter", "website", "twitter" ], "valueType": "array" }, { "settingCategory": "client_settings", "settingKey": "client_category", "settingValue": [ "Corporate", "startup", "small company", "services business", "retails", "cafe & restaurant" ], "valueType": "array" }, { "settingCategory": "client_settings", "settingKey": "invoice_default_client_type", "settingValue": "company", "valueType": "string" }, { "settingCategory": "client_settings", "settingKey": "quote_default_client_type", "settingValue": "company", "valueType": "string" }, { "settingCategory": "client_settings", "settingKey": "pos_default_client_type", "settingValue": "people", "valueType": "string" }, { "settingCategory": "client_settings", "settingKey": "pos_default_client", "settingValue": "609e0057246f2359b0c4c31f", "valueType": "string" } ] ================================================ FILE: backend/src/setup/defaultSettings/companySettings.json ================================================ [ { "settingCategory": "company_settings", "settingKey": "company_name", "settingValue": "COMPANY Name", "valueType": "string" }, { "settingCategory": "company_settings", "settingKey": "company_logo", "settingValue": "public/uploads/setting/company-logo.png", "valueType": "image" }, { "settingCategory": "company_settings", "settingKey": "company_icon", "settingValue": "public/uploads/setting/company-logo.png", "valueType": "image" }, { "settingCategory": "company_settings", "settingKey": "company_address", "settingValue": "25 , Your Company Address", "valueType": "string" }, { "settingCategory": "company_settings", "settingKey": "company_state", "settingValue": "New York", "valueType": "string" }, { "settingCategory": "company_settings", "settingKey": "company_country", "settingValue": "United State", "valueType": "string" }, { "settingCategory": "company_settings", "settingKey": "company_email", "settingValue": "youremail@example.com", "valueType": "string" }, { "settingCategory": "company_settings", "settingKey": "company_phone", "settingValue": "+1 345234654", "valueType": "string" }, { "settingCategory": "company_settings", "settingKey": "company_website", "settingValue": "www.example.com", "valueType": "string" }, { "settingCategory": "company_settings", "settingKey": "company_tax_number", "settingValue": "91231255234", "valueType": "string" }, { "settingCategory": "company_settings", "settingKey": "company_vat_number", "settingValue": "91231255234", "valueType": "string" }, { "settingCategory": "company_settings", "settingKey": "company_reg_number", "settingValue": "00001231421", "valueType": "string" }, { "settingCategory": "company_settings", "settingKey": "company_bank_account", "settingValue": "iban : 00001231421", "valueType": "string" } ] ================================================ FILE: backend/src/setup/defaultSettings/financeSettings.json ================================================ [ { "settingCategory": "finance_settings", "settingKey": "last_invoice_number", "settingValue": 0, "valueType": "number" }, { "settingCategory": "finance_settings", "settingKey": "last_quote_number", "settingValue": 0, "valueType": "number" }, { "settingCategory": "finance_settings", "settingKey": "last_offer_number", "settingValue": 0, "valueType": "number" }, { "settingCategory": "finance_settings", "settingKey": "last_payment_number", "settingValue": 0, "valueType": "number" }, { "settingCategory": "finance_settings", "settingKey": "invoice_prefix", "settingValue": "inv-", "valueType": "string" }, { "settingCategory": "finance_settings", "settingKey": "quote_prefix", "settingValue": "qot-", "valueType": "string" }, { "settingCategory": "finance_settings", "settingKey": "offer_prefix", "settingValue": "ofr-", "valueType": "string" }, { "settingCategory": "finance_settings", "settingKey": "payment_prefix", "settingValue": "pym-", "valueType": "string" } ] ================================================ FILE: backend/src/setup/defaultSettings/invoiceSettings.json ================================================ [ { "settingCategory": "invoice_settings", "settingKey": "invoice_show_product_tax", "settingValue": false, "valueType": "boolean" }, { "settingCategory": "invoice_settings", "settingKey": "invoice_load_default_client", "settingValue": false, "valueType": "boolean" }, { "settingCategory": "invoice_settings", "settingKey": "invoice_pdf_footer", "settingValue": "Invoice was created on a computer and is valid without the signature and seal", "valueType": "string" }, { "settingCategory": "invoice_settings", "settingKey": "invoice_status", "settingValue": ["draft", "pending", "sent", "received", "refund", "cancelled", "on hold"], "valueType": "array" } ] ================================================ FILE: backend/src/setup/defaultSettings/moneyFormatSettings.json ================================================ [ { "settingCategory": "money_format_settings", "settingKey": "default_currency_code", "settingValue": "USD", "valueType": "string" }, { "settingCategory": "money_format_settings", "settingKey": "currency_name", "settingValue": "US Dollars", "valueType": "string" }, { "settingCategory": "money_format_settings", "settingKey": "currency_symbol", "settingValue": "$", "valueType": "string" }, { "settingCategory": "money_format_settings", "settingKey": "currency_position", "settingValue": "before", "valueType": "string" }, { "settingCategory": "money_format_settings", "settingKey": "decimal_sep", "settingValue": ".", "valueType": "string" }, { "settingCategory": "money_format_settings", "settingKey": "thousand_sep", "settingValue": ",", "valueType": "string" }, { "settingCategory": "money_format_settings", "settingKey": "cent_precision", "settingValue": 2, "valueType": "number" }, { "settingCategory": "money_format_settings", "settingKey": "zero_format", "settingValue": false, "valueType": "boolean" } ] ================================================ FILE: backend/src/setup/defaultSettings/quoteSettings.json ================================================ [ { "settingCategory": "quote_settings", "settingKey": "quote_show_product_tax", "settingValue": false, "valueType": "boolean" }, { "settingCategory": "quote_settings", "settingKey": "quote_load_default_client", "settingValue": false, "valueType": "boolean" }, { "settingCategory": "quote_settings", "settingKey": "quote_status", "settingValue": [ "draft", "pending", "sent", "negotiation", "accepted", "declined", "cancelled" ], "valueType": "array" }, { "settingCategory": "quote_settings", "settingKey": "quote_pdf_footer", "settingValue": "Quote was created on a computer and is valid without the signature and seal", "valueType": "string" } ] ================================================ FILE: backend/src/setup/reset.js ================================================ require('dotenv').config({ path: '.env' }); require('dotenv').config({ path: '.env.local' }); const mongoose = require('mongoose'); mongoose.connect(process.env.DATABASE); async function deleteData() { const Admin = require('../models/coreModels/Admin'); const AdminPassword = require('../models/coreModels/AdminPassword'); const Setting = require('../models/coreModels/Setting'); const PaymentMode = require('../models/appModels/PaymentMode'); const Taxes = require('../models/appModels/Taxes'); await Admin.deleteMany(); await AdminPassword.deleteMany(); await PaymentMode.deleteMany(); await Taxes.deleteMany(); console.log('👍 Admin Deleted. To setup demo admin data, run\n\n\t npm run setup\n\n'); await Setting.deleteMany(); console.log('👍 Setting Deleted. To setup Setting data, run\n\n\t npm run setup\n\n'); process.exit(); } deleteData(); ================================================ FILE: backend/src/setup/setup.js ================================================ require('dotenv').config({ path: '.env' }); require('dotenv').config({ path: '.env.local' }); const { globSync } = require('glob'); const fs = require('fs'); const { generate: uniqueId } = require('shortid'); const mongoose = require('mongoose'); mongoose.connect(process.env.DATABASE); async function setupApp() { try { const Admin = require('../models/coreModels/Admin'); const AdminPassword = require('../models/coreModels/AdminPassword'); const newAdminPassword = new AdminPassword(); const salt = uniqueId(); const passwordHash = newAdminPassword.generateHash(salt, 'admin123'); const demoAdmin = { email: 'admin@admin.com', name: 'IDURAR', surname: 'Admin', enabled: true, role: 'owner', }; const result = await new Admin(demoAdmin).save(); const AdminPasswordData = { password: passwordHash, emailVerified: true, salt: salt, user: result._id, }; await new AdminPassword(AdminPasswordData).save(); console.log('👍 Admin created : Done!'); const Setting = require('../models/coreModels/Setting'); const settingFiles = []; const settingsFiles = globSync('./src/setup/defaultSettings/**/*.json'); for (const filePath of settingsFiles) { const file = JSON.parse(fs.readFileSync(filePath, 'utf-8')); settingFiles.push(...file); } await Setting.insertMany(settingFiles); console.log('👍 Settings created : Done!'); const PaymentMode = require('../models/appModels/PaymentMode'); const Taxes = require('../models/appModels/Taxes'); await Taxes.insertMany([{ taxName: 'Tax 0%', taxValue: '0', isDefault: true }]); console.log('👍 Taxes created : Done!'); await PaymentMode.insertMany([ { name: 'Default Payment', description: 'Default Payment Mode (Cash , Wire Transfer)', isDefault: true, }, ]); console.log('👍 PaymentMode created : Done!'); console.log('🥳 Setup completed :Success!'); process.exit(); } catch (e) { console.log('\n🚫 Error! The Error info is below'); console.log(e); process.exit(); } } setupApp(); ================================================ FILE: backend/src/setup/setupConfig.json ================================================ [ { "setupCategory": "setup_config", "setupKey": "idurar_app_version", "setupValue": "3.0.0", "valueType": "string" }, { "setupCategory": "setup_config", "setupKey": "idurar_app_unique_id", "setupValue": "", "valueType": "string" }, { "setupCategory": "setup_config", "setupKey": "use_env_database", "setupValue": false, "valueType": "boolean" }, { "setupCategory": "setup_config", "setupKey": "DATABASE", "setupValue": "", "valueType": "string" }, { "setupCategory": "setup_config", "setupKey": "JWT_SECRET", "setupValue": "your_jwt_secret", "valueType": "string" }, { "setupCategory": "setup_config", "setupKey": "idurar_app_domain", "setupValue": "", "valueType": "string" }, { "setupCategory": "setup_config", "setupKey": "idurar_app_email", "setupValue": "", "valueType": "string" }, { "setupCategory": "setup_config", "setupKey": "idurar_app_country", "setupValue": "", "valueType": "string" }, { "setupCategory": "setup_config", "setupKey": "idurar_app_timezone", "setupValue": "", "valueType": "string" }, { "setupCategory": "setup_config", "setupKey": "idurar_app_licence_email", "setupValue": "", "valueType": "string" }, { "setupCategory": "setup_config", "setupKey": "idurar_app_licence_key", "setupValue": "", "valueType": "string" }, { "setupCategory": "setup_config", "setupKey": "idurar_app_licence_type", "setupValue": "free_trial", "valueType": "string" }, { "setupCategory": "setup_config", "setupKey": "idurar_app_licence_expired_date", "setupValue": "", "valueType": "date" }, { "setupCategory": "setup_config", "setupKey": "idurar_app_licence_validate", "setupValue": false, "valueType": "boolean" }, { "setupCategory": "setup_config", "setupKey": "idurar_setup_done", "setupValue": false, "valueType": "boolean" }, { "setupCategory": "setup_config", "setupKey": "NODE_ENV", "setupValue": "production", "valueType": "string" }, { "setupCategory": "setup_config", "setupKey": "idurar_maintenance_mode", "setupValue": false, "valueType": "boolean" }, { "setupCategory": "setup_config", "setupKey": "idurar_load_default_settings", "setupValue": true, "valueType": "boolean" }, { "setupCategory": "setup_config", "setupKey": "idurar_load_demo_data", "setupValue": false, "valueType": "boolean" } ] ================================================ FILE: backend/src/utils/countryList.js ================================================ const listTimeZones = [ { code: 'AF', countryName: 'Afghanistan', timeZones: ['Asia/Kabul'], }, { code: 'AL', countryName: 'Albania', timeZones: ['Europe/Tirane'], }, { code: 'DZ', countryName: 'Algeria', timeZones: ['Africa/Algiers'], }, { code: 'AR', countryName: 'Argentina', timeZones: [ 'America/Argentina/Buenos_Aires', 'America/Argentina/Cordoba', 'America/Argentina/Salta', 'America/Argentina/Jujuy', 'America/Argentina/Tucuman', 'America/Argentina/Catamarca', 'America/Argentina/La_Rioja', 'America/Argentina/San_Juan', 'America/Argentina/Mendoza', 'America/Argentina/San_Luis', 'America/Argentina/Rio_Gallegos', 'America/Argentina/Ushuaia', ], }, { code: 'AM', countryName: 'Armenia', timeZones: ['Asia/Yerevan'], }, { code: 'AU', countryName: 'Australia', timeZones: [ 'Australia/Lord_Howe', 'Antarctica/Macquarie', 'Australia/Hobart', 'Australia/Currie', 'Australia/Melbourne', 'Australia/Sydney', 'Australia/Broken_Hill', 'Australia/Brisbane', 'Australia/Lindeman', 'Australia/Adelaide', 'Australia/Darwin', 'Australia/Perth', 'Australia/Eucla', ], }, { code: 'AT', countryName: 'Austria', timeZones: ['Europe/Vienna'], }, { code: 'AZ', countryName: 'Azerbaijan', timeZones: ['Asia/Baku'], }, { code: 'BH', countryName: 'Bahrain', timeZones: ['Asia/Bahrain'], }, { code: 'BD', countryName: 'Bangladesh', timeZones: ['Asia/Dhaka'], }, { code: 'BY', countryName: 'Belarus', timeZones: ['Europe/Minsk'], }, { code: 'BE', countryName: 'Belgium', timeZones: ['Europe/Brussels'], }, { code: 'BZ', countryName: 'Belize', timeZones: ['America/Belize'], }, { code: 'BT', countryName: 'Bhutan', timeZones: ['Asia/Thimphu'], }, { code: 'BO', countryName: 'Bolivia', timeZones: ['America/La_Paz'], }, { code: 'BA', countryName: 'Bosnia and Herzegovina', timeZones: ['Europe/Sarajevo'], }, { code: 'BW', countryName: 'Botswana', timeZones: ['Africa/Gaborone'], }, { code: 'BR', countryName: 'Brazil', timeZones: [ 'America/Noronha', 'America/Belem', 'America/Fortaleza', 'America/Recife', 'America/Araguaina', 'America/Maceio', 'America/Bahia', 'America/Sao_Paulo', 'America/Campo_Grande', 'America/Cuiaba', 'America/Santarem', 'America/Porto_Velho', 'America/Boa_Vista', 'America/Manaus', 'America/Eirunepe', 'America/Rio_Branco', ], }, { code: 'BN', countryName: 'Brunei', timeZones: ['Asia/Brunei'], }, { code: 'BG', countryName: 'Bulgaria', timeZones: ['Europe/Sofia'], }, { code: 'KH', countryName: 'Cambodia', timeZones: ['Asia/Phnom_Penh'], }, { code: 'CM', countryName: 'Cameroon', timeZones: ['Africa/Douala'], }, { code: 'CA', countryName: 'Canada', timeZones: [ 'America/St_Johns', 'America/Halifax', 'America/Glace_Bay', 'America/Moncton', 'America/Goose_Bay', 'America/Blanc-Sablon', 'America/Toronto', 'America/Nipigon', 'America/Thunder_Bay', 'America/Iqaluit', 'America/Pangnirtung', 'America/Atikokan', 'America/Winnipeg', 'America/Rainy_River', 'America/Resolute', 'America/Rankin_Inlet', 'America/Regina', 'America/Swift_Current', 'America/Edmonton', 'America/Cambridge_Bay', 'America/Yellowknife', 'America/Inuvik', 'America/Creston', 'America/Dawson_Creek', 'America/Fort_Nelson', 'America/Vancouver', 'America/Whitehorse', 'America/Dawson', ], }, { code: 'CL', countryName: 'Chile', timeZones: ['America/Santiago', 'Pacific/Easter'], }, { code: 'CN', countryName: 'China', timeZones: ['Asia/Shanghai', 'Asia/Urumqi'], }, { code: 'CO', countryName: 'Colombia', timeZones: ['America/Bogota'], }, { code: 'CD', countryName: 'Congo (DRC)', timeZones: ['Africa/Kinshasa', 'Africa/Lubumbashi'], }, { code: 'CR', countryName: 'Costa Rica', timeZones: ['America/Costa_Rica'], }, { code: 'CI', countryName: 'Côte d’Ivoire', timeZones: ['Africa/Abidjan'], }, { code: 'HR', countryName: 'Croatia', timeZones: ['Europe/Zagreb'], }, { code: 'CU', countryName: 'Cuba', timeZones: ['America/Havana'], }, { code: 'CZ', countryName: 'Czech Republic', timeZones: ['Europe/Prague'], }, { code: 'DK', countryName: 'Denmark', timeZones: ['Europe/Copenhagen'], }, { code: 'DJ', countryName: 'Djibouti', timeZones: ['Africa/Djibouti'], }, { code: 'DO', countryName: 'Dominican Republic', timeZones: ['America/Santo_Domingo'], }, { code: 'EC', countryName: 'Ecuador', timeZones: ['America/Guayaquil', 'Pacific/Galapagos'], }, { code: 'EG', countryName: 'Egypt', timeZones: ['Africa/Cairo'], }, { code: 'SV', countryName: 'El Salvador', timeZones: ['America/El_Salvador'], }, { code: 'ER', countryName: 'Eritrea', timeZones: ['Africa/Asmara'], }, { code: 'EE', countryName: 'Estonia', timeZones: ['Europe/Tallinn'], }, { code: 'ET', countryName: 'Ethiopia', timeZones: ['Africa/Addis_Ababa'], }, { code: 'FO', countryName: 'Faroe Islands', timeZones: ['Atlantic/Faroe'], }, { code: 'FI', countryName: 'Finland', timeZones: ['Europe/Helsinki'], }, { code: 'FR', countryName: 'France', timeZones: ['Europe/Paris'], }, { code: 'GE', countryName: 'Georgia', timeZones: ['Asia/Tbilisi'], }, { code: 'DE', countryName: 'Germany', timeZones: ['Europe/Berlin', 'Europe/Busingen'], }, { code: 'GR', countryName: 'Greece', timeZones: ['Europe/Athens'], }, { code: 'GL', countryName: 'Greenland', timeZones: ['America/Godthab', 'America/Danmarkshavn', 'America/Scoresbysund', 'America/Thule'], }, { code: 'GT', countryName: 'Guatemala', timeZones: ['America/Guatemala'], }, { code: 'HT', countryName: 'Haiti', timeZones: ['America/Port-au-Prince'], }, { code: 'HN', countryName: 'Honduras', timeZones: ['America/Tegucigalpa'], }, { code: 'HK', countryName: 'Hong Kong SAR', timeZones: ['Asia/Hong_Kong'], }, { code: 'HU', countryName: 'Hungary', timeZones: ['Europe/Budapest'], }, { code: 'IS', countryName: 'Iceland', timeZones: ['Atlantic/Reykjavik'], }, { code: 'IN', countryName: 'India', timeZones: ['Asia/Kolkata'], }, { code: 'ID', countryName: 'Indonesia', timeZones: ['Asia/Jakarta', 'Asia/Pontianak', 'Asia/Makassar', 'Asia/Jayapura'], }, { code: 'IR', countryName: 'Iran', timeZones: ['Asia/Tehran'], }, { code: 'IQ', countryName: 'Iraq', timeZones: ['Asia/Baghdad'], }, { code: 'IE', countryName: 'Ireland', timeZones: ['Europe/Dublin'], }, { code: 'IL', countryName: 'Israel', timeZones: ['Asia/Jerusalem'], }, { code: 'IT', countryName: 'Italy', timeZones: ['Europe/Rome'], }, { code: 'JM', countryName: 'Jamaica', timeZones: ['America/Jamaica'], }, { code: 'JP', countryName: 'Japan', timeZones: ['Asia/Tokyo'], }, { code: 'JO', countryName: 'Jordan', timeZones: ['Asia/Amman'], }, { code: 'KZ', countryName: 'Kazakhstan', timeZones: ['Asia/Almaty', 'Asia/Qyzylorda', 'Asia/Aqtobe', 'Asia/Aqtau', 'Asia/Oral'], }, { code: 'KE', countryName: 'Kenya', timeZones: ['Africa/Nairobi'], }, { code: 'KR', countryName: 'Korea', timeZones: ['Asia/Seoul'], }, { code: 'KW', countryName: 'Kuwait', timeZones: ['Asia/Kuwait'], }, { code: 'KG', countryName: 'Kyrgyzstan', timeZones: ['Asia/Bishkek'], }, { code: 'LA', countryName: 'Laos', timeZones: ['Asia/Vientiane'], }, { code: 'LV', countryName: 'Latvia', timeZones: ['Europe/Riga'], }, { code: 'LB', countryName: 'Lebanon', timeZones: ['Asia/Beirut'], }, { code: 'LY', countryName: 'Libya', timeZones: ['Africa/Tripoli'], }, { code: 'LI', countryName: 'Liechtenstein', timeZones: ['Europe/Vaduz'], }, { code: 'LT', countryName: 'Lithuania', timeZones: ['Europe/Vilnius'], }, { code: 'LU', countryName: 'Luxembourg', timeZones: ['Europe/Luxembourg'], }, { code: 'MO', countryName: 'Macao SAR', timeZones: ['Asia/Macau'], }, { code: 'MK', countryName: 'Macedonia, FYRO', timeZones: ['Europe/Skopje'], }, { code: 'MY', countryName: 'Malaysia', timeZones: ['Asia/Kuala_Lumpur', 'Asia/Kuching'], }, { code: 'MV', countryName: 'Maldives', timeZones: ['Indian/Maldives'], }, { code: 'ML', countryName: 'Mali', timeZones: ['Africa/Bamako'], }, { code: 'MT', countryName: 'Malta', timeZones: ['Europe/Malta'], }, { code: 'MX', countryName: 'Mexico', timeZones: [ 'America/Mexico_City', 'America/Cancun', 'America/Merida', 'America/Monterrey', 'America/Matamoros', 'America/Mazatlan', 'America/Chihuahua', 'America/Ojinaga', 'America/Hermosillo', 'America/Tijuana', 'America/Bahia_Banderas', ], }, { code: 'MD', countryName: 'Moldova', timeZones: ['Europe/Chisinau'], }, { code: 'MC', countryName: 'Monaco', timeZones: ['Europe/Monaco'], }, { code: 'MN', countryName: 'Mongolia', timeZones: ['Asia/Ulaanbaatar', 'Asia/Hovd', 'Asia/Choibalsan'], }, { code: 'ME', countryName: 'Montenegro', timeZones: ['Europe/Podgorica'], }, { code: 'MA', countryName: 'Morocco', timeZones: ['Africa/Casablanca'], }, { code: 'MM', countryName: 'Myanmar', timeZones: ['Asia/Rangoon'], }, { code: 'NP', countryName: 'Nepal', timeZones: ['Asia/Kathmandu'], }, { code: 'NL', countryName: 'Netherlands', timeZones: ['Europe/Amsterdam'], }, { code: 'NZ', countryName: 'New Zealand', timeZones: ['Pacific/Auckland', 'Pacific/Chatham'], }, { code: 'NI', countryName: 'Nicaragua', timeZones: ['America/Managua'], }, { code: 'NG', countryName: 'Nigeria', timeZones: ['Africa/Lagos'], }, { code: 'NO', countryName: 'Norway', timeZones: ['Europe/Oslo'], }, { code: 'OM', countryName: 'Oman', timeZones: ['Asia/Muscat'], }, { code: 'PK', countryName: 'Pakistan', timeZones: ['Asia/Karachi'], }, { code: 'PA', countryName: 'Panama', timeZones: ['America/Panama'], }, { code: 'PY', countryName: 'Paraguay', timeZones: ['America/Asuncion'], }, { code: 'PE', countryName: 'Peru', timeZones: ['America/Lima'], }, { code: 'PH', countryName: 'Philippines', timeZones: ['Asia/Manila'], }, { code: 'PL', countryName: 'Poland', timeZones: ['Europe/Warsaw'], }, { code: 'PT', countryName: 'Portugal', timeZones: ['Europe/Lisbon', 'Atlantic/Madeira', 'Atlantic/Azores'], }, { code: 'PR', countryName: 'Puerto Rico', timeZones: ['America/Puerto_Rico'], }, { code: 'QA', countryName: 'Qatar', timeZones: ['Asia/Qatar'], }, { code: 'RE', countryName: 'Réunion', timeZones: ['Indian/Reunion'], }, { code: 'RO', countryName: 'Romania', timeZones: ['Europe/Bucharest'], }, { code: 'RU', countryName: 'Russia', timeZones: [ 'Europe/Kaliningrad', 'Europe/Moscow', 'Europe/Simferopol', 'Europe/Volgograd', 'Europe/Astrakhan', 'Europe/Samara', 'Europe/Ulyanovsk', 'Asia/Yekaterinburg', 'Asia/Omsk', 'Asia/Novosibirsk', 'Asia/Barnaul', 'Asia/Novokuznetsk', 'Asia/Krasnoyarsk', 'Asia/Irkutsk', 'Asia/Chita', 'Asia/Yakutsk', 'Asia/Khandyga', 'Asia/Vladivostok', 'Asia/Ust-Nera', 'Asia/Magadan', 'Asia/Sakhalin', 'Asia/Srednekolymsk', 'Asia/Kamchatka', 'Asia/Anadyr', ], }, { code: 'RW', countryName: 'Rwanda', timeZones: ['Africa/Kigali'], }, { code: 'SA', countryName: 'Saudi Arabia', timeZones: ['Asia/Riyadh'], }, { code: 'SN', countryName: 'Senegal', timeZones: ['Africa/Dakar'], }, { code: 'RS', countryName: 'Serbia', timeZones: ['Europe/Belgrade'], }, { code: 'SG', countryName: 'Singapore', timeZones: ['Asia/Singapore'], }, { code: 'SK', countryName: 'Slovakia', timeZones: ['Europe/Bratislava'], }, { code: 'SI', countryName: 'Slovenia', timeZones: ['Europe/Ljubljana'], }, { code: 'SO', countryName: 'Somalia', timeZones: ['Africa/Mogadishu'], }, { code: 'ZA', countryName: 'South Africa', timeZones: ['Africa/Johannesburg'], }, { code: 'ES', countryName: 'Spain', timeZones: ['Europe/Madrid', 'Africa/Ceuta', 'Atlantic/Canary'], }, { code: 'LK', countryName: 'Sri Lanka', timeZones: ['Asia/Colombo'], }, { code: 'SE', countryName: 'Sweden', timeZones: ['Europe/Stockholm'], }, { code: 'CH', countryName: 'Switzerland', timeZones: ['Europe/Zurich'], }, { code: 'SY', countryName: 'Syria', timeZones: ['Asia/Damascus'], }, { code: 'TW', countryName: 'Taiwan', timeZones: ['Asia/Taipei'], }, { code: 'TJ', countryName: 'Tajikistan', timeZones: ['Asia/Dushanbe'], }, { code: 'TH', countryName: 'Thailand', timeZones: ['Asia/Bangkok'], }, { code: 'TT', countryName: 'Trinidad and Tobago', timeZones: ['America/Port_of_Spain'], }, { code: 'TN', countryName: 'Tunisia', timeZones: ['Africa/Tunis'], }, { code: 'TR', countryName: 'Turkey', timeZones: ['Europe/Istanbul'], }, { code: 'TM', countryName: 'Turkmenistan', timeZones: ['Asia/Ashgabat'], }, { code: 'UA', countryName: 'Ukraine', timeZones: ['Europe/Kiev', 'Europe/Uzhgorod', 'Europe/Zaporozhye'], }, { code: 'AE', countryName: 'United Arab Emirates', timeZones: ['Asia/Dubai'], }, { code: 'GB', countryName: 'United Kingdom', timeZones: ['Europe/London'], }, { code: 'US', countryName: 'United States', timeZones: [ 'America/New_York', 'America/Detroit', 'America/Kentucky/Louisville', 'America/Kentucky/Monticello', 'America/Indiana/Indianapolis', 'America/Indiana/Vincennes', 'America/Indiana/Winamac', 'America/Indiana/Marengo', 'America/Indiana/Petersburg', 'America/Indiana/Vevay', 'America/Chicago', 'America/Indiana/Tell_City', 'America/Indiana/Knox', 'America/Menominee', 'America/North_Dakota/Center', 'America/North_Dakota/New_Salem', 'America/North_Dakota/Beulah', 'America/Denver', 'America/Boise', 'America/Phoenix', 'America/Los_Angeles', 'America/Anchorage', 'America/Juneau', 'America/Sitka', 'America/Metlakatla', 'America/Yakutat', 'America/Nome', 'America/Adak', 'Pacific/Honolulu', ], }, { code: 'UY', countryName: 'Uruguay', timeZones: ['America/Montevideo'], }, { code: 'UZ', countryName: 'Uzbekistan', timeZones: ['Asia/Samarkand', 'Asia/Tashkent'], }, { code: 'VE', countryName: 'Venezuela', timeZones: ['America/Caracas'], }, { code: 'VN', countryName: 'Vietnam', timeZones: ['Asia/Ho_Chi_Minh'], }, { code: 'YE', countryName: 'Yemen', timeZones: ['Asia/Aden'], }, { code: 'ZW', countryName: 'Zimbabwe', timeZones: ['Africa/Harare'], }, ]; ================================================ FILE: backend/src/utils/currency.js ================================================ const currencyList = [ 'USD', 'CAD', 'EUR', 'AED', 'AFN', 'ALL', 'AMD', 'ARS', 'AUD', 'AZN', 'BAM', 'BDT', 'BGN', 'BHD', 'BIF', 'BND', 'BOB', 'BRL', 'BWP', 'BYR', 'BZD', 'CDF', 'CHF', 'CLP', 'CNY', 'COP', 'CRC', 'CVE', 'CZK', 'DJF', 'DKK', 'DOP', 'DZD', 'EEK', 'EGP', 'ERN', 'ETB', 'GBP', 'GEL', 'GHS', 'GNF', 'GTQ', 'HKD', 'HNL', 'HRK', 'HUF', 'IDR', 'ILS', 'INR', 'IQD', 'IRR', 'ISK', 'JMD', 'JOD', 'JPY', 'KES', 'KHR', 'KMF', 'KRW', 'KWD', 'KZT', 'LBP', 'LKR', 'LTL', 'LVL', 'LYD', 'MAD', 'MDL', 'MGA', 'MKD', 'MMK', 'MOP', 'MUR', 'MXN', 'MYR', 'MZN', 'NAD', 'NGN', 'NIO', 'NOK', 'NPR', 'NZD', 'OMR', 'PAB', 'PEN', 'PHP', 'PKR', 'PLN', 'PYG', 'QAR', 'RON', 'RSD', 'RUB', 'RWF', 'SAR', 'SDG', 'SEK', 'SGD', 'SOS', 'SYP', 'THB', 'TND', 'TOP', 'TRY', 'TTD', 'TWD', 'TZS', 'UAH', 'UGX', 'UYU', 'UZS', 'VEF', 'VES', 'VND', 'XAF', 'XCD', 'XOF', 'YER', 'ZAR', 'ZMK', ]; exports.checkCurrency = (code) => { return currencyList.includes(code.toUpperCase()); }; ================================================ FILE: backend/src/utils/currencyList.js ================================================ exports.currencyList = [ { currency_symbol: '$', currency_position: 'before', decimal_sep: '.', thousand_sep: ',', cent_precision: 2, zero_format: true, currency_name: 'US Dollar', currency_code: 'USD', enabled: true, }, { currency_symbol: '€', currency_position: 'after', decimal_sep: '.', thousand_sep: ' ', cent_precision: 2, zero_format: true, currency_name: 'Euro', currency_code: 'EUR', enabled: true, }, ]; ================================================ FILE: backend/src/utils/is-path-inside.js ================================================ const path = require('path'); // is implementation of is-path-inside npm package exports.isPathInside = (childPath, parentPath) => { const relation = path.relative(parentPath, childPath); return Boolean( relation && relation !== '..' && !relation.startsWith(`..${path.sep}`) && relation !== path.resolve(childPath) ); }; ================================================ FILE: doc/README.fr.md ================================================ #### French Translation

Open "Fair-Code" Source ERP / CRM | Node.js React.js

IDURAR ERP CRM | Simple à utiliser | 44 Langues

[www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) ## 🇦🇱 🇩🇿 🇧🇩 🇧🇬 🇨🇳 🇭🇷 🇨🇿 🇩🇰 🇳🇱 🇺🇸 🇪🇪 🇫🇷 🇩🇪 🇬🇷 🇮🇳 🇭🇺 🇮🇩 🇮🇹 🇯🇵 🇰🇷 🇱🇻 🇱🇹 🇲🇰 🇲🇾 🇳🇴 🇵🇱 🇧🇷 🇵🇹 🇮🇷 🇷🇴 🇷🇺 🇸🇰 🇸🇮 🇪🇸 🇸🇪 🇹🇭 🇹🇷 🇺🇦 🇵🇰 🇻🇳 🇷🇸 🇪🇦 🇵🇭 🇫🇮 IDURAR est un Open "Fair-Code" Source ERP / CRM (Facturation / Inventaire / Comptabilité / RH) Basé sue le Mern Stack avancé (Node.js / Express.js / MongoDb / React.js ) avec Ant Design (AntD) et Redux
**Démo de l'application en direct** : [https://www.idurarapp.com/demo-erp-crm/](https://www.idurarapp.com/demo-erp-crm/) **Identifiants** : ``` nom d'utilisateur : admin@admin.com mot de passe : admin123 ``` ``` 🚀 Donnez une étoile ⭐️ & faites un Fork de ce projet ... Bonne programmation! 🤩` ``` ## License IDURAR est un Open Code Source gratuit [fair-code](http://faircode.io) distribué sous la [**IDURAR License 1.0**](https://github.com/idurar/idurar-erp-crm/blob/master/LICENSE) ## License FAQ : ## Caractéristiques : Gestion des factures 💰 Gestion des stocks 🧳 Gestion comptable 📈 Gestion des ressources humaines 🧑‍🤝‍🧑 Ant Design Framework(AntD) 🐜 Basé sur le Mern Stack (Node.js / Express.js / MongoDb / React.js ) 👨‍💻 ### Puis-je utiliser IDURAR à des fins commerciales : - Oui, vous pouvez utiliser IDURAR gratuitement à des fins personnelles ou commerciales. ### Puis-je personnaliser IDURAR en tant que SaaS et le fournir à d'autres utilisateurs ? Non, vous ne pouvez pas personnaliser IDURAR en tant que SaaS et le fournir à d'autres utilisateurs. Vous n'êtes pas autorisé à fournir le logiciel IDURAR à des tiers en tant que service hébergé ou géré ou en tant que logiciel en tant que service (SaaS), où le service fournit aux utilisateurs un accès à un ensemble substantiel de fonctionnalités de ce logiciel. ### Pour des services de développement personnalisés ou un support premium : [Contactez-nous](mailto:hello@idurarapp.com) ## Comment déployer IDURAR ERP CRM : 🔥 Je vous invite à un webinaire IDURAR gratuit chaque semaine (cours Node.js React.js), où vous apprendrez à déployer IDURAR sur le cloud et à créer une nouvelle API et une nouvelle application CRUD avec IDURAR en une heure seulement ? Veuillez remplir ce formulaire si vous êtes intéressé : [https://forms.gle/qz2YZ3xQFQ77bGhS8](https://forms.gle/qz2YZ3xQFQ77bGhS8) Le webinaire aura lieu ce mercredi à 13h GMT. ## Nos Sponsors # Open Source ERP CRM ## Application ERP / CRM Open Source gratuite IDURAR est un ERP / CRM Open Source basé sur le "Fair-Code" (Facturation / Inventaire / Comptabilité / RH) basé sur la stack Mern (Node.js / Express.js / MongoDb / React.js ) avec Ant Design (AntD) et Redux **Démo de l'application en direct** : [https://www.idurarapp.com/demo-erp-crm/](https://www.idurarapp.com/demo-erp-crm/) ## Premiers Pas 1.[Cloner le dépôt](INSTALLATION-INSTRUCTIONS.md#step-1-clone-the-repository) 2.[Créer votre compte MongoDB et votre cluster de base de données](INSTALLATION-INSTRUCTIONS.md#Step-2-Create-Your-MongoDB-Account-and-Database-Cluster) 3.[Modifier le fichier d'environnement](INSTALLATION-INSTRUCTIONS.md#Step-3-Edit-the-Environment-File) 4.[Mettre à jour l'URI MongoDB](INSTALLATION-INSTRUCTIONS.md#Step-4-Update-MongoDB-URI) 5.[Installer les dépendances backend](INSTALLATION-INSTRUCTIONS.md#Step-5-Install-Backend-Dependencies) 6.[Exécuter le script de configuration](INSTALLATION-INSTRUCTIONS.md#Step-6-Run-Setup-Script) 7.[Exécuter le serveur backend](INSTALLATION-INSTRUCTIONS.md#Step-7-Run-the-Backend-Server) 8.[Installer les dépendances frontend](INSTALLATION-INSTRUCTIONS.md#Step-8-Install-Frontend-Dependencies) 9.[Exécuter le serveur Frontend](INSTALLATION-INSTRUCTIONS.md#Step-9-Run-the-Frontend-Server) ## Docker Compose pour le développement local - configurer les variables d'environnement supplémentaires, si nécessaire, dans le fichier ci-dessous ```bash docker-compose.yml ``` - Après avoir configuré les éléments nécessaires, exécutez la commande suivante : ```bash docker-compose up -d ``` Cela construira les images et lancera les conteneurs pour le frontend, le backend et MongoDB. **_Remarque:_** Cette configuration docker-compose est associée uniquement au développement local. ## Contribuer 1.[Comment Contribuer](https://github.com/idurar/idurar-erp-crm/blob/master/CONTRIBUTING.md#how-to-contribute) 2.[Signaler des problèmes](https://github.com/idurar/idurar-erp-crm/blob/master/CONTRIBUTING.md#reporting-issues) 3.[Travailler sur des problèmes](https://github.com/idurar/idurar-erp-crm/blob/master/CONTRIBUTING.md#working-on-issues) 4.[Soumettre des pull requests](https://github.com/idurar/idurar-erp-crm/blob/master/CONTRIBUTING.md#submitting-pull-requests) 5.[Directives de commit](https://github.com/idurar/idurar-erp-crm/blob/master/CONTRIBUTING.md#commit-guidelines) 6.[Directives de codage](https://github.com/idurar/idurar-erp-crm/blob/master/CONTRIBUTING.md#coding-guidelines) 7.[Questions](https://github.com/idurar/idurar-erp-crm/blob/master/CONTRIBUTING.md#questions) ## Service de développement personnalisé Des services de développement personnalisés sont disponibles : [Contactez-nous](mailto:hello@idurarapp.com) ## Montrez votre soutien N'oubliez pas de donner une ⭐️ à ce projet ... Bonne programmation! ================================================ FILE: doc/README.sp.md ================================================ #### Spanish Translation

ERP/CRM de Código Abierto y "Fair-Code" | Node.js React.js

IDURAR ERP CRM | Fácil de usar | 44 Idiomas

[www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) ## 🇦🇱 🇩🇿 🇧🇩 🇧🇬 🇨🇳 🇭🇷 🇨🇿 🇩🇰 🇳🇱 🇺🇸 🇪🇪 🇫🇷 🇩🇪 🇬🇷 🇮🇳 🇭🇺 🇮🇩 🇮🇹 🇯🇵 🇰🇷 🇱🇻 🇱🇹 🇲🇰 🇲🇾 🇳🇴 🇵🇱 🇧🇷 🇵🇹 🇮🇷 🇷🇴 🇷🇺 🇸🇰 🇸🇮 🇪🇸 🇸🇪 🇹🇭 🇹🇷 🇺🇦 🇵🇰 🇻🇳 🇷🇸 🇪🇦 🇵🇭 🇫🇮 IDURAR es un ERP/CRM de Código Abierto y "Fair-Code" (Facturación/Inventario/Contabilidad/RRHH) basado en Advanced Mern Stack (Node.js/Express.js/MongoDb/React.js) con Ant Design (AntD) y Redux
**Demo en Vivo** : [https://www.idurarapp.com/demo-erp-crm/](https://www.idurarapp.com/demo-erp-crm/) **Credenciales** : ``` usuario: admin@admin.com contraseña: admin123 ``` ``` 🚀 Dale una Estrella ⭐️ y Haz un Fork a este proyecto ... ¡Feliz codificación!🤩` ``` ## Licencia IDURAR es un Código Abierto Gratuito bajo [fair-code](http://faircode.io) distribuido bajo la [**IDURAR License 1.0**](https://github.com/idurar/idurar-erp-crm/blob/master/LICENSE) ## Preguntas Frecuentes sobre la Licencia: : ## Características : Gestión de Facturas 💰 Gestión de Inventario 🧳 Gestión Contable 📈 Gestión de Recursos Humanos 🧑‍🤝‍🧑 Ant Design Framework(AntD) 🐜 Basado en Mern Stack (Node.js / Express.js / MongoDb / React.js ) 👨‍💻 ### ¿Puedo usar IDURAR con fines comerciales? : - Sí, puedes usar IDURAR de forma gratuita para uso personal o comercial. ### ¿Puedo personalizar IDURAR como SaaS y ofrecerlo a otros usuarios? No, no puedes personalizar IDURAR como SaaS y ofrecerlo a otros usuarios. No se permite proporcionar el software IDURAR a terceros como un servicio hospedado o gestionado, o como software como servicio (SaaS), donde el servicio proporciona a los usuarios acceso a un conjunto sustancial de funciones o características de este software. ### Para servicios de desarrollo personalizado o soporte premium: [Ponte en contacto](mailto:hello@idurarapp.com) ## Cómo Desplegar IDURAR ERP CRM : 🔥 Me gustaría invitarte a un seminario web semanal gratuito de IDURAR (curso Node.js React.js), donde aprenderás cómo desplegar IDURAR en la nube y crear una nueva API y una nueva aplicación CRUD con IDURAR en solo una hora. Completa este formulario si estás interesado: [https://forms.gle/qz2YZ3xQFQ77bGhS8](https://forms.gle/qz2YZ3xQFQ77bGhS8) El seminario web será este miércoles a la 1 pm GMT. ## Nuestros Patrocinadores # Open Source ERP CRM ## Aplicación ERP/CRM de Código Abierto y Gratuito IDURAR es un ERP/CRM de Código Abierto y "Fair-Code" (Facturación/Inventario/Contabilidad/RRHH) basado en Advanced Mern Stack (Node.js/Express.js/MongoDb/React.js) con Ant Design (AntD) y Redux **Demo en Vivo** : [https://www.idurarapp.com/demo-erp-crm/](https://www.idurarapp.com/demo-erp-crm/) ## Comenzando 1.[Clona el repositorio](INSTALLATION-INSTRUCTIONS.md#step-1-clone-the-repository) 2.[Crea tu cuenta y clúster de base de datos en MongoDB](INSTALLATION-INSTRUCTIONS.md#Step-2-Create-Your-MongoDB-Account-and-Database-Cluster) 3.[Edita el archivo de entorno](INSTALLATION-INSTRUCTIONS.md#Step-3-Edit-the-Environment-File) 4.[Actualiza la URI de MongoDB](INSTALLATION-INSTRUCTIONS.md#Step-4-Update-MongoDB-URI) 5.[Instala las Dependencias del Backend](INSTALLATION-INSTRUCTIONS.md#Step-5-Install-Backend-Dependencies) 6.[Ejecuta el Script de Configuración](INSTALLATION-INSTRUCTIONS.md#Step-6-Run-Setup-Script) 7.[Ejecuta el Servidor Backend](INSTALLATION-INSTRUCTIONS.md#Step-7-Run-the-Backend-Server) 8.[Instala las Dependencias del Frontend](INSTALLATION-INSTRUCTIONS.md#Step-8-Install-Frontend-Dependencies) 9.[Ejecuta el Servidor Frontend](INSTALLATION-INSTRUCTIONS.md#Step-9-Run-the-Frontend-Server) ## Docker Compose para desarrollo local - configura variables de entorno adicionales, si es necesario, en el siguiente archivo ```bash docker-compose.yml ``` - Después de las configuraciones necesarias, ejecuta el siguiente comando: ```bash docker-compose up -d ``` Esto construirá las imágenes y pondrá en marcha los contenedores para el frontend, backend y MongoDB. **_NOTA:_** Esta configuración de docker-compose está asociada solo para desarrollo local. ## Contribuir 1.[Cómo contribuir](https://github.com/idurar/idurar-erp-crm/blob/master/CONTRIBUTING.md#how-to-contribute) 2.[Reportar problemas](https://github.com/idurar/idurar-erp-crm/blob/master/CONTRIBUTING.md#reporting-issues) 3.[Trabajar en problemas](https://github.com/idurar/idurar-erp-crm/blob/master/CONTRIBUTING.md#working-on-issues) 4.[Enviar solicitudes de extracción](https://github.com/idurar/idurar-erp-crm/blob/master/CONTRIBUTING.md#submitting-pull-requests) 5.[Directrices para los commits](https://github.com/idurar/idurar-erp-crm/blob/master/CONTRIBUTING.md#commit-guidelines) 6.[Directrices de codificación](https://github.com/idurar/idurar-erp-crm/blob/master/CONTRIBUTING.md#coding-guidelines) 7.[Preguntas](https://github.com/idurar/idurar-erp-crm/blob/master/CONTRIBUTING.md#questions) ## Servicio de Desarrollo Personalizado Los servicios de desarrollo personalizado están disponibles: [Contactez-nous](mailto:hello@idurarapp.com) ## Muestra tu apoyo ¡No olvides darle una ⭐️ a este proyecto ... ¡Feliz codificación! ================================================ FILE: features/ar_eg_ملف_مفتوح_المصدر_مجاني_للبرمجيات_ERP_CRM.md ================================================ # IDURAR برنامج إدارة الموارد التخطيطية وعلاقات العملاء مفتوح المصدر GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) العرض التوضيحي: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) الموقع الإلكتروني: [https://www.idurarapp.com](https://www.idurarapp.com) ## تكوين البرنامج IDURAR تطبيق ERP & CRM مفتوح المصدر ومجاني، يعتمد على "mern-stack" : Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## إدارة المستخدمين: - السماح للمسؤولين بإنشاء وتحرير وحذف حسابات المستخدمين. - تنفيذ نظام التحكم في الوصول المستند إلى الأدوار لإدارة أذونات المستخدمين. - توفير آليات المصادقة والتفويض لضمان الوصول الآمن. ## إدارة علاقات العملاء (CRM): - تمكين المستخدمين من إنشاء وإدارة سجلات الاتصال للعملاء المحتملين والعملاء. - تنفيذ وظائف توليد العملاء المحتملين وتأهيلهم لتتبع فرص المبيعات المحتملة. - توفير أدوات لإدارة تاريخ التواصل مع العملاء، بما في ذلك الرسائل البريدية والمكالمات والاجتماعات. - السماح للمستخدمين بجدولة المواعيد وإرسال إشعارات أو تذكيرات للعملاء. ## إدارة المبيعات: - السماح للمستخدمين بإنشاء وإدارة أوامر البيع، مرتبطة بعملاء محددين. - تنفيذ تتبع المخزون للتحقق من توافر المنتج وتحديث مستويات المخزون بعد كل بيع. - إنشاء الفواتير والتعامل مع تكامل الدفع مع بوابات الدفع الشهيرة. - توفير لوحات المعلومات والتقارير لمراقبة أداء المبيعات وتحليل الاتجاهات. ## إدارة المشتريات: - السماح للمستخدمين بإنشاء وإدارة أوامر الشراء، محددة الكمية والمنتجات المطلوبة. - تتبع معلومات المورد وإدارة علاقات الموردين. - استلام السلع وتحديث مستويات المخزون وفقًا لذلك. - التعامل مع فواتير الشراء والمدفوعات للموردين. ## إدارة المخزون: - توفير أدوات لإدارة وتتبع مستويات المخزون، بما في ذلك نقل المخزون وتعديلاته. - إعداد إشعارات تلقائية لمستويات المخزون المنخفضة وإنشاء أوامر الشراء عند الحاجة لإعادة التزود. - توفير قدرات مسح الباركود لإدارة المخزون بكفاءة. - تمكين المستخدمين من تصنيف المنتجات وتحديد السمات وتحديد معلومات التسعير. ## إدارة المالية: - تنفيذ نظام دفتر الأستاذ العام لتتبع المعاملات المالية، بما في ذلك المصروفات والإيرادات. - إدارة الحسابات المدينة والحسابات الدائنة، بما في ذلك إصدار الفواتير وتتبع الدفعات. - إنشاء تقارير مالية، بما في ذلك الميزانية العمومية وقوائم الدخل. - تكامل مع برامج المحاسبة الشهيرة لإدارة مالية سلسة. ## إدارة المشاريع: - توفير قدرات إدارة المشاريع، مما يتيح للمستخدمين إنشاء وتتبع المشاريع. - تعيين المهام لأعضاء الفريق، وتحديد المواعيد النهائية، ومراقبة التقدم. - تخصيص الموارد وتتبع مصاريف المشروع. - توفير ميزات التعاون مثل مشاركة المستندات والاتصال في الوقت الحقيقي. ## التقارير والتحليلات: - إنشاء تقارير وتحليلات شاملة حول جوانب مختلفة من العمل. - توفير لوحات المعلومات قابلة للتخصيص لمراقبة مؤشرات الأداء الرئيسية. - السماح للمستخدمين بتعريف تقارير مخصصة بناءً على متطلبات محددة. - تنفيذ تقنيات تصور البيانات لتقديم المعلومات بطريقة جذابة بصريًا. ## التكامل والتخصيص: - تمكين التكامل مع تطبيقات أو واجهات برمجة التطبيقات الخارجية الشهيرة، مثل أدوات التسويق عبر البريد الإلكتروني أو منصات CRM. - السماح بتخصيص وظائف التطبيق ومظهره وفقًا لاحتياجات الأعمال المحددة. - توفير واجهة برمجة التطبيقات (API) أو الويب هوكس لتسهيل تبادل البيانات بين تطبيق ERP & CRM والأنظمة الأخرى. ## واجهة سهلة الاستخدام: - تصميم واجهة سهلة الاستخدام ومتجاوبة ومستخدمة باستخدام React.js و Ant Design. - تنفيذ قوائم تنقل سهلة الاستخدام ووظائف البحث والتصفية. - ضمان واجهة مستخدم متسقة وجذابة بصريًا عبر أجهزة مختلفة وأحجام الشاشة. ================================================ FILE: features/bg_bg_свободен_отворен_източник_erp_crm_софтуер.md ================================================ # IDURAR Софтуер за управление на отворен код ERP & CRM GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Демо: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Уебсайт: [https://www.idurarapp.com](https://www.idurarapp.com) ## Стек от софтуерни технологии IDURAR е безплатен софтуер с отворен код за управление на ERP & CRM приложения, базиран на "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Управление на потребителите: - Позволява на администраторите да създават, редактират и изтриват потребителски акаунти. - Имплементира контрол на достъпа на базата на роли за управление на потребителските права. - Предоставя механизми за удостоверяване на самоличността и разрешаване на достъпа, за да се осигури сигурен достъп. ## Управление на клиентските взаимоотношения (CRM): - Позволява на потребителите да създават и управляват контактни записи за потенциални клиенти и клиенти. - Имплементира функционалности за генериране и квалифициране на потенциални продажби, за проследяване на възможности за продажби. - Предоставя инструменти за управление на историята на комуникацията с клиентите, включително имейли, обаждания и срещи. - Позволява на потребителите да планират срещи и да изпращат известия или напомняния на клиентите. ## Управление на продажбите: - Позволява на потребителите да създават и управляват поръчки за продажби, свързани с конкретни клиенти. - Имплементира проследяване на наличността на продукти и актуализира нивата на склад след всяка продажба. - Генерира фактури и се грижи за интеграцията на плащанията с популярни платежни портали. - Предоставя табла и отчети за наблюдение на продажбите и анализ на тенденциите. ## Управление на закупките: - Позволява на потребителите да създават и управляват поръчки за закупуване, указвайки количество и желани продукти. - Проследява информация за доставчици и управлява отношенията с доставчици. - Получава стоки и актуализира нивата на склада съответно. - Справя се със закупни фактури и плащания към доставчици. ## Управление на склада: - Предоставя инструменти за управление и проследяване на нивата на склада, включително прехвърляне на стоки и корекции. - Задава автоматични известия за ниските нива на наличност и генерира поръчки при необходимост от допълване на запасите. - Предлага възможности за сканиране на баркодове за ефективно управление на склада. - Позволява на потребителите да категоризират продуктите, да определят атрибути и да задават информация за ценообразуването. ## Финансово управление: - Имплементира система за главна книга за проследяване на финансовите транзакции, включително разходи и приходи. - Управлява дебиторските и кредиторските сметки, включително фактуриране и проследяване на плащанията. - Генерира финансови отчети, включително балансови отчети и отчети за приходите. - Интегрира с популярни софтуерни приложения за синхронно финансово управление. ## Управление на проекти: - Предоставя възможности за управление на проекти, позволяващи на потребителите да създават и проследяват проекти. - Задава задачи на членове на екипа, срокове и наблюдава напредъка. - Разпределя ресурси и проследява разходите по проекта. - Предлага функционалности за сътрудничество, като споделяне на документи и комуникация в реално време. ## Отчети и анализи: - Генерира изчерпателни отчети и анализи за различни аспекти на бизнеса. - Предоставя персонализируеми табла за наблюдение на ключови показатели за ефективност (KPI). - Позволява на потребителите да дефинират персонализирани отчети, базирани на конкретни изисквания. - Имплементира визуализация на данни за представяне на информация по визуално привлекателен начин. ## Интеграция и персонализация: - Позволява интеграция с популярни приложения или API-и на трети страни, като инструменти за електронен маркетинг или платформи за управление на клиентски взаимоотношения (CRM). - Позволява персонализация на функционалността и външния вид на приложението в съответствие с конкретните бизнес нужди. - Предоставя API или уеб-кукове, за да улесни обмена на данни между ERP & CRM приложението и други системи. ## Потребителски интерфейс, удобен за потребителя: - Проектира интуитивен, отзивчив и потребителски интерфейс, използвайки React.js и Ant Design. - Имплементира лесни за използване навигационни менюта, функции за търсене и филтри. - Осигурява последователен и визуално привлекателен потребителски интерфейс на различни устройства и размери на екрана. ================================================ FILE: features/bn_bd_ফ্রি_ওপেন_সোর্স_ইআরপি_সিআরএম_সফটওয়্যার.md ================================================ # IDURAR ওপেন-সোর্স ইআরপি এবং সিআরএম সফটওয়্যার গিটহাব: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) ডেমো: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) ওয়েবসাইট: [https://www.idurarapp.com](https://www.idurarapp.com) ## সফটওয়্যার স্ট্যাক IDURAR ফ্রি ওপেন-সোর্স ইআরপি এবং সিআরএম অ্যাপ, "মার্ন-স্ট্যাক" ভিত্তিক: নোড.জেএস, রিয়েক্ট.জেএস, রিডাক্স, এক্সপ্রেস.জেএস, মঙ্গোডিবি, অ্যান্টডিজাইন (অ্যান্টডি) ## ব্যবহারকারী ব্যবস্থাপনা: - প্রশাসকদের ব্যবহারকারী অ্যাকাউন্ট তৈরি, সম্পাদনা এবং মুছে ফেলার সুযোগ দিন। - ব্যবহারকারী অনুমতি পরিচালনা করতে ভূমিকা ভিত্তিক অ্যাক্সেস নিয়ন্ত্রণ সংজ্ঞায়িত করুন। - নিরাপত্তা নিশ্চিত করতে প্রমাণীকরণ এবং অনুমোদন পদ্ধতিগুলি প্রদান করুন। ## গ্রাহক সম্পর্ক ব্যবস্থাপনা (সিআরএম): - ব্যবহারকারীদের লিড, সম্ভাব্য ক্রয়কারীদের এবং গ্রাহকদের যোগাযোগের রেকর্ড তৈরি এবং পরিচালনা করার সুযোগ দিন। - সম্ভাব্য বিক্রয় সুযোগগুলি ট্র্যাক করতে লিড উত্পাদন এবং যোগ্যতা ব্যবস্থাপনা সংজ্ঞায়িত করুন। - গ্রাহকের যোগাযোগ ইতিহাস পরিচালনার জন্য সরঞ্জাম প্রদান করুন, যার মধ্যে ইমেল, কল এবং মিটিংস রয়েছে। - ব্যবহারকারীদের নীতি করে নিয়োগ করুন এবং গ্রাহকদের বিজ্ঞপ্তি বা অনুস্মারক প্রেরণ করুন। ## বিক্রয় ব্যবস্থাপনা: - ব্যবহারকারীদের বিক্রয় আদেশ তৈরি এবং পরিচালনা করার সুযোগ দিন, যা নির্দিষ্ট গ্রাহকদের সাথে সংযুক্ত করুন। - পণ্যের উপস্থিতি পরীক্ষা করতে ইনভেন্টরি ট্র্যাক করুন এবং প্রতিটি বিক্রয়ের পরে স্টক স্তর আপডেট করুন। - চালান তৈরি করুন এবং জনপ্রিয় পেমেন্ট গেটওয়েস সহ পেমেন্ট ইন্টিগ্রেশন হ্যান্ডল করুন। - বিক্রয় কর্মক্ষমতা মনিটর করতে ড্যাশবোর্ড এবং প্রতিবেদন প্রদান করুন এবং প্রবণতা বিশ্লেষণ করুন। ## ক্রয় ব্যবস্থাপনা: - ব্যবহারকারীদের ক্রয় আদেশ তৈরি এবং পরিচালনা করার সুযোগ দিন, পরিমাণ এবং পছন্দসই পণ্য নির্দিষ্ট করুন। - সরবরাহকারী তথ্য ট্র্যাক করুন এবং সরবরাহকারী সম্পর্ক পরিচালনা করুন। - পণ্য গ্রহণ করুন এবং স্টক স্তর সময়মত আপডেট করুন। - সরবরাহ চালান এবং সরবরাহকারীদের সাথে পেমেন্ট হ্যান্ডল করুন। ## ইনভেন্টরি ব্যবস্থাপনা: - স্টক স্তর পরিচালনার জন্য সরঞ্জাম প্রদান করুন, যা স্টক স্থানান্তর এবং সংশোধন সহ অনুসরণ করতে সাহায্য করে। - লো স্টক স্তরের জন্য স্বয়ংক্রিয় বিজ্ঞপ্তি সেট করুন এবং পুনরায় স্টক পূরণ করতে ক্রয় আদেশ তৈরি করুন। - দক্ষতার স্টক পরিচালনার জন্য বারকোড স্ক্যানিং সুযোগ প্রদান করুন। - ব্যবহারকারীদের পণ্য বিভাগীকরণ, গুণগত বৈশিষ্ট্য সংজ্ঞায়িত করুন এবং মূল্য তথ্য সেট করুন। ## আর্থিক ব্যবস্থাপনা: - আর্থিক লেজার সিস্টেম সংযোজন করুন যাতে ব্যয় এবং আয়ের মধ্যে আর্থিক লেনদেন ট্র্যাক করা যায়, এবং হিসাব রক্ষা করা যায়। - প্রাপ্য এবং প্রদানযোগ্য হিসাব সহ আউটসোর্স হিসাব ব্যবস্থাপনা করুন, যার মধ্যে ইনভয়েসিং এবং পেমেন্ট ট্র্যাকিং রয়েছে। - সমন্বয় শীট এবং আয় বিবরণী সহ আর্থিক রিপোর্ট তৈরি করুন। - একটি সহজ আর্থিক ব্যবস্থাপনার জন্য জনপ্রিয় হিসাবনিকাশ সফটওয়্যারের সাথে সংযোগ করুন। ## প্রকল্প ব্যবস্থাপনা: - ব্যবহারকারীদের প্রকল্প ব্যবস্থাপনা সুযোগ প্রদান করুন, যার মধ্যে প্রকল্প তৈরি এবং অনুসরণ করা হয়। - দলের সদস্যদের কাজ বরাদ্দ করুন, শেষ সময় সেট করুন এবং প্রগতি মনিটর করুন। - সম্পদ বরাদ্দ করুন এবং প্রকল্প ব্যয় মনিটর করুন। - নথি ভাগাভাগি এবং সময়সীমার যোগাযোগের মতো সহযোগিতার সুযোগ প্রদান করুন। ## রিপোর্টিং এবং বিশ্লেষণ: - ব্যবসায়িক বিভিন্ন দিকে বিস্তারিত রিপোর্ট এবং বিশ্লেষণ তৈরি করুন। - মূল্যবান কর্মক্ষমতা সূচক (কেপিআই) মনিটর করার জন্য কাস্টমাইজযোগ্য ড্যাশবোর্ড প্রদান করুন। - নির্দিষ্ট প্রয়োজনগুলির উপর ভিত্তি করে কাস্টম রিপোর্ট সংজ্ঞায়িত করার সুযোগ দিন। - তথ্যগুলি ভিজ্যুয়ালাইজেশন পদ্ধতিগুলি ব্যবহার করে তথ্য আরো আকর্ষণীয়ভাবে প্রদর্শন করার সুযোগ দিন। ## ইন্টিগ্রেশন এবং কাস্টমাইজেশন: - ইমেল মার্কেটিং টুল বা সিআরএম প্ল্যাটফর্ম সহ জনপ্রিয় তৃতীয়-পক্ষ অ্যাপ্লিকেশন বা এপিআইর সাথে ইন্টিগ্রেশন সক্ষম করুন। - ব্যবসায়িক প্রয়োজনগুলির উপর ভিত্তি করে অ্যাপ্লিকেশনের কার্যক্রম এবং প্রদর্শন কাস্টমাইজ করার সুযোগ দিন। - ইআরপি এবং সিআরএম অ্যাপ এবং অন্যান্য সিস্টেমগুলির মধ্যে ডেটা আদান-প্রদান সুবিধা প্রদান করার জন্য একটি এপিআই বা ওয়েবহুক প্রদান করুন। ## ব্যবহারকারী বন্ধুপ্রিয় ইন্টারফেস: - রিয়েক্ট.জেএস এবং অ্যান্ট ডিজাইন ব্যবহার করে একটি সুবিধাজনক, সামর্থ্যযুক্ত এবং ব্যবহারকারীর জন্য বন্ধুপ্রিয় ইন্টারফেস ডিজাইন করুন। - সহজে ব্যবহার করা যায় নেভিগেশন মেনু, অনুসন্ধান সুবিধাগুলি এবং ফিল্টারগুলি সংজ্ঞায়িত করুন। - বিভিন্ন ডিভাইস এবং স্ক্রিন সাইজে একটি সমন্বিত এবং ভিজ্যুয়ালি আকর্ষণীয় ইউআই নিশ্চিত করুন। ================================================ FILE: features/ca_es_software_erp_crm_de_codi_obert_gratuït.md ================================================ # IDURAR Software de ERP y CRM de código abierto GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Sitio web: [https://www.idurarapp.com](https://www.idurarapp.com) ## Pila de software IDURAR es una aplicación gratuita de ERP y CRM de código abierto, basada en "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Gestión de usuarios: - Permitir a los administradores crear, editar y eliminar cuentas de usuario. - Implementar control de acceso basado en roles para gestionar los permisos de los usuarios. - Proporcionar mecanismos de autenticación y autorización para garantizar un acceso seguro. ## Gestión de relaciones con los clientes (CRM): - Permitir a los usuarios crear y gestionar registros de contacto para clientes potenciales y clientes. - Implementar funcionalidades de generación y calificación de leads para rastrear oportunidades de venta potenciales. - Proporcionar herramientas para gestionar el historial de comunicación con los clientes, incluyendo correos electrónicos, llamadas y reuniones. - Permitir a los usuarios programar citas y enviar notificaciones o recordatorios a los clientes. ## Gestión de ventas: - Permitir a los usuarios crear y gestionar pedidos de venta, asociándolos con clientes específicos. - Implementar seguimiento de inventario para verificar la disponibilidad de productos y actualizar los niveles de stock después de cada venta. - Generar facturas y gestionar la integración de pagos con pasarelas de pago populares. - Proporcionar paneles de control e informes para monitorear el rendimiento de las ventas y analizar las tendencias. ## Gestión de compras: - Permitir a los usuarios crear y gestionar órdenes de compra, especificando la cantidad y los productos deseados. - Rastrear información de proveedores y gestionar las relaciones con los proveedores. - Recibir bienes y actualizar los niveles de inventario en consecuencia. - Gestionar facturas de compra y pagos a proveedores. ## Gestión de inventario: - Proporcionar herramientas para gestionar y rastrear los niveles de inventario, incluyendo transferencias de stock y ajustes. - Configurar notificaciones automáticas para niveles de stock bajos y generar órdenes de compra cuando sea necesario reponer existencias. - Ofrecer capacidades de escaneo de códigos de barras para una gestión eficiente del inventario. - Permitir a los usuarios categorizar productos, definir atributos y establecer información de precios. ## Gestión financiera: - Implementar un sistema de libro mayor para rastrear transacciones financieras, incluyendo gastos e ingresos. - Gestionar cuentas por cobrar y cuentas por pagar, incluyendo facturación y seguimiento de pagos. - Generar informes financieros, incluyendo balances y estados de ingresos. - Integrar con software de contabilidad populares para una gestión financiera sin problemas. ## Gestión de proyectos: - Proporcionar capacidades de gestión de proyectos, permitiendo a los usuarios crear y rastrear proyectos. - Asignar tareas a los miembros del equipo, establecer plazos y monitorear el progreso. - Asignar recursos y rastrear los gastos del proyecto. - Ofrecer características de colaboración como compartir documentos y comunicación en tiempo real. ## Informes y análisis: - Generar informes y análisis completos sobre diversos aspectos del negocio. - Proporcionar paneles de control personalizables para monitorear indicadores clave de rendimiento (KPI). - Permitir a los usuarios definir informes personalizados basados en requisitos específicos. - Implementar técnicas de visualización de datos para presentar información de manera visualmente atractiva. ## Integración y personalización: - Permitir la integración con aplicaciones o APIs de terceros populares, como herramientas de marketing por correo electrónico o plataformas de CRM. - Permitir la personalización de la funcionalidad y apariencia de la aplicación según las necesidades comerciales específicas. - Proporcionar una API o webhooks para facilitar el intercambio de datos entre la aplicación de ERP y CRM y otros sistemas. ## Interfaz amigable para el usuario: - Diseñar una interfaz intuitiva, receptiva y fácil de usar utilizando React.js y Ant Design. - Implementar menús de navegación fáciles de usar, funcionalidades de búsqueda y filtros. - Garantizar una interfaz de usuario consistente y visualmente atractiva en diferentes dispositivos y tamaños de pantalla. ================================================ FILE: features/cs_cz_volný_otevřený_zdroj_erp_crm_software.md ================================================ # IDURAR Open-Source ERP & CRM Software GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Webová stránka: [https://www.idurarapp.com](https://www.idurarapp.com) ## Softwarový stack IDURAR Bezplatná open-source ERP & CRM aplikace, založená na "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Správa uživatelů: - Umožňuje administrátorům vytvářet, upravovat a mazat uživatelské účty. - Implementuje řízení přístupu založené na rolích pro správu uživatelských oprávnění. - Poskytuje mechanismy pro autentizaci a autorizaci, aby byl zajištěn bezpečný přístup. ## Správa vztahů se zákazníky (CRM): - Umožňuje uživatelům vytvářet a spravovat kontaktní záznamy pro zájemce, potenciální zákazníky a zákazníky. - Implementuje funkce generování a vyhodnocování příležitostí pro sledování potenciálních prodejních příležitostí. - Poskytuje nástroje pro správu historie komunikace se zákazníky, včetně e-mailů, hovorů a schůzek. - Umožňuje uživatelům plánovat schůzky a odesílat oznámení nebo připomínky zákazníkům. ## Správa prodeje: - Umožňuje uživatelům vytvářet a spravovat prodejní objednávky a přiřazovat je konkrétním zákazníkům. - Implementuje sledování stavu skladu pro kontrolu dostupnosti produktů a aktualizaci úrovní skladu po každé prodeji. - Generuje faktury a zajišťuje integraci platebních bran s populárními platebními bránami. - Poskytuje přehledy a zprávy pro monitorování výkonnosti prodeje a analýzu trendů. ## Správa nákupu: - Umožňuje uživatelům vytvářet a spravovat nákupní objednávky s určením množství a požadovaných produktů. - Sleduje informace o dodavatelích a spravuje vztahy s dodavateli. - Přijímá zboží a aktualizuje úrovně skladu. - Zajišťuje nákupní faktury a platby dodavatelům. ## Správa skladu: - Poskytuje nástroje pro správu a sledování úrovní skladu, včetně přesunů a úprav zásob. - Nastavuje automatická oznámení o nízkých úrovních zásob a generuje nákupní objednávky při potřebě doplnění zásob. - Nabízí možnost skenování čárových kódů pro efektivní správu skladu. - Umožňuje uživatelům kategorizovat produkty, definovat atributy a stanovit informace o cenách. ## Finanční řízení: - Implementuje systém hlavní knihy pro sledování finančních transakcí, včetně výdajů a příjmů. - Spravuje pohledávky a závazky, včetně fakturace a sledování plateb. - Generuje finanční zprávy, včetně rozvahy a výkazů zisku a ztráty. - Integruje se s populárním účetním softwarem pro bezproblémové finanční řízení. ## Řízení projektů: - Poskytuje možnosti řízení projektů, které umožňují uživatelům vytvářet a sledovat projekty. - Přiřazuje úkoly členům týmu, stanovuje termíny a monitoruje pokrok. - Přiděluje zdroje a sleduje náklady na projekty. - Nabízí funkce spolupráce, jako je sdílení dokumentů a komunikace v reálném čase. ## Reporting a analýza: - Generuje komplexní zprávy a analýzy různých aspektů podnikání. - Poskytuje přizpůsobitelné přehledy pro monitorování klíčových ukazatelů výkonnosti (KPI). - Umožňuje uživatelům definovat vlastní zprávy na základě konkrétních požadavků. - Implementuje techniky vizualizace dat pro prezentaci informací vizuálně atraktivním způsobem. ## Integrace a přizpůsobení: - Umožňuje integraci s populárními aplikacemi třetích stran nebo API, jako jsou nástroje pro e-mailový marketing nebo platformy CRM. - Umožňuje přizpůsobení funkcionality a vzhledu aplikace na základě konkrétních podnikových potřeb. - Poskytuje API nebo webhooks pro usnadnění výměny dat mezi aplikací ERP & CRM a dalšími systémy. ## Uživatelsky přívětivé rozhraní: - Navrhněte intuitivní, responzivní a uživatelsky přívětivé rozhraní pomocí React.js a Ant Design. - Implementuje snadno použitelné navigační menu, vyhledávací funkce a filtry. - Zajišťuje konzistentní a vizuálně atraktivní uživatelské rozhraní na různých zařízeních a velikostech obrazovky. ================================================ FILE: features/da_dk_gratis_åben_kilde_erp_crm_software.md ================================================ # IDURAR Åben-Source ERP & CRM-Software GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Hjemmeside: [https://www.idurarapp.com](https://www.idurarapp.com) ## Software Stack IDURAR Gratis åben-source erp & crm-app, baseret på "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Brugeradministration: - Tillad administratorer at oprette, redigere og slette brugerkonti. - Implementer rollebaseret adgangskontrol til at administrere brugerrettigheder. - Tilbyd autentificerings- og autorisationsmekanismer for at sikre sikker adgang. ## Kunde Relationsstyring (CRM): - Gør det muligt for brugere at oprette og administrere kontaktoplysninger for leads, potentielle kunder og kunder. - Implementer funktionaliteter til leadgenerering og kvalificering for at spore potentielle salgsmuligheder. - Tilbyd værktøjer til at administrere kundekommunikationshistorik, herunder e-mails, opkald og møder. - Tillad brugere at planlægge aftaler og sende meddelelser eller påmindelser til kunder. ## Salgsstyring: - Tillad brugere at oprette og administrere salgsordrer og tilknytte dem til specifikke kunder. - Implementer lagerstyring for at kontrollere produkttilgængelighed og opdatere lagerbeholdningen efter hver salg. - Generer fakturaer og håndter betalingsintegration med populære betalingsgateways. - Tilbyd dashboards og rapporter til overvågning af salgspræstation og analyse af tendenser. ## Indkøbsstyring: - Tillad brugere at oprette og administrere indkøbsordrer og specificere mængde og ønskede produkter. - Spor leverandøroplysninger og administrer leverandørforhold. - Modtag varer og opdater lagerbeholdningen i overensstemmelse hermed. - Håndter købsfakturaer og betalinger til leverandører. ## Lagerstyring: - Tilbyd værktøjer til at administrere og spore lagerbeholdning, herunder lageroverførsler og justeringer. - Opsæt automatisk meddelelse om lav lagerbeholdning og generer indkøbsordrer, når genopfyldning er nødvendig. - Tilbyd stregkodescanning til effektiv lagerstyring. - Gør det muligt for brugere at kategorisere produkter, definere attributter og angive prisoplysninger. ## Økonomistyring: - Implementer et hovedbogssystem til at spore økonomiske transaktioner, herunder udgifter og indtægter. - Administrer debitorer og kreditorer, herunder fakturering og sporing af betalinger. - Generer økonomiske rapporter, herunder balance og resultatopgørelse. - Integrer med populær regnskabssoftware til problemfri økonomistyring. ## Projektstyring: - Tilbyd projektstyringsfunktioner, der giver brugerne mulighed for at oprette og spore projekter. - Tildel opgaver til teammedlemmer, sæt deadlines og overvåg fremskridt. - Allokér ressourcer og spore projektudgifter. - Tilbyd samarbejdsfunktioner som dokumentdeling og kommunikation i realtid. ## Rapportering og Analyse: - Generer omfattende rapporter og analyser om forskellige aspekter af virksomheden. - Tilbyd tilpasselige dashboards til overvågning af nøglepræstationsindikatorer (KPI'er). - Tillad brugere at definere brugerdefinerede rapporter baseret på specifikke krav. - Implementer teknikker til datavisualisering for at præsentere information på en visuelt tiltalende måde. ## Integration og Tilpasning: - Muliggør integration med populære tredjepartsapplikationer eller API'er, såsom e-mail-marketingværktøjer eller CRM-platforme. - Tillad tilpasning af appens funktionalitet og udseende baseret på specifikke forretningsbehov. - Tilbyd en API eller webhooks for at lette dataudveksling mellem ERP- og CRM-appen og andre systemer. ## Brugervenligt Interface: - Design et intuitivt, responsivt og brugervenligt interface ved hjælp af React.js og Ant Design. - Implementer nemt navigationsmenuer, søgefunktioner og filtre. - Sikre en konsistent og visuelt tiltalende brugergrænseflade på forskellige enheder og skærmstørrelser. ================================================ FILE: features/de_de_frei_offene_quelle_erp_crm_software.md ================================================ # IDURAR Open-Source ERP & CRM Software GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Website: [https://www.idurarapp.com](https://www.idurarapp.com) ## Software-Stack IDURAR Kostenlose Open-Source ERP & CRM Anwendung, basierend auf dem "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Benutzerverwaltung: - Ermöglichen Sie Administratoren die Erstellung, Bearbeitung und Löschung von Benutzerkonten. - Implementieren Sie rollenbasierte Zugriffskontrolle zur Verwaltung von Benutzerberechtigungen. - Bieten Sie Authentifizierungs- und Autorisierungsmechanismen, um einen sicheren Zugriff zu gewährleisten. ## Kundenbeziehungsmanagement (CRM): - Ermöglichen Sie Benutzern die Erstellung und Verwaltung von Kontaktdaten für Leads, Interessenten und Kunden. - Implementieren Sie Funktionen zur Lead-Generierung und -Qualifizierung, um potenzielle Verkaufschancen zu verfolgen. - Bieten Sie Tools zur Verwaltung der Kommunikationshistorie mit Kunden, einschließlich E-Mails, Anrufen und Meetings. - Ermöglichen Sie Benutzern die Planung von Terminen und den Versand von Benachrichtigungen oder Erinnerungen an Kunden. ## Vertriebsmanagement: - Ermöglichen Sie Benutzern die Erstellung und Verwaltung von Verkaufsaufträgen und deren Zuordnung zu bestimmten Kunden. - Implementieren Sie eine Bestandsverfolgung, um die Produktverfügbarkeit zu überprüfen und die Lagerbestände nach jedem Verkauf zu aktualisieren. - Generieren Sie Rechnungen und integrieren Sie sich mit gängigen Zahlungsgateways. - Bieten Sie Dashboards und Berichte zur Überwachung der Verkaufsleistung und zur Analyse von Trends. ## Einkaufsmanagement: - Ermöglichen Sie Benutzern die Erstellung und Verwaltung von Bestellungen und die Angabe von Menge und gewünschten Produkten. - Verfolgen Sie Lieferanteninformationen und verwalten Sie Lieferantenbeziehungen. - Nehmen Sie Waren entgegen und aktualisieren Sie die Lagerbestände entsprechend. - Bearbeiten Sie Einkaufsrechnungen und Zahlungen an Lieferanten. ## Lagerverwaltung: - Bieten Sie Tools zur Verwaltung und Verfolgung der Lagerbestände, einschließlich Lagertransfers und Anpassungen. - Richten Sie automatische Benachrichtigungen für niedrige Lagerbestände ein und generieren Sie Bestellungen, wenn eine Nachbestellung erforderlich ist. - Bieten Sie Barcode-Scan-Funktionen für eine effiziente Lagerverwaltung. - Ermöglichen Sie Benutzern die Kategorisierung von Produkten, die Definition von Attributen und die Festlegung von Preisinformationen. ## Finanzmanagement: - Implementieren Sie ein Hauptbuchsystem zur Verfolgung von Finanztransaktionen, einschließlich Ausgaben und Einnahmen. - Verwalten Sie Forderungen und Verbindlichkeiten, einschließlich Rechnungsstellung und Zahlungsverfolgung. - Generieren Sie Finanzberichte, einschließlich Bilanzen und Gewinn- und Verlustrechnungen. - Integrieren Sie sich mit gängiger Buchhaltungssoftware für nahtloses Finanzmanagement. ## Projektmanagement: - Bieten Sie Projektmanagementfunktionen, mit denen Benutzer Projekte erstellen und verfolgen können. - Weisen Sie Aufgaben an Teammitglieder zu, setzen Sie Fristen und überwachen Sie den Fortschritt. - Weisen Sie Ressourcen zu und verfolgen Sie Projektausgaben. - Bieten Sie Kollaborationsfunktionen wie das Teilen von Dokumenten und die Echtzeitkommunikation. ## Berichterstattung und Analyse: - Generieren Sie umfassende Berichte und Analysen zu verschiedenen Aspekten des Unternehmens. - Bieten Sie anpassbare Dashboards zur Überwachung von Leistungskennzahlen (KPIs). - Ermöglichen Sie Benutzern die Definition benutzerdefinierter Berichte basierend auf spezifischen Anforderungen. - Implementieren Sie Datenvisualisierungstechniken, um Informationen auf ansprechende Weise darzustellen. ## Integration und Anpassung: - Ermöglichen Sie die Integration mit gängigen Drittanbieter-Anwendungen oder APIs, wie z.B. E-Mail-Marketing-Tools oder CRM-Plattformen. - Erlauben Sie die Anpassung der Funktionalität und des Erscheinungsbilds der Anwendung basierend auf spezifischen Geschäftsanforderungen. - Bieten Sie eine API oder Webhooks zur erleichterten Datenübertragung zwischen der ERP & CRM Anwendung und anderen Systemen. ## Benutzerfreundliche Benutzeroberfläche: - Entwerfen Sie eine intuitive, reaktionsfähige und benutzerfreundliche Benutzeroberfläche mit React.js und Ant Design. - Implementieren Sie benutzerfreundliche Navigationsmenüs, Suchfunktionen und Filter. - Stellen Sie eine konsistente und visuell ansprechende Benutzeroberfläche auf verschiedenen Geräten und Bildschirmgrößen sicher. ================================================ FILE: features/el_gr_ελεύθερο_ανοικτο_πηγαίο_erp_crm_λογισμικό.md ================================================ # IDURAR Λογισμικό ERP & CRM ανοιχτού κώδικα GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Επίδειξη: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Ιστοσελίδα: [https://www.idurarapp.com](https://www.idurarapp.com) ## Στοίβα Λογισμικού Το IDURAR είναι μια δωρεάν εφαρμογή ERP & CRM ανοιχτού κώδικα, βασισμένη στο "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Διαχείριση Χρηστών: - Επιτρέπει στους διαχειριστές να δημιουργούν, επεξεργάζονται και διαγράφουν λογαριασμούς χρηστών. - Υλοποιεί έλεγχο πρόσβασης με βάση τον ρόλο για τη διαχείριση των δικαιωμάτων των χρηστών. - Παρέχει μηχανισμούς πιστοποίησης και εξουσιοδότησης για να εξασφαλίσει ασφαλή πρόσβαση. ## Διαχείριση Σχέσεων με Πελάτες (CRM): - Επιτρέπει στους χρήστες να δημιουργούν και να διαχειρίζονται επαφές για προοπτικούς πελάτες και πελάτες. - Υλοποιεί λειτουργίες για την παραγωγή και την πιστοποίηση προοπτικών πωλήσεων για την παρακολούθηση δυνατοτήτων πωλήσεων. - Παρέχει εργαλεία για τη διαχείριση του ιστορικού επικοινωνίας με τους πελάτες, συμπεριλαμβανομένων των ηλεκτρονικών μηνυμάτων, των τηλεφωνικών κλήσεων και των συναντήσεων. - Επιτρέπει στους χρήστες να προγραμματίζουν ραντεβού και να στέλνουν ειδοποιήσεις ή υπενθυμίσεις στους πελάτες. ## Διαχείριση Πωλήσεων: - Επιτρέπει στους χρήστες να δημιουργούν και να διαχειρίζονται παραγγελίες πωλήσεων, συσχετίζοντάς τις με συγκεκριμένους πελάτες. - Υλοποιεί παρακολούθηση αποθέματος για να ελέγχει τη διαθεσιμότητα των προϊόντων και να ενημερώνει τα επίπεδα αποθέματος μετά από κάθε πώληση. - Δημιουργεί τιμολόγια και χειρίζεται την ολοκλήρωση πληρωμής με δημοφιλείς πύλες πληρωμής. - Παρέχει πίνακες ελέγχου και αναφορές για την παρακολούθηση της απόδοσης των πωλήσεων και την ανάλυση των τάσεων. ## Διαχείριση Αγορών: - Επιτρέπει στους χρήστες να δημιουργούν και να διαχειρίζονται παραγγελίες αγορών, καθορίζοντας την ποσότητα και τα επιθυμητά προϊόντα. - Παρακολουθεί τις πληροφορίες των προμηθευτών και διαχειρίζεται τις σχέσεις με τους προμηθευτές. - Λαμβάνει αγαθά και ενημερώνει τα επίπεδα αποθέματος αναλόγως. - Χειρίζεται τις αγοραπωλησίες και τις πληρωμές προς τους προμηθευτές. ## Διαχείριση Αποθέματος: - Παρέχει εργαλεία για τη διαχείριση και την παρακολούθηση των επιπέδων αποθέματος, συμπεριλαμβανομένων των μεταφορών αποθέματος και των προσαρμογών. - Ρυθμίζει αυτόματες ειδοποιήσεις για χαμηλά επίπεδα αποθέματος και δημιουργεί παραγγελίες αγοράς όταν απαιτείται ανεφοδιασμός. - Παρέχει δυνατότητες σάρωσης γραφικών κωδικών για αποτελεσματική διαχείριση αποθέματος. - Επιτρέπει στους χρήστες να κατηγοριοποιούν προϊόντα, να καθορίζουν χαρακτηριστικά και να ορίζουν πληροφορίες τιμολόγησης. ## Οικονομική Διαχείριση: - Υλοποιεί ένα σύστημα γενικού λογιστηρίου για την καταγραφή οικονομικών συναλλαγών, συμπεριλαμβανομένων των εξόδων και των εσόδων. - Διαχειρίζεται τους λογαριασμούς πιστωτών και χρεωστών, συμπεριλαμβανομένης της τιμολόγησης και της παρακολούθησης πληρωμών. - Δημιουργεί οικονομικές αναφορές, συμπεριλαμβανομένων των ισολογισμών και των καταστάσεων αποτελεσμάτων. - Ενσωματώνεται με δημοφιλές λογισμικό λογιστικής για απροβλημάτιστη οικονομική διαχείριση. ## Διαχείριση Έργων: - Παρέχει δυνατότητες διαχείρισης έργων, επιτρέποντας στους χρήστες να δημιουργούν και να παρακολουθούν έργα. - Αναθέτει εργασίες σε μέλη της ομάδας, ορίζει προθεσμίες και παρακολουθεί την πρόοδο. - Κατανέμει πόρους και παρακολουθεί τα έξοδα του έργου. - Προσφέρει δυνατότητες συνεργασίας, όπως κοινή χρήση εγγράφων και επικοινωνία σε πραγματικό χρόνο. ## Αναφορές και Αναλύσεις: - Δημιουργεί λεπτομερείς αναφορές και αναλύσεις για διάφορες πτυχές της επιχείρησης. - Παρέχει προσαρμόσιμους πίνακες ελέγχου για την παρακολούθηση των βασικών δεικτών απόδοσης (KPIs). - Επιτρέπει στους χρήστες να ορίζουν προσαρμοσμένες αναφορές βάσει συγκεκριμένων απαιτήσεων. - Υλοποιεί τεχνικές οπτικοποίησης δεδομένων για να παρουσιάσει τις πληροφορίες με ελκυστικό τρόπο. ## Ενσωμάτωση και Προσαρμογή: - Επιτρέπει την ενσωμάτωση με δημοφιλείς εφαρμογές τρίτων ή διεπαφές προγραμματισμού εφαρμογών (APIs), όπως εργαλεία email marketing ή πλατφόρμες CRM. - Επιτρέπει την προσαρμογή της λειτουργικότητας και της εμφάνισης της εφαρμογής βάσει των συγκεκριμένων αναγκών της επιχείρησης. - Παρέχει ένα API ή webhooks για να διευκολύνει την ανταλλαγή δεδομένων μεταξύ της εφαρμογής ERP & CRM και άλλων συστημάτων. ## Χρήστική Διεπαφή: - Σχεδιάζει μια ευανάγνωστη, ευέλικτη και χρήστική διεπαφή χρήστη χρησιμοποιώντας το React.js και το Ant Design. - Υλοποιεί εύχρηστα μενού πλοήγησης, λειτουργίες αναζήτησης και φίλτρων. - Βεβαιώνεται για μια συνεπή και αισθητικά ελκυστική διεπαφή χρήστη σε διάφορες συσκευές και μεγέθη οθονών. ================================================ FILE: features/en_us_free_open_source_erp_crm_software.md ================================================ # IDURAR Open-Source ERP & CRM Software GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Website: [https://www.idurarapp.com](https://www.idurarapp.com) ## Sofware Stack IDURAR is a free open-source ERP & CRM app based on the "mern-stack". It utilizes the following technologies: Node.js, React.js, Redux, Express.js, MongoDB, and AntDesign (AntD). ## User Management: - Administrators can create, edit, and delete user accounts. - Role-based access control is implemented to manage user permissions. - Authentication and authorization mechanisms ensure secure access. ## Customer Relationship Management (CRM): - Users can create and manage contact records for leads, prospects, and customers. - Lead generation and qualification functionalities are implemented to track potential sales opportunities. - Tools are provided for managing customer communication history, including emails, calls, and meetings. - Users can schedule appointments and send notifications or reminders to customers. ## Sales Management: - Users can create and manage sales orders, associating them with specific customers. - Inventory tracking is implemented to check product availability and update stock levels after each sale. - Invoices are generated and payment integration with popular payment gateways is handled. - Dashboards and reports are provided to monitor sales performance and analyze trends. ## Purchase Management: - Users can create and manage purchase orders, specifying the quantity and desired products. - Supplier information is tracked and supplier relationships are managed. - Goods are received and inventory levels are updated accordingly. - Purchase invoices and payments to suppliers are handled. ## Inventory Management: - Tools are provided to manage and track inventory levels, including stock transfers and adjustments. - Automatic notifications for low stock levels are set up, and purchase orders are generated when restocking is required. - Barcode scanning capabilities are offered for efficient inventory management. - Users can categorize products, define attributes, and set pricing information. ## Financial Management: - A general ledger system is implemented to track financial transactions, including expenses and revenue. - Accounts receivable and accounts payable are managed, including invoicing and payment tracking. - Financial reports, including balance sheets and income statements, are generated. - Integration with popular accounting software allows for seamless financial management. ## Project Management: - Project management capabilities are provided, allowing users to create and track projects. - Tasks can be assigned to team members, deadlines can be set, and progress can be monitored. - Resources can be allocated and project expenses can be tracked. - Collaboration features such as document sharing and real-time communication are offered. ## Reporting and Analytics: - Comprehensive reports and analytics are generated on various aspects of the business. - Customizable dashboards are provided to monitor key performance indicators (KPIs). - Users can define custom reports based on specific requirements. - Data visualization techniques are implemented to present information in a visually appealing manner. ## Integration and Customization: - Integration with popular third-party applications or APIs, such as email marketing tools or CRM platforms, is enabled. - The app's functionality and appearance can be customized based on specific business needs. - An API or webhooks are provided to facilitate data exchange between the ERP & CRM app and other systems. ## User-friendly Interface: - An intuitive, responsive, and user-friendly interface is designed using React.js and Ant Design. - Easy-to-use navigation menus, search functionalities, and filters are implemented. - A consistent and visually appealing UI is ensured across different devices and screen sizes. ================================================ FILE: features/es_es_software_erp_crm_de_código_abierto_y_gratis.md ================================================ # IDURAR Software de ERP y CRM de código abierto GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Sitio web: [https://www.idurarapp.com](https://www.idurarapp.com) ## Pila de software IDURAR es una aplicación gratuita de ERP y CRM de código abierto, basada en "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Gestión de usuarios: - Permitir a los administradores crear, editar y eliminar cuentas de usuario. - Implementar control de acceso basado en roles para gestionar los permisos de los usuarios. - Proporcionar mecanismos de autenticación y autorización para garantizar un acceso seguro. ## Gestión de relaciones con los clientes (CRM): - Permitir a los usuarios crear y gestionar registros de contacto para clientes potenciales y clientes. - Implementar funcionalidades de generación y calificación de clientes potenciales para hacer seguimiento de oportunidades de venta. - Proporcionar herramientas para gestionar el historial de comunicación con los clientes, incluyendo correos electrónicos, llamadas y reuniones. - Permitir a los usuarios programar citas y enviar notificaciones o recordatorios a los clientes. ## Gestión de ventas: - Permitir a los usuarios crear y gestionar órdenes de venta, asociándolas con clientes específicos. - Implementar seguimiento de inventario para verificar la disponibilidad de productos y actualizar los niveles de stock después de cada venta. - Generar facturas y gestionar la integración de pagos con pasarelas de pago populares. - Proporcionar paneles de control e informes para monitorear el desempeño de ventas y analizar tendencias. ## Gestión de compras: - Permitir a los usuarios crear y gestionar órdenes de compra, especificando la cantidad y los productos deseados. - Hacer seguimiento de la información del proveedor y gestionar las relaciones con los proveedores. - Recibir mercancías y actualizar los niveles de inventario en consecuencia. - Gestionar facturas de compra y pagos a proveedores. ## Gestión de inventario: - Proporcionar herramientas para gestionar y hacer seguimiento de los niveles de inventario, incluyendo transferencias de stock y ajustes. - Configurar notificaciones automáticas para niveles de stock bajos y generar órdenes de compra cuando sea necesario reponer el stock. - Ofrecer capacidades de escaneo de códigos de barras para una gestión eficiente del inventario. - Permitir a los usuarios categorizar productos, definir atributos y establecer información de precios. ## Gestión financiera: - Implementar un sistema de libro mayor para hacer seguimiento de transacciones financieras, incluyendo gastos e ingresos. - Gestionar cuentas por cobrar y cuentas por pagar, incluyendo facturación y seguimiento de pagos. - Generar informes financieros, incluyendo balances y estados de ingresos. - Integrar con software de contabilidad popular para una gestión financiera sin problemas. ## Gestión de proyectos: - Proporcionar capacidades de gestión de proyectos, permitiendo a los usuarios crear y hacer seguimiento de proyectos. - Asignar tareas a miembros del equipo, establecer fechas límite y monitorear el progreso. - Asignar recursos y hacer seguimiento de los gastos del proyecto. - Ofrecer funciones de colaboración como compartir documentos y comunicación en tiempo real. ## Informes y análisis: - Generar informes y análisis completos sobre varios aspectos del negocio. - Proporcionar paneles de control personalizables para monitorear indicadores clave de rendimiento (KPI). - Permitir a los usuarios definir informes personalizados basados en requisitos específicos. - Implementar técnicas de visualización de datos para presentar la información de manera visualmente atractiva. ## Integración y personalización: - Permitir la integración con aplicaciones de terceros populares o APIs, como herramientas de marketing por correo electrónico o plataformas de CRM. - Permitir la personalización de la funcionalidad y apariencia de la aplicación según las necesidades específicas del negocio. - Proporcionar una API o webhooks para facilitar el intercambio de datos entre la aplicación de ERP y CRM y otros sistemas. ## Interfaz fácil de usar: - Diseñar una interfaz intuitiva, receptiva y fácil de usar utilizando React.js y Ant Design. - Implementar menús de navegación fáciles de usar, funcionalidades de búsqueda y filtros. - Garantizar una interfaz de usuario consistente y visualmente atractiva en diferentes dispositivos y tamaños de pantalla. ================================================ FILE: features/et_ee_tasuta_avatud_lähtekoodiga_erp_crm_tarkvara.md ================================================ # IDURAR Open-Source ERP & CRM Tarkvara GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Veebisait: [https://www.idurarapp.com](https://www.idurarapp.com) ## Tarkvara Stack IDURAR Tasuta avatud lähtekoodiga erp & crm rakendus, mis põhineb "mern-stack" tehnoloogial: Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Kasutajate haldamine: - Võimaldab administraatoritel luua, muuta ja kustutada kasutajakontosid. - Rakenda rollipõhine juurdepääsu kontroll kasutajaõiguste haldamiseks. - Paku autentimis- ja autoriseerimismehhanisme turvalise juurdepääsu tagamiseks. ## Kliendisuhte haldamine (CRM): - Võimaldab kasutajatel luua ja hallata kontaktisikute andmeid müügivihjete, potentsiaalsete klientide ja klientide jaoks. - Rakenda müügivihjete genereerimise ja kvalifitseerimise funktsionaalsust, et jälgida potentsiaalseid müügivõimalusi. - Paku tööriistu kliendikommunikatsiooni ajaloo haldamiseks, sealhulgas e-kirjad, kõned ja kohtumised. - Võimaldab kasutajatel planeerida kohtumisi ja saata teateid või meeldetuletusi klientidele. ## Müügihaldus: - Võimaldab kasutajatel luua ja hallata müügiordereid, sidudes need konkreetsete klientidega. - Rakenda laojäägi jälgimist, et kontrollida toodete saadavust ja värskendada varude taset pärast igat müüki. - Genereeri arveid ja hõlbusta makse integreerimist populaarsete makseväravatega. - Paku juhtpaneeli ja aruandeid müügitulemuste jälgimiseks ja suundumuste analüüsimiseks. ## Ostuhaldus: - Võimaldab kasutajatel luua ja hallata ostutellimusi, määrates koguse ja soovitud tooted. - Jälgige tarnija teavet ja haldage tarnijasuhet. - Vastu võtke kaupu ja värskendage vastavalt varude taset. - Hõlbusta ostuarveid ja makseid tarnijatele. ## Varude haldamine: - Paku tööriistu varude tasemete haldamiseks ja jälgimiseks, sealhulgas varude ülekandeid ja kohandusi. - Seadista automaatseid teatisi madalate varude tasemete kohta ja genereeri ostutellimusi, kui on vaja täiendavat varustust. - Paku vöötkoodi skannimise võimalusi tõhusaks varude haldamiseks. - Võimaldab kasutajatel kategoriseerida tooteid, määratleda atribuute ja seada hinnateavet. ## Finantsjuhtimine: - Rakenda pearaamatute süsteem finantstehingute jälgimiseks, sealhulgas kulude ja tulude kohta. - Halla saadaolevaid ja saamataolevaid kontosid, sealhulgas arvete koostamine ja maksete jälgimine. - Genereeri finantsaruandeid, sealhulgas bilanssi ja kasumiaruannet. - Integreeru populaarsete raamatupidamistarkvaradega, et tagada sujuv finantsjuhtimine. ## Projektihaldus: - Paku projektihalduse võimalusi, mis võimaldavad kasutajatel luua ja jälgida projekte. - Määra ülesandeid meeskonnaliikmetele, seadista tähtajad ja jälgi edenemist. - Jaota ressursse ja jälgige projekti kulusid. - Paku koostöövõimalusi, nagu dokumentide jagamine ja reaalajas suhtlus. ## Aruandlus ja analüütika: - Genereeri põhjalikke aruandeid ja analüüse ettevõtte erinevate aspektide kohta. - Paku kohandatavaid juhtpaneeli, et jälgida olulisi jõudlusnäitajaid (KPI-d). - Võimalda kasutajatel määratleda kohandatud aruandeid vastavalt konkreetsetele nõuetele. - Rakenda andmete visualiseerimise tehnikaid, et esitada teavet visuaalselt atraktiivsel viisil. ## Integreerimine ja kohandamine: - Võimalda integreerimist populaarsete kolmanda osapoole rakenduste või API-dega, nagu e-posti turundustööriistad või CRM platvormid. - Lubage rakenduse funktsionaalsuse ja välimuse kohandamist vastavalt konkreetsetele ärinõuetele. - Paku API-d või veebikonksusid, et hõlbustada andmevahetust ERP & CRM rakenduse ja teiste süsteemide vahel. ## Kasutajasõbralik liides: - Kujundage intuitiivne, reageeriv ja kasutajasõbralik liides, kasutades React.js ja Ant Designi. - Rakenda lihtsasti kasutatavaid navigeerimismenüüsid, otsingufunktsioone ja filtreid. - Taga järjepidev ja visuaalselt atraktiivne kasutajaliides erinevatel seadmetel ja ekraanisuurustel. ================================================ FILE: features/fa_ir_رایگان_منبع_باز_نرم‌افزار_مدیریت_مالی_و_ارتباطات.md ================================================ # نرم‌افزار متن‌باز IDURAR ERP & CRM گیت‌هاب: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) نمایش آنلاین: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) وبسایت: [https://www.idurarapp.com](https://www.idurarapp.com) ## مجموعه نرم‌افزاری IDURAR نرم‌افزار ERP & CRM متن‌باز رایگان است که بر اساس "mern-stack" ساخته شده است: Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## مدیریت کاربران: - امکان ایجاد، ویرایش و حذف حساب‌های کاربری توسط مدیران. - پیاده‌سازی کنترل دسترسی بر اساس نقش برای مدیریت مجوزهای کاربران. - ارائه مکانیزم‌های احراز هویت و اعتبارسنجی برای تضمین دسترسی امن. ## مدیریت رابطه با مشتری (CRM): - امکان ایجاد و مدیریت رکوردهای تماس برای سرنخ‌ها، چشم‌اندازها و مشتریان توسط کاربران. - پیاده‌سازی قابلیت تولید و تایید سرنخ برای پیگیری فرصت‌های فروش پتانسیل. - ارائه ابزارهای مدیریت تاریخچه ارتباط با مشتری، از جمله ایمیل‌ها، تماس‌ها و جلسات. - امکان برنامه‌ریزی قرار ملاقات و ارسال اعلان یا یادآور به مشتریان. ## مدیریت فروش: - امکان ایجاد و مدیریت سفارشات فروش و ارتباط آن‌ها با مشتریان خاص. - پیگیری موجودی کالا برای بررسی قابلیت تامین و بروزرسانی سطح موجودی پس از هر فروش. - تولید فاکتورها و ادغام پرداخت با درگاه‌های پرداخت معروف. - ارائه داشبوردها و گزارش‌ها برای پایش عملکرد فروش و تجزیه و تحلیل روند‌ها. ## مدیریت خرید: - امکان ایجاد و مدیریت سفارشات خرید با تعیین تعداد و محصولات مورد نظر توسط کاربران. - پیگیری اطلاعات تامین‌کننده و مدیریت روابط با تامین‌کنندگان. - دریافت کالاها و بروزرسانی سطح موجودی به‌منظور. - مدیریت فاکتورها و پرداخت به تامین‌کنندگان. ## مدیریت موجودی: - ارائه ابزارها برای مدیریت و پیگیری سطح موجودی، از جمله انتقال و تنظیمات موجودی. - تنظیم اعلان‌های خودکار برای سطح موجودی کم و تولید سفارش خرید هنگام نیاز به تأمین مجدد. - ارائه قابلیت اسکن بارکد برای مدیریت موثر موجودی. - امکان دسته‌بندی محصولات، تعریف ویژگی‌ها و تنظیم اطلاعات قیمت‌گذاری. ## مدیریت مالی: - پیاده‌سازی سیستم دفتر کل برای پیگیری تراکنش‌های مالی، از جمله هزینه‌ها و درآمدها. - مدیریت حساب‌های دریافتی و پرداختی، از جمله صدور فاکتور و پیگیری پرداخت. - تولید گزارش‌های مالی، از جمله ترازنامه و صورت‌سود و زیان. - ادغام با نرم‌افزارهای حسابداری معروف برای مدیریت مالی بی‌درز. ## مدیریت پروژه: - ارائه قابلیت مدیریت پروژه، اجازه می‌دهد کاربران بتوانند پروژه‌ها را ایجاد و پیگیری کنند. - اختصاص وظایف به اعضای تیم، تعیین مهلت‌ها و پیگیری پیشرفت. - تخصیص منابع و پیگیری هزینه‌های پروژه. - ارائه ویژگی‌های همکاری مانند به اشتراک گذاری سند و ارتباط به‌صورت زمان‌واقع. ## گزارش‌گیری و تجزیه و تحلیل: - تولید گزارش‌ها و تجزیه و تحلیل جامع درباره جوانب مختلف کسب و کار. - ارائه داشبوردهای قابل تنظیم برای پایش شاخص‌های کلیدی عملکرد (KPIs). - امکان تعریف گزارش‌های سفارشی بر اساس نیازهای خاص. - پیاده‌سازی تکنیک‌های تجسم داده برای ارائه اطلاعات به صورت جذاب بصری. ## ادغام و سفارشی‌سازی: - امکان ادغام با برنامه‌ها یا رابط‌های برنامه‌نویسی از طرف سوم معروف، مانند ابزارهای بازاریابی ایمیل یا پلتفرم‌های CRM. - امکان سفارشی‌سازی عملکرد و ظاهر برنامه بر اساس نیازهای خاص کسب‌وکار. - ارائه API یا وبهوک برای تسهیل تبادل داده بین نرم‌افزار ERP & CRM و سایر سیستم‌ها. ## رابط کاربری کاربرپسند: - طراحی رابط کاربری ساده، واکنش‌گرا و کاربرپسند با استفاده از React.js و Ant Design. - پیاده‌سازی منوهای ناوبری آسان، قابلیت جستجو و فیلتر. - تضمین یک رابط کاربری یکپارچه و جذاب بصری در دستگاه‌ها و اندازه‌های صفحه مختلف. ================================================ FILE: features/fi_fi_ilmainen_avoin_lähdekoodi_erp_crm_ohjelmisto.md ================================================ # IDURAR Avoin lähdekoodin ERP- ja CRM-ohjelmisto GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Verkkosivusto: [https://www.idurarapp.com](https://www.idurarapp.com) ## Ohjelmistopino IDURAR on ilmainen avoimen lähdekoodin ERP- ja CRM-sovellus, joka perustuu "mern-stackiin": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Käyttäjähallinta: - Salli ylläpitäjien luoda, muokata ja poistaa käyttäjätilit. - Toteuta roolipohjainen pääsynhallinta käyttäjäoikeuksien hallintaan. - Tarjoa todennus- ja valtuutusmekanismit varmistaaksesi turvallisen pääsyn. ## Asiakassuhteen hallinta (CRM): - Mahdollista käyttäjien luoda ja hallita yhteystietoja liideille, potentiaalisille asiakkaille ja asiakkaille. - Toteuta liidien luonti- ja kelpoisuustoiminnot potentiaalisten myyntimahdollisuuksien seuraamiseksi. - Tarjoa työkalut asiakaskommunikaation historian hallintaan, mukaan lukien sähköpostit, puhelut ja kokoukset. - Salli käyttäjien aikatauluttaa tapaamisia ja lähettää ilmoituksia tai muistutuksia asiakkaille. ## Myynnin hallinta: - Salli käyttäjien luoda ja hallita myyntitilauksia, liittämällä ne tiettyihin asiakkaisiin. - Toteuta varaston seuranta tarkistaaksesi tuotteiden saatavuuden ja päivitä varastotasot jokaisen myynnin jälkeen. - Luo laskuja ja käsittele maksujen integrointi suosittujen maksuyhdyskäytävien kanssa. - Tarjoa kojetauluja ja raportteja myyntisuorituksen seuraamiseksi ja trendien analysoimiseksi. ## Hankinnan hallinta: - Salli käyttäjien luoda ja hallita ostotilauksia, määrittämällä määrä ja halutut tuotteet. - Seuraa toimittajatietoja ja hallitse toimittajasuhteita. - Vastaanota tavaroita ja päivitä varastotasot sen mukaisesti. - Käsittele ostolaskuja ja maksuja toimittajille. ## Varastonhallinta: - Tarjoa työkaluja varastonhallinnan ja varastotason seurantaan, mukaan lukien varaston siirrot ja säädöt. - Aseta automaattiset ilmoitukset matalista varastotasoista ja luo ostotilauksia, kun täydennystä tarvitaan. - Tarjoa viivakoodinlukutaito tehokasta varastonhallintaa varten. - Mahdollista käyttäjien luokitella tuotteet, määritellä ominaisuuksia ja asettaa hinnoittelutiedot. ## Taloushallinta: - Toteuta pääkirjan järjestelmä taloudellisten tapahtumien seurantaan, mukaan lukien kulut ja tulot. - Hallitse saamisia ja velkoja, mukaan lukien laskutus ja maksuseuranta. - Luo taloudellisia raportteja, mukaan lukien tase- ja tuloslaskelmat. - Integroi suosittujen kirjanpito-ohjelmistojen kanssa saumaton taloushallinta. ## Projektinhallinta: - Tarjoa projektinhallintatoiminnot, joiden avulla käyttäjät voivat luoda ja seurata projekteja. - Aseta tehtäviä tiimin jäsenille, aseta määräajat ja seuraa edistymistä. - Allokoi resursseja ja seuraa projektikuluja. - Tarjoa yhteistyöominaisuuksia, kuten asiakirjojen jakaminen ja reaaliaikainen viestintä. ## Raportointi ja analytiikka: - Luo kattavia raportteja ja analytiikkaa yrityksen eri osa-alueista. - Tarjoa muokattavia kojetauluja keskeisten suorituskykymittareiden (KPI) seurantaan. - Salli käyttäjien määritellä mukautettuja raportteja tiettyjen vaatimusten perusteella. - Toteuta tietojen visualisointitekniikoita esittääksesi tiedot visuaalisesti houkuttelevalla tavalla. ## Integraatio ja mukauttaminen: - Mahdollista integraatio suosittujen kolmannen osapuolen sovellusten tai rajapintojen kanssa, kuten sähköpostimarkkinointityökalujen tai CRM-alustojen kanssa. - Salli sovelluksen toiminnallisuuden ja ulkoasun mukauttaminen tiettyjen liiketoimintatarpeiden perusteella. - Tarjoa API tai webhooks helpottamaan tietojen vaihtoa ERP- ja CRM-sovelluksen ja muiden järjestelmien välillä. ## Käyttäjäystävällinen käyttöliittymä: - Suunnittele intuitiivinen, responsiivinen ja käyttäjäystävällinen käyttöliittymä käyttäen React.js:ää ja Ant Designia. - Toteuta helppokäyttöiset navigointivalikot, hakuominaisuudet ja suodattimet. - Varmista johdonmukainen ja visuaalisesti houkutteleva käyttöliittymä eri laitteissa ja näyttöjen koossa. ================================================ FILE: features/fr_fr_gratuit_logiciel_erp_crm_open_source.md ================================================ # IDURAR Logiciel ERP & CRM Open-Source GitHub : [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Démo : [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Site Web : [https://www.idurarapp.com](https://www.idurarapp.com) ## Stack logiciel IDURAR est une application ERP & CRM open-source gratuite, basée sur la pile "mern-stack" : Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Gestion des utilisateurs : - Permettre aux administrateurs de créer, éditer et supprimer des comptes utilisateur. - Mettre en place un contrôle d'accès basé sur les rôles pour gérer les autorisations des utilisateurs. - Fournir des mécanismes d'authentification et d'autorisation pour garantir un accès sécurisé. ## Gestion de la relation client (CRM) : - Permettre aux utilisateurs de créer et de gérer des fiches de contact pour les prospects et les clients. - Mettre en place des fonctionnalités de génération et de qualification des leads pour suivre les opportunités de vente potentielles. - Fournir des outils pour gérer l'historique des communications avec les clients, y compris les e-mails, les appels et les réunions. - Permettre aux utilisateurs de planifier des rendez-vous et d'envoyer des notifications ou des rappels aux clients. ## Gestion des ventes : - Permettre aux utilisateurs de créer et de gérer des commandes de vente, en les associant à des clients spécifiques. - Mettre en place un suivi des stocks pour vérifier la disponibilité des produits et mettre à jour les niveaux de stock après chaque vente. - Générer des factures et gérer l'intégration des paiements avec des passerelles de paiement populaires. - Fournir des tableaux de bord et des rapports pour surveiller les performances des ventes et analyser les tendances. ## Gestion des achats : - Permettre aux utilisateurs de créer et de gérer des commandes d'achat, en spécifiant la quantité et les produits souhaités. - Suivre les informations sur les fournisseurs et gérer les relations avec les fournisseurs. - Réceptionner les marchandises et mettre à jour les niveaux de stock en conséquence. - Gérer les factures d'achat et les paiements aux fournisseurs. ## Gestion des stocks : - Fournir des outils pour gérer et suivre les niveaux de stock, y compris les transferts de stock et les ajustements. - Mettre en place des notifications automatiques pour les niveaux de stock bas et générer des commandes d'achat lorsque le réapprovisionnement est nécessaire. - Offrir des capacités de numérisation de codes-barres pour une gestion efficace des stocks. - Permettre aux utilisateurs de catégoriser les produits, de définir des attributs et des informations de tarification. ## Gestion financière : - Mettre en place un système de grand livre pour suivre les transactions financières, y compris les dépenses et les revenus. - Gérer les comptes clients et les comptes fournisseurs, y compris la facturation et le suivi des paiements. - Générer des rapports financiers, y compris les bilans et les comptes de résultats. - Intégrer des logiciels comptables populaires pour une gestion financière transparente. ## Gestion de projet : - Fournir des fonctionnalités de gestion de projet, permettant aux utilisateurs de créer et de suivre des projets. - Assigner des tâches aux membres de l'équipe, fixer des délais et suivre les progrès. - Allouer des ressources et suivre les dépenses liées aux projets. - Offrir des fonctionnalités de collaboration telles que le partage de documents et la communication en temps réel. ## Rapports et analyses : - Générer des rapports complets et des analyses sur différents aspects de l'entreprise. - Fournir des tableaux de bord personnalisables pour suivre les indicateurs de performance clés (KPI). - Permettre aux utilisateurs de définir des rapports personnalisés en fonction de leurs besoins spécifiques. - Mettre en place des techniques de visualisation des données pour présenter les informations de manière attrayante. ## Intégration et personnalisation : - Permettre l'intégration avec des applications tierces populaires ou des API, telles que des outils de marketing par e-mail ou des plateformes CRM. - Permettre la personnalisation de la fonctionnalité et de l'apparence de l'application en fonction des besoins spécifiques de l'entreprise. - Fournir une API ou des webhooks pour faciliter l'échange de données entre l'application ERP & CRM et d'autres systèmes. ## Interface conviviale : - Concevoir une interface intuitive, réactive et conviviale en utilisant React.js et Ant Design. - Mettre en place des menus de navigation faciles à utiliser, des fonctionnalités de recherche et des filtres. - Assurer une interface utilisateur cohérente et visuellement attrayante sur différents appareils et tailles d'écran. ================================================ FILE: features/hi_in_मुफ्त_खुला_स्रोत_ईआरपी_सीआरएम_सॉफ़्टवेयर.md ================================================ # IDURAR ओपन-सोर्स ईआरपी और सीआरएम सॉफ्टवेयर गिटहब: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) डेमो: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) वेबसाइट: [https://www.idurarapp.com](https://www.idurarapp.com) ## सॉफ्टवेयर स्टैक IDURAR मुफ्त ओपन-सोर्स ईआरपी और सीआरएम ऐप, "mern-stack" पर आधारित है: नोड.जेएस रिएक्ट.जेएस रीडक्स एक्सप्रेस.जेएस एमओएनजीबी एंटडिजाइन (एंटडी) ## उपयोगकर्ता प्रबंधन: - प्रशासकों को उपयोगकर्ता खातों को बनाने, संपादित करने और हटाने की अनुमति देना। - उपयोगकर्ता अनुमतियों का प्रबंधन करने के लिए भूमिका-आधारित पहुंच नियंत्रण कार्यान्वयन करें। - सुरक्षित पहुंच सुनिश्चित करने के लिए प्रमाणीकरण और अधिकृतता तंत्र प्रदान करें। ## ग्राहक संबंध प्रबंधन (सीआरएम): - उपयोगकर्ताओं को लीड, संभावित ग्राहकों और ग्राहकों के लिए संपर्क रिकॉर्ड बनाने और प्रबंधित करने की अनुमति दें। - बिक्री के अवसरों के पीछे लगातार जाँच करने और योग्यता कार्यान्वयन करने के सुविधाएँ को कार्यान्वित करें। - ग्राहक संचार इतिहास को प्रबंधित करने के लिए उपकरण प्रदान करें, जिसमें ईमेल, कॉल और मीटिंग्स शामिल हों। - उपयोगकर्ताओं को अपॉइंटमेंट शेड्यूल करने और ग्राहकों को सूचनाएँ या अनुस्मारक भेजने की अनुमति दें। ## बिक्री प्रबंधन: - उपयोगकर्ताओं को बिक्री आदेश बनाने और प्रबंधित करने की अनुमति दें, उन्हें विशेष ग्राहकों से जोड़ें। - प्रोडक्ट उपलब्धता की जांच करने और प्रत्येक बिक्री के बाद स्टॉक स्तर को अपडेट करने के लिए इन्वेंटरी ट्रैकिंग कार्यान्वित करें। - चालान जनरेट करें और प्रसिद्ध भुगतान गेटवे के साथ भुगतान समकक्षता का संचालन करें। - बिक्री कार्यान्वयन और रुझानों का निगरानी करने के लिए डैशबोर्ड और रिपोर्ट प्रदान करें। ## खरीद प्रबंधन: - उपयोगकर्ताओं को खरीद आदेश बनाने और प्रबंधित करने की अनुमति दें, मात्रा और वांछित प्रोडक्ट्स को निर्दिष्ट करें। - आपूर्ति सूचना का ट्रैक करें और आपूर्ति संबंधी संबंधों का प्रबंधन करें। - माल ग्रहण करें और इन्वेंटरी स्तर को उसके अनुसार अपडेट करें। - आपूर्ति चालान और आपूर्ति वितरण के लिए भुगतान का संचालन करें। ## इन्वेंटरी प्रबंधन: - स्टॉक स्तर को प्रबंधित और ट्रैक करने के लिए उपकरण प्रदान करें, जिसमें स्टॉक ट्रांसफर और समायोजन शामिल हों। - कम स्टॉक स्तर के लिए स्वचालित सूचनाएँ सेट करें और जब आपूर्ति भर्ती की आवश्यकता हो तो खरीद आदेश जनरेट करें। - कुशल इन्वेंटरी प्रबंधन के लिए बारकोड स्कैनिंग क्षमताएँ प्रदान करें। - उपयोगकर्ताओं को उत्पादों को वर्गीकृत करने, विशेषताओं को परिभाषित करने और मूल्य जानकारी सेट करने की अनुमति दें। ## वित्तीय प्रबंधन: - वित्तीय लेजर प्रणाली कार्यान्वित करें, जिसमें खर्च और राजस्व सहित वित्तीय लेन-देन का ट्रैकिंग होता है। - खाता रसीद और खाता भुगतान, समेकित भुगतान और भुगतान का ट्रैकिंग करें। - बैलेंस शीट और आय-व्यय विवरण सहित वित्तीय रिपोर्ट जनरेट करें। - सुविधाजनक वित्तीय प्रबंधन के लिए प्रसिद्ध लेखांकन सॉफ्टवेयर के साथ एकीकृत करें। ## परियोजना प्रबंधन: - परियोजना प्रबंधन क्षमताएँ प्रदान करें, जिसमें उपयोगकर्ताओं को परियोजनाओं को बनाने और ट्रैक करने की अनुमति मिलती है। - टीम सदस्यों को कार्यों का निर्धारण करें, समयसीमा निर्धारित करें और प्रगति का निगरान करें। - संसाधनों का आवंटन करें और परियोजना खर्चों का निगरान करें। - दस्तावेज़ साझा करने और वास्तविक समय पर संचार जैसी सहयोग की सुविधाएँ प्रदान करें। ## रिपोर्टिंग और विश्लेषण: - व्यापार के विभिन्न पहलुओं पर व्यापक रिपोर्ट और विश्लेषण जनरेट करें। - मुद्रितीय प्रदर्शन के कुंजी प्रदर्शक (केपीआई) का निगरान करने के लिए अनुकूलनयोग्य डैशबोर्ड प्रदान करें। - उपयोगकर्ताओं को विशेष आवश्यकताओं पर आधारित कस्टम रिपोर्टें परिभाषित करने की अनुमति दें। - डेटा दृश्यीकरण तकनीकों को कार्यान्वित करके जानकारी को एक दृश्यात्मक रूप में प्रस्तुत करें। ## एकीकरण और अनुकूलन: - ईमेल मार्केटिंग उपकरण या सीआरएम प्लेटफॉर्म जैसे प्रसिद्ध थर्ड-पार्टी एप्लिकेशन या एपीआई के साथ एकीकरण की सुविधा प्रदान करें। - ऐप की कार्यान्वयनिकता और दिखावट को व्यापारिक आवश्यकताओं पर आधारित अनुकूलित करने की अनुमति दें। - एपीआई या वेबहुक्स प्रदान करके ईआरपी और सीआरएम ऐप और अन्य सिस्टम के बीच डेटा विनिमय को सुविधाजनक बनाएं। ## उपयोगकर्ता-मित्रपूर्ण इंटरफ़ेस: - रिएक्ट.जेएस और एंट डिजाइन का उपयोग करके एक सरल, प्रतिसादी और उपयोगकर्ता-मित्रपूर्ण इंटरफ़ेस डिजाइन करें। - उपयोगकर्ता को सरल नेविगेशन मेनू, खोज सुविधाएँ और फ़िल्टर प्रदान करें। - विभिन्न डिवाइस और स्क्रीन आकारों पर संगत और दृश्यात्मक यूआई सुनिश्चित करें। ================================================ FILE: features/hr_hr_besplatni_otvoreni_izvor_erp_crm_softver.md ================================================ # IDURAR Open-Source ERP & CRM Softver GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Web stranica: [https://www.idurarapp.com](https://www.idurarapp.com) ## Tehnološki skup IDURAR Besplatna open-source erp & crm aplikacija, bazirana na "mern-stack" : Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Upravljanje korisnicima: - Omogućavanje administratorima stvaranje, uređivanje i brisanje korisničkih računa. - Implementacija pristupa temeljenog na ulogama za upravljanje korisničkim dozvolama. - Pružanje mehanizama za autentifikaciju i autorizaciju radi osiguravanja sigurnog pristupa. ## Upravljanje odnosima s klijentima (CRM): - Omogućavanje korisnicima stvaranje i upravljanje kontaktima za potencijalne klijente i postojeće klijente. - Implementacija funkcionalnosti generiranja i kvalifikacije potencijalnih prodajnih prilika radi praćenja mogućnosti prodaje. - Pružanje alata za upravljanje povijesti komunikacije s klijentima, uključujući e-poštu, pozive i sastanke. - Omogućavanje korisnicima zakazivanje sastanaka i slanje obavijesti ili podsjetnika klijentima. ## Upravljanje prodajom: - Omogućavanje korisnicima stvaranje i upravljanje prodajnim narudžbama, povezujući ih s određenim klijentima. - Implementacija praćenja inventara radi provjere dostupnosti proizvoda i ažuriranja stanja zaliha nakon svake prodaje. - Generiranje računa i integracija s popularnim platnim uslugama. - Pružanje nadzora i izvještaja za praćenje prodajne uspješnosti i analizu trendova. ## Upravljanje nabavkom: - Omogućavanje korisnicima stvaranje i upravljanje narudžbama nabave, specificirajući količinu i željene proizvode. - Praćenje informacija o dobavljačima i upravljanje odnosima s dobavljačima. - Primanje robe i ažuriranje stanja zaliha prema tome. - Upravljanje računima nabave i plaćanjima dobavljačima. ## Upravljanje zalihama: - Pružanje alata za upravljanje i praćenje stanja zaliha, uključujući prijenose i prilagodbe zaliha. - Postavljanje automatskih obavijesti za niske razine zaliha i generiranje narudžbi nabave kada je potrebno obnoviti zalihe. - Omogućavanje mogućnosti skeniranja bar kodova radi učinkovitog upravljanja zalihama. - Omogućavanje korisnicima kategorizaciju proizvoda, definiranje atributa i postavljanje informacija o cijenama. ## Financijsko upravljanje: - Implementacija sustava glavne knjige za praćenje financijskih transakcija, uključujući troškove i prihode. - Upravljanje potraživanjima i obvezama, uključujući izdavanje računa i praćenje plaćanja. - Generiranje financijskih izvještaja, uključujući bilance i izvještaje o dobiti i gubitku. - Integracija s popularnim računovodstvenim softverom radi besprijekornog financijskog upravljanja. ## Upravljanje projektima: - Pružanje mogućnosti upravljanja projektima, omogućavajući korisnicima stvaranje i praćenje projekata. - Dodjeljivanje zadataka članovima tima, postavljanje rokova i praćenje napretka. - Alokacija resursa i praćenje troškova projekta. - Pružanje značajki suradnje poput dijeljenja dokumenata i komunikacije u stvarnom vremenu. ## Izvješća i analitika: - Generiranje sveobuhvatnih izvješća i analitike o različitim aspektima poslovanja. - Pružanje prilagodljivih nadzornih ploča za praćenje ključnih pokazatelja uspješnosti (KPI). - Omogućavanje korisnicima definiranje prilagođenih izvješća prema specifičnim zahtjevima. - Implementacija tehnika vizualizacije podataka za prezentaciju informacija na vizualno privlačan način. ## Integracija i prilagođavanje: - Omogućavanje integracije s popularnim aplikacijama ili API-ima trećih strana, poput alata za e-poštu ili platformi za upravljanje odnosima s klijentima. - Omogućavanje prilagođavanja funkcionalnosti i izgleda aplikacije prema specifičnim poslovnim potrebama. - Pružanje API-ja ili web-kuka za olakšavanje razmjene podataka između ERP & CRM aplikacije i drugih sustava. ## Korisničko sučelje jednostavno za korištenje: - Dizajniranje intuitivnog, responsivnog i korisnički prijateljskog sučelja koristeći React.js i Ant Design. - Implementacija jednostavnih navigacijskih izbornika, funkcionalnosti pretraživanja i filtara. - Osiguravanje dosljednog i vizualno privlačnog korisničkog sučelja na različitim uređajima i veličinama zaslona. ================================================ FILE: features/hu_hu_ingyenes_nyílt_forráskódú_erp_crm_szoftver.md ================================================ # IDURAR Nyílt forráskódú ERP & CRM szoftver GitHub : [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo : [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Weboldal : [https://www.idurarapp.com](https://www.idurarapp.com) ## Szoftver technológia Az IDURAR ingyenes nyílt forráskódú erp & crm alkalmazás, amely a "mern-stack" alapján működik: Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Felhasználókezelés: - Lehetővé teszi az adminisztrátorok számára a felhasználói fiókok létrehozását, szerkesztését és törlését. - Implementálja a szerep alapú hozzáférési vezérlést a felhasználói engedélyek kezeléséhez. - Biztosít hitelesítési és jogosultságkezelési mechanizmusokat a biztonságos hozzáférés biztosításához. ## Ügyfélkapcsolat-kezelés (CRM): - Lehetővé teszi a felhasználók számára a kapcsolatfelvételi adatok létrehozását és kezelését a potenciális vevők és ügyfelek számára. - Implementálja a vezetékképzési és minősítési funkciókat a potenciális értékesítési lehetőségek nyomon követéséhez. - Biztosít eszközöket az ügyfél kommunikációs előzményeinek kezeléséhez, beleértve az e-maileket, hívásokat és találkozókat. - Lehetővé teszi a felhasználóknak az időpontok ütemezését és értesítéseket vagy emlékeztetőket küld az ügyfeleknek. ## Értékesítési kezelés: - Lehetővé teszi a felhasználók számára az értékesítési rendelések létrehozását és kezelését, azokat az adott ügyfelekkel kapcsolatosan. - Implementálja az áruk nyomon követését a termék elérhetőségének ellenőrzéséhez és a készletszintek frissítéséhez minden értékesítés után. - Számlákat generál és kezeli a fizetési integrációt a népszerű fizetési átjárókkal. - Biztosít irányítópultokat és jelentéseket az értékesítési teljesítmény monitorozásához és a trendek elemzéséhez. ## Beszerzési kezelés: - Lehetővé teszi a felhasználók számára a beszerzési rendelések létrehozását és kezelését, a mennyiség és a kívánt termékek meghatározásával. - Követi a beszállítói információkat és kezeli a beszállítói kapcsolatokat. - Fogadja a termékeket és frissíti a készletszinteket ennek megfelelően. - Kezeli a beszerzési számlákat és a beszállítókhoz történő fizetéseket. ## Készletkezelés: - Biztosít eszközöket a készletszintek kezeléséhez és nyomon követéséhez, beleértve a készletátadásokat és a beállításokat. - Beállít automatikus értesítéseket az alacsony készletszintekről és generáljon beszerzési rendeléseket, amikor a készlet újratöltésére van szükség. - Kínál vonalkódolvasási képességeket hatékony készletkezeléshez. - Lehetővé teszi a felhasználóknak a termékek kategorizálását, attribútumok meghatározását és árazási információk beállítását. ## Pénzügyi kezelés: - Implementáljon egy általános könyvelő rendszert a pénzügyi tranzakciók nyomon követéséhez, beleértve a költségeket és a bevételeket. - Kezelje az eladói és vevői számlákat, beleértve a számlázást és a fizetés nyomon követését. - Generáljon pénzügyi jelentéseket, beleértve az egyenlegkimutatást és az eredménykimutatást. - Integráljon népszerű könyvelő szoftverekkel a zökkenőmentes pénzügyi kezelés érdekében. ## Projektkezelés: - Biztosítson projektmenedzsment képességeket, amelyek lehetővé teszik a felhasználók számára a projektek létrehozását és nyomon követését. - Rendeljen feladatokat a csapattagoknak, állítson határidőket és kövesse nyomon a haladást. - Allokáljon erőforrásokat és kövesse a projekt kiadásait. - Kínáljon együttműködési funkciókat, például dokumentummegosztást és valós idejű kommunikációt. ## Jelentések és analitika: - Generáljon átfogó jelentéseket és elemzéseket a vállalkozás különböző aspektusairól. - Biztosítson testreszabható irányítópultokat a kulcsfontosságú teljesítménymutatók (KPI-k) monitorozásához. - Lehetővé teszi a felhasználók számára a specifikus követelmények alapján meghatározott egyedi jelentések meghatározását. - Implementálja az adatvizualizációs technikákat az információk vonzó módon történő bemutatásához. ## Integráció és testreszabás: - Lehetővé teszi a népszerű harmadik fél alkalmazások vagy API-k, például az e-mail marketing eszközök vagy a CRM platformok integrálását. - Lehetővé teszi az alkalmazás funkcionalitásának és megjelenésének testreszabását a konkrét üzleti igények alapján. - Biztosítson API-t vagy webhorgokat az adatcserének megkönnyítéséhez az ERP & CRM alkalmazás és más rendszerek között. ## Felhasználóbarát felület: - Készítsen intuitív, reszponzív és felhasználóbarát felületet React.js és Ant Design segítségével. - Implementáljon könnyen használható navigációs menük, keresési funkciókat és szűrőket. - Biztosítson következetes és vizuálisan vonzó felhasználói felületet különböző eszközökön és képernyőméreteken. ================================================ FILE: features/id_id_perangkat_lunak_erp_crm_sumber_terbuka_gratis.md ================================================ # Perangkat Lunak ERP & CRM Sumber Terbuka IDURAR GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Website: [https://www.idurarapp.com](https://www.idurarapp.com) ## Tumpukan Perangkat Lunak Aplikasi ERP & CRM gratis dan sumber terbuka IDURAR, berbasis "mern-stack" : Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Manajemen Pengguna: - Memungkinkan administrator untuk membuat, mengedit, dan menghapus akun pengguna. - Mengimplementasikan kontrol akses berbasis peran untuk mengelola izin pengguna. - Menyediakan mekanisme autentikasi dan otorisasi untuk memastikan akses yang aman. ## Manajemen Hubungan Pelanggan (CRM): - Memungkinkan pengguna untuk membuat dan mengelola catatan kontak untuk prospek dan pelanggan. - Mengimplementasikan fungsi generasi dan kualifikasi prospek untuk melacak peluang penjualan potensial. - Menyediakan alat untuk mengelola riwayat komunikasi pelanggan, termasuk email, telepon, dan pertemuan. - Memungkinkan pengguna untuk menjadwalkan janji dan mengirim pemberitahuan atau pengingat kepada pelanggan. ## Manajemen Penjualan: - Memungkinkan pengguna untuk membuat dan mengelola pesanan penjualan, yang terkait dengan pelanggan tertentu. - Mengimplementasikan pelacakan inventaris untuk memeriksa ketersediaan produk dan memperbarui tingkat stok setelah setiap penjualan. - Menghasilkan faktur dan mengelola integrasi pembayaran dengan gateway pembayaran populer. - Menyediakan dasbor dan laporan untuk memantau kinerja penjualan dan menganalisis tren. ## Manajemen Pembelian: - Memungkinkan pengguna untuk membuat dan mengelola pesanan pembelian, dengan menyebutkan jumlah dan produk yang diinginkan. - Melacak informasi pemasok dan mengelola hubungan dengan pemasok. - Menerima barang dan memperbarui tingkat persediaan sesuai dengan itu. - Menangani faktur dan pembayaran pembelian kepada pemasok. ## Manajemen Persediaan: - Menyediakan alat untuk mengelola dan melacak tingkat persediaan, termasuk transfer stok dan penyesuaian. - Mengatur notifikasi otomatis untuk tingkat persediaan yang rendah dan menghasilkan pesanan pembelian ketika persediaan perlu diisi ulang. - Menawarkan kemampuan pemindaian barcode untuk manajemen persediaan yang efisien. - Memungkinkan pengguna untuk mengategorikan produk, mendefinisikan atribut, dan menetapkan informasi harga. ## Manajemen Keuangan: - Mengimplementasikan sistem buku besar umum untuk melacak transaksi keuangan, termasuk pengeluaran dan pendapatan. - Mengelola piutang dan hutang, termasuk faktur dan pelacakan pembayaran. - Menghasilkan laporan keuangan, termasuk neraca dan laporan laba rugi. - Mengintegrasikan dengan perangkat lunak akuntansi populer untuk manajemen keuangan yang mulus. ## Manajemen Proyek: - Menyediakan kemampuan manajemen proyek, memungkinkan pengguna untuk membuat dan melacak proyek. - Menugaskan tugas kepada anggota tim, menetapkan batas waktu, dan memantau kemajuan. - Mengalokasikan sumber daya dan melacak biaya proyek. - Menawarkan fitur kolaborasi seperti berbagi dokumen dan komunikasi real-time. ## Pelaporan dan Analitik: - Menghasilkan laporan dan analitik komprehensif tentang berbagai aspek bisnis. - Menyediakan dasbor yang dapat disesuaikan untuk memantau indikator kinerja utama (KPI). - Memungkinkan pengguna untuk menentukan laporan kustom berdasarkan persyaratan tertentu. - Mengimplementasikan teknik visualisasi data untuk menyajikan informasi secara menarik secara visual. ## Integrasi dan Kustomisasi: - Memungkinkan integrasi dengan aplikasi pihak ketiga atau API populer, seperti alat pemasaran email atau platform CRM. - Memungkinkan kustomisasi fungsionalitas dan tampilan aplikasi berdasarkan kebutuhan bisnis tertentu. - Menyediakan API atau webhook untuk memfasilitasi pertukaran data antara aplikasi ERP & CRM dan sistem lainnya. ## Antarmuka yang Ramah Pengguna: - Mendesain antarmuka yang intuitif, responsif, dan ramah pengguna menggunakan React.js dan Ant Design. - Mengimplementasikan menu navigasi yang mudah digunakan, fungsi pencarian, dan filter. - Memastikan antarmuka yang konsisten dan menarik secara visual di berbagai perangkat dan ukuran layar. ================================================ FILE: features/it_it_software_erp_crm_open_source_gratuito.md ================================================ # IDURAR Software ERP e CRM Open-Source GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Sito web: [https://www.idurarapp.com](https://www.idurarapp.com) ## Stack Software IDURAR è un'app ERP e CRM open-source gratuita, basata su "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Gestione Utenti: - Consenti agli amministratori di creare, modificare ed eliminare account utente. - Implementa un controllo degli accessi basato sui ruoli per gestire le autorizzazioni degli utenti. - Fornisci meccanismi di autenticazione e autorizzazione per garantire un accesso sicuro. ## Gestione delle Relazioni con i Clienti (CRM): - Consenti agli utenti di creare e gestire record di contatto per potenziali clienti e clienti. - Implementa funzionalità di generazione e qualificazione dei lead per tracciare opportunità di vendita potenziali. - Fornisci strumenti per gestire la cronologia delle comunicazioni con i clienti, inclusi email, chiamate e incontri. - Consenti agli utenti di pianificare appuntamenti e inviare notifiche o promemoria ai clienti. ## Gestione delle Vendite: - Consenti agli utenti di creare e gestire ordini di vendita, associandoli a clienti specifici. - Implementa il tracciamento dell'inventario per verificare la disponibilità dei prodotti e aggiornare i livelli di stock dopo ogni vendita. - Genera fatture e gestisci l'integrazione dei pagamenti con popolari gateway di pagamento. - Fornisci dashboard e report per monitorare le prestazioni delle vendite e analizzare le tendenze. ## Gestione degli Acquisti: - Consenti agli utenti di creare e gestire ordini di acquisto, specificando la quantità e i prodotti desiderati. - Tieni traccia delle informazioni sui fornitori e gestisci le relazioni con i fornitori. - Ricevi merci e aggiorna di conseguenza i livelli di inventario. - Gestisci fatture di acquisto e pagamenti ai fornitori. ## Gestione dell'Inventario: - Fornisci strumenti per gestire e tracciare i livelli di inventario, inclusi trasferimenti di stock e regolazioni. - Imposta notifiche automatiche per i livelli di stock bassi e genera ordini di acquisto quando è necessario rifornirsi. - Offri funzionalità di scansione dei codici a barre per una gestione efficiente dell'inventario. - Consenti agli utenti di categorizzare i prodotti, definire attributi e impostare informazioni sui prezzi. ## Gestione Finanziaria: - Implementa un sistema di contabilità generale per tracciare le transazioni finanziarie, inclusi spese e entrate. - Gestisci i crediti e i debiti, inclusa la fatturazione e il tracciamento dei pagamenti. - Genera report finanziari, inclusi bilanci e conti economici. - Integra con software di contabilità popolari per una gestione finanziaria senza soluzione di continuità. ## Gestione dei Progetti: - Fornisci funzionalità di gestione dei progetti, consentendo agli utenti di creare e monitorare progetti. - Assegna compiti ai membri del team, imposta scadenze e monitora i progressi. - Alloca risorse e monitora le spese del progetto. - Offri funzionalità di collaborazione come la condivisione di documenti e la comunicazione in tempo reale. ## Reporting e Analisi: - Genera report e analisi completi su vari aspetti dell'attività. - Fornisci dashboard personalizzabili per monitorare gli indicatori chiave di performance (KPI). - Consenti agli utenti di definire report personalizzati in base a requisiti specifici. - Implementa tecniche di visualizzazione dei dati per presentare le informazioni in modo accattivante dal punto di vista visivo. ## Integrazione e Personalizzazione: - Consenti l'integrazione con applicazioni o API di terze parti popolari, come strumenti di email marketing o piattaforme CRM. - Consenti la personalizzazione delle funzionalità e dell'aspetto dell'app in base alle specifiche esigenze aziendali. - Fornisci un'API o webhook per facilitare lo scambio di dati tra l'app ERP e CRM e altri sistemi. ## Interfaccia Utente User-friendly: - Progetta un'interfaccia intuitiva, responsiva e user-friendly utilizzando React.js e Ant Design. - Implementa menu di navigazione facili da usare, funzionalità di ricerca e filtri. - Assicura un'interfaccia utente coerente e visivamente accattivante su diversi dispositivi e dimensioni dello schermo. ================================================ FILE: features/ja_jp_フリーオープンソースERP CRMソフトウェア.md ================================================ # IDURAR オープンソース ERP&CRMソフトウェア GitHub:[https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) デモ:[https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) ウェブサイト:[https://www.idurarapp.com](https://www.idurarapp.com) ## ソフトウェアスタック IDURARは、Node.js、React.js、Redux、Express.js、MongoDB、AntDesign(AntD)をベースにした無料のオープンソースERP&CRMアプリです。 ## ユーザー管理: - 管理者がユーザーアカウントを作成、編集、削除できるようにします。 - ユーザーの権限を管理するための役割ベースのアクセス制御を実装します。 - 安全なアクセスを確保するための認証および認可メカニズムを提供します。 ## 顧客関係管理(CRM): - ユーザーがリード、見込み顧客、および顧客の連絡記録を作成および管理できるようにします。 - 潜在的な営業機会を追跡するためのリード生成および資格機能を実装します。 - メール、電話、ミーティングなどの顧客とのコミュニケーション履歴を管理するためのツールを提供します。 - ユーザーがアポイントメントをスケジュールし、顧客に通知やリマインダーを送信できるようにします。 ## 販売管理: - ユーザーが特定の顧客と関連付けて販売注文を作成および管理できるようにします。 - 製品の在庫状況を確認し、各販売後に在庫レベルを更新するための在庫追跡を実装します。 - 請求書を生成し、人気のある支払いゲートウェイとの支払い統合を処理します。 - 販売パフォーマンスを監視し、トレンドを分析するためのダッシュボードとレポートを提供します。 ## 購買管理: - ユーザーが数量と希望する製品を指定して発注を作成および管理できるようにします。 - 供給業者の情報を追跡し、供給業者との関係を管理します。 - 商品を受け取り、在庫レベルを適切に更新します。 - 供給業者への購買請求書と支払いを処理します。 ## 在庫管理: - 在庫のレベルを管理および追跡するためのツールを提供します。在庫の移動や調整を含みます。 - 在庫が不足している場合に自動通知を設定し、再補充が必要な場合に発注書を生成します。 - 効率的な在庫管理のためのバーコードスキャン機能を提供します。 - ユーザーが製品を分類し、属性を定義し、価格情報を設定できるようにします。 ## 財務管理: - 費用や収益などの財務取引を追跡するための総勘定元帳システムを実装します。 - 売掛金や買掛金を管理し、請求書や支払いの追跡を行います。 - 貸借対照表や損益計算書などの財務レポートを生成します。 - 人気のある会計ソフトウェアとのシームレスな財務管理を実現します。 ## プロジェクト管理: - ユーザーがプロジェクトを作成し、追跡できるプロジェクト管理機能を提供します。 - チームメンバーにタスクを割り当て、締め切りを設定し、進捗状況を監視します。 - リソースを割り当て、プロジェクトの費用を追跡します。 - ドキュメント共有やリアルタイムコミュニケーションなどのコラボレーション機能を提供します。 ## レポートと分析: - ビジネスのさまざまな側面について包括的なレポートと分析を生成します。 - キーパフォーマンスインジケーター(KPI)を監視するためのカスタマイズ可能なダッシュボードを提供します。 - 特定の要件に基づいてカスタムレポートを定義できるようにします。 - データ可視化技術を実装して、情報を視覚的に魅力的な形式で表示します。 ## 統合とカスタマイズ: - メールマーケティングツールやCRMプラットフォームなどの人気のあるサードパーティアプリケーションやAPIとの統合を可能にします。 - 特定のビジネスニーズに基づいてアプリの機能と外観をカスタマイズできるようにします。 - ERP&CRMアプリと他のシステム間のデータ交換を容易にするためのAPIまたはWebフックを提供します。 ## ユーザーフレンドリーなインターフェース: - React.jsとAnt Designを使用して直感的でレスポンシブで使いやすいインターフェースを設計します。 - 簡単に使用できるナビゲーションメニューや検索機能、フィルターを実装します。 - 異なるデバイスと画面サイズで一貫した視覚的に魅力的なUIを確保します。 ================================================ FILE: features/ko_kr_자유_오픈_소스_ERP_CRM_소프트웨어.md ================================================ # IDURAR 오픈 소스 ERP & CRM 소프트웨어 GitHub : [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) 데모 : [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) 웹사이트 : [https://www.idurarapp.com](https://www.idurarapp.com) ## 소프트웨어 스택 IDURAR 무료 오픈 소스 erp & crm 앱, "mern-stack"을 기반으로 함: Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## 사용자 관리: - 관리자가 사용자 계정을 생성, 편집 및 삭제할 수 있도록 허용합니다. - 역할 기반의 액세스 제어를 구현하여 사용자 권한을 관리합니다. - 안전한 액세스를 보장하기 위해 인증 및 권한 부여 메커니즘을 제공합니다. ## 고객 관계 관리 (CRM): - 사용자가 잠재 고객, 전망 고객 및 고객을 위한 연락처 기록을 생성 및 관리할 수 있도록 합니다. - 잠재적인 영업 기회를 추적하기 위한 리드 생성 및 자격 인증 기능을 구현합니다. - 이메일, 전화 및 회의 등을 포함한 고객과의 커뮤니케이션 기록을 관리하는 도구를 제공합니다. - 사용자가 약속을 예약하고 고객에게 알림이나 리마인더를 보낼 수 있도록 합니다. ## 영업 관리: - 사용자가 영업 주문을 생성하고 관리할 수 있도록 하며, 이를 특정 고객과 연결합니다. - 제품 가용성을 확인하고 각 판매 후 재고 수준을 업데이트하기 위해 재고 추적을 구현합니다. - 인기 있는 결제 게이트웨이와의 결제 통합을 처리하고 송장을 생성합니다. - 판매 성과를 모니터링하고 동향을 분석하기 위한 대시보드 및 보고서를 제공합니다. ## 구매 관리: - 사용자가 수량과 원하는 제품을 지정하여 구매 주문을 생성 및 관리할 수 있도록 합니다. - 공급업체 정보를 추적하고 공급업체 관계를 관리합니다. - 상품을 수령하고 재고 수준을 업데이트합니다. - 공급업체에 대한 구매 송장 및 지불을 처리합니다. ## 재고 관리: - 재고 수준을 관리하고 추적하기 위한 도구를 제공합니다. 이는 재고 이동 및 조정을 포함합니다. - 재고가 부족한 경우 자동 알림 설정 및 보충이 필요한 경우 구매 주문 생성을 설정합니다. - 효율적인 재고 관리를 위한 바코드 스캐닝 기능을 제공합니다. - 사용자가 제품을 분류하고 속성을 정의하며 가격 정보를 설정할 수 있도록 합니다. ## 재무 관리: - 비용 및 수익을 포함한 재무 거래를 추적하기 위한 일반 원장 시스템을 구현합니다. - 매출채권 및 매입채무를 관리하며, 송장 및 지불 추적을 포함합니다. - 재무 보고서를 생성하며, 재무 상태표와 손익 계산서를 포함합니다. - 인기 있는 회계 소프트웨어와의 원활한 재무 관리를 위해 통합합니다. ## 프로젝트 관리: - 사용자가 프로젝트를 생성하고 추적할 수 있는 프로젝트 관리 기능을 제공합니다. - 팀 멤버에게 작업을 할당하고 마감일을 설정하며 진행 상황을 모니터링할 수 있습니다. - 자원을 할당하고 프로젝트 비용을 추적합니다. - 문서 공유 및 실시간 커뮤니케이션과 같은 협업 기능을 제공합니다. ## 보고 및 분석: - 비즈니스의 다양한 측면에 대한 포괄적인 보고서 및 분석을 생성합니다. - 핵심 성과 지표 (KPI)를 모니터링하기 위한 사용자 정의 대시보드를 제공합니다. - 특정 요구 사항에 기반한 사용자 정의 보고서를 정의할 수 있습니다. - 정보를 시각적으로 표현하기 위해 데이터 시각화 기법을 구현합니다. ## 통합 및 사용자 정의: - 이메일 마케팅 도구나 CRM 플랫폼과 같은 인기 있는 타사 애플리케이션 또는 API와의 통합을 가능하게 합니다. - 특정 비즈니스 요구 사항에 따라 앱의 기능과 외관을 사용자 정의할 수 있습니다. - ERP & CRM 앱과 다른 시스템 간의 데이터 교환을 용이하게 하기 위해 API 또는 웹훅을 제공합니다. ## 사용자 친화적 인터페이스: - React.js와 Ant Design을 사용하여 직관적이고 반응형이며 사용자 친화적인 인터페이스를 디자인합니다. - 사용하기 쉬운 탐색 메뉴, 검색 기능 및 필터를 구현합니다. - 다양한 기기와 화면 크기에서 일관되고 시각적으로 매력적인 UI를 보장합니다. ================================================ FILE: features/lt_lt_nemokamas_atviras_kodo_erp_crm_programinė_įranga.md ================================================ # IDURAR Atviro kodo ERP ir CRM programinė įranga GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Tinklapis: [https://www.idurarapp.com](https://www.idurarapp.com) ## Programinės įrangos rinkinys IDURAR Nemokama atviro kodo erp ir crm programa, pagrįsta "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Vartotojų valdymas: - Leisti administratoriams kurti, redaguoti ir ištrinti vartotojų paskyras. - Įdiegti vaidmenų pagrįstą prieigos kontrolę, valdyti vartotojų leidimus. - Užtikrinti autentifikacijos ir autorizacijos mechanizmus, užtikrinančius saugų prieigą. ## Klientų ryšių valdymas (CRM): - Leisti vartotojams kurti ir valdyti kontaktų įrašus potencialiems klientams ir klientams. - Įdiegti potencialių pardavimų galimybių generavimo ir kvalifikavimo funkcijas. - Teikti įrankius klientų ryšių istorijos valdymui, įskaitant el. pašto, skambučių ir susitikimų įrašus. - Leisti vartotojams planuoti susitikimus ir siųsti pranešimus ar priminimus klientams. ## Pardavimų valdymas: - Leisti vartotojams kurti ir valdyti pardavimų užsakymus, susiejant juos su konkretaus kliento informacija. - Įdiegti prekių atsekimo sistemą, patikrinti prekių prieinamumą ir atnaujinti atsargas po kiekvieno pardavimo. - Generuoti sąskaitas faktūras ir tvarkyti mokėjimų integraciją su populiariais mokėjimo šliuzais. - Teikti informacijos suvestines ir ataskaitas, stebėti pardavimų veiklą ir analizuoti tendencijas. ## Pirkimo valdymas: - Leisti vartotojams kurti ir valdyti pirkimo užsakymus, nurodydami kiekį ir norimas prekes. - Sekti tiekimo informaciją ir valdyti tiekimo santykius. - Gavus prekes, atnaujinti atsargų lygius. - Tvarkyti pirkimo sąskaitas faktūras ir mokėjimus tiekėjams. ## Atsargų valdymas: - Suteikti įrankius valdyti ir sekti atsargų lygius, įskaitant atsargų perkėlimus ir korekcijas. - Nustatyti automatinį pranešimą apie mažas atsargų lygius ir generuoti pirkimo užsakymus, kai reikia papildyti atsargas. - Siūlyti brūkšninio kodo skenavimo galimybes efektyviam atsargų valdymui. - Leisti vartotojams kategorizuoti produktus, apibrėžti atributus ir nustatyti kainų informaciją. ## Finansinis valdymas: - Įdiegti bendrojo žurnalo sistemą finansiniams sandoriams, įskaitant išlaidas ir pajamas. - Valdyti debitorius ir kreditorius, įskaitant sąskaitų faktūras ir mokėjimų stebėjimą. - Generuoti finansines ataskaitas, įskaitant balanso ataskaitas ir pelno ir nuostolio ataskaitas. - Integruoti su populiaria finansinės apskaitos programine įranga, užtikrinant sklandų finansinį valdymą. ## Projektų valdymas: - Suteikti projektų valdymo galimybes, leidžiančias vartotojams kurti ir stebėti projektus. - Priskirti užduotis komandos nariams, nustatyti terminus ir stebėti pažangą. - Skirti išteklius ir stebėti projektų išlaidas. - Siūlyti bendradarbiavimo funkcijas, tokias kaip dokumentų bendrinimas ir realaus laiko bendravimas. ## Ataskaitos ir analitika: - Generuoti išsamią ataskaitą ir analitiką apie įvairius verslo aspektus. - Teikti tinkinamas informacijos suvestines, skirtas stebėti pagrindinius veiklos rodiklius (KPI). - Leisti vartotojams apibrėžti tinkinamas ataskaitas pagal konkrečius reikalavimus. - Įdiegti duomenų vizualizavimo technikas, kad informacija būtų pateikiama vizualiai patrauklia forma. ## Integracija ir tinkinimas: - Leisti integruoti su populiariomis trečiųjų šalių programomis ar API, pvz., el. pašto rinkodaros įrankiais ar CRM platformomis. - Leisti tinkinti programos funkcionalumą ir išvaizdą pagal konkretų verslo poreikį. - Teikti API arba webhooks, palengvinančius duomenų mainus tarp ERP ir CRM programos bei kitų sistemų. ## Vartotojui draugiškas sąsaja: - Sukurti intuityvią, reaguojančią ir vartotojui draugišką sąsają, naudojant React.js ir Ant Design. - Įdiegti lengvai naudojamus naršymo meniu, paieškos funkcijas ir filtrus. - Užtikrinti nuoseklią ir vizualiai patrauklią naudotojo sąsają skirtinguose įrenginiuose ir ekrano dydžiuose. ================================================ FILE: features/lv_lv_bezmaksas_atvērtā_koda_erp_crm_programmatūra.md ================================================ # IDURAR Atvērtā koda ERP un CRM programmatūra GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Mājaslapa: [https://www.idurarapp.com](https://www.idurarapp.com) ## Programmatūras tehnoloģiju komplekts IDURAR bezmaksas atvērtā koda erp & crm lietotne, balstīta uz "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Lietotāju pārvaldība: - Ļauj administratoriem izveidot, labot un dzēst lietotāja kontus. - Ievieš lomu pamatotas piekļuves vadības funkcionalitāti, lai pārvaldītu lietotāju atļaujas. - Nodrošina autentifikācijas un autorizācijas mehānismus, lai nodrošinātu drošu piekļuvi. ## Klientu attiecību pārvaldība (CRM): - Ļauj lietotājiem izveidot un pārvaldīt kontaktu ierakstus potenciāliem pārdošanas iespējām un klientiem. - Ievieš potenciālo pārdošanas iespēju ģenerēšanas un kvalifikācijas funkcionalitātes, lai sekotu līdzi potenciālajām pārdošanas iespējām. - Nodrošina rīkus klientu komunikācijas vēstures pārvaldībai, ieskaitot e-pastus, zvanus un tikšanās. - Ļauj lietotājiem ieplānot tikšanās un nosūtīt paziņojumus vai atgādinājumus klientiem. ## Pārdošanas pārvaldība: - Ļauj lietotājiem izveidot un pārvaldīt pārdošanas pasūtījumus, tos saistot ar konkrētiem klientiem. - Ievieš krājumu izsekošanu, lai pārbaudītu produktu pieejamību un atjauninātu krājuma līmeņus pēc katras pārdošanas. - Ģenerē rēķinus un apstrādā maksājumu integrāciju ar populārām maksājumu vārtām. - Nodrošina vadības panelus un pārskatus, lai uzraudzītu pārdošanas veiktspēju un analizētu tendences. ## Iepirkumu pārvaldība: - Ļauj lietotājiem izveidot un pārvaldīt iepirkumu pasūtījumus, norādot daudzumu un vēlamās preces. - Seko piegādātāja informācijai un pārvalda piegādātāju attiecības. - Saņem preces un atjaunina krājumu līmenis atbilstoši. - Apstrādā iepirkuma rēķinus un maksājumus piegādātājiem. ## Krājumu pārvaldība: - Nodrošina rīkus, lai pārvaldītu un izsekotu krājumu līmeņus, ieskaitot krājuma pārvedumus un pielāgojumus. - Iestatiet automātiskas paziņojumus par zemu krājumu līmeni un ģenerējiet iepirkumu pasūtījumus, ja nepieciešams atjaunot krājumus. - Piedāvā skenēšanas iespējas efektīvai krājumu pārvaldībai. - Ļauj lietotājiem kategorizēt produktus, definēt atribūtus un iestatīt cenu informāciju. ## Finanšu pārvaldība: - Ievieš galveno grāmatvedības sistēmu, lai izsekotu finanšu darījumus, ieskaitot izdevumus un ienākumus. - Pārvalda debitoru un kreditoru kontus, ieskaitot rēķinu izrakstīšanu un maksājumu izsekošanu. - Ģenerē finanšu pārskatus, ieskaitot bilances un ieņēmumu paziņojumus. - Integrējas ar populāro grāmatvedības programmatūru bez šķēršļiem finanšu pārvaldībai. ## Projektu pārvaldība: - Nodrošina projektu pārvaldības iespējas, ļaujot lietotājiem izveidot un sekot līdzi projektiem. - Piešķir uzdevumus komandas locekļiem, iestata termiņus un uzrauga progresu. - Piešķir resursus un seko projektu izdevumiem. - Piedāvā sadarbības funkcijas, piemēram, dokumentu kopīgošanu un reāllaika komunikāciju. ## Pārskatu un analītikas: - Ģenerē visaptverošus pārskatus un analītiku par dažādiem uzņēmuma aspektiem. - Nodrošina pielāgojamus vadības paneļus, lai uzraudzītu galvenos veiktspējas rādītājus (KPI). - Ļauj lietotājiem definēt pielāgotus pārskatus, pamatojoties uz konkrētiem prasībām. - Ievieš datu vizualizācijas tehnikas, lai vizuāli pievilcīgi attēlotu informāciju. ## Integrācija un pielāgošana: - Nodrošina integrāciju ar populārām trešās puses lietojumprogrammām vai API, piemēram, e-pasta mārketinga rīkiem vai CRM platformām. - Ļauj pielāgot lietotnes funkcionalitāti un izskatu, pamatojoties uz konkrētiem uzņēmuma vajadzībām. - Nodrošina API vai tīmekļa āķus, lai atvieglotu datu apmaiņu starp ERP un CRM lietotni un citām sistēmām. ## Lietotājam draudzīga saskarne: - Izstrādā intuitīvu, reaģējošu un lietotājam draudzīgu saskarni, izmantojot React.js un Ant Design. - Ievieš viegli lietojamus navigācijas izvēlnes, meklēšanas funkcionalitāti un filtrus. - Nodrošina vienotu un vizuāli pievilcīgu lietotāja saskarni dažādos ierīcēs un ekrāna izmēros. ================================================ FILE: features/mk_mk_фрее_опен_сорсе_ерп_црм_софтвер.md ================================================ # IDURAR Open-Source ERP & CRM Софтвер GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Демо: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Веб-страница: [https://www.idurarapp.com](https://www.idurarapp.com) ## Стек на софтвер IDURAR Бесплатен отворен извор на erp & crm апликација, базирана на "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Управување со корисници: - Овозможи на администраторите да креираат, уредуваат и бришат кориснички сметки. - Имплементирајте контрола на пристапот базирана на улоги за управување со кориснички привилегии. - Обезбеди механизми за автентикација и авторизација за да се обезбеди безбеден пристап. ## Управување со односите со клиентите (CRM): - Овозможи на корисниците да креираат и управуваат контактни записи за потенцијални клиенти и клиенти. - Имплементирајте функционалности за генерирање и квалификација на потенцијални продажбени можност. - Обезбеди алатки за управување со историјата на комуникација со клиентите, вклучувајќи е-пошти, повици и средби. - Овозможи на корисниците да закажуваат средби и да испраќаат известувања или потсетници до клиентите. ## Управување со продажбите: - Дозволи на корисниците да креираат и управуваат нарачки за продажба, поврзувајќи ги со специфични клиенти. - Имплементирајте следење на залихата за проверка на достапноста на производите и ажурирање на нивните нивоа по секоја продажба. - Генерирајте фактури и се занимавајте со интеграција на плаќање со популарни платежни портали. - Обезбеди таблици и извештаи за следење на перформансите на продажбите и анализирање на трендовите. ## Управување со купувањето: - Дозволи на корисниците да креираат и управуваат нарачки за купување, наведувајќи количина и желени производи. - Праќајте информации за доставувачот и управувајте со односите со доставувачите. - Примајте роба и ажурирајте ги нивните нивоа на залиха соодветно. - Се занимавајте со фактури за купување и плаќање на доставувачите. ## Управување со залихата: - Обезбеди алатки за управување и следење на нивоата на залиха, вклучувајќи трансфери на залиха и прилагодувања. - Поставете автоматски известувања за ниски нивоа на залиха и генерирање на нарачки за купување кога е потребно да се дополни залихата. - Понудете можности за скенирање на баркодови за ефикасно управување со залихата. - Овозможи на корисниците да категоризираат производи, да дефинираат атрибути и да постават информации за ценување. ## Финансиско управување: - Имплементирајте систем за главна книга за следење на финансиските трансакции, вклучувајќи трошоци и приходи. - Управувајте со дебиторски и кредиторски сметки, вклучувајќи фактурирање и следење на плаќањата. - Генерирајте финансиски извештаи, вклучувајќи балансна состојба и извештаи за приходи и трошоци. - Интегрирајте го со популарни финансиски софтвери за безпроблемно финансиско управување. ## Управување на проекти: - Обезбеди можности за управување на проекти, овозможувајќи на корисниците да креираат и следат проекти. - Доделување на задачи на членовите на тимот, поставување на рокови и следење на напредокот. - Распределување на ресурси и следење на трошоците на проектот. - Понудете можности за соработка, како споделување на документи и комуникација во реално време. ## Извештаи и аналитика: - Генерирајте комплетни извештаи и аналитика за различни аспекти на бизнисот. - Обезбедете прилагодливи таблици за следење на кључните показатели на перформанси (KPI). - Дозволете на корисниците да дефинираат прилагодени извештаи базирани на специфични барања. - Имплементирајте техники за визуелизација на податоците за претставување на информациите на визуелно привлечен начин. ## Интеграција и прилагодување: - Овозможете интеграција со популарни апликации или API-и од трети страни, како алатки за маркетинг преку е-пошта или CRM платформи. - Дозволете прилагодување на функционалноста и изгледот на апликацијата врз основа на специфични потреби на бизнисот. - Обезбедете API или веб-куки за олеснување на размената на податоци помеѓу ERP & CRM апликацијата и други системи. ## Кориснички пријателски интерфејс: - Дизајнирајте интуитивен, респонзивен и кориснички пријателски интерфејс со користење на React.js и Ant Design. - Имплементирајте лесно за користење менија за навигација, функционалности за пребарување и филтри. - Обезбедете конзистентен и визуелно привлечен кориснички интерфејс на различни уреди и големини на екранот. ================================================ FILE: features/ms_my_fail_terbuka_sumber_erp_crm_perisian.md ================================================ # Perisian Sumber Terbuka IDURAR ERP & CRM GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Laman Web: [https://www.idurarapp.com](https://www.idurarapp.com) ## Tumpukan Perisian IDURAR adalah aplikasi ERP & CRM sumber terbuka percuma, berdasarkan "tumpukan mern": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Pengurusan Pengguna: - Membenarkan pentadbir untuk mencipta, mengedit, dan menghapus akaun pengguna. - Menggunakan kawalan akses berdasarkan peranan untuk menguruskan kebenaran pengguna. - Menyediakan mekanisme pengesahan dan kebenaran untuk memastikan akses yang selamat. ## Pengurusan Hubungan Pelanggan (CRM): - Membolehkan pengguna mencipta dan menguruskan rekod hubungan pelanggan untuk prospek, pelanggan potensial, dan pelanggan. - Mengimplementasikan fungsi penjanaan dan penilaian prospek untuk mengesan peluang jualan yang berpotensi. - Menyediakan alat untuk menguruskan sejarah komunikasi dengan pelanggan, termasuk emel, panggilan, dan pertemuan. - Membolehkan pengguna menjadualkan janji temu dan menghantar pemberitahuan atau peringatan kepada pelanggan. ## Pengurusan Jualan: - Membolehkan pengguna mencipta dan menguruskan pesanan jualan, mengaitkannya dengan pelanggan tertentu. - Mengimplementasikan penjejakan inventori untuk memeriksa ketersediaan produk dan mengemaskini tahap stok setelah setiap jualan. - Menghasilkan invois dan menguruskan integrasi pembayaran dengan gerbang pembayaran popular. - Menyediakan papan pemuka dan laporan untuk memantau prestasi jualan dan menganalisis trend. ## Pengurusan Pembelian: - Membolehkan pengguna mencipta dan menguruskan pesanan pembelian, menentukan kuantiti dan produk yang dikehendaki. - Menjejaki maklumat pembekal dan menguruskan hubungan dengan pembekal. - Menerima barang dan mengemaskini tahap inventori mengikut keadaan. - Menguruskan invois pembelian dan pembayaran kepada pembekal. ## Pengurusan Inventori: - Menyediakan alat untuk mengurus dan menjejaki tahap inventori, termasuk pemindahan stok dan penyesuaian. - Menetapkan pemberitahuan automatik untuk tahap stok yang rendah dan menghasilkan pesanan pembelian apabila perlu mengisi semula stok. - Menawarkan keupayaan pengimbasan kod bar untuk pengurusan inventori yang cekap. - Membolehkan pengguna mengategorikan produk, menentukan atribut, dan menetapkan maklumat harga. ## Pengurusan Kewangan: - Mengimplementasikan sistem buku besar untuk menjejaki transaksi kewangan, termasuk perbelanjaan dan pendapatan. - Menguruskan piutang dan hutang, termasuk invois dan penjejakan pembayaran. - Menghasilkan laporan kewangan, termasuk neraca dan penyata pendapatan. - Mengintegrasikan dengan perisian perakaunan popular untuk pengurusan kewangan yang lancar. ## Pengurusan Projek: - Menyediakan kemampuan pengurusan projek, membolehkan pengguna mencipta dan menjejaki projek. - Menetapkan tugas kepada ahli pasukan, menetapkan tarikh akhir, dan memantau kemajuan. - Mengagihkan sumber dan menjejaki perbelanjaan projek. - Menawarkan ciri-ciri kolaborasi seperti perkongsian dokumen dan komunikasi secara masa nyata. ## Pelaporan dan Analisis: - Menghasilkan laporan dan analisis menyeluruh mengenai pelbagai aspek perniagaan. - Menyediakan papan pemuka yang boleh disesuaikan untuk memantau petunjuk prestasi utama (KPI). - Membolehkan pengguna menentukan laporan khusus berdasarkan keperluan tertentu. - Mengimplementasikan teknik visualisasi data untuk menyajikan maklumat secara menarik secara visual. ## Integrasi dan Penyesuaian: - Membolehkan integrasi dengan aplikasi pihak ketiga atau API popular, seperti alat pemasaran melalui emel atau platform CRM. - Membolehkan penyesuaian fungsi dan penampilan aplikasi berdasarkan keperluan perniagaan tertentu. - Menyediakan API atau webhooks untuk memudahkan pertukaran data antara aplikasi ERP & CRM dan sistem lain. ## Antara Muka Mesra Pengguna: - Reka bentuk antara muka yang intuitif, responsif, dan mesra pengguna menggunakan React.js dan Ant Design. - Mengimplementasikan menu navigasi yang mudah digunakan, fungsi carian, dan penapis. - Memastikan antara muka yang konsisten dan menarik secara visual di pelbagai peranti dan saiz skrin. ================================================ FILE: features/nb_no_gratis_åpen_kilde_erp_crm_programvare.md ================================================ # IDURAR Åpen kildekode ERP og CRM-programvare GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Nettsted: [https://www.idurarapp.com](https://www.idurarapp.com) ## Programvarestabel IDURAR Gratis åpen kildekode ERP og CRM-app, basert på "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Brukerstyring: - Tillat administratorer å opprette, redigere og slette brukerkontoer. - Implementer rollebasert tilgangskontroll for å administrere brukerrettigheter. - Tilby autentiserings- og autorisasjonsmekanismer for å sikre sikker tilgang. ## Kunderelasjonshåndtering (CRM): - Gjør det mulig for brukere å opprette og administrere kontaktregistre for potensielle kunder og kunder. - Implementer funksjonalitet for generering og kvalifisering av potensielle salgsmuligheter. - Tilby verktøy for å administrere kommunikasjonshistorikk med kunder, inkludert e-poster, samtaler og møter. - Tillat brukere å planlegge avtaler og sende varsler eller påminnelser til kunder. ## Salgsstyring: - Tillat brukere å opprette og administrere salgsordrer og knytte dem til spesifikke kunder. - Implementer lagerstyring for å sjekke produkttilgjengelighet og oppdatere beholdningsnivåer etter hver salg. - Generer fakturaer og håndter betalingsintegrasjon med populære betalingsportaler. - Tilby dashboards og rapporter for å overvåke salgsprestasjoner og analysere trender. ## Innkjøpsstyring: - Tillat brukere å opprette og administrere innkjøpsordrer, spesifisere mengde og ønskede produkter. - Spor leverandørinformasjon og administrer leverandørforhold. - Motta varer og oppdater beholdningsnivåer i henhold. - Håndter innkjøpsfakturaer og betalinger til leverandører. ## Lagerstyring: - Tilby verktøy for å administrere og spore beholdningsnivåer, inkludert vareoverføringer og justeringer. - Sett opp automatiske varsler for lav beholdning og generer innkjøpsordrer når det er behov for påfylling. - Tilby strekkodeskanning for effektiv lagerstyring. - Gjør det mulig for brukere å kategorisere produkter, definere attributter og angi priser. ## Økonomistyring: - Implementer et hovedboksystem for å spore økonomiske transaksjoner, inkludert utgifter og inntekter. - Administrer utestående fordringer og gjeld, inkludert fakturering og betalingssporing. - Generer økonomiske rapporter, inkludert balanse og resultatregnskap. - Integrer med populær regnskapsprogramvare for sømløs økonomistyring. ## Prosjektstyring: - Tilby prosjektstyringsfunksjoner som lar brukere opprette og følge opp prosjekter. - Tildel oppgaver til teammedlemmer, sett frister og overvåk fremdrift. - Alloker ressurser og spore prosjektkostnader. - Tilby samarbeidsfunksjoner som dokumentdeling og sanntidskommunikasjon. ## Rapportering og analyse: - Generer omfattende rapporter og analyser om ulike aspekter av virksomheten. - Tilby tilpassbare dashboards for overvåking av nøkkelindikatorer for ytelse (KPIer). - Tillat brukere å definere egendefinerte rapporter basert på spesifikke krav. - Implementer datavisualiseringsteknikker for å presentere informasjon på en visuelt tiltalende måte. ## Integrering og tilpasning: - Gjør det mulig med integrasjon med populære tredjepartsapplikasjoner eller API-er, som e-postmarkedsføringsverktøy eller CRM-plattformer. - Tillat tilpasning av appens funksjonalitet og utseende basert på spesifikke forretningsbehov. - Tilby en API eller webhooks for å lette datautveksling mellom ERP- og CRM-appen og andre systemer. ## Brukervennlig grensesnitt: - Design et intuitivt, responsivt og brukervennlig grensesnitt ved hjelp av React.js og Ant Design. - Implementer enkelt navigasjonsmenyer, søkefunksjoner og filtre. - Sørg for en konsistent og visuelt tiltalende brukergrensesnitt på ulike enheter og skjermstørrelser. ================================================ FILE: features/nl_nl_vrije_open_source_erp_crm_software.md ================================================ # IDURAR Open-Source ERP & CRM Software GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Website: [https://www.idurarapp.com](https://www.idurarapp.com) ## Software Stack IDURAR Gratis open-source erp & crm app, gebaseerd op "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Gebruikersbeheer: - Sta beheerders toe om gebruikersaccounts aan te maken, te bewerken en te verwijderen. - Implementeer op rollen gebaseerde toegangscontrole om gebruikersrechten te beheren. - Zorg voor authenticatie- en autorisatiemechanismen om veilige toegang te garanderen. ## Klantrelatiebeheer (CRM): - Maak het mogelijk voor gebruikers om contactgegevens voor leads, prospects en klanten aan te maken en te beheren. - Implementeer functionaliteiten voor leadgeneratie en -kwalificatie om potentiële verkoopkansen bij te houden. - Bied tools voor het beheren van de communicatiegeschiedenis met klanten, waaronder e-mails, telefoongesprekken en vergaderingen. - Sta gebruikers toe afspraken in te plannen en meldingen of herinneringen naar klanten te sturen. ## Verkoopbeheer: - Sta gebruikers toe om verkooporders aan te maken en te beheren, waarbij ze deze koppelen aan specifieke klanten. - Implementeer voorraadbeheer om de beschikbaarheid van producten te controleren en de voorraadniveaus bij te werken na elke verkoop. - Genereer facturen en handel betalingsintegratie af met populaire betaalgateways. - Bied dashboards en rapporten om de verkoopprestaties te monitoren en trends te analyseren. ## Inkoopbeheer: - Sta gebruikers toe om inkooporders aan te maken en te beheren, waarbij ze de hoeveelheid en gewenste producten specificeren. - Volg leveranciersinformatie en beheer leveranciersrelaties. - Ontvang goederen en werk de voorraadniveaus dienovereenkomstig bij. - Handel inkoopfacturen en betalingen aan leveranciers af. ## Voorraadbeheer: - Bied tools om voorraadniveaus te beheren en bij te houden, inclusief voorraadoverdrachten en aanpassingen. - Stel automatische meldingen in voor lage voorraadniveaus en genereer inkooporders wanneer aanvulling nodig is. - Bied mogelijkheden voor het scannen van barcodes voor efficiënt voorraadbeheer. - Sta gebruikers toe om producten te categoriseren, attributen te definiëren en prijsinformatie in te stellen. ## Financieel beheer: - Implementeer een grootboeksysteem om financiële transacties bij te houden, inclusief kosten en opbrengsten. - Beheer debiteuren en crediteuren, inclusief facturering en betalingsregistratie. - Genereer financiële rapporten, waaronder balans en winst- en verliesrekening. - Integreer met populaire boekhoudsoftware voor naadloos financieel beheer. ## Projectbeheer: - Bied projectmanagementmogelijkheden, waarmee gebruikers projecten kunnen aanmaken en volgen. - Wijs taken toe aan teamleden, stel deadlines in en bewaak de voortgang. - Wijs middelen toe en volg projectuitgaven. - Bied samenwerkingsfuncties zoals het delen van documenten en realtime communicatie. ## Rapportage en analyse: - Genereer uitgebreide rapporten en analyses over verschillende aspecten van het bedrijf. - Bied aanpasbare dashboards om belangrijke prestatie-indicatoren (KPI's) te volgen. - Sta gebruikers toe om aangepaste rapporten te definiëren op basis van specifieke vereisten. - Implementeer datavisualisatietechnieken om informatie op een visueel aantrekkelijke manier te presenteren. ## Integratie en aanpassing: - Maak integratie mogelijk met populaire externe applicaties of API's, zoals e-mailmarketingtools of CRM-platforms. - Sta aanpassing van de functionaliteit en het uiterlijk van de app toe op basis van specifieke zakelijke behoeften. - Bied een API of webhooks aan om gegevensuitwisseling tussen de ERP & CRM-app en andere systemen te vergemakkelijken. ## Gebruiksvriendelijke interface: - Ontwerp een intuïtieve, responsieve en gebruiksvriendelijke interface met behulp van React.js en Ant Design. - Implementeer gebruiksvriendelijke navigatiemenu's, zoekfunctionaliteiten en filters. - Zorg voor een consistente en visueel aantrekkelijke UI op verschillende apparaten en schermformaten. ================================================ FILE: features/pl_pl_bezpłatne_otwarte_źródło_erp_crm_oprogramowanie.md ================================================ # Oprogramowanie IDURAR Open-Source ERP & CRM GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Strona internetowa: [https://www.idurarapp.com](https://www.idurarapp.com) ## Stos technologiczny IDURAR Free to darmowe oprogramowanie ERP & CRM oparte na "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Zarządzanie użytkownikami: - Pozwala administratorom tworzyć, edytować i usuwać konta użytkowników. - Wdraża oparte na rolach zarządzanie dostępem do zarządzania uprawnieniami użytkowników. - Zapewnia mechanizmy uwierzytelniania i autoryzacji w celu zapewnienia bezpiecznego dostępu. ## Zarządzanie relacjami z klientami (CRM): - Umożliwia użytkownikom tworzenie i zarządzanie rekordami kontaktowymi dla potencjalnych klientów i klientów. - Wdraża funkcje generowania i kwalifikowania potencjalnych leadów w celu śledzenia możliwości sprzedaży. - Udostępnia narzędzia do zarządzania historią komunikacji z klientami, w tym e-mailem, rozmowami telefonicznymi i spotkaniami. - Pozwala użytkownikom planować spotkania i wysyłać powiadomienia lub przypomnienia do klientów. ## Zarządzanie sprzedażą: - Pozwala użytkownikom tworzyć i zarządzać zamówieniami sprzedaży, powiązując je z konkretnymi klientami. - Wdraża śledzenie stanu magazynowego w celu sprawdzenia dostępności produktów i aktualizacji poziomów zapasów po każdej sprzedaży. - Generuje faktury i obsługuje integrację płatności z popularnymi bramkami płatności. - Udostępnia panele i raporty do monitorowania wyników sprzedaży i analizy trendów. ## Zarządzanie zakupami: - Pozwala użytkownikom tworzyć i zarządzać zamówieniami zakupu, określając ilość i pożądane produkty. - Śledzi informacje o dostawcach i zarządza relacjami z dostawcami. - Odbiera towary i aktualizuje poziomy zapasów odpowiednio. - Obsługuje faktury zakupowe i płatności dla dostawców. ## Zarządzanie magazynem: - Udostępnia narzędzia do zarządzania i śledzenia poziomów zapasów, w tym transferów i dostosowań zapasów. - Umożliwia ustawienie automatycznych powiadomień o niskim poziomie zapasów i generowanie zamówień zakupu w przypadku konieczności uzupełnienia zapasów. - Oferuje możliwość skanowania kodów kreskowych w celu efektywnego zarządzania zapasami. - Umożliwia użytkownikom kategoryzowanie produktów, definiowanie atrybutów i ustalanie informacji o cenach. ## Zarządzanie finansowe: - Wdraża system księgowy do śledzenia transakcji finansowych, w tym wydatków i przychodów. - Zarządza należnościami i zobowiązaniami, w tym fakturowaniem i śledzeniem płatności. - Generuje raporty finansowe, w tym bilanse i rachunki zysków i strat. - Integruje się z popularnym oprogramowaniem księgowym dla płynnego zarządzania finansami. ## Zarządzanie projektami: - Oferuje możliwości zarządzania projektami, umożliwiając użytkownikom tworzenie i śledzenie projektów. - Przydziela zadania członkom zespołu, ustala terminy i monitoruje postępy. - Przydzielanie zasobów i śledzenie kosztów projektu. - Oferuje funkcje współpracy, takie jak udostępnianie dokumentów i komunikacja w czasie rzeczywistym. ## Raportowanie i analiza: - Generuje kompleksowe raporty i analizy dotyczące różnych aspektów działalności. - Udostępnia spersonalizowane panele do monitorowania kluczowych wskaźników wydajności (KPI). - Pozwala użytkownikom definiować niestandardowe raporty zgodnie z konkretnymi wymaganiami. - Wdraża techniki wizualizacji danych w celu przedstawienia informacji w atrakcyjny sposób wizualny. ## Integracja i dostosowanie: - Umożliwia integrację z popularnymi aplikacjami zewnętrznymi lub interfejsami API, takimi jak narzędzia do marketingu mailowego lub platformy CRM. - Pozwala dostosować funkcjonalność i wygląd aplikacji zgodnie z konkretnymi potrzebami biznesowymi. - Udostępnia interfejs API lub webhooki do ułatwienia wymiany danych między aplikacją ERP & CRM a innymi systemami. ## Przyjazny interfejs użytkownika: - Projektuje intuicyjny, responsywny i przyjazny dla użytkownika interfejs przy użyciu React.js i Ant Design. - Wdraża łatwo obsługiwane menu nawigacyjne, funkcje wyszukiwania i filtry. - Zapewnia spójny i atrakcyjny wizualnie interfejs użytkownika na różnych urządzeniach i rozmiarach ekranu. ================================================ FILE: features/pt_br_software_de_erp_e_crm_de_código_aberto_gratuito.md ================================================ # IDURAR Software ERP & CRM de código aberto GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Website: [https://www.idurarapp.com](https://www.idurarapp.com) ## Pilha de Software IDURAR é um aplicativo gratuito de ERP e CRM de código aberto, baseado na pilha "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Gerenciamento de Usuários: - Permitir que os administradores criem, editem e excluam contas de usuário. - Implementar controle de acesso baseado em funções para gerenciar permissões de usuário. - Fornecer mecanismos de autenticação e autorização para garantir acesso seguro. ## Gerenciamento de Relacionamento com o Cliente (CRM): - Permitir que os usuários criem e gerenciem registros de contato para leads, prospects e clientes. - Implementar funcionalidades de geração e qualificação de leads para rastrear oportunidades de vendas potenciais. - Fornecer ferramentas para gerenciar o histórico de comunicação com o cliente, incluindo e-mails, chamadas e reuniões. - Permitir que os usuários agendem compromissos e enviem notificações ou lembretes aos clientes. ## Gerenciamento de Vendas: - Permitir que os usuários criem e gerenciem pedidos de venda, associando-os a clientes específicos. - Implementar rastreamento de estoque para verificar a disponibilidade do produto e atualizar os níveis de estoque após cada venda. - Gerar faturas e lidar com integração de pagamento com gateways de pagamento populares. - Fornecer painéis e relatórios para monitorar o desempenho de vendas e analisar tendências. ## Gerenciamento de Compras: - Permitir que os usuários criem e gerenciem pedidos de compra, especificando a quantidade e os produtos desejados. - Rastrear informações do fornecedor e gerenciar relacionamentos com fornecedores. - Receber mercadorias e atualizar os níveis de estoque de acordo. - Lidar com faturas de compra e pagamentos a fornecedores. ## Gerenciamento de Estoque: - Fornecer ferramentas para gerenciar e rastrear os níveis de estoque, incluindo transferências e ajustes de estoque. - Configurar notificações automáticas para níveis baixos de estoque e gerar pedidos de compra quando for necessário repor o estoque. - Oferecer capacidades de leitura de código de barras para um gerenciamento eficiente de estoque. - Permitir que os usuários categorizem produtos, definam atributos e informações de preços. ## Gerenciamento Financeiro: - Implementar um sistema de contabilidade geral para rastrear transações financeiras, incluindo despesas e receitas. - Gerenciar contas a receber e contas a pagar, incluindo faturamento e rastreamento de pagamentos. - Gerar relatórios financeiros, incluindo balanços e demonstrações de resultados. - Integrar-se a softwares de contabilidade populares para um gerenciamento financeiro perfeito. ## Gerenciamento de Projetos: - Fornecer capacidades de gerenciamento de projetos, permitindo que os usuários criem e acompanhem projetos. - Atribuir tarefas aos membros da equipe, definir prazos e monitorar o progresso. - Alocar recursos e acompanhar os gastos do projeto. - Oferecer recursos de colaboração, como compartilhamento de documentos e comunicação em tempo real. ## Relatórios e Análises: - Gerar relatórios e análises abrangentes sobre vários aspectos do negócio. - Fornecer painéis personalizáveis para monitorar indicadores-chave de desempenho (KPIs). - Permitir que os usuários definam relatórios personalizados com base em requisitos específicos. - Implementar técnicas de visualização de dados para apresentar informações de maneira visualmente atraente. ## Integração e Personalização: - Permitir a integração com aplicativos de terceiros populares ou APIs, como ferramentas de marketing por e-mail ou plataformas de CRM. - Permitir a personalização da funcionalidade e aparência do aplicativo com base nas necessidades específicas do negócio. - Fornecer uma API ou webhooks para facilitar a troca de dados entre o aplicativo ERP & CRM e outros sistemas. ## Interface Amigável ao Usuário: - Projetar uma interface intuitiva, responsiva e amigável ao usuário usando React.js e Ant Design. - Implementar menus de navegação fáceis de usar, funcionalidades de pesquisa e filtros. - Garantir uma IU consistente e visualmente atraente em diferentes dispositivos e tamanhos de tela. ================================================ FILE: features/pt_pt_software_de_erp_crm_de_código_aberto_gratuito.md ================================================ # IDURAR Software ERP e CRM de código aberto GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Website: [https://www.idurarapp.com](https://www.idurarapp.com) ## Pilha de Software IDURAR é um aplicativo ERP e CRM de código aberto gratuito, baseado em "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Gestão de Usuários: - Permitir aos administradores criar, editar e excluir contas de usuário. - Implementar controle de acesso baseado em funções para gerenciar permissões de usuário. - Fornecer mecanismos de autenticação e autorização para garantir acesso seguro. ## Gestão de Relacionamento com o Cliente (CRM): - Permitir que os usuários criem e gerenciem registros de contatos para leads, prospects e clientes. - Implementar funcionalidades de geração e qualificação de leads para rastrear oportunidades de vendas potenciais. - Fornecer ferramentas para gerenciar o histórico de comunicação com o cliente, incluindo e-mails, ligações e reuniões. - Permitir que os usuários agendem compromissos e enviem notificações ou lembretes aos clientes. ## Gestão de Vendas: - Permitir que os usuários criem e gerenciem pedidos de venda, associando-os a clientes específicos. - Implementar rastreamento de estoque para verificar a disponibilidade do produto e atualizar os níveis de estoque após cada venda. - Gerar faturas e lidar com integração de pagamento com gateways de pagamento populares. - Fornecer painéis e relatórios para monitorar o desempenho de vendas e analisar tendências. ## Gestão de Compras: - Permitir que os usuários criem e gerenciem pedidos de compra, especificando a quantidade e os produtos desejados. - Rastrear informações do fornecedor e gerenciar relacionamentos com fornecedores. - Receber mercadorias e atualizar os níveis de estoque de acordo. - Lidar com faturas de compra e pagamentos a fornecedores. ## Gestão de Inventário: - Fornecer ferramentas para gerenciar e rastrear os níveis de estoque, incluindo transferências e ajustes de estoque. - Configurar notificações automáticas para níveis baixos de estoque e gerar pedidos de compra quando for necessário repor o estoque. - Oferecer recursos de leitura de código de barras para um gerenciamento eficiente de estoque. - Permitir que os usuários categorizem produtos, definam atributos e informações de preços. ## Gestão Financeira: - Implementar um sistema de contabilidade geral para rastrear transações financeiras, incluindo despesas e receitas. - Gerenciar contas a receber e contas a pagar, incluindo faturamento e rastreamento de pagamentos. - Gerar relatórios financeiros, incluindo balanços e demonstrações de resultados. - Integrar com software de contabilidade popular para uma gestão financeira perfeita. ## Gestão de Projetos: - Fornecer recursos de gestão de projetos, permitindo que os usuários criem e acompanhem projetos. - Atribuir tarefas aos membros da equipe, definir prazos e monitorar o progresso. - Alocar recursos e acompanhar despesas do projeto. - Oferecer recursos de colaboração, como compartilhamento de documentos e comunicação em tempo real. ## Relatórios e Análises: - Gerar relatórios abrangentes e análises sobre diversos aspectos do negócio. - Fornecer painéis personalizáveis para monitorar indicadores-chave de desempenho (KPIs). - Permitir que os usuários definam relatórios personalizados com base em requisitos específicos. - Implementar técnicas de visualização de dados para apresentar informações de maneira visualmente atraente. ## Integração e Personalização: - Permitir integração com aplicativos de terceiros populares ou APIs, como ferramentas de marketing por e-mail ou plataformas de CRM. - Permitir personalização da funcionalidade e aparência do aplicativo com base nas necessidades específicas do negócio. - Fornecer uma API ou webhooks para facilitar a troca de dados entre o aplicativo ERP e CRM e outros sistemas. ## Interface Amigável: - Projetar uma interface intuitiva, responsiva e amigável usando React.js e Ant Design. - Implementar menus de navegação fáceis de usar, funcionalidades de pesquisa e filtros. - Garantir uma interface consistente e visualmente atraente em diferentes dispositivos e tamanhos de tela. ================================================ FILE: features/ro_ro_software_erp_crm_open_source_gratuit.md ================================================ # IDURAR Software ERP și CRM Open-Source GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Website: [https://www.idurarapp.com](https://www.idurarapp.com) ## Stivă de software IDURAR este o aplicație ERP și CRM open-source gratuită, bazată pe "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Managementul utilizatorilor: - Permite administratorilor să creeze, editeze și șteargă conturi de utilizator. - Implementează controlul accesului bazat pe roluri pentru gestionarea permisiunilor utilizatorilor. - Furnizează mecanisme de autentificare și autorizare pentru a asigura un acces securizat. ## Managementul relațiilor cu clienții (CRM): - Permite utilizatorilor să creeze și să gestioneze înregistrări de contact pentru clienți potențiali și existenți. - Implementează funcționalități de generare și calificare a lead-urilor pentru a urmări oportunitățile potențiale de vânzări. - Furnizează instrumente pentru gestionarea istoricului de comunicare cu clienții, inclusiv e-mailuri, apeluri și întâlniri. - Permite utilizatorilor să programeze întâlniri și să trimită notificări sau mementouri clienților. ## Managementul vânzărilor: - Permite utilizatorilor să creeze și să gestioneze comenzi de vânzare, asociindu-le cu clienți specifici. - Implementează urmărirea inventarului pentru a verifica disponibilitatea produselor și a actualiza nivelurile de stoc după fiecare vânzare. - Generează facturi și gestionează integrarea plăților cu gateway-uri populare de plată. - Furnizează tablouri de bord și rapoarte pentru monitorizarea performanțelor de vânzări și analiza tendințelor. ## Managementul achizițiilor: - Permite utilizatorilor să creeze și să gestioneze comenzi de achiziții, specificând cantitatea și produsele dorite. - Urmărește informațiile furnizorului și gestionează relațiile cu furnizorii. - Primește bunuri și actualizează nivelurile de inventar în consecință. - Gestionează facturile de achiziții și plățile către furnizori. ## Managementul inventarului: - Furnizează instrumente pentru gestionarea și urmărirea nivelurilor de inventar, inclusiv transferuri de stoc și ajustări. - Configurează notificări automate pentru nivelurile scăzute de stoc și generează comenzi de achiziții atunci când este necesară reînnoirea stocului. - Oferă capacități de scanare a codurilor de bare pentru gestionarea eficientă a inventarului. - Permite utilizatorilor să clasifice produsele, să definească atribute și să seteze informații de preț. ## Managementul financiar: - Implementează un sistem de registrul general pentru urmărirea tranzacțiilor financiare, inclusiv cheltuieli și venituri. - Gestionează creanțele și datoriile, inclusiv facturare și urmărirea plăților. - Generează rapoarte financiare, inclusiv bilanțuri și state de venituri. - Integrează cu software-uri populare de contabilitate pentru gestionarea financiară fără probleme. ## Managementul proiectelor: - Furnizează capacități de gestionare a proiectelor, permițând utilizatorilor să creeze și să urmărească proiecte. - Alocă sarcini membrilor echipei, stabilește termene limită și monitorizează progresul. - Alocați resurse și urmăriți cheltuielile proiectului. - Oferă funcționalități de colaborare, cum ar fi partajarea de documente și comunicarea în timp real. ## Raportare și analiză: - Generează rapoarte cuprinzătoare și analize asupra diferitelor aspecte ale afacerii. - Furnizează tablouri de bord personalizabile pentru monitorizarea indicatorilor cheie de performanță (KPI). - Permite utilizatorilor să definească rapoarte personalizate în funcție de cerințe specifice. - Implementează tehnici de vizualizare a datelor pentru a prezenta informațiile într-un mod vizual atractiv. ## Integrare și personalizare: - Permite integrarea cu aplicații terțe populare sau API-uri, cum ar fi instrumentele de marketing prin e-mail sau platformele CRM. - Permite personalizarea funcționalității și aspectului aplicației în funcție de nevoile specifice ale afacerii. - Furnizează o API sau webhook-uri pentru a facilita schimbul de date între aplicația ERP și CRM și alte sisteme. ## Interfață prietenoasă pentru utilizator: - Proiectați o interfață intuitivă, receptivă și prietenoasă pentru utilizator folosind React.js și Ant Design. - Implementați meniuri de navigare ușor de utilizat, funcționalități de căutare și filtre. - Asigurați o interfață utilizator coerentă și vizual atractivă pe diferite dispozitive și dimensiuni de ecran. ================================================ FILE: features/ru_ru_бесплатное_открытое_программное_обеспечение_erp_crm.md ================================================ # IDURAR Открытое ERP и CRM программное обеспечение GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Демо: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Веб-сайт: [https://www.idurarapp.com](https://www.idurarapp.com) ## Стек программного обеспечения IDURAR Бесплатное открытое ERP и CRM приложение, основанное на "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Управление пользователями: - Позволяет администраторам создавать, редактировать и удалять учетные записи пользователей. - Реализует управление доступом на основе ролей для управления правами пользователей. - Обеспечивает аутентификацию и авторизацию для обеспечения безопасного доступа. ## Управление взаимоотношениями с клиентами (CRM): - Позволяет пользователям создавать и управлять контактными записями для потенциальных клиентов и клиентов. - Реализует функциональность генерации и квалификации лидов для отслеживания потенциальных продаж. - Предоставляет инструменты для управления историей коммуникации с клиентами, включая электронные письма, звонки и встречи. - Позволяет пользователям назначать встречи и отправлять уведомления или напоминания клиентам. ## Управление продажами: - Позволяет пользователям создавать и управлять заказами, связывая их с конкретными клиентами. - Реализует отслеживание запасов для проверки наличия продукции и обновления уровней запасов после каждой продажи. - Генерирует счета и обрабатывает интеграцию платежей с популярными платежными шлюзами. - Предоставляет панели управления и отчеты для мониторинга результативности продаж и анализа тенденций. ## Управление закупками: - Позволяет пользователям создавать и управлять заказами на закупку, указывая количество и необходимые продукты. - Отслеживает информацию о поставщиках и управляет взаимоотношениями с поставщиками. - Принимает товары и соответствующим образом обновляет уровни запасов. - Обрабатывает счета на закупку и платежи поставщикам. ## Управление запасами: - Предоставляет инструменты для управления и отслеживания уровней запасов, включая перемещение и корректировку запасов. - Настраивает автоматические уведомления о низком уровне запасов и генерирует заказы на закупку при необходимости пополнения запасов. - Предлагает возможности сканирования штрих-кодов для эффективного управления запасами. - Позволяет пользователям классифицировать продукты, определять атрибуты и устанавливать информацию о ценообразовании. ## Финансовое управление: - Реализует систему главной книги для отслеживания финансовых операций, включая расходы и доходы. - Управляет дебиторской и кредиторской задолженностью, включая выставление счетов и отслеживание платежей. - Генерирует финансовые отчеты, включая баланс и отчет о доходах. - Интегрируется с популярными программами бухгалтерии для беспроблемного финансового управления. ## Управление проектами: - Предоставляет возможности управления проектами, позволяя пользователям создавать и отслеживать проекты. - Назначает задачи участникам команды, устанавливает сроки и контролирует прогресс. - Распределяет ресурсы и отслеживает затраты на проект. - Предлагает функции совместной работы, такие как обмен документами и общение в режиме реального времени. ## Отчетность и аналитика: - Генерирует подробные отчеты и аналитику по различным аспектам бизнеса. - Предоставляет настраиваемые панели управления для отслеживания ключевых показателей эффективности (KPI). - Позволяет пользователям определять настраиваемые отчеты на основе конкретных требований. - Реализует техники визуализации данных для представления информации в привлекательном визуальном виде. ## Интеграция и настройка: - Обеспечивает интеграцию с популярными сторонними приложениями или API, такими как инструменты электронного маркетинга или платформы CRM. - Позволяет настраивать функциональность и внешний вид приложения на основе конкретных потребностей бизнеса. - Предоставляет API или вебхуки для облегчения обмена данными между ERP и CRM приложением и другими системами. ## Пользовательский интерфейс, удобный для использования: - Разрабатывает интуитивно понятный, отзывчивый и удобный для пользователя интерфейс с использованием React.js и Ant Design. - Реализует простые в использовании навигационные меню, функции поиска и фильтры. - Обеспечивает согласованный и привлекательный визуальный интерфейс на различных устройствах и размерах экрана. ================================================ FILE: features/sk_sk_zdarma_otvorene_zdrojove_erp_crm_software.md ================================================ # IDURAR Open-Source ERP & CRM Software GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Webová stránka: [https://www.idurarapp.com](https://www.idurarapp.com) ## Softvérový stack IDURAR Bezplatná open-source ERP & CRM aplikácia, založená na "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Správa používateľov: - Umožňuje administrátorom vytvárať, upravovať a mazať používateľské účty. - Implementuje riadenie prístupu založené na rolách na správu používateľských oprávnení. - Poskytuje autentifikačné a autorizačné mechanizmy pre zabezpečený prístup. ## Manažment vzťahov s klientmi (CRM): - Umožňuje používateľom vytvárať a spravovať kontaktné záznamy pre záujemcov, potenciálnych zákazníkov a zákazníkov. - Implementuje funkcie generovania a kvalifikácie záujmov na sledovanie potenciálnych predajných príležitostí. - Poskytuje nástroje na správu histórie komunikácie s klientmi, vrátane e-mailov, hovorov a stretnutí. - Umožňuje používateľom plánovať stretnutia a posielať oznámenia alebo pripomienky zákazníkom. ## Manažment predaja: - Umožňuje používateľom vytvárať a spravovať predajné objednávky a priradiť ich konkrétnym zákazníkom. - Implementuje sledovanie stavu skladu na kontrolu dostupnosti produktov a aktualizáciu úrovní skladu po každom predaji. - Generuje faktúry a zabezpečuje integráciu platobných brán populárnych platobných systémov. - Poskytuje prehľady a správy na monitorovanie výkonnosti predaja a analýzu trendov. ## Manažment nákupu: - Umožňuje používateľom vytvárať a spravovať nákupné objednávky s určením množstva a požadovaných produktov. - Sleduje informácie o dodávateľoch a spravuje vzťahy s dodávateľmi. - Prijíma tovar a aktualizuje úrovne skladu. - Spravuje nákupné faktúry a platby dodávateľom. ## Manažment skladu: - Poskytuje nástroje na správu a sledovanie úrovní skladu, vrátane presunov a úprav zásob. - Nastavuje automatické oznámenia o nízkych úrovniach skladu a generuje nákupné objednávky pri potrebe doplnenia zásob. - Ponúka možnosti skenovania čiarových kódov pre efektívne riadenie skladu. - Umožňuje používateľom kategorizovať produkty, definovať atribúty a stanoviť cenové informácie. ## Finančný manažment: - Implementuje systém vedenia hlavnej knihy na sledovanie finančných transakcií, vrátane výdavkov a príjmov. - Spravuje pohľadávky a záväzky vrátane vystavovania faktúr a sledovania platieb. - Generuje finančné správy, vrátane bilancií a výkazov ziskov a strát. - Integruje sa s populárnym účtovným softvérom pre bezproblémový finančný manažment. ## Manažment projektov: - Poskytuje schopnosti riadenia projektov, umožňujúc používateľom vytvárať a sledovať projekty. - Priradzuje úlohy členom tímu, stanovuje termíny a monitoruje pokrok. - Priraďuje zdroje a sleduje náklady na projekty. - Ponúka funkcie spolupráce, ako je zdieľanie dokumentov a komunikácia v reálnom čase. ## Výkazníctvo a analýza: - Generuje komplexné správy a analýzy rôznych aspektov podnikania. - Poskytuje možnosť prispôsobenia prehľadov na monitorovanie kľúčových ukazovateľov výkonnosti (KPI). - Umožňuje používateľom definovať vlastné správy na základe konkrétnych požiadaviek. - Implementuje techniky vizualizácie údajov pre prezentáciu informácií v atraktívnej vizuálnej forme. ## Integrácia a prispôsobenie: - Umožňuje integráciu s populárnymi aplikáciami alebo rozhraniami tretích strán, ako sú nástroje na e-mailový marketing alebo platformy CRM. - Umožňuje prispôsobenie funkcionality a vzhľadu aplikácie na základe konkrétnych podnikateľských potrieb. - Poskytuje API alebo webhooks na zjednodušenie výmeny údajov medzi ERP & CRM aplikáciou a inými systémami. ## Používateľsky prívetivé rozhranie: - Navrhnite intuitívne, responzívne a používateľsky prívetivé rozhranie pomocou React.js a Ant Design. - Implementuje jednoduché navigačné menu, vyhľadávacie funkcie a filtre. - Zabezpečuje konzistentné a vizuálne príťažlivé používateľské rozhranie na rôznych zariadeniach a veľkostiach obrazovky. ================================================ FILE: features/sl_si_brezplačni_odprtokodni_erp_crm_programski_oprema.md ================================================ # IDURAR Odprtokodna ERP in CRM programska oprema GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Spletna stran: [https://www.idurarapp.com](https://www.idurarapp.com) ## Sklad programske opreme IDURAR Brezplačna odprtokodna ERP in CRM aplikacija, zasnovana na "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Upravljanje uporabnikov: - Omogočanje administratorjem ustvarjanje, urejanje in brisanje uporabniških računov. - Uvedba upravljanja dostopa na podlagi vlog za upravljanje uporabniških dovoljenj. - Zagotavljanje mehanizmov za preverjanje pristnosti in pooblastil za zagotavljanje varnega dostopa. ## Upravljanje odnosov s strankami (CRM): - Omogočanje uporabnikom ustvarjanje in upravljanje stikov za potencialne stranke in stranke. - Uvedba funkcionalnosti za generiranje in kvalifikacijo potencialnih prodajnih priložnosti. - Zagotavljanje orodij za upravljanje zgodovine komunikacije s strankami, vključno z elektronsko pošto, klici in sestanki. - Omogočanje uporabnikom, da načrtujejo sestanke in pošiljajo obvestila ali opomnike strankam. ## Upravljanje prodaje: - Omogočanje uporabnikom ustvarjanje in upravljanje prodajnih naročil, povezovanje z določenimi strankami. - Uvedba sledenja zalogam za preverjanje razpoložljivosti izdelkov in posodabljanje stanja zalog po vsaki prodaji. - Generiranje računov in obvladovanje integracije plačil z priljubljenimi plačilnimi prehodi. - Zagotavljanje nadzornih plošč in poročil za spremljanje prodajne uspešnosti in analizo trendov. ## Upravljanje naročilnic: - Omogočanje uporabnikom ustvarjanje in upravljanje naročilnic, določanje količine in želenih izdelkov. - Sledenje informacijam o dobaviteljih in upravljanje odnosov z dobavitelji. - Prejemanje blaga in ustrezno posodabljanje stanja zalog. - Obvladovanje naročilnic in plačil dobaviteljem. ## Upravljanje zalog: - Zagotavljanje orodij za upravljanje in sledenje stanju zalog, vključno s prenosi in prilagoditvami zalog. - Nastavitev samodejnih obvestil o nizkih stanjih zalog in generiranje naročilnic, ko je potrebno dopolnjevanje zalog. - Ponujanje zmogljivosti skeniranja črtnih kod za učinkovito upravljanje zalog. - Omogočanje uporabnikom razvrščanje izdelkov, določanje atributov in nastavitev cenovnih informacij. ## Finančno upravljanje: - Uvedba sistema glavne knjige za sledenje finančnim transakcijam, vključno s stroški in prihodki. - Upravljanje terjatev in obveznosti, vključno z izdajanjem računov in sledenjem plačil. - Generiranje finančnih poročil, vključno z bilancami stanja in izkazi uspeha. - Integracija s priljubljeno računovodsko programsko opremo za nemoteno finančno upravljanje. ## Upravljanje projektov: - Zagotavljanje sposobnosti upravljanja projektov, ki omogoča uporabnikom ustvarjanje in sledenje projektom. - Dodeljevanje nalog članom ekipe, določanje rokov in spremljanje napredka. - Dodeljevanje virov in spremljanje stroškov projekta. - Ponujanje funkcij sodelovanja, kot je deljenje dokumentov in komunikacija v realnem času. ## Poročanje in analitika: - Generiranje celovitih poročil in analitike o različnih vidikih poslovanja. - Zagotavljanje prilagodljivih nadzornih plošč za spremljanje ključnih kazalnikov uspešnosti (KPI). - Omogočanje uporabnikom določanje prilagojenih poročil glede na posebne zahteve. - Uvedba tehnike vizualizacije podatkov za prikazovanje informacij na privlačen način. ## Integracija in prilagajanje: - Omogočanje integracije s priljubljenimi aplikacijami tretjih oseb ali vmesniki API, kot so orodja za e-poštni marketing ali platforme CRM. - Dovoljevanje prilagajanja funkcionalnosti in izgleda aplikacije glede na posebne poslovne potrebe. - Zagotavljanje API-ja ali spletnih kaveljčkov za olajšanje izmenjave podatkov med ERP in CRM aplikacijo ter drugimi sistemi. ## Uporabniku prijazen vmesnik: - Oblikovanje intuitivnega, odzivnega in uporabniku prijaznega vmesnika z uporabo React.js in Ant Design. - Uvedba enostavno uporabnih navigacijskih menijev, funkcionalnosti iskanja in filtrov. - Zagotavljanje doslednega in privlačnega uporabniškega vmesnika na različnih napravah in zaslonih. ================================================ FILE: features/sr_rs_besplatni_otvoreni_izvor_erp_crm_softver.md ================================================ # IDURAR Open-Source ERP & CRM Softver GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Veb sajt: [https://www.idurarapp.com](https://www.idurarapp.com) ## Softverski skup IDURAR Besplatan otvoreni ERP i CRM softver, baziran na "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Upravljanje korisnicima: - Dozvolite administratorima da kreiraju, uređuju i brišu korisničke naloge. - Implementirajte kontrolu pristupa zasnovanu na ulogama kako biste upravljali korisničkim dozvolama. - Pružite mehanizme za autentifikaciju i autorizaciju kako biste osigurali siguran pristup. ## Upravljanje odnosima sa klijentima (CRM): - Omogućite korisnicima da kreiraju i upravljaju kontaktima za potencijalne klijente i postojeće klijente. - Implementirajte funkcionalnosti generisanja i kvalifikacije potencijalnih prodajnih prilika. - Pružite alate za upravljanje istorijom komunikacije sa klijentima, uključujući e-poštu, pozive i sastanke. - Dozvolite korisnicima da zakazuju termine i šalju obaveštenja ili podsetnike klijentima. ## Upravljanje prodajom: - Dozvolite korisnicima da kreiraju i upravljaju prodajnim nalozima, povezujući ih sa određenim klijentima. - Implementirajte praćenje inventara radi provere dostupnosti proizvoda i ažuriranja nivoa zaliha nakon svake prodaje. - Generišite fakture i integrišite se sa popularnim platnim gateway-ima. - Pružite kontrolne table i izveštaje za praćenje prodajne performanse i analizu trendova. ## Upravljanje nabavkom: - Dozvolite korisnicima da kreiraju i upravljaju narudžbinama nabavke, specificirajući količinu i željene proizvode. - Pratite informacije o dobavljačima i upravljajte odnosima sa dobavljačima. - Primajte robu i ažurirajte nivoe zaliha prema tome. - Upravljajte fakturama nabavke i plaćanjima dobavljačima. ## Upravljanje zalihama: - Pružite alate za upravljanje i praćenje nivoa zaliha, uključujući prenos i prilagođavanje zaliha. - Postavite automatska obaveštenja za niske nivoe zaliha i generišite narudžbe nabavke kada je potrebno dopunjavanje zaliha. - Ponudite mogućnosti skeniranja barkoda za efikasno upravljanje zalihama. - Omogućite korisnicima da kategorizuju proizvode, definišu atribute i postave informacije o cenama. ## Finansijsko upravljanje: - Implementirajte sistem glavne knjige za praćenje finansijskih transakcija, uključujući troškove i prihode. - Upravljajte potraživanjima i obavezama, uključujući fakturisanje i praćenje plaćanja. - Generišite finansijske izveštaje, uključujući bilanse stanja i izveštaje o prihodima. - Integrišite se sa popularnim softverima za računovodstvo radi besprekornog finansijskog upravljanja. ## Upravljanje projektima: - Pružite mogućnosti upravljanja projektima, omogućavajući korisnicima da kreiraju i prate projekte. - Dodeljujte zadatke članovima tima, postavljajte rokove i pratite napredak. - Alocirajte resurse i pratite troškove projekta. - Ponudite funkcionalnosti saradnje, kao što su deljenje dokumenata i komunikacija u realnom vremenu. ## Izveštavanje i analitika: - Generišite sveobuhvatne izveštaje i analitiku o različitim aspektima poslovanja. - Pružite prilagodljive kontrolne table za praćenje ključnih pokazatelja performansi (KPI-jeva). - Dozvolite korisnicima da definišu prilagođene izveštaje na osnovu specifičnih zahteva. - Implementirajte tehnike vizualizacije podataka radi prikaza informacija na vizuelno privlačan način. ## Integracija i prilagođavanje: - Omogućite integraciju sa popularnim aplikacijama trećih strana ili API-jima, kao što su alati za e-poštu ili platforme za CRM. - Dozvolite prilagođavanje funkcionalnosti i izgleda aplikacije prema specifičnim poslovnim potrebama. - Pružite API ili webhooks kako biste olakšali razmenu podataka između ERP i CRM aplikacije i drugih sistema. ## Korisnički prijateljski interfejs: - Dizajnirajte intuitivan, responsivan i korisnički prijateljski interfejs koristeći React.js i Ant Design. - Implementirajte jednostavne navigacione menije, funkcionalnosti pretrage i filtere. - Osigurajte dosledan i vizuelno privlačan korisnički interfejs na različitim uređajima i veličinama ekrana. ================================================ FILE: features/sv_se_fri_öppen_källkods_erp_crm_programvara.md ================================================ # IDURAR Öppen källkod ERP & CRM-programvara GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Webbplats: [https://www.idurarapp.com](https://www.idurarapp.com) ## Programvarustack IDURAR Gratis öppen källkod erp & crm-app, baserad på "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Användarhantering: - Tillåt administratörer att skapa, redigera och ta bort användarkonton. - Implementera rollbaserad åtkomstkontroll för att hantera användarbehörigheter. - Tillhandahåll autentiserings- och auktoriseringsmekanismer för att säkerställa säker åtkomst. ## Kundrelationhantering (CRM): - Möjliggör för användare att skapa och hantera kontaktregister för leads, prospekteringar och kunder. - Implementera funktionalitet för leadgenerering och kvalificering för att följa potentiella försäljningsmöjligheter. - Tillhandahåll verktyg för att hantera kundkommunikationshistorik, inklusive e-post, samtal och möten. - Tillåt användare att schemalägga möten och skicka meddelanden eller påminnelser till kunder. ## Försäljningshantering: - Tillåt användare att skapa och hantera försäljningsorder och koppla dem till specifika kunder. - Implementera lagerövervakning för att kontrollera produkttillgänglighet och uppdatera lagerstatus efter varje försäljning. - Generera fakturor och hantera betalningsintegration med populära betalningsportaler. - Tillhandahåll instrumentpaneler och rapporter för att övervaka försäljningsprestanda och analysera trender. ## Inköpshantering: - Tillåt användare att skapa och hantera inköpsorder och ange antal och önskade produkter. - Spåra leverantörsinformation och hantera leverantörsrelationer. - Ta emot varor och uppdatera lagerstatus därefter. - Hantera inköpsfakturor och betalningar till leverantörer. ## Lagerhantering: - Tillhandahåll verktyg för att hantera och spåra lagerstatus, inklusive lageröverföringar och justeringar. - Ställ in automatiska aviseringar för låga lagerstatus och generera inköpsorder när påfyllning krävs. - Erbjud streckkodsläsarfunktioner för effektiv lagerhantering. - Möjliggör för användare att kategorisera produkter, definiera attribut och ange prisinformation. ## Ekonomihantering: - Implementera ett huvudbokssystem för att spåra ekonomiska transaktioner, inklusive utgifter och intäkter. - Hantera kundfordringar och leverantörsskulder, inklusive fakturering och betalningsuppföljning. - Generera ekonomiska rapporter, inklusive balansräkningar och resultaträkningar. - Integrera med populär redovisningsprogramvara för sömlös ekonomihantering. ## Projektledning: - Tillhandahåll projektledningsfunktioner som gör att användare kan skapa och följa projekt. - Tilldela uppgifter till teammedlemmar, ställ in deadlines och övervaka framsteg. - Tilldela resurser och följa projektutgifter. - Erbjud samarbetsfunktioner som dokumentdelning och kommunikation i realtid. ## Rapportering och analys: - Generera omfattande rapporter och analyser om olika aspekter av verksamheten. - Tillhandahåll anpassningsbara instrumentpaneler för att övervaka nyckeltal (KPI:er). - Tillåt användare att definiera anpassade rapporter utifrån specifika krav. - Implementera tekniker för datavisualisering för att presentera information på ett visuellt tilltalande sätt. ## Integration och anpassning: - Möjliggör integration med populära tredjepartsapplikationer eller API:er, som e-postmarknadsföringsverktyg eller CRM-plattformar. - Tillåt anpassning av appens funktionalitet och utseende baserat på specifika affärsbehov. - Tillhandahåll en API eller webhooks för att underlätta datautbyte mellan ERP- och CRM-appen och andra system. ## Användarvänligt gränssnitt: - Designa ett intuitivt, responsivt och användarvänligt gränssnitt med hjälp av React.js och Ant Design. - Implementera lättanvända navigeringsmenyer, sökfunktioner och filter. - Se till att gränssnittet är konsekvent och visuellt tilltalande på olika enheter och skärmstorlekar. ================================================ FILE: features/th_th_ฟรี_โปรแกรม_ตัวจัดการแหล่งข้อมูลโปรแกรม_ERP_CRM.md ================================================ # ซอฟต์แวร์ ERP & CRM โอเพ่นซอร์ส IDURAR GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) เว็บไซต์: [https://www.idurarapp.com](https://www.idurarapp.com) ## สแต็กซอฟต์แวร์ IDURAR เป็นแอปฟรีเปิดตัว ERP & CRM ซึ่งอ้างอิงจาก "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## การจัดการผู้ใช้ - อนุญาตให้ผู้ดูแลระบบสร้าง แก้ไข และลบบัญชีผู้ใช้ - ใช้การควบคุมการเข้าถึงบทบาทเพื่อจัดการสิทธิ์ผู้ใช้ - ให้กลไกการรับรองและอนุญาตเพื่อให้มั่นใจในการเข้าถึงที่ปลอดภัย ## การจัดการความสัมพันธ์กับลูกค้า (CRM) - อนุญาตให้ผู้ใช้สร้างและจัดการบันทึกการติดต่อสำหรับลีด ลูกค้าเป้าหมาย และลูกค้า - ดำเนินการสร้างลีดและฟังก์ชันการตรวจสอบคุณสมบัติเพื่อติดตามโอกาสการขายที่เป็นไปได้ - ให้เครื่องมือสำหรับการจัดการประวัติการสื่อสารกับลูกค้า รวมถึงอีเมล โทรศัพท์ และการประชุม - อนุญาตให้ผู้ใช้กำหนดวันนัดหมายและส่งการแจ้งเตือนหรือการเตือนลูกค้า ## การจัดการการขาย - อนุญาตให้ผู้ใช้สร้างและจัดการคำสั่งซื้อการขาย โดยผูกมันกับลูกค้าที่เฉพาะเจาะจง - ดำเนินการติดตามสินค้าในสต็อกเพื่อตรวจสอบสถานะความพร้อมของสินค้าและอัปเดตระดับสต็อกหลังจากทุกครั้งที่มีการขาย - สร้างใบแจ้งหนี้และจัดการการผสมรวมการชำระเงินกับเกตเวย์การชำระเงินที่นิยม - ให้แผงควบคุมและรายงานเพื่อตรวจสอบผลงานการขายและวิเคราะห์แนวโน้ม ## การจัดการการซื้อ - อนุญาตให้ผู้ใช้สร้างและจัดการใบสั่งซื้อการซื้อ โดยระบุปริมาณและผลิตภัณฑ์ที่ต้องการ - ติดตามข้อมูลผู้ผลิตและจัดการความสัมพันธ์กับผู้ผลิต - รับสินค้าและอัปเดตระดับสต็อกตามความเหมาะสม - จัดการใบแจ้งซื้อและการชำระเงินกับผู้ผลิต ## การจัดการสต็อก - ให้เครื่องมือสำหรับการจัดการและติดตามระดับสต็อก รวมถึงการโอนสต็อกและการปรับปรุง - ตั้งค่าการแจ้งเตือนอัตโนมัติสำหรับระดับสต็อกต่ำและสร้างใบสั่งซื้อเมื่อต้องการเติมสต็อก - ให้ความสามารถในการสแกนบาร์โค้ดเพื่อการจัดการสต็อกที่มีประสิทธิภาพ - อนุญาตให้ผู้ใช้จัดหมวดหมู่ผลิตภัณฑ์ กำหนดคุณสมบัติ และตั้งค่าข้อมูลราคา ## การจัดการทางการเงิน - ดำเนินการสร้างระบบบัญชีสมุดรายวันเพื่อติดตามธุรกรรมทางการเงิน รวมถึงรายรับและรายจ่าย - จัดการบัญชีลูกหนี้และบัญชีเจ้าหนี้ รวมถึงการออกใบแจ้งหนี้และการติดตามการชำระเงิน - สร้างรายงานทางการเงิน รวมถึงงบทดุลและงบกำไรขาดทุน - ผสานร่วมกับซอฟต์แวร์บัญชีที่นิยมเพื่อการจัดการทางการเงินอย่างราบรื่น ## การจัดการโครงการ - ให้ความสามารถในการจัดการโครงการ อนุญาตให้ผู้ใช้สร้างและติดตามโครงการ - กำหนดงานให้สมาชิกในทีม ตั้งกำหนดเวลา และติดตามความคืบหน้า - จัดสรรทรัพยากรและติดตามค่าใช้จ่ายในโครงการ - ให้คุณสมบัติการทำงานร่วมกัน เช่นการแบ่งปันเอกสารและการสื่อสารแบบเรียลไทม์ ## รายงานและการวิเคราะห์ - สร้างรายงานและการวิเคราะห์ที่ครอบคลุมทั้งหมดในด้านต่างๆ ของธุรกิจ - ให้แผงควบคุมที่กำหนดเองเพื่อตรวจสอบตัวชี้วัดประสิทธิภาพหลัก (KPI) - อนุญาตให้ผู้ใช้กำหนดรายงานที่กำหนดเองตามความต้องการเฉพาะ - ดำเนินการนำเสนอข้อมูลด้วยเทคนิคการแสดงผลที่น่าสนใจตามที่ต้องการ ## การรวมระบบและการปรับแต่ง - อนุญาตให้รวมระบบกับแอปพลิเคชันหรือ API ที่ได้รับความนิยม เช่นเครื่องมือการตลาดทางอีเมลหรือแพลตฟอร์ม CRM - อนุญาตให้ปรับแต่งความสามารถและลักษณะของแอปพลิเคชันตามความต้องการธุรกิจเฉพาะ - ให้ API หรือเว็บฮุกเพื่อสfacilitateการแลกเปลี่ยนข้อมูลระหว่างแอปพลิเคชัน ERP & CRM และระบบอื่นๆ ## อินเตอร์เฟซที่ใช้งานง่าย - ออกแบบอินเตอร์เฟซที่ใช้งานง่ายและตอบสนองต่อผู้ใช้โดยใช้ React.js และ Ant Design - ดำเนินการใช้งานเมนูการนำทาง ฟังก์ชันการค้นหา และตัวกรองที่ใช้งานง่าย - รับประกันการใช้งานอินเตอร์เฟซที่สอดคล้องและมีความสวยงามตรงกับอุปกรณ์และขนาดหน้าจอที่แตกต่างกัน ================================================ FILE: features/tr_tr_ücretsiz_açık_kaynak_erp_crm_yazılımı.md ================================================ # IDURAR Açık Kaynaklı ERP ve CRM Yazılımı GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Web sitesi: [https://www.idurarapp.com](https://www.idurarapp.com) ## Yazılım Yığını IDURAR Ücretsiz açık kaynaklı erp ve crm uygulaması, "mern-stack" üzerine kuruludur: Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Kullanıcı Yönetimi: - Yöneticilere kullanıcı hesapları oluşturma, düzenleme ve silme izni verir. - Kullanıcı izinlerini yönetmek için rol tabanlı erişim kontrolü uygular. - Güvenli erişimi sağlamak için kimlik doğrulama ve yetkilendirme mekanizmaları sağlar. ## Müşteri İlişkileri Yönetimi (CRM): - Kullanıcıların potansiyel satış fırsatlarını takip etmek için müşteri adayları ve müşteriler için iletişim kayıtları oluşturmasına ve yönetmesine olanak tanır. - Potansiyel satış fırsatlarını takip etmek ve değerlendirmek için lead jenerasyon ve nitelendirme işlevlerini uygular. - E-postalar, telefon görüşmeleri ve toplantılar da dahil olmak üzere müşteri iletişim geçmişini yönetmek için araçlar sağlar. - Kullanıcıların randevuları planlamasına ve müşterilere bildirim veya hatırlatıcı göndermesine izin verir. ## Satış Yönetimi: - Kullanıcıların belirli müşterilerle ilişkilendirerek satış siparişleri oluşturmasına ve yönetmesine izin verir. - Her satıştan sonra ürün mevcudiyetini kontrol etmek ve stok seviyelerini güncellemek için envanter takibi yapar. - Faturalar oluşturur ve popüler ödeme geçitleriyle ödeme entegrasyonunu yönetir. - Satış performansını izlemek ve trendleri analiz etmek için panolar ve raporlar sağlar. ## Satın Alma Yönetimi: - Kullanıcıların miktarı ve istenen ürünleri belirterek satın alma siparişleri oluşturmasına ve yönetmesine izin verir. - Tedarikçi bilgilerini takip eder ve tedarikçi ilişkilerini yönetir. - Malzemeleri teslim alır ve envanter seviyelerini buna göre günceller. - Satın alma faturalarını ve tedarikçilere yapılan ödemeleri yönetir. ## Stok Yönetimi: - Stok transferleri ve düzeltmeler de dahil olmak üzere stok seviyelerini yönetmek ve takip etmek için araçlar sağlar. - Düşük stok seviyeleri için otomatik bildirimler sağlar ve yeniden stoklama gerektiğinde satın alma siparişleri oluşturur. - Verimli stok yönetimi için barkod tarama yetenekleri sunar. - Kullanıcılara ürünleri kategorize etme, öznitelikleri tanımlama ve fiyatlandırma bilgilerini belirleme imkanı sunar. ## Finansal Yönetim: - Giderler ve gelirler de dahil olmak üzere finansal işlemleri takip etmek için genel muhasebe sistemi uygular. - Tahsilat ve ödeme takibi de dahil olmak üzere alacak ve borç hesaplarını yönetir. - Bilanço ve gelir tablosu da dahil olmak üzere finansal raporlar oluşturur. - Sorunsuz finansal yönetim için popüler muhasebe yazılımlarıyla entegrasyon sağlar. ## Proje Yönetimi: - Kullanıcılara projeler oluşturma ve takip etme yeteneği sağlar. - Görevleri takım üyelerine atar, son teslim tarihlerini belirler ve ilerlemeyi izler. - Kaynakları tahsis eder ve proje giderlerini takip eder. - Belge paylaşımı ve anlık iletişim gibi işbirliği özellikleri sunar. ## Raporlama ve Analitik: - İşletmenin çeşitli yönleriyle ilgili kapsamlı raporlar ve analitikler oluşturur. - Anahtar performans göstergelerini (KPI'lar) izlemek için özelleştirilebilir panolar sağlar. - Kullanıcıların belirli gereksinimlere dayalı özel raporlar tanımlamasına izin verir. - Bilgileri görsel olarak çekici bir şekilde sunmak için veri görselleştirme tekniklerini uygular. ## Entegrasyon ve Özelleştirme: - E-posta pazarlama araçları veya CRM platformları gibi popüler üçüncü taraf uygulamalar veya API'larla entegrasyonu sağlar. - Uygulamanın işlevselliğini ve görünümünü belirli iş gereksinimlerine göre özelleştirmeye izin verir. - ERP ve CRM uygulaması ile diğer sistemler arasında veri alışverişini kolaylaştırmak için bir API veya webhooks sağlar. ## Kullanıcı Dostu Arayüz: - React.js ve Ant Design kullanarak sezgisel, duyarlı ve kullanıcı dostu bir arayüz tasarlar. - Kolay kullanımlı gezinme menüleri, arama işlevleri ve filtreler uygular. - Farklı cihazlar ve ekran boyutları arasında tutarlı ve görsel olarak çekici bir kullanıcı arayüzü sağlar. ================================================ FILE: features/uk_ua_безкоштовне_відкрите_джерело_erp_crm_програмне_забезпечення.md ================================================ # IDURAR Відкритий ERP та CRM-софт GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Демо: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Веб-сайт: [https://www.idurarapp.com](https://www.idurarapp.com) ## Стек програмного забезпечення IDURAR Безкоштовний відкритий ERP та CRM-додаток, заснований на "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Управління користувачами: - Дозволяє адміністраторам створювати, редагувати та видаляти облікові записи користувачів. - Реалізувати контроль доступу на основі ролей для управління дозволами користувачів. - Забезпечити механізми аутентифікації та авторизації для забезпечення безпечного доступу. ## Управління взаємовідносинами з клієнтами (CRM): - Дозволяє користувачам створювати та управляти контактними записами для потенційних клієнтів та клієнтів. - Реалізувати функціонал залучення та кваліфікації лідів для відстеження потенційних продажних можливостей. - Надати інструменти для управління історією комунікації з клієнтами, включаючи електронну пошту, дзвінки та зустрічі. - Дозволяє користувачам планувати зустрічі та надсилати сповіщення або нагадування клієнтам. ## Управління продажами: - Дозволяє користувачам створювати та управляти замовленнями на продаж, пов'язуючи їх з конкретними клієнтами. - Реалізувати відстеження запасів для перевірки наявності продуктів та оновлення рівня запасів після кожної продажу. - Генерувати рахунки та обробляти інтеграцію платежів з популярними платіжними шлюзами. - Надати панелі управління та звіти для контролю продажів та аналізу тенденцій. ## Управління закупівлями: - Дозволяє користувачам створювати та управляти замовленнями на закупівлю, вказуючи кількість та бажані товари. - Відстежувати інформацію про постачальників та управляти взаєминами з постачальниками. - Отримувати товари та оновлювати рівні запасів відповідно. - Обробляти покупку рахунків та платежі постачальникам. ## Управління запасами: - Надати інструменти для управління та відстеження рівнів запасів, включаючи переміщення та коригування запасів. - Налаштувати автоматичні сповіщення про низькі рівні запасів та генерувати замовлення на закупівлю при необхідності поповнення запасів. - Надати можливості сканування штрих-кодів для ефективного управління запасами. - Дозволити користувачам категоризувати продукти, визначати атрибути та встановлювати інформацію про ціни. ## Фінансове управління: - Реалізувати систему головної книги для відстеження фінансових транзакцій, включаючи витрати та доходи. - Управляти дебіторською та кредиторською заборгованістю, включаючи виставлення рахунків та відстеження платежів. - Генерувати фінансові звіти, включаючи баланси та звіти про прибутки. - Інтегрувати з популярними бухгалтерськими програмами для безпроблемного фінансового управління. ## Управління проектами: - Надати можливості управління проектами, що дозволяють користувачам створювати та відстежувати проекти. - Призначати завдання членам команди, встановлювати терміни виконання та контролювати прогрес. - Розподіляти ресурси та відстежувати витрати на проект. - Надавати можливості співпраці, такі як спільний доступ до документів та комунікація в реальному часі. ## Звітність та аналітика: - Генерувати комплексні звіти та аналітику з різних аспектів бізнесу. - Надавати настроювані панелі управління для контролю ключових показників ефективності (KPI). - Дозволяти користувачам визначати власні звіти на основі конкретних вимог. - Реалізувати техніки візуалізації даних для представлення інформації в привабливій візуальній формі. ## Інтеграція та настроювання: - Забезпечити можливість інтеграції з популярними сторонніми додатками або API, такими як інструменти електронного маркетингу поштою або платформи CRM. - Дозволити настроювання функціональності та зовнішнього вигляду додатка на основі конкретних потреб бізнесу. - Надати API або вебхуки для сприяння обміну даними між ERP та CRM-додатком та іншими системами. ## Інтерфейс, зручний для користувачів: - Розробка інтуїтивно зрозумілого, адаптивного та зручного для користувачів інтерфейсу з використанням React.js та Ant Design. - Реалізація простого використання навігаційних меню, функцій пошуку та фільтрів. - Забезпечення однорідного та привабливого візуального інтерфейсу на різних пристроях та розмірах екрану. ================================================ FILE: features/ur_pk_مفت_کھولیں_سورس_erp_crm_سافٹ ویئر.md ================================================ # IDURAR اوپن سورس ERP & CRM سافٹ ویئر GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) ڈیمو: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) ویب سائٹ: [https://www.idurarapp.com](https://www.idurarapp.com) ## سافٹ ویئر اسٹیک IDURAR مفت اوپن سورس erp & crm ایپ، "mern-stack" پر مبنی ہے: Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## صارف کا نظم و ضبط: - ایڈمنسٹریٹرز کو صارف اکاؤنٹس تشکیل، ترمیم اور حذف کرنے کی اجازت دیں۔ - صارف کی اجازت کو مدیریت کرنے کے لئے کردار پر مبنی رسائی کنٹرول پیش کریں۔ - محفوظ رسائی کی یقینیت کے لئے تصدیق اور اجازت کے آلات فراہم کریں۔ ## گاہک تعلقات کی مدیریت (CRM): - صارفوں کو لیڈز، پروسپیکٹس اور گاہکوں کے لئے رابطہ ریکارڈ تشکیل اور مدیریت کرنے کی اجازت دیں۔ - فروختی مواقع کی پیشگوئی اور تصدیق کی کی قابلیتیں پیش کریں۔ - گاہک کے ساتھ رابطے کی تاریخ کو مدیریت کرنے کے لئے آلات فراہم کریں، جس میں ای میلز، کالز اور میٹنگز شامل ہوں۔ - صارفوں کو ملاقاتوں کا شیڈول بنانے اور گاہکوں کو نوٹیفکیشن یا یاد دلانے کی اجازت دیں۔ ## فروخت کی مدیریت: - صارفوں کو فروخت کی آرڈرز تشکیل اور مدیریت کرنے کی اجازت دیں، انہیں خاص گاہکوں سے منسلک کریں۔ - موجودہ میں مصنوعات کی دستیابیت کی جانچ پڑتال اور ہر فروخت کے بعد اسٹاک کی سطحوں کو اپ ڈیٹ کریں۔ - انوائسز بنائیں اور مقبول ادائیگی گیٹ وے کے ساتھ ادائیگی تعامل کو سنبھالیں۔ - فروخت کی کارکردگی کا نظارہ کرنے اور روایاتی خلاصوں کا تجزیہ کرنے کے لئے ڈیش بورڈز اور رپورٹس فراہم کریں۔ ## خریداری کی مدیریت: - صارفوں کو خریداری کی آرڈرز تشکیل اور مدیریت کرنے کی اجازت دیں، مقدار اور مطلوبہ مصنوعات کی وضاحت کریں۔ - سپلائر کی معلومات کی پیچیدگی کو ٹریک کریں اور سپلائر تعلقات کا نظم و ضبط کریں۔ - سامان کو وصول کریں اور اسٹاک کی سطحوں کو مطابقت کے ساتھ اپ ڈیٹ کریں۔ - خریداری کی انوائسز اور سپلائرز کو ادائیگی کا سنبھالنا کریں۔ ## انوائنٹری مینجمنٹ: - انوائنٹری کی سطحوں کو مینجمنٹ اور ٹریک کرنے کے لئے آلات فراہم کریں، جن میں اسٹاک ٹرانسفر اور ایڈجسٹمنٹ شامل ہوں۔ - کم اسٹاک کی اطلاعات کے لئے خودکار نوٹیفکیشنز کی تشکیل کریں اور جب بھی اسٹاک کی دوبارہ تعمیر کی ضرورت ہو تو خریداری کے آرڈرز بنائیں۔ - کارآمد انوائسٹری مینجمنٹ کے لئے بارکوڈ اسکیننگ کی صلاحیت فراہم کریں۔ - صارفوں کو مصنوعات کا زمرہ بنانے، خصوصیات تعریف کرنے اور قیمتی معلومات تعین کرنے کی اجازت دیں۔ ## مالی مینجمنٹ: - مالی لیجر سسٹم کو مدیریت کریں تاکہ مالی لین دین کے لئے معاملات کی ٹریکنگ ہو سکے، شامل ہیں اخراجات اور آمدنی۔ - وصولی اور ادائیگیوں کی مدیریت کریں، ان میں انوائسنگ اور ادائیگی کی ٹریکنگ شامل ہوں۔ - مالی رپورٹس تیار کریں، شامل ہیں بیلنس شیٹس اور انکم اسٹیٹمنٹس۔ - مقبول مالی مینجمنٹ کے لئے مشہور اکاؤنٹنگ سافٹ ویئر کے ساتھ انٹیگریشنٹ کریں۔ ## پروجیکٹ مینجمنٹ: - پروجیکٹ مینجمنٹ کی صلاحیتیں فراہم کریں، صارفوں کو پروجیکٹس تشکیل اور ٹریک کرنے کی اجازت دیں۔ - ٹیم کے رکنوں کو ٹاسکس کا تفویض کریں، مہلکے تعین کریں اور پیش رفت کا نظارہ کریں۔ - وسائل کو تقسیم کریں اور پروجیکٹ خرچ کی ٹریکنگ کریں۔ - دستاویزات کی شیئرنگ اور ریل ٹائم کمیونیکیشن جیسی تعاونی خصوصیات فراہم کریں۔ ## رپورٹنگ اور تجزیہ: - کاروبار کے مختلف پہلوؤں پر مکمل رپورٹس اور تجزیہ تیار کریں۔ - کلیدی کارکردگی اشاریوں (KPIs) کا نظارت کرنے کے لئے تخصیص پذیر ڈیش بورڈز فراہم کریں۔ - صارفوں کو مخصوص ضروریات پر مبنی کسٹم رپورٹس کی تعریف کرنے کی اجازت دیں۔ - معلومات کو خوبصورتی سے پیش کرنے کے لئے ڈیٹا وزیوالائزیشن تکنیکس کو پیش کریں۔ ## انٹیگریشن اور کسٹمائزیشن: - مقبول تیسری طرف کے اہم اہم ایپلیکیشنز یا APIز کے ساتھ انٹیگریشن فراہم کریں، مثلاً ای میل مارکیٹنگ ٹولز یا CRM پلیٹ فارمز۔ - تفویض کی تشکیل اور دکان کی ظاہریت کو مخصوص کاروباری ضروریات پر مبنی کسٹمائزیشن کی اجازت دیں۔ - ERP & CRM ایپ اور دیگر سسٹمز کے درمیان ڈیٹا تبادلے کو آسان بنانے کے لئے ای پی آئی یا ویب ہکس فراہم کریں۔ ## صارف دوستانہ انٹرفیس: - React.js اور Ant Design کا استعمال کرتے ہوئے سمجھدار، ریسپانسیو اور صارف دوستانہ انٹرفیس ڈیزائن کریں۔ - استعمال میں آسان نیویگیشن مینوز، تلاش کی صلاحیتیں اور فلٹرز کو پیش کریں۔ - مختلف آلات اور اسکرین سائزز پر مستقل اور خوبصورت یو آئی یو کی یقینیت فراہم کریں۔ ================================================ FILE: features/vi_vn_chương_trình_quản_lý_doanh_nghiệp_crm_nguồn_mở_miễn_phí.md ================================================ # IDURAR Phần mềm ERP & CRM mã nguồn mở GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) Demo: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) Trang web: [https://www.idurarapp.com](https://www.idurarapp.com) ## Cấu trúc phần mềm IDURAR là ứng dụng ERP & CRM mã nguồn mở miễn phí, dựa trên "mern-stack": Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## Quản lý người dùng: - Cho phép quản trị viên tạo, chỉnh sửa và xóa tài khoản người dùng. - Thực hiện kiểm soát quyền truy cập dựa trên vai trò để quản lý quyền hạn của người dùng. - Cung cấp cơ chế xác thực và ủy quyền để đảm bảo quyền truy cập an toàn. ## Quản lý mối quan hệ khách hàng (CRM): - Cho phép người dùng tạo và quản lý thông tin liên hệ cho khách hàng tiềm năng và khách hàng. - Thực hiện chức năng tạo và xác định tiềm năng bán hàng để theo dõi cơ hội bán hàng tiềm năng. - Cung cấp công cụ quản lý lịch sử giao tiếp với khách hàng, bao gồm email, cuộc gọi và cuộc họp. - Cho phép người dùng lên lịch hẹn và gửi thông báo hoặc nhắc nhở cho khách hàng. ## Quản lý bán hàng: - Cho phép người dùng tạo và quản lý đơn hàng bán hàng, liên kết chúng với khách hàng cụ thể. - Thực hiện theo dõi hàng tồn kho để kiểm tra tình trạng hàng hóa và cập nhật mức tồn sau mỗi giao dịch bán hàng. - Tạo hóa đơn và xử lý tích hợp thanh toán với các cổng thanh toán phổ biến. - Cung cấp bảng điều khiển và báo cáo để theo dõi hiệu suất bán hàng và phân tích xu hướng. ## Quản lý mua hàng: - Cho phép người dùng tạo và quản lý đơn đặt hàng, xác định số lượng và sản phẩm mong muốn. - Theo dõi thông tin nhà cung cấp và quản lý mối quan hệ với nhà cung cấp. - Nhận hàng và cập nhật mức tồn kho tương ứng. - Xử lý hóa đơn mua hàng và thanh toán cho nhà cung cấp. ## Quản lý hàng tồn kho: - Cung cấp công cụ để quản lý và theo dõi mức tồn kho, bao gồm chuyển kho và điều chỉnh. - Thiết lập thông báo tự động cho mức tồn kho thấp và tạo đơn đặt hàng khi cần phải nhập kho. - Cung cấp khả năng quét mã vạch để quản lý hàng tồn kho hiệu quả. - Cho phép người dùng phân loại sản phẩm, xác định thuộc tính và thiết lập thông tin giá cả. ## Quản lý tài chính: - Thực hiện hệ thống sổ cái chung để theo dõi giao dịch tài chính, bao gồm chi phí và doanh thu. - Quản lý công nợ và công nợ phải trả, bao gồm lập hóa đơn và theo dõi thanh toán. - Tạo báo cáo tài chính, bao gồm bảng cân đối kế toán và báo cáo thu nhập. - Tích hợp với phần mềm kế toán phổ biến để quản lý tài chính một cách liền mạch. ## Quản lý dự án: - Cung cấp khả năng quản lý dự án, cho phép người dùng tạo và theo dõi dự án. - Giao nhiệm vụ cho thành viên nhóm, đặt hạn chế và theo dõi tiến độ. - Phân bổ tài nguyên và theo dõi chi phí dự án. - Cung cấp tính năng hợp tác như chia sẻ tài liệu và giao tiếp thời gian thực. ## Báo cáo và phân tích: - Tạo báo cáo và phân tích chi tiết về các khía cạnh khác nhau của doanh nghiệp. - Cung cấp bảng điều khiển tùy chỉnh để theo dõi các chỉ số hiệu suất chính (KPI). - Cho phép người dùng xác định báo cáo tùy chỉnh dựa trên yêu cầu cụ thể. - Thực hiện các kỹ thuật trực quan hóa dữ liệu để trình bày thông tin một cách hấp dẫn mắt. ## Tích hợp và tùy chỉnh: - Cho phép tích hợp với các ứng dụng hoặc API của bên thứ ba phổ biến, chẳng hạn như các công cụ email marketing hoặc nền tảng CRM. - Cho phép tùy chỉnh chức năng và giao diện ứng dụng dựa trên nhu cầu kinh doanh cụ thể. - Cung cấp API hoặc webhooks để tạo điều kiện trao đổi dữ liệu giữa ứng dụng ERP & CRM và các hệ thống khác. ## Giao diện thân thiện với người dùng: - Thiết kế giao diện trực quan, đáp ứng và thân thiện với người dùng bằng cách sử dụng React.js và Ant Design. - Thực hiện các menu điều hướng, chức năng tìm kiếm và bộ lọc dễ sử dụng. - Đảm bảo giao diện người dùng nhất quán và hấp dẫn trực quan trên các thiết bị và kích thước màn hình khác nhau. ================================================ FILE: features/zh_cn_免费开源ERP CRM软件.md ================================================ # IDURAR 开源 ERP & CRM 软件 GitHub: [https://github.com/idurar/idurar-erp-crm](https://github.com/idurar/idurar-erp-crm) 演示: [https://www.idurarapp.com/open-source-erp-crm/](https://www.idurarapp.com/open-source-erp-crm/) 网站: [https://www.idurarapp.com](https://www.idurarapp.com) ## 软件堆栈 IDURAR 免费开源的 ERP & CRM 应用,基于 "mern-stack":Node.js React.js Redux Express.js MongoDB AntDesign (AntD) ## 用户管理: - 允许管理员创建、编辑和删除用户账户。 - 实现基于角色的访问控制,管理用户权限。 - 提供身份验证和授权机制,确保安全访问。 ## 客户关系管理 (CRM): - 允许用户创建和管理潜在客户、预期客户和现有客户的联系记录。 - 实现潜在销售机会的生成和资格认定功能,以跟踪潜在销售机会。 - 提供工具来管理客户沟通历史,包括电子邮件、电话和会议。 - 允许用户安排约会并向客户发送通知或提醒。 ## 销售管理: - 允许用户创建和管理销售订单,并将其与特定客户关联。 - 实现库存跟踪,检查产品可用性,并在每次销售后更新库存水平。 - 生成发票,并与流行的支付网关集成处理付款。 - 提供仪表板和报告,监控销售业绩并分析趋势。 ## 采购管理: - 允许用户创建和管理采购订单,指定数量和所需产品。 - 跟踪供应商信息并管理供应商关系。 - 接收货物并相应地更新库存水平。 - 处理采购发票和向供应商付款。 ## 库存管理: - 提供工具来管理和跟踪库存水平,包括库存转移和调整。 - 设置低库存水平的自动通知,并在需要重新进货时生成采购订单。 - 提供条形码扫描功能,实现高效的库存管理。 - 允许用户对产品进行分类、定义属性和设置定价信息。 ## 财务管理: - 实现总账系统,跟踪财务交易,包括支出和收入。 - 管理应收账款和应付账款,包括发票和付款跟踪。 - 生成财务报表,包括资产负债表和利润表。 - 与流行的会计软件集成,实现无缝的财务管理。 ## 项目管理: - 提供项目管理功能,允许用户创建和跟踪项目。 - 分配任务给团队成员,设置截止日期并监控进度。 - 分配资源并跟踪项目费用。 - 提供文档共享和实时通信等协作功能。 ## 报告和分析: - 生成全面的业务报告和分析。 - 提供可自定义的仪表板,监控关键绩效指标 (KPIs)。 - 允许用户根据特定需求定义自定义报告。 - 实施数据可视化技术,以视觉上吸引人的方式呈现信息。 ## 集成和定制: - 支持与流行的第三方应用程序或 API 的集成,例如电子邮件营销工具或 CRM 平台。 - 允许根据特定业务需求定制应用程序的功能和外观。 - 提供 API 或 Webhooks,促进 ERP & CRM 应用程序与其他系统之间的数据交换。 ## 用户友好界面: - 使用 React.js 和 Ant Design 设计直观、响应式和用户友好的界面。 - 实现易于使用的导航菜单、搜索功能和筛选器。 - 确保在不同设备和屏幕尺寸上具有一致且视觉上吸引人的用户界面。 ================================================ FILE: frontend/.eslintrc.js ================================================ module.exports = { root: true, env: { browser: true, es2020: true }, extends: [ 'eslint:recommended', 'plugin:react/recommended', 'plugin:react/jsx-runtime', 'plugin:react-hooks/recommended', ], ignorePatterns: ['dist', '.eslintrc.cjs'], parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, settings: { react: { version: '18.2' } }, plugins: ['react-refresh'], rules: { 'react-refresh/only-export-components': ['warn', { allowConstantExport: true }], 'react/prop-types': 0, }, }; ================================================ FILE: frontend/.gitignore ================================================ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # dependencies /node_modules /.pnp .pnp.js # testing /coverage # production /dist # misc .DS_Store .env.local .env.development.local .env.test.local .env.production.local npm-debug.log* yarn-debug.log* yarn-error.log* ================================================ FILE: frontend/.prettierignore ================================================ # Ignore artifacts: build coverage node_modules public ================================================ FILE: frontend/.prettierrc ================================================ { "printWidth": 100, "trailingComma": "es5", "tabWidth": 2, "semi": true, "singleQuote": true } ================================================ FILE: frontend/.vscode/settings.json ================================================ { "editor.formatOnPaste": true, "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode", "[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, "[jsonc]": { "editor.defaultFormatter": "esbenp.prettier-vscode" }, "[markdown]": { "editor.quickSuggestions": { "comments": "on", "strings": "on", "other": "on" } } } ================================================ FILE: frontend/README.md ================================================ This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). ## Available Scripts In the project directory, you can run: ### `yarn start` Runs the app in the development mode.
Open [http://localhost:3000](http://localhost:3000) to view it in the browser. The page will reload if you make edits.
You will also see any lint errors in the console. ### `yarn test` Launches the test runner in the interactive watch mode.
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. ### `yarn build` Builds the app for production to the `build` folder.
It correctly bundles React in production mode and optimizes the build for the best performance. The build is minified and the filenames include the hashes.
Your app is ready to be deployed! See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. ### `yarn eject` **Note: this is a one-way operation. Once you `eject`, you can’t go back!** If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. ## Learn More You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). To learn React, check out the [React documentation](https://reactjs.org/). ### Code Splitting This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting ### Analyzing the Bundle Size This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size ### Making a Progressive Web App This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app ### Advanced Configuration This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration ### Deployment This section has moved here: https://facebook.github.io/create-react-app/docs/deployment ### `yarn build` fails to minify This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify ================================================ FILE: frontend/index.html ================================================ IDURAR ERP CRM | Free Open Source Accounting Invoice Quote
================================================ FILE: frontend/jsconfig.json ================================================ { "compilerOptions": { "baseUrl": "src", "paths": { "@/*": ["./*"] } }, "exclude": ["node_modules", "dist"] } ================================================ FILE: frontend/package.json ================================================ { "name": "idurar-erp-crm", "version": "4.1.0", "engines": { "node": "20.9.0", "npm": "10.2.4" }, "type": "module", "dependencies": { "@ant-design/icons": "^5.3.0", "@ant-design/pro-layout": "^7.17.19", "@reduxjs/toolkit": "^2.2.1", "@vitejs/plugin-react": "^4.3.1", "antd": "^5.14.1", "axios": "^1.6.2", "cross-env": "7.0.3", "currency.js": "2.0.4", "dayjs": "^1.11.10", "just-compare": "^2.3.0", "react": "^18.3.1", "react-dom": "^18.2.0", "react-quill": "^2.0.0", "react-redux": "^9.1.0", "react-router-dom": "^6.22.0", "redux": "^5.0.1", "reselect": "^5.1.0", "shortid": "^2.2.16", "vite": "^5.4.8" }, "scripts": { "dev": "vite", "build": "vite build", "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", "preview": "vite preview", "dev:remote": "cross-env VITE_DEV_REMOTE=remote npm run dev" }, "devDependencies": { "@types/react": "^18.2.38", "@types/react-dom": "^18.2.17", "eslint": "^8.56.0", "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.4", "prettier": "3.1.0" } } ================================================ FILE: frontend/public/robots.txt ================================================ ================================================ FILE: frontend/rollup.config.js ================================================ import dynamicImportVars from '@rollup/plugin-dynamic-import-vars'; // function importModule(path) { // // who knows what will be imported here? // return import(path); // } export default { plugins: [ dynamicImportVars({ // options }), ], }; ================================================ FILE: frontend/src/RootApp.jsx ================================================ import './style/app.css'; import { Suspense, lazy } from 'react'; import { BrowserRouter } from 'react-router-dom'; import { Provider } from 'react-redux'; import store from '@/redux/store'; import PageLoader from '@/components/PageLoader'; const IdurarOs = lazy(() => import('./apps/IdurarOs')); export default function RoutApp() { return ( }> ); } ================================================ FILE: frontend/src/apps/ErpApp.jsx ================================================ import { useLayoutEffect } from 'react'; import { useEffect } from 'react'; import { selectAppSettings } from '@/redux/settings/selectors'; import { useDispatch, useSelector } from 'react-redux'; import { Layout } from 'antd'; import { useAppContext } from '@/context/appContext'; import Navigation from '@/apps/Navigation/NavigationContainer'; import HeaderContent from '@/apps/Header/HeaderContainer'; import PageLoader from '@/components/PageLoader'; import { settingsAction } from '@/redux/settings/actions'; import { selectSettings } from '@/redux/settings/selectors'; import AppRouter from '@/router/AppRouter'; import useResponsive from '@/hooks/useResponsive'; import storePersist from '@/redux/storePersist'; export default function ErpCrmApp() { const { Content } = Layout; // const { state: stateApp, appContextAction } = useAppContext(); // // const { app } = appContextAction; // const { isNavMenuClose, currentApp } = stateApp; const { isMobile } = useResponsive(); const dispatch = useDispatch(); useLayoutEffect(() => { dispatch(settingsAction.list({ entity: 'setting' })); }, []); // const appSettings = useSelector(selectAppSettings); const { isSuccess: settingIsloaded } = useSelector(selectSettings); // useEffect(() => { // const { loadDefaultLang } = storePersist.get('firstVisit'); // if (appSettings.idurar_app_language && !loadDefaultLang) { // window.localStorage.setItem('firstVisit', JSON.stringify({ loadDefaultLang: true })); // } // }, [appSettings]); if (settingIsloaded) return ( {isMobile ? ( ) : ( )} ); else return ; } ================================================ FILE: frontend/src/apps/Header/HeaderContainer.jsx ================================================ import { useSelector } from 'react-redux'; import { Link, useNavigate } from 'react-router-dom'; import { Avatar, Dropdown, Layout, Badge, Button } from 'antd'; // import Notifications from '@/components/Notification'; import { LogoutOutlined, ToolOutlined, UserOutlined } from '@ant-design/icons'; import { selectCurrentAdmin } from '@/redux/auth/selectors'; import { FILE_BASE_URL } from '@/config/serverApiConfig'; import useLanguage from '@/locale/useLanguage'; import UpgradeButton from './UpgradeButton'; export default function HeaderContent() { const currentAdmin = useSelector(selectCurrentAdmin); const { Header } = Layout; const translate = useLanguage(); const ProfileDropdown = () => { const navigate = useNavigate(); return (
navigate('/profile')}> {currentAdmin?.name?.charAt(0)?.toUpperCase()}

{currentAdmin?.name} {currentAdmin?.surname}

{currentAdmin?.email}

); }; const DropdownMenu = ({ text }) => { return {text}; }; const items = [ { label: , key: 'ProfileDropdown', }, { type: 'divider', }, { icon: , key: 'settingProfile', label: ( ), }, { icon: , key: 'settingApp', label: {translate('app_settings')}, }, { type: 'divider', }, { icon: , key: 'logout', label: {translate('logout')}, }, ]; return (
{/* */} {currentAdmin?.name?.charAt(0)?.toUpperCase()} {/* */} {/* */}
); } // console.log( // '🚀 Welcome to IDURAR ERP CRM! Did you know that we also offer commercial customization services? Contact us at hello@idurarapp.com for more information.' // ); ================================================ FILE: frontend/src/apps/Header/UpgradeButton.jsx ================================================ import { Avatar, Popover, Button, Badge, Col, List } from 'antd'; // import Notifications from '@/components/Notification'; import { RocketOutlined } from '@ant-design/icons'; import useLanguage from '@/locale/useLanguage'; export default function UpgradeButton() { const translate = useLanguage(); return ( ); } console.log( '🚀 Welcome to IDURAR ERP CRM! Did you know that we also offer commercial customization services? Contact us at hello@idurarapp.com for more information.' ); ================================================ FILE: frontend/src/apps/IdurarOs.jsx ================================================ import { lazy, Suspense, useEffect, useState } from 'react'; import { useSelector } from 'react-redux'; import { selectAuth } from '@/redux/auth/selectors'; import { AppContextProvider } from '@/context/appContext'; import PageLoader from '@/components/PageLoader'; import AuthRouter from '@/router/AuthRouter'; import Localization from '@/locale/Localization'; import { notification } from 'antd'; const ErpApp = lazy(() => import('./ErpApp')); const DefaultApp = () => ( }> ); export default function IdurarOs() { const { isLoggedIn } = useSelector(selectAuth); console.log( '🚀 Welcome to IDURAR ERP CRM! Did you know that we also offer commercial customization services? Contact us at hello@idurarapp.com for more information.' ); // // Online state // const [isOnline, setIsOnline] = useState(navigator.onLine); // useEffect(() => { // // Update network status // const handleStatusChange = () => { // setIsOnline(navigator.onLine); // if (!isOnline) { // console.log('🚀 ~ useEffect ~ navigator.onLine:', navigator.onLine); // notification.config({ // duration: 20, // maxCount: 1, // }); // // Code to execute when there is internet connection // notification.error({ // message: 'No internet connection', // description: 'Cannot connect to the Internet, Check your internet network', // }); // } // }; // // Listen to the online status // window.addEventListener('online', handleStatusChange); // // Listen to the offline status // window.addEventListener('offline', handleStatusChange); // // Specify how to clean up after this effect for performance improvment // return () => { // window.removeEventListener('online', handleStatusChange); // window.removeEventListener('offline', handleStatusChange); // }; // }, [navigator.onLine]); if (!isLoggedIn) return ( ); else { return ; } } ================================================ FILE: frontend/src/apps/Navigation/NavigationContainer.jsx ================================================ import { useState, useEffect } from 'react'; import { Link, useLocation, useNavigate } from 'react-router-dom'; import { Button, Drawer, Layout, Menu } from 'antd'; import { useAppContext } from '@/context/appContext'; import useLanguage from '@/locale/useLanguage'; import logoIcon from '@/style/images/logo-icon.svg'; import logoText from '@/style/images/logo-text.svg'; import useResponsive from '@/hooks/useResponsive'; import { SettingOutlined, CustomerServiceOutlined, ContainerOutlined, FileSyncOutlined, DashboardOutlined, TagOutlined, TagsOutlined, UserOutlined, CreditCardOutlined, MenuOutlined, FileOutlined, ShopOutlined, FilterOutlined, WalletOutlined, ReconciliationOutlined, } from '@ant-design/icons'; const { Sider } = Layout; export default function Navigation() { const { isMobile } = useResponsive(); return isMobile ? : ; } function Sidebar({ collapsible, isMobile = false }) { let location = useLocation(); const { state: stateApp, appContextAction } = useAppContext(); const { isNavMenuClose } = stateApp; const { navMenu } = appContextAction; const [showLogoApp, setLogoApp] = useState(isNavMenuClose); const [currentPath, setCurrentPath] = useState(location.pathname.slice(1)); const translate = useLanguage(); const navigate = useNavigate(); const items = [ { key: 'dashboard', icon: , label: {translate('dashboard')}, }, { key: 'customer', icon: , label: {translate('customers')}, }, { key: 'invoice', icon: , label: {translate('invoices')}, }, { key: 'quote', icon: , label: {translate('quote')}, }, { key: 'payment', icon: , label: {translate('payments')}, }, { key: 'paymentMode', label: {translate('payments_mode')}, icon: , }, { key: 'taxes', label: {translate('taxes')}, icon: , }, { key: 'generalSettings', label: {translate('settings')}, icon: , }, { key: 'about', label: {translate('about')}, icon: , }, ]; useEffect(() => { if (location) if (currentPath !== location.pathname) { if (location.pathname === '/') { setCurrentPath('dashboard'); } else setCurrentPath(location.pathname.slice(1)); } }, [location, currentPath]); useEffect(() => { if (isNavMenuClose) { setLogoApp(isNavMenuClose); } const timer = setTimeout(() => { if (!isNavMenuClose) { setLogoApp(isNavMenuClose); } }, 200); return () => clearTimeout(timer); }, [isNavMenuClose]); const onCollapse = () => { navMenu.collapse(); }; return (
navigate('/')} style={{ cursor: 'pointer', }} > Logo {!showLogoApp && ( Logo )}
); } function MobileSidebar() { const [visible, setVisible] = useState(false); const showDrawer = () => { setVisible(true); }; const onClose = () => { setVisible(false); }; return ( <> ); } ================================================ FILE: frontend/src/auth/auth.service.js ================================================ import { API_BASE_URL } from '@/config/serverApiConfig'; import axios from 'axios'; import errorHandler from '@/request/errorHandler'; import successHandler from '@/request/successHandler'; export const login = async ({ loginData }) => { try { const response = await axios.post( API_BASE_URL + `login?timestamp=${new Date().getTime()}`, loginData ); const { status, data } = response; successHandler( { data, status }, { notifyOnSuccess: false, notifyOnFailed: true, } ); return data; } catch (error) { return errorHandler(error); } }; export const register = async ({ registerData }) => { try { const response = await axios.post(API_BASE_URL + `register`, registerData); const { status, data } = response; successHandler( { data, status }, { notifyOnSuccess: true, notifyOnFailed: true, } ); return data; } catch (error) { return errorHandler(error); } }; export const verify = async ({ userId, emailToken }) => { try { const response = await axios.get(API_BASE_URL + `verify/${userId}/${emailToken}`); const { status, data } = response; successHandler( { data, status }, { notifyOnSuccess: true, notifyOnFailed: true, } ); return data; } catch (error) { return errorHandler(error); } }; export const resetPassword = async ({ resetPasswordData }) => { try { const response = await axios.post(API_BASE_URL + `resetpassword`, resetPasswordData); const { status, data } = response; successHandler( { data, status }, { notifyOnSuccess: true, notifyOnFailed: true, } ); return data; } catch (error) { return errorHandler(error); } }; export const logout = async () => { axios.defaults.withCredentials = true; try { // window.localStorage.clear(); const response = await axios.post(API_BASE_URL + `logout?timestamp=${new Date().getTime()}`); const { status, data } = response; successHandler( { data, status }, { notifyOnSuccess: false, notifyOnFailed: true, } ); return data; } catch (error) { return errorHandler(error); } }; // console.log( // '🚀 Welcome to IDURAR ERP CRM! Did you know that we also offer commercial customization services? Contact us at hello@idurarapp.com for more information.' // ); ================================================ FILE: frontend/src/auth/index.js ================================================ export * from './auth.service'; ================================================ FILE: frontend/src/components/AutoCompleteAsync/index.jsx ================================================ import { useState, useEffect, useRef } from 'react'; import { request } from '@/request'; import useOnFetch from '@/hooks/useOnFetch'; import useDebounce from '@/hooks/useDebounce'; import { useNavigate } from 'react-router-dom'; import { Select, Empty } from 'antd'; import useLanguage from '@/locale/useLanguage'; export default function AutoCompleteAsync({ entity, displayLabels, searchFields, outputValue = '_id', redirectLabel = 'Add New', withRedirect = false, urlToRedirect = '/', value, /// this is for update onChange, /// this is for update }) { const translate = useLanguage(); const addNewValue = { value: 'redirectURL', label: `+ ${translate(redirectLabel)}` }; const [selectOptions, setOptions] = useState([]); const [currentValue, setCurrentValue] = useState(undefined); const isUpdating = useRef(true); const isSearching = useRef(false); const [searching, setSearching] = useState(false); const [valToSearch, setValToSearch] = useState(''); const [debouncedValue, setDebouncedValue] = useState(''); const navigate = useNavigate(); const handleSelectChange = (newValue) => { isUpdating.current = false; // setCurrentValue(value[outputValue] || value); // set nested value or value // onChange(newValue[outputValue] || newValue); if (onChange) { if (newValue) onChange(newValue[outputValue] || newValue); } if (newValue === 'redirectURL' && withRedirect) { navigate(urlToRedirect); } }; const handleOnSelect = (value) => { setCurrentValue(value[outputValue] || value); // set nested value or value }; const [, cancel] = useDebounce( () => { // setState("Typing stopped"); setDebouncedValue(valToSearch); }, 500, [valToSearch] ); const asyncSearch = async (options) => { return await request.search({ entity, options }); }; let { onFetch, result, isSuccess, isLoading } = useOnFetch(); const labels = (optionField) => { return displayLabels.map((x) => optionField[x]).join(' '); }; useEffect(() => { const options = { q: debouncedValue, fields: searchFields, }; const callback = asyncSearch(options); onFetch(callback); return () => { cancel(); }; }, [debouncedValue]); const onSearch = (searchText) => { isSearching.current = true; setSearching(true); // setOptions([]); // setCurrentValue(undefined); setValToSearch(searchText); }; useEffect(() => { if (isSuccess) { setOptions(result); } else { setSearching(false); // setCurrentValue(undefined); // setOptions([]); } }, [isSuccess, result]); useEffect(() => { // this for update Form , it's for setField if (value && isUpdating.current) { setOptions([value]); setCurrentValue(value[outputValue] || value); // set nested value or value onChange(value[outputValue] || value); isUpdating.current = false; } }, [value]); return ( ); } ================================================ FILE: frontend/src/components/CollapseBox/index.jsx ================================================ import React from 'react'; import { Row, Col } from 'antd'; const CollapseBoxButton = ({ onChange, title }) => { return (
{title}
); }; const TopCollapseBox = ({ isOpen, children }) => { const show = isOpen ? { display: 'block', opacity: 1 } : { display: 'none', opacity: 0 }; return (
{children}
); }; const BottomCollapseBox = ({ isOpen, children }) => { const show = isOpen ? { display: 'none', opacity: 0 } : { display: 'block', opacity: 1 }; return (
{children}
); }; export default function CollapseBox({ topContent, bottomContent, buttonTitle, isCollapsed, onCollapse, }) { const collapsed = isCollapsed ? 'collapsed' : ''; return ( <> {topContent}
{bottomContent}
); } ================================================ FILE: frontend/src/components/CreateForm/index.jsx ================================================ import { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { crud } from '@/redux/crud/actions'; import { useCrudContext } from '@/context/crud'; import { selectCreatedItem } from '@/redux/crud/selectors'; import useLanguage from '@/locale/useLanguage'; import { Button, Form } from 'antd'; import Loading from '@/components/Loading'; export default function CreateForm({ config, formElements, withUpload = false }) { let { entity } = config; const dispatch = useDispatch(); const { isLoading, isSuccess } = useSelector(selectCreatedItem); const { crudContextAction } = useCrudContext(); const { panel, collapsedBox, readBox } = crudContextAction; const [form] = Form.useForm(); const translate = useLanguage(); const onSubmit = (fieldsValue) => { // Manually trim values before submission if (fieldsValue.file && withUpload) { fieldsValue.file = fieldsValue.file[0].originFileObj; } // const trimmedValues = Object.keys(fieldsValue).reduce((acc, key) => { // acc[key] = typeof fieldsValue[key] === 'string' ? fieldsValue[key].trim() : fieldsValue[key]; // return acc; // }, {}); dispatch(crud.create({ entity, jsonData: fieldsValue, withUpload })); }; useEffect(() => { if (isSuccess) { readBox.open(); collapsedBox.open(); panel.open(); form.resetFields(); dispatch(crud.resetAction({ actionType: 'create' })); dispatch(crud.list({ entity })); } }, [isSuccess]); return (
{formElements}
); } ================================================ FILE: frontend/src/components/CrudModal/index.jsx ================================================ import { useEffect } from 'react'; import { Modal } from 'antd'; import { useDispatch, useSelector } from 'react-redux'; import { crud } from '@/redux/crud/actions'; import { useCrudContext } from '@/context/crud'; import { selectDeletedItem } from '@/redux/crud/selectors'; import useLanguage from '@/locale/useLanguage'; export default function DeleteModal({ config, children }) { const translate = useLanguage(); let { entity, modalTitle = translate('delete_confirmation') } = config; const dispatch = useDispatch(); const { current, isLoading, isSuccess } = useSelector(selectDeletedItem); const { state, crudContextAction } = useCrudContext(); const { isModalOpen } = state; const { modal } = crudContextAction; useEffect(() => { if (isSuccess) { modal.close(); dispatch(crud.list({ entity })); } }, [isSuccess]); const handleOk = () => { const id = current._id; dispatch(crud.delete({ entity, id })); }; const handleCancel = () => { if (!isLoading) modal.close(); }; return ( {children} ); } ================================================ FILE: frontend/src/components/DataTable/DataTable.jsx ================================================ import { useCallback, useEffect } from 'react'; import { EyeOutlined, EditOutlined, DeleteOutlined, EllipsisOutlined, RedoOutlined, ArrowRightOutlined, ArrowLeftOutlined, } from '@ant-design/icons'; import { Dropdown, Table, Button, Input } from 'antd'; import { PageHeader } from '@ant-design/pro-layout'; import { useSelector, useDispatch } from 'react-redux'; import { crud } from '@/redux/crud/actions'; import { selectListItems } from '@/redux/crud/selectors'; import useLanguage from '@/locale/useLanguage'; import { dataForTable } from '@/utils/dataStructure'; import { useMoney, useDate } from '@/settings'; import { generate as uniqueId } from 'shortid'; import { useCrudContext } from '@/context/crud'; function AddNewItem({ config }) { const { crudContextAction } = useCrudContext(); const { collapsedBox, panel } = crudContextAction; const { ADD_NEW_ENTITY } = config; const handelClick = () => { panel.open(); collapsedBox.close(); }; return ( ); } export default function DataTable({ config, extra = [] }) { let { entity, dataTableColumns, DATATABLE_TITLE, fields, searchConfig } = config; const { crudContextAction } = useCrudContext(); const { panel, collapsedBox, modal, readBox, editBox, advancedBox } = crudContextAction; const translate = useLanguage(); const { moneyFormatter } = useMoney(); const { dateFormat } = useDate(); const items = [ { label: translate('Show'), key: 'read', icon: , }, { label: translate('Edit'), key: 'edit', icon: , }, ...extra, { type: 'divider', }, { label: translate('Delete'), key: 'delete', icon: , }, ]; const handleRead = (record) => { dispatch(crud.currentItem({ data: record })); panel.open(); collapsedBox.open(); readBox.open(); }; function handleEdit(record) { dispatch(crud.currentItem({ data: record })); dispatch(crud.currentAction({ actionType: 'update', data: record })); editBox.open(); panel.open(); collapsedBox.open(); } function handleDelete(record) { dispatch(crud.currentAction({ actionType: 'delete', data: record })); modal.open(); } function handleUpdatePassword(record) { dispatch(crud.currentItem({ data: record })); dispatch(crud.currentAction({ actionType: 'update', data: record })); advancedBox.open(); panel.open(); collapsedBox.open(); } let dispatchColumns = []; if (fields) { dispatchColumns = [...dataForTable({ fields, translate, moneyFormatter, dateFormat })]; } else { dispatchColumns = [...dataTableColumns]; } dataTableColumns = [ ...dispatchColumns, { title: '', key: 'action', fixed: 'right', render: (_, record) => ( { switch (key) { case 'read': handleRead(record); break; case 'edit': handleEdit(record); break; case 'delete': handleDelete(record); break; case 'updatePassword': handleUpdatePassword(record); break; default: break; } // else if (key === '2')handleCloseTask }, }} trigger={['click']} > e.preventDefault()} /> ), }, ]; const { result: listResult, isLoading: listIsLoading } = useSelector(selectListItems); const { pagination, items: dataSource } = listResult; const dispatch = useDispatch(); const handelDataTableLoad = useCallback((pagination) => { const options = { page: pagination.current || 1, items: pagination.pageSize || 10 }; dispatch(crud.list({ entity, options })); }, []); const filterTable = (e) => { const value = e.target.value; const options = { q: value, fields: searchConfig?.searchFields || '' }; dispatch(crud.list({ entity, options })); }; const dispatcher = () => { dispatch(crud.list({ entity })); }; useEffect(() => { const controller = new AbortController(); dispatcher(); return () => { controller.abort(); }; }, []); return ( <> window.history.back()} backIcon={} title={DATATABLE_TITLE} ghost={false} extra={[ , , , ]} style={{ padding: '20px 0px', }} > item._id} dataSource={dataSource} pagination={pagination} loading={listIsLoading} onChange={handelDataTableLoad} scroll={{ x: true }} /> ); } ================================================ FILE: frontend/src/components/DeleteModal/index.jsx ================================================ import { useEffect, useState } from 'react'; import { Modal } from 'antd'; import { useDispatch, useSelector } from 'react-redux'; import { crud } from '@/redux/crud/actions'; import { useCrudContext } from '@/context/crud'; import { useAppContext } from '@/context/appContext'; import { selectDeletedItem } from '@/redux/crud/selectors'; import { valueByString } from '@/utils/helpers'; import useLanguage from '@/locale/useLanguage'; export default function DeleteModal({ config }) { const translate = useLanguage(); let { entity, deleteModalLabels, deleteMessage = translate('are_you_sure_you_want_to_delete'), modalTitle = translate('delete_confirmation'), } = config; const dispatch = useDispatch(); const { current, isLoading, isSuccess } = useSelector(selectDeletedItem); const { state, crudContextAction } = useCrudContext(); const { appContextAction } = useAppContext(); const { panel, readBox } = crudContextAction; const { navMenu } = appContextAction; const { isModalOpen } = state; const { modal } = crudContextAction; const [displayItem, setDisplayItem] = useState(''); useEffect(() => { if (isSuccess) { console.log('🚀 ~ useEffect ~ DeleteModal isSuccess:', isSuccess); modal.close(); dispatch(crud.list({ entity })); // dispatch(crud.resetAction({actionType:"delete"})); // check here maybe it wrong } if (current) { let labels = deleteModalLabels.map((x) => valueByString(current, x)).join(' '); setDisplayItem(labels); } }, [isSuccess, current]); const handleOk = () => { const id = current._id; dispatch(crud.delete({ entity, id })); readBox.close(); modal.close(); panel.close(); navMenu.collapse(); }; const handleCancel = () => { if (!isLoading) modal.close(); }; return (

{deleteMessage} {displayItem}

); } ================================================ FILE: frontend/src/components/IconMenu/index.jsx ================================================ import { DesktopOutlined, SettingOutlined, CustomerServiceOutlined, FileTextOutlined, FileSyncOutlined, DashboardOutlined, TeamOutlined, UserOutlined, CreditCardOutlined, BankOutlined, } from '@ant-design/icons'; export const IconMenu = ({ name }) => { const elements = { DesktopOutlined: DesktopOutlined, SettingOutlined: SettingOutlined, CustomerServiceOutlined: CustomerServiceOutlined, FileTextOutlined: FileTextOutlined, FileSyncOutlined: FileSyncOutlined, DashboardOutlined: DashboardOutlined, TeamOutlined: TeamOutlined, UserOutlined: UserOutlined, CreditCardOutlined: CreditCardOutlined, BankOutlined: BankOutlined, Default: DesktopOutlined, }; const IconTag = elements[name || 'Default'] || SettingOutlined; return ; }; ================================================ FILE: frontend/src/components/Loading/index.jsx ================================================ import { Spin } from 'antd'; import { LoadingOutlined } from '@ant-design/icons'; export default function Loading({ isLoading, children }) { const antIcon = ; return ( {children} ); } ================================================ FILE: frontend/src/components/MoneyInputFormItem/index.jsx ================================================ import { Form, InputNumber } from 'antd'; import { useMoney } from '@/settings'; export default function MoneyInputFormItem({ updatePrice, value = 0, readOnly = false }) { const { amountFormatter, currency_symbol, currency_position, cent_precision, currency_code } = useMoney(); return ( amountFormatter({ amount: value, currency_code })} /> ); } ================================================ FILE: frontend/src/components/MultiStepSelectAsync/index.jsx ================================================ import { useState, useEffect } from 'react'; import { Select, Space } from 'antd'; import { request } from '@/request'; import errorHandler from '@/request/errorHandler'; const { Option } = Select; const asyncList = (entity) => { return request.list({ entity }); }; const asyncFilter = (entity, options) => { return request.filter({ entity, options }); }; const MultiStepSelectAsync = ({ firstSelectProps = {}, secondSelectProps = {}, firstSelectIdKey = '_id', firstSelectValueKey = 'value', firstSelectLabelKey = 'label', secondSelectIdKey = '_id', secondSelectValueKey = 'value', secondSelectLabelKey = 'label', entityName, subEntityName = 'items', value = {}, onChange, style, }) => { const firstSelectedOption = value.firstSelectedOption; const [firstSelectOptions, setFirstSelectOptions] = useState([]); const [secondSelectOptions, setSecondSelectOptions] = useState([]); const [loading, setLoading] = useState(false); useEffect(() => { async function fetchData() { setLoading(true); try { if (firstSelectedOption) { const data = await asyncFilter(entityName, { filter: '_id', equal: firstSelectedOption[firstSelectIdKey], }); setSecondSelectOptions(data?.result?.[0]?.[subEntityName]); return; } const data = await asyncList(entityName); setFirstSelectOptions(data.result); } catch (error) { errorHandler(error); } finally { setLoading(false); } } fetchData(); }, [firstSelectedOption]); return ( {firstSelectedOption && ( )} ); }; export default MultiStepSelectAsync; ================================================ FILE: frontend/src/components/NotFound/index.jsx ================================================ import { Result, Button } from 'antd'; import { useNavigate } from 'react-router-dom'; import useLanguage from '@/locale/useLanguage'; export default function NotFound({ entity = '' }) { const translate = useLanguage(); const navigate = useNavigate(); return ( { navigate('/'); }} > {translate('Back')} } /> ); } ================================================ FILE: frontend/src/components/Notification/index.jsx ================================================ import React from 'react'; import { DeleteOutlined } from '@ant-design/icons'; import { Button } from 'antd'; const Notifications = () => { const [notifications, setNotifications] = React.useState([ { id: 1, text: 'First notificationnnnnnnnnnnnnnnnn' }, { id: 2, text: 'Second notification' }, { id: 3, text: 'Third ' }, { id: 4, text: 'Fourth notification' }, { id: 5, text: 'Fifth notification' }, { id: 6, text: 'Sixth notification' }, ]); const deleteNotification = (id) => { const updatedNotifications = notifications.filter((n) => n.id !== id); setNotifications(updatedNotifications); }; return (

Notifications

{notifications.map((notification) => (
))}
); }; export default Notifications; ================================================ FILE: frontend/src/components/PageLoader/index.jsx ================================================ import React from 'react'; import { Spin } from 'antd'; import { LoadingOutlined } from '@ant-design/icons'; const PageLoader = () => { const antIcon = ; return (
); }; export default PageLoader; ================================================ FILE: frontend/src/components/ReadItem/index.jsx ================================================ import { useEffect, useState } from 'react'; import { Row, Col } from 'antd'; import { useSelector } from 'react-redux'; import dayjs from 'dayjs'; import { dataForRead } from '@/utils/dataStructure'; import { useCrudContext } from '@/context/crud'; import { selectCurrentItem } from '@/redux/crud/selectors'; import { valueByString } from '@/utils/helpers'; import useLanguage from '@/locale/useLanguage'; import { useDate } from '@/settings'; export default function ReadItem({ config }) { const { dateFormat } = useDate(); let { readColumns, fields } = config; const translate = useLanguage(); const { result: currentResult } = useSelector(selectCurrentItem); const { state } = useCrudContext(); const { isReadBoxOpen } = state; const [listState, setListState] = useState([]); if (fields) readColumns = [...dataForRead({ fields: fields, translate: translate })]; useEffect(() => { const list = []; readColumns.map((props) => { const propsKey = props.dataIndex; const propsTitle = props.title; const isDate = props.isDate || false; let value = valueByString(currentResult, propsKey); value = isDate ? dayjs(value).format(dateFormat) : value; list.push({ propsKey, label: propsTitle, value: value }); }); setListState(list); }, [currentResult]); const show = isReadBoxOpen ? { display: 'block', opacity: 1 } : { display: 'none', opacity: 0 }; const itemsList = listState.map((item) => { return (

{item.label}

:

{item.value}

); }); return
{itemsList}
; } ================================================ FILE: frontend/src/components/SearchItem/index.jsx ================================================ import { useState, useEffect, useRef } from 'react'; import useDebounce from '@/hooks/useDebounce'; import { Select, Empty } from 'antd'; import { SearchOutlined } from '@ant-design/icons'; import { useSelector, useDispatch } from 'react-redux'; import { crud } from '@/redux/crud/actions'; import { useCrudContext } from '@/context/crud'; import { selectSearchedItems } from '@/redux/crud/selectors'; function SearchItemComponent({ config, onRerender }) { let { entity, searchConfig } = config; const { displayLabels, searchFields, outputValue = '_id' } = searchConfig; const dispatch = useDispatch(); const { crudContextAction } = useCrudContext(); const { panel, collapsedBox, readBox } = crudContextAction; const { result, isLoading, isSuccess } = useSelector(selectSearchedItems); const [selectOptions, setOptions] = useState([]); const [currentValue, setCurrentValue] = useState(undefined); const isSearching = useRef(false); const [searching, setSearching] = useState(false); const [valToSearch, setValToSearch] = useState(''); const [debouncedValue, setDebouncedValue] = useState(''); const [, cancel] = useDebounce( () => { setDebouncedValue(valToSearch); }, 500, [valToSearch] ); const labels = (optionField) => { return displayLabels.map((x) => optionField[x]).join(' '); }; useEffect(() => { if (debouncedValue != '') { const options = { q: debouncedValue, fields: searchFields, }; dispatch(crud.search({ entity, options })); } return () => { cancel(); }; }, [debouncedValue]); const onSearch = (searchText) => { if (searchText && searchText != '') { isSearching.current = true; setSearching(true); setOptions([]); setCurrentValue(undefined); setValToSearch(searchText); } }; const onSelect = (data) => { const currentItem = result.find((item) => { return item[outputValue] === data; }); dispatch(crud.currentItem({ data: currentItem })); panel.open(); collapsedBox.open(); readBox.open(); onRerender(); }; useEffect(() => { if (isSearching.current) { if (isSuccess) { setOptions(result); } else { setSearching(false); setCurrentValue(undefined); setOptions([]); } } }, [isSuccess, result]); return ( ); } export default function SearchItem({ config }) { const [state, setState] = useState([0]); const onRerender = () => { setState([state + 1]); }; return state.map((comp) => ( )); } ================================================ FILE: frontend/src/components/SelectAsync/index.jsx ================================================ import { useState, useEffect } from 'react'; import { request } from '@/request'; import useFetch from '@/hooks/useFetch'; import { Select, Tag } from 'antd'; import { useNavigate } from 'react-router-dom'; import { generate as uniqueId } from 'shortid'; import color from '@/utils/color'; import useLanguage from '@/locale/useLanguage'; const SelectAsync = ({ entity, displayLabels = ['name'], outputValue = '_id', redirectLabel = '', withRedirect = false, urlToRedirect = '/', placeholder = 'select', value, onChange, }) => { const translate = useLanguage(); const [selectOptions, setOptions] = useState([]); const [currentValue, setCurrentValue] = useState(undefined); const navigate = useNavigate(); const asyncList = () => { return request.list({ entity }); }; const { result, isLoading: fetchIsLoading, isSuccess } = useFetch(asyncList); useEffect(() => { isSuccess && setOptions(result); }, [isSuccess]); const labels = (optionField) => { return displayLabels.map((x) => optionField[x]).join(' '); }; useEffect(() => { if (value !== undefined) { const val = value?.[outputValue] ?? value; setCurrentValue(val); onChange(val); } }, [value]); const handleSelectChange = (newValue) => { if (newValue === 'redirectURL') { navigate(urlToRedirect); } else { const val = newValue?.[outputValue] ?? newValue; setCurrentValue(newValue); onChange(val); } }; const optionsList = () => { const list = []; // if (selectOptions.length === 0 && withRedirect) { // const value = 'redirectURL'; // const label = `+ ${translate(redirectLabel)}`; // list.push({ value, label }); // } selectOptions.map((optionField) => { const value = optionField[outputValue] ?? optionField; const label = labels(optionField); const currentColor = optionField[outputValue]?.color ?? optionField?.color; const labelColor = color.find((x) => x.color === currentColor); list.push({ value, label, color: labelColor?.color }); }); return list; }; return ( ); }; export default SelectAsync; ================================================ FILE: frontend/src/components/SelectTag/index.jsx ================================================ import { Select, Tag } from 'antd'; import { generate as uniqueId } from 'shortid'; export default function SelectTag({ options, defaultValue }) { return ( ); } ================================================ FILE: frontend/src/components/SidePanel/index.jsx ================================================ import { useState, useEffect } from 'react'; import { useCrudContext } from '@/context/crud'; import { useAppContext } from '@/context/appContext'; import { Grid, Layout, Drawer } from 'antd'; import { MenuOutlined } from '@ant-design/icons'; import CollapseBox from '../CollapseBox'; const { useBreakpoint } = Grid; const { Sider } = Layout; export default function SidePanel({ config, topContent, bottomContent, fixHeaderPanel }) { const screens = useBreakpoint(); const { ADD_NEW_ENTITY } = config; const { state, crudContextAction } = useCrudContext(); const { isPanelClose, isBoxCollapsed } = state; const { panel, collapsedBox } = crudContextAction; const [isSidePanelClose, setSidePanel] = useState(isPanelClose); const [leftSider, setLeftSider] = useState('-1px'); const [opacitySider, setOpacitySider] = useState(0); const [paddingTopSider, setPaddingTopSider] = useState('20px'); // const { state: stateApp, appContextAction } = useAppContext(); // const { isNavMenuClose } = stateApp; // const { navMenu } = appContextAction; useEffect(() => { let timer = []; if (isPanelClose) { setOpacitySider(0); setPaddingTopSider('20px'); timer = setTimeout(() => { setLeftSider('-1px'); setSidePanel(isPanelClose); }, 200); } else { setSidePanel(isPanelClose); setLeftSider(0); timer = setTimeout(() => { setOpacitySider(1); setPaddingTopSider(0); }, 200); } return () => clearTimeout(timer); }, [isPanelClose]); const collapsePanel = () => { panel.collapse(); }; const collapsePanelBox = () => { collapsedBox.collapse(); }; return (
{fixHeaderPanel}
// // ); } ================================================ FILE: frontend/src/components/TabsContent/TabsContent.jsx ================================================ import { Tabs, Row, Col } from 'antd'; const SettingsLayout = ({ children }) => { return (
{children}
); }; const TopCard = ({ pageTitle }) => { return (

{pageTitle}

); }; const RightMenu = ({ children, pageTitle }) => { return (
{children}
); }; export default function TabsContent({ content, defaultActiveKey, pageTitle }) { const items = content.map((item, index) => { return { key: item.key ? item.key : index + '_' + item.label.replace(/ /g, '_'), label: (
{item.icon} {item.label}
), children: {item.children}, }; }); const renderTabBar = (props, DefaultTabBar) => ( ); return ( ); } ================================================ FILE: frontend/src/components/Tag/index.jsx ================================================ import { Tag } from 'antd'; import useLanguage from '@/locale/useLanguage'; export function StatusTag({ status = 'draft' }) { const translate = useLanguage(); let color = () => { return status === 'draft' ? 'cyan' : status === 'sent' ? 'blue' : status === 'accepted' ? 'green' : status === 'expired' ? 'orange' : 'red'; }; return {translate(status)}; } ================================================ FILE: frontend/src/components/UpdateForm/index.jsx ================================================ import { useEffect } from 'react'; import dayjs from 'dayjs'; import { useDispatch, useSelector } from 'react-redux'; import { crud } from '@/redux/crud/actions'; import { useCrudContext } from '@/context/crud'; import { selectUpdatedItem } from '@/redux/crud/selectors'; import useLanguage from '@/locale/useLanguage'; import { Button, Form } from 'antd'; import Loading from '@/components/Loading'; export default function UpdateForm({ config, formElements, withUpload = false }) { let { entity } = config; const translate = useLanguage(); const dispatch = useDispatch(); const { current, isLoading, isSuccess } = useSelector(selectUpdatedItem); const { state, crudContextAction } = useCrudContext(); ///// const { panel, collapsedBox, readBox } = crudContextAction; const showCurrentRecord = () => { readBox.open(); }; ///// const [form] = Form.useForm(); const onSubmit = (fieldsValue) => { const id = current._id; if (fieldsValue.file && withUpload) { fieldsValue.file = fieldsValue.file[0].originFileObj; } // const trimmedValues = Object.keys(fieldsValue).reduce((acc, key) => { // acc[key] = typeof fieldsValue[key] === 'string' ? fieldsValue[key].trim() : fieldsValue[key]; // return acc; // }, {}); dispatch(crud.update({ entity, id, jsonData: fieldsValue, withUpload })); }; useEffect(() => { if (current) { let newValues = { ...current }; if (newValues.birthday) { newValues = { ...newValues, birthday: dayjs(newValues['birthday']).format('YYYY-MM-DDTHH:mm:ss.SSSZ'), }; } if (newValues.date) { newValues = { ...newValues, date: dayjs(newValues['date']).format('YYYY-MM-DDTHH:mm:ss.SSSZ'), }; } if (newValues.expiredDate) { newValues = { ...newValues, expiredDate: dayjs(newValues['expiredDate']).format('YYYY-MM-DDTHH:mm:ss.SSSZ'), }; } if (newValues.created) { newValues = { ...newValues, created: dayjs(newValues['created']).format('YYYY-MM-DDTHH:mm:ss.SSSZ'), }; } if (newValues.updated) { newValues = { ...newValues, updated: dayjs(newValues['updated']).format('YYYY-MM-DDTHH:mm:ss.SSSZ'), }; } form.resetFields(); form.setFieldsValue(newValues); } }, [current]); useEffect(() => { if (isSuccess) { readBox.open(); collapsedBox.open(); panel.open(); form.resetFields(); dispatch(crud.resetAction({ actionType: 'update' })); dispatch(crud.list({ entity })); } }, [isSuccess]); const { isEditBoxOpen } = state; const show = isEditBoxOpen ? { display: 'block', opacity: 1 } : { display: 'none', opacity: 0 }; return (
{formElements}
); } ================================================ FILE: frontend/src/components/Visibility/index.jsx ================================================ export default function Visibility({ isOpen, children }) { const show = isOpen ? { display: 'block', opacity: 1 } : { display: 'none', opacity: 0 }; return
{children}
; } ================================================ FILE: frontend/src/components/outsideClick.js/demo.js ================================================ import { useState } from 'react'; import ReactDOM from 'react-dom'; import Dropdown from './Dropdown'; import './styles.css'; function App() { const [vegetagle, setVegetable] = useState(undefined); const [fruit, setFruit] = useState(undefined); return (

Hello CodeSandbox

Start editing to see some magic happen!

setVegetable(v)} options={['Tomato', 'Cucumber', 'Potato']} /> setFruit(v)} options={['Apple', 'Banana', 'Orange', 'Mango']} />
); } const rootElement = document.getElementById('root'); ReactDOM.render(, rootElement); ================================================ FILE: frontend/src/components/outsideClick.js/index.js ================================================ import { useEffect, useState, useRef } from 'react'; const Dropdown = ({ value, options, placeholder = 'Select', onChange }) => { const node = useRef(); const [open, setOpen] = useState(false); const handleClick = (e) => { if (node.current.contains(e.target)) { // inside click return; } // outside click setOpen(false); }; const handleChange = (selectedValue) => { onChange(selectedValue); setOpen(false); }; useEffect(() => { document.addEventListener('mousedown', handleClick); return () => { document.removeEventListener('mousedown', handleClick); }; }, [open]); return (
{open && (
    {options.map((opt) => (
  • handleChange(opt)}> {opt}
  • ))}
)}
); }; export default Dropdown; ================================================ FILE: frontend/src/config/serverApiConfig.js ================================================ export const API_BASE_URL = import.meta.env.PROD || import.meta.env.VITE_DEV_REMOTE == 'remote' ? import.meta.env.VITE_BACKEND_SERVER + 'api/' : 'http://localhost:8888/api/'; export const BASE_URL = import.meta.env.PROD || import.meta.env.VITE_DEV_REMOTE ? import.meta.env.VITE_BACKEND_SERVER : 'http://localhost:8888/'; export const WEBSITE_URL = import.meta.env.PROD ? 'http://cloud.idurarapp.com/' : 'http://localhost:3000/'; export const DOWNLOAD_BASE_URL = import.meta.env.PROD || import.meta.env.VITE_DEV_REMOTE ? import.meta.env.VITE_BACKEND_SERVER + 'download/' : 'http://localhost:8888/download/'; export const ACCESS_TOKEN_NAME = 'x-auth-token'; export const FILE_BASE_URL = import.meta.env.VITE_FILE_BASE_URL; // console.log( // '🚀 Welcome to IDURAR ERP CRM! Did you know that we also offer commercial customization services? Contact us at hello@idurarapp.com for more information.' // ); ================================================ FILE: frontend/src/context/adavancedCrud/actions.jsx ================================================ import * as actionTypes from './types'; const contextActions = (dispatch) => { return { modal: { open: () => { dispatch({ type: actionTypes.OPEN_MODAL }); }, close: () => { dispatch({ type: actionTypes.CLOSE_MODAL }); }, }, readPanel: { open: () => { dispatch({ type: actionTypes.OPEN_PANEL, keyState: 'read' }); }, close: () => { dispatch({ type: actionTypes.CLOSE_PANEL }); }, }, updatePanel: { open: () => { dispatch({ type: actionTypes.OPEN_PANEL, keyState: 'update' }); }, close: () => { dispatch({ type: actionTypes.CLOSE_PANEL }); }, }, createPanel: { open: () => { dispatch({ type: actionTypes.OPEN_PANEL, keyState: 'create' }); }, close: () => { dispatch({ type: actionTypes.CLOSE_PANEL }); }, }, recordPanel: { open: () => { dispatch({ type: actionTypes.OPEN_PANEL, keyState: 'recordPayment', }); }, close: () => { dispatch({ type: actionTypes.CLOSE_PANEL }); }, }, }; }; export default contextActions; ================================================ FILE: frontend/src/context/adavancedCrud/index.jsx ================================================ import { useMemo, useReducer, createContext, useContext } from 'react'; import { initialState, contextReducer } from './reducer'; import contextActions from './actions'; import contextSelectors from './selectors'; const AdavancedCrudContext = createContext(); function AdavancedCrudContextProvider({ children }) { const [state, dispatch] = useReducer(contextReducer, initialState); const value = useMemo(() => [state, dispatch], [state]); return {children}; } function useAdavancedCrudContext() { const context = useContext(AdavancedCrudContext); if (context === undefined) { throw new Error('useAdavancedCrudContext must be used within a AdavancedCrudContextProvider'); } const [state, dispatch] = context; const adavancedCrudContextAction = contextActions(dispatch); const adavancedCrudContextSelector = contextSelectors(state); return { state, adavancedCrudContextAction, adavancedCrudContextSelector }; } export { AdavancedCrudContextProvider, useAdavancedCrudContext }; ================================================ FILE: frontend/src/context/adavancedCrud/reducer.jsx ================================================ import * as actionTypes from './types'; export const initialState = { create: { isOpen: false, }, update: { isOpen: false, }, read: { isOpen: false, }, recordPayment: { isOpen: false, }, deleteModal: { isOpen: false, }, dataTableList: { isOpen: true, }, last: null, }; export function contextReducer(state, action) { const { keyState = null } = action; switch (action.type) { case actionTypes.OPEN_MODAL: return { ...state, deleteModal: { isOpen: true }, }; case actionTypes.CLOSE_MODAL: return { ...state, deleteModal: { isOpen: false }, }; case actionTypes.OPEN_PANEL: return { ...initialState, dataTableList: { isOpen: false, }, [keyState]: { isOpen: true }, }; case actionTypes.CLOSE_PANEL: return { ...initialState, }; default: { throw new Error(`Unhandled action type: ${action.type}`); } } } ================================================ FILE: frontend/src/context/adavancedCrud/selectors.jsx ================================================ const contextSelectors = (state) => { return { isModalOpen: () => { return state.isModalOpen; }, isPanelOpen: () => { return state.isPanelOpen; }, isBoxOpen: () => { return state.isBoxOpen; }, }; }; export default contextSelectors; ================================================ FILE: frontend/src/context/adavancedCrud/types.jsx ================================================ export const OPEN_MODAL = 'OPEN_MODAL'; export const CLOSE_MODAL = 'CLOSE_MODAL'; export const OPEN_PANEL = 'OPEN_PANEL'; export const CLOSE_PANEL = 'CLOSE_PANEL'; export const COLLAPSE_PANEL = 'COLLAPSE_PANEL'; ================================================ FILE: frontend/src/context/appContext/actions.jsx ================================================ import * as actionTypes from './types'; const contextActions = (dispatch) => { return { navMenu: { open: () => { dispatch({ type: actionTypes.OPEN_NAV_MENU }); }, close: () => { dispatch({ type: actionTypes.CLOSE_NAV_MENU }); }, collapse: () => { dispatch({ type: actionTypes.COLLAPSE_NAV_MENU }); }, }, app: { open: (appName) => { dispatch({ type: actionTypes.CHANGE_APP, playload: appName }); }, default: () => { dispatch({ type: actionTypes.DEFAULT_APP }); }, }, }; }; export default contextActions; ================================================ FILE: frontend/src/context/appContext/index.jsx ================================================ import { useMemo, useReducer, createContext, useContext } from 'react'; import { initialState, contextReducer } from './reducer'; import contextActions from './actions'; const AppContext = createContext(); function AppContextProvider({ children }) { const [state, dispatch] = useReducer(contextReducer, initialState); const value = useMemo(() => [state, dispatch], [state]); return {children}; } function useAppContext() { const context = useContext(AppContext); if (context === undefined) { throw new Error('useAppContext must be used within a AppContextProvider'); } const [state, dispatch] = context; const appContextAction = contextActions(dispatch); // const appContextSelector = contextSelectors(state); return { state, appContextAction }; } export { AppContextProvider, useAppContext }; ================================================ FILE: frontend/src/context/appContext/reducer.jsx ================================================ import * as actionTypes from './types'; export const initialState = { isNavMenuClose: false, currentApp: 'default', }; export function contextReducer(state, action) { switch (action.type) { case actionTypes.OPEN_NAV_MENU: return { ...state, isNavMenuClose: false, }; case actionTypes.CLOSE_NAV_MENU: return { ...state, isNavMenuClose: true, }; case actionTypes.COLLAPSE_NAV_MENU: return { ...state, isNavMenuClose: !state.isNavMenuClose, }; case actionTypes.CHANGE_APP: return { ...state, currentApp: action.playload, }; case actionTypes.DEFAULT_APP: return { ...state, currentApp: 'default', }; default: { throw new Error(`Unhandled action type: ${action.type}`); } } } ================================================ FILE: frontend/src/context/appContext/types.jsx ================================================ export const OPEN_NAV_MENU = 'OPEN_NAV_MENU'; export const CLOSE_NAV_MENU = 'CLOSE_NAV_MENU'; export const COLLAPSE_NAV_MENU = 'COLLAPSE_NAV_MENU'; export const CHANGE_APP = 'CHANGE_APP'; export const DEFAULT_APP = 'DEFAULT_APP'; ================================================ FILE: frontend/src/context/crud/actions.jsx ================================================ import * as actionTypes from './types'; const contextActions = (dispatch) => { return { modal: { open: () => { dispatch({ type: actionTypes.OPEN_MODAL }); }, close: () => { dispatch({ type: actionTypes.CLOSE_MODAL }); }, }, advancedBox: { open: () => { dispatch({ type: actionTypes.OPEN_ADVANCED_BOX }); }, close: () => { dispatch({ type: actionTypes.CLOSE_ADVANCED_BOX }); }, }, editBox: { open: () => { dispatch({ type: actionTypes.OPEN_EDIT_BOX }); }, close: () => { dispatch({ type: actionTypes.CLOSE_EDIT_BOX }); }, }, panel: { open: () => { dispatch({ type: actionTypes.OPEN_PANEL }); }, close: () => { dispatch({ type: actionTypes.CLOSE_PANEL }); }, collapse: () => { dispatch({ type: actionTypes.COLLAPSE_PANEL }); }, }, collapsedBox: { open: () => { dispatch({ type: actionTypes.OPEN_BOX }); }, close: () => { dispatch({ type: actionTypes.CLOSE_BOX }); }, collapse: () => { dispatch({ type: actionTypes.COLLAPSE_BOX }); }, }, readBox: { open: () => { dispatch({ type: actionTypes.OPEN_READ_BOX }); console.log('readBox open'); }, close: () => { dispatch({ type: actionTypes.CLOSE_READ_BOX }); console.log('readBox close'); }, collapse: () => { dispatch({ type: actionTypes.COLLAPSE_READ_BOX }); }, }, }; }; export default contextActions; ================================================ FILE: frontend/src/context/crud/index.jsx ================================================ import { useMemo, useReducer, createContext, useContext } from 'react'; import { initialState, contextReducer } from './reducer'; import contextActions from './actions'; import contextSelectors from './selectors'; const CrudContext = createContext(); function CrudContextProvider({ children }) { const [state, dispatch] = useReducer(contextReducer, initialState); const value = useMemo(() => [state, dispatch], [state]); return {children}; } function useCrudContext() { const context = useContext(CrudContext); if (context === undefined) { throw new Error('useCrudContext must be used within a CrudContextProvider'); } const [state, dispatch] = context; const crudContextAction = contextActions(dispatch); const crudContextSelector = contextSelectors(state); return { state, crudContextAction, crudContextSelector }; } export { CrudContextProvider, useCrudContext }; ================================================ FILE: frontend/src/context/crud/reducer.jsx ================================================ import * as actionTypes from './types'; export const initialState = { isModalOpen: false, isPanelClose: true, isBoxCollapsed: false, isReadBoxOpen: false, isAdvancedBoxOpen: false, isEditBoxOpen: false, }; export function contextReducer(state, action) { switch (action.type) { case actionTypes.OPEN_MODAL: return { ...state, isModalOpen: true, }; case actionTypes.CLOSE_MODAL: return { ...state, isModalOpen: false, }; case actionTypes.OPEN_PANEL: return { ...state, isPanelClose: false, }; case actionTypes.CLOSE_PANEL: return { ...state, isPanelClose: true, }; case actionTypes.COLLAPSE_PANEL: return { ...state, isPanelClose: !state.isPanelClose, }; case actionTypes.OPEN_BOX: return { ...state, isBoxCollapsed: true, }; case actionTypes.CLOSE_BOX: return { ...state, isBoxCollapsed: false, }; case actionTypes.COLLAPSE_BOX: return { ...state, isBoxCollapsed: !state.isBoxCollapsed, }; case actionTypes.OPEN_READ_BOX: return { ...state, isAdvancedBoxOpen: false, isEditBoxOpen: false, isReadBoxOpen: true, }; case actionTypes.CLOSE_READ_BOX: return { ...state, isReadBoxOpen: false, }; case actionTypes.OPEN_ADVANCED_BOX: return { ...state, isReadBoxOpen: false, isEditBoxOpen: false, isAdvancedBoxOpen: true, }; case actionTypes.CLOSE_ADVANCED_BOX: return { ...state, isAdvancedBoxOpen: false, }; case actionTypes.OPEN_EDIT_BOX: return { ...state, isReadBoxOpen: false, isAdvancedBoxOpen: false, isEditBoxOpen: true, }; case actionTypes.CLOSE_EDIT_BOX: return { ...state, isEditBoxOpen: false, }; case actionTypes.COLLAPSE_READ_BOX: return { ...state, isReadBoxOpen: !state.isReadBoxOpen, }; default: { throw new Error(`Unhandled action type: ${action.type}`); } } } ================================================ FILE: frontend/src/context/crud/selectors.jsx ================================================ const contextSelectors = (state) => { return { isModalOpen: () => { return state.isModalOpen; }, isPanelOpen: () => { return state.isPanelOpen; }, isBoxOpen: () => { return state.isBoxOpen; }, }; }; export default contextSelectors; ================================================ FILE: frontend/src/context/crud/types.jsx ================================================ export const OPEN_MODAL = 'OPEN_MODAL'; export const CLOSE_MODAL = 'CLOSE_MODAL'; export const OPEN_ADVANCED_BOX = 'OPEN_ADVANCED_BOX'; export const CLOSE_ADVANCED_BOX = 'CLOSE_ADVANCED_BOX'; export const OPEN_EDIT_BOX = 'OPEN_EDIT_BOX'; export const CLOSE_EDIT_BOX = 'CLOSE_EDIT_BOX'; export const OPEN_PANEL = 'OPEN_PANEL'; export const CLOSE_PANEL = 'CLOSE_PANEL'; export const COLLAPSE_PANEL = 'COLLAPSE_PANEL'; export const OPEN_BOX = 'OPEN_BOX'; export const CLOSE_BOX = 'CLOSE_BOX'; export const COLLAPSE_BOX = 'COLLAPSE_BOX'; export const OPEN_READ_BOX = 'OPEN_READ_BOX'; export const CLOSE_READ_BOX = 'CLOSE_READ_BOX'; export const COLLAPSE_READ_BOX = 'COLLAPSE_READ_BOX'; ================================================ FILE: frontend/src/context/erp/actions.jsx ================================================ import * as actionTypes from './types'; const contextActions = (dispatch) => { return { modal: { open: () => { dispatch({ type: actionTypes.OPEN_MODAL }); }, close: () => { dispatch({ type: actionTypes.CLOSE_MODAL }); }, }, readPanel: { open: () => { dispatch({ type: actionTypes.OPEN_PANEL, keyState: 'read' }); }, close: () => { dispatch({ type: actionTypes.CLOSE_PANEL }); }, }, updatePanel: { open: () => { dispatch({ type: actionTypes.OPEN_PANEL, keyState: 'update' }); }, close: () => { dispatch({ type: actionTypes.CLOSE_PANEL }); }, }, createPanel: { open: () => { dispatch({ type: actionTypes.OPEN_PANEL, keyState: 'create' }); }, close: () => { dispatch({ type: actionTypes.CLOSE_PANEL }); }, }, recordPanel: { open: () => { dispatch({ type: actionTypes.OPEN_PANEL, keyState: 'recordPayment', }); }, close: () => { dispatch({ type: actionTypes.CLOSE_PANEL }); }, }, }; }; export default contextActions; ================================================ FILE: frontend/src/context/erp/index.jsx ================================================ import { useMemo, useReducer, createContext, useContext } from 'react'; import { initialState, contextReducer } from './reducer'; import contextActions from './actions'; import contextSelectors from './selectors'; const ErpContext = createContext(); function ErpContextProvider({ children }) { const [state, dispatch] = useReducer(contextReducer, initialState); const value = useMemo(() => [state, dispatch], [state]); return {children}; } function useErpContext() { const context = useContext(ErpContext); if (context === undefined) { throw new Error('useErpContext must be used within a ErpContextProvider'); } const [state, dispatch] = context; const erpContextAction = contextActions(dispatch); const erpContextSelector = contextSelectors(state); return { state, erpContextAction, erpContextSelector }; } export { ErpContextProvider, useErpContext }; ================================================ FILE: frontend/src/context/erp/reducer.jsx ================================================ import * as actionTypes from './types'; export const initialState = { create: { isOpen: false, }, update: { isOpen: false, }, read: { isOpen: false, }, recordPayment: { isOpen: false, }, deleteModal: { isOpen: false, }, dataTableList: { isOpen: true, }, last: null, }; export function contextReducer(state, action) { const { keyState = null } = action; switch (action.type) { case actionTypes.OPEN_MODAL: return { ...state, deleteModal: { isOpen: true }, }; case actionTypes.CLOSE_MODAL: return { ...state, deleteModal: { isOpen: false }, }; case actionTypes.OPEN_PANEL: return { ...initialState, dataTableList: { isOpen: false, }, [keyState]: { isOpen: true }, }; case actionTypes.CLOSE_PANEL: return { ...initialState, }; default: { throw new Error(`Unhandled action type: ${action.type}`); } } } ================================================ FILE: frontend/src/context/erp/selectors.jsx ================================================ const contextSelectors = (state) => { return { isModalOpen: () => { return state.isModalOpen; }, isPanelOpen: () => { return state.isPanelOpen; }, isBoxOpen: () => { return state.isBoxOpen; }, }; }; export default contextSelectors; ================================================ FILE: frontend/src/context/erp/types.jsx ================================================ export const OPEN_MODAL = 'OPEN_MODAL'; export const CLOSE_MODAL = 'CLOSE_MODAL'; export const OPEN_PANEL = 'OPEN_PANEL'; export const CLOSE_PANEL = 'CLOSE_PANEL'; export const COLLAPSE_PANEL = 'COLLAPSE_PANEL'; ================================================ FILE: frontend/src/context/profileContext/actions.jsx ================================================ import * as actionTypes from './types'; const contextActions = (dispatch) => { return { modal: { open: () => { dispatch({ type: actionTypes.OPEN_MODAL }); }, close: () => { dispatch({ type: actionTypes.CLOSE_MODAL }); }, }, updatePanel: { open: () => { dispatch({ type: actionTypes.OPEN_PANEL, keyState: 'update' }); }, close: () => { dispatch({ type: actionTypes.CLOSE_PANEL }); }, }, }; }; export default contextActions; ================================================ FILE: frontend/src/context/profileContext/index.jsx ================================================ import { useMemo, useReducer, createContext, useContext } from 'react'; import { initialState, contextReducer } from './reducer'; import contextActions from './actions'; import contextSelectors from './selectors'; const ProfileContext = createContext(); function ProfileContextProvider({ children }) { const [state, dispatch] = useReducer(contextReducer, initialState); const value = useMemo(() => [state, dispatch], [state]); return {children}; } function useProfileContext() { const context = useContext(ProfileContext); if (context === undefined) { throw new Error('useProfileContext must be used within a ProfileContextProvider'); } const [state, dispatch] = context; const profileContextAction = contextActions(dispatch); const profileContextSelector = contextSelectors(state); return { state, profileContextAction, profileContextSelector }; } export { ProfileContextProvider, useProfileContext }; ================================================ FILE: frontend/src/context/profileContext/reducer.jsx ================================================ import * as actionTypes from './types'; export const initialState = { read: { isOpen: true, }, update: { isOpen: false, }, passwordModal: { isOpen: false, }, }; export function contextReducer(state, action) { const { keyState = null } = action; switch (action.type) { case actionTypes.OPEN_MODAL: return { ...state, passwordModal: { isOpen: true }, }; case actionTypes.CLOSE_MODAL: return { ...state, passwordModal: { isOpen: false }, }; case actionTypes.OPEN_PANEL: return { ...initialState, read: { isOpen: false, }, [keyState]: { isOpen: true }, }; case actionTypes.CLOSE_PANEL: return { ...initialState, }; default: { throw new Error(`Unhandled action type: ${action.type}`); } } } ================================================ FILE: frontend/src/context/profileContext/selectors.jsx ================================================ const contextSelectors = (state) => { return { isModalOpen: () => { return state.isModalOpen; }, isPanelOpen: () => { return state.isPanelOpen; }, }; }; export default contextSelectors; ================================================ FILE: frontend/src/context/profileContext/types.jsx ================================================ export const OPEN_MODAL = 'OPEN_PASSWORD_MODAL'; export const CLOSE_MODAL = 'CLOSE_PASSWORD_MODAL'; export const OPEN_PANEL = 'OPEN_PROFILE_PANEL'; export const CLOSE_PANEL = 'CLOSE_PROFILE_PANEL'; ================================================ FILE: frontend/src/forms/AdminForm.jsx ================================================ import { Form, Input, Select } from 'antd'; import { UploadOutlined, CloseOutlined, CheckOutlined } from '@ant-design/icons'; import { message, Upload, Button, Switch } from 'antd'; import useLanguage from '@/locale/useLanguage'; const beforeUpload = (file) => { const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png'; if (!isJpgOrPng) { message.error('You can only upload JPG/PNG file!'); } const isLt2M = file.size / 1024 / 1024 < 2; if (!isLt2M) { message.error('Image must smaller than 2MB!'); } return isJpgOrPng && isLt2M; }; export default function AdminForm({ isUpdateForm = false, isForAdminOwner = false }) { const translate = useLanguage(); return ( <> {!isUpdateForm && ( )} } unCheckedChildren={} /> {/* e.fileList} > */} ); } ================================================ FILE: frontend/src/forms/AdvancedSettingsForm.jsx ================================================ import { Switch, Form, Input, Button, Space, Select } from 'antd'; import { CloseOutlined, CheckOutlined, MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'; import { useSelector } from 'react-redux'; import { selectCurrentItem } from '@/redux/crud/selectors'; import { useState } from 'react'; import useLanguage from '@/locale/useLanguage'; export function SelectType() { const translate = useLanguage(); return ( {(fields, { add, remove }) => ( <> {fields.map((field) => ( remove(field.name)} /> ))} )} ); } export default function AdvancedSettingsForm({ isUpdateForm = false }) { const translate = useLanguage(); const { result } = useSelector(selectCurrentItem); const [type, setType] = useState(null); const options = ['number', 'text', 'date']; const handleChange = (value) => { setType(value); }; return ( <> ) ) : null} } unCheckedChildren={} /> ); } ================================================ FILE: frontend/src/forms/CurrencyForm.jsx ================================================ import React from 'react'; import { Switch, Form, Input } from 'antd'; import { CloseOutlined, CheckOutlined } from '@ant-design/icons'; export default function CurrencyForm({ isUpdateForm = false }) { return ( <> } unCheckedChildren={} /> ); } ================================================ FILE: frontend/src/forms/CustomerForm.jsx ================================================ import { Form, Input } from 'antd'; import { validatePhoneNumber } from '@/utils/helpers'; import useLanguage from '@/locale/useLanguage'; export default function CustomerForm({ isUpdateForm = false }) { const translate = useLanguage(); const validateEmptyString = (_, value) => { if (value && value.trim() === '') { return Promise.reject(new Error('Field cannot be empty')); } return Promise.resolve(); }; return ( <> ); } ================================================ FILE: frontend/src/forms/DynamicForm/index.jsx ================================================ import { useState } from 'react'; import { DatePicker, Input, Form, Select, InputNumber, Switch, Tag } from 'antd'; import { CloseOutlined, CheckOutlined } from '@ant-design/icons'; import useLanguage from '@/locale/useLanguage'; import { useMoney, useDate } from '@/settings'; import AutoCompleteAsync from '@/components/AutoCompleteAsync'; import SelectAsync from '@/components/SelectAsync'; import { generate as uniqueId } from 'shortid'; import { countryList } from '@/utils/countryList'; export default function DynamicForm({ fields, isUpdateForm = false }) { const [feedback, setFeedback] = useState(); return (
{Object.keys(fields).map((key) => { let field = fields[key]; if ((isUpdateForm && !field.disableForUpdate) || !field.disableForForm) { field.name = key; if (!field.label) field.label = key; if (field.hasFeedback) return ( ); else if (feedback && field.feedback) { if (feedback == field.feedback) return ; } else { return ; } } })}
); } function FormElement({ field, feedback, setFeedback }) { const translate = useLanguage(); const money = useMoney(); const { dateFormat } = useDate(); const { TextArea } = Input; const SelectComponent = () => ( ); const SelectWithTranslationComponent = () => ( ); const SelectWithFeedbackComponent = ({ feedbackValue, lanchFeedback }) => ( ); const ColorComponent = () => ( ); const TagComponent = () => ( ); const ArrayComponent = () => ( ); const CountryComponent = () => ( ); const SearchComponent = () => { return ( ); }; const formItemComponent = { select: , selectWithTranslation: , selectWithFeedback: ( ), color: , tag: , array: , country: , search: , }; const compunedComponent = { string: ( ), url: , textarea: