// nuxt 3 - plugins/my-plugin.ts import { useStore } from "~/stores/index"; import axios from "axios"; import { io } from "socket.io-client"; export default defineNuxtPlugin(() => { const module = "application"; const mode = "dev"; const paths = [ { name: "dev", url: "https://dev.api.utopia.com.vn/" }, { name: "local", url: "http://localhost:8000/" }, { name: "prod", url: "https://api.utopia.com.vn/" }, ]; const path = paths.find((v) => v.name === mode).url; const apis = [ { name: 'sendemail', url: 'send-email/' }, { name: 'deleteentry', url: 'delete-entry/' }, { name: 'emailpreview', url: 'email-preview/' }, { name: 'workflow', url: 'workflow/execute/' }, { name: 'accountentry', url: 'account-entry/', params: {} }, { name: 'accountmultientry', url: 'account-multi-entry/', params: {} }, { name: 'entryfile', url: 'data/Entry_File/', url_detail: 'data-detail/Entry_File/', params: { values: 'id,file__file,file__name,file__caption,file,file__user__fullname,create_time' } }, { name: 'importsetting', url: 'data/Import_Setting/', url_detail: 'data-detail/Import_Setting/', params: {} }, { name: 'modelfields', url: 'model-fields/', params: {} }, { name: 'readexcel', url: 'read-excel/', params: {} }, { name: 'findkey', url: 'find-key/', params: {} }, { name: 'dealerrights', url: 'data/Biz_Rights/', url_detail: 'data-detail/Biz_Rights/', params: { sort: '-id' } }, { name: "individual", url: "data/Individual/", url_detail: "data-detail/Individual/", params: { sort: "-id", values: "id,customer,dob,sex,sex__name,sex__en,zalo,facebook,company,company__fullname,create_time,update_time", }, }, { name: "transactiondiscount", url: "data/Transaction_Discount/", url_detail: "data-detail/Transaction_Discount/", params: { values: "id,transaction,discount,discount__code,discount__name,type,type__code,type__name,value,create_time,update_time" } }, { name: "organization", url: "data/Organization/", url_detail: "data-detail/Organization/", params: { sort: "-id", values: "id,customer,shortname,established_date,website,type,type__name,create_time,update_time", }, }, { name: "co_op", url: "data/Co_Ownership/", url_detail: "data-detail/Co_Ownership/", params: { values: 'id,transaction,people,people__code,people__fullname,people__phone,people__legal_code' } }, { name: "companytype", url: "data/Company_Type/", url_detail: "data-detail/Company_Type/", params: { values: "id,code,name,create_time", }, }, { name: "cart", url: "data/Cart/", url_detail: "data-detail/Cart/", commit: 'cart', params: { sort: "id", values: "id,code,name,dealer,dealer__code,dealer__name,create_time", distinct_values: { label: { type: "Concat", field: ["code", "name"] } }, summary: "annotate", } }, { name: "payment_schedule", url: "data/Payment_Schedule/", url_detail: "data-detail/Payment_Schedule/", params: { sort: "-id", values: "batch_date,amount_remain,penalty_remain,penalty_paid,penalty_amount,penalty_reduce,ovd_days,remain_amount,paid_amount,txn_detail__transaction__product__trade_code,txn_detail__status,txn_detail__transaction__product__code,txn_detail__phase__name,txn_detail,id,txn_detail__transaction__customer__fullname,txn_detail__transaction__customer__code,txn_detail__transaction__customer__legal_code,status__name,type__name,code,from_date,txn_detail__transaction__policy__code,to_date,amount,cycle,cycle_days,txn_detail__transaction,type,status,updater,entry,detail,txn_detail__transaction__code,txn_detail__code" }, }, { name: "people", url: "data/People/", url_detail: "data-detail/People/", params: { sort: "-id", values: "id,issued_place,issued_place__code,issued_place__name,contact_address,address,country__name,company__fullname,legal_code,company,country,email,creator,code,fullname,dob,sex,legal_code,sex__name,phone,issued_date,legal_type,legal_type__name,address,note,updater,updater__fullname,create_time,update_time", distinct_values: { label: { type: "Concat", field: ["code", "fullname", "phone"] }, order: { type: "RowNumber" }, }, summary: "annotate", }, }, { name: 'productnote', url: 'data/Product_Note/', url_detail: 'data-detail/Product_Note/', commit: 'productnote', params: {sort: 'id',values: 'id,detail,user,user__username,user__fullname,create_time,update_time,ref,ref__cart__dealer,ref__trade_code' } }, { name:"customernote", url: "data/Customer_Note/", url_detail: "data-detail/Customer_Note/", params: { values: 'id,ref,detail,user,create_time,update_time' } }, { name: 'entrytype', url: 'data/Entry_Type/', url_detail: 'data-detail/Entry_Type/', params: {} }, { name: 'entrycategory', url: 'data/Entry_Category/', url_detail: 'data-detail/Entry_Category/', params: {} }, { name: 'accounttype', url: 'data/Account_Type/', url_detail: 'data-detail/Account_Type/', params: { sort: 'id' } }, { name: 'internalaccount', url: 'data/Internal_Account/', url_detail: 'data-detail/Internal_Account/', params: { sort: 'branch,currency,type', values: 'id,currency,currency__code,currency__name,code,balance,create_time,update_time,type,type__code,type__name,branch,branch__code,branch__name', distinct_values: { label: { type: 'Concat', field: ['branch__name', 'code', 'type__name'] } }, summary: 'annotate' } }, { name: "currency", url: "data/Currency/", url_detail: "data-detail/Currency/", params: {} }, { name: "approvestatus", url: "data/Approve_Status/", url_detail: "data-detail/Approve_Status/", params: {} }, { name: 'bizrights', url: 'data/Biz_Rights/', url_detail: 'data-detail/Biz_Rights/', params: { sort: '-id' } }, { name: "feetype", url: "data/Fee_Type/", url_detail: "data-detail/Fee_Type/", params: { sort: "id", values: "id,index,code,name,type,value,type__code,type__name,method,method__code,method__name,create_time", distinct_values: { label: { type: "Concat", field: ["name", "method__name", "type__name", "value"], }, }, summary: "annotate", }, }, { name: "dealersetting", url: "data/Biz_Setting/", url_detail: "data-detail/Biz_Setting/", params: { sort: "index" }, }, { name: "documentaudit", url: "data/Document_Audit/", url_detail: "data-detail/Document_Audit/", params: { sort: "index" }, }, { name: "documenttype", url: "data/Document_Type/", url_detail: "data-detail/Document_Type/", params: { sort: "index" }, }, { name: "getcodeCustomer", url: "increment/Customer/KH/", params: {}, }, { name: "getcodepeople", url: "increment/People/RE/", params: {}, }, { name: "getcodecompany", url: "increment/Company/CP/", params: {}, }, { name: "country", url: "data/Country/", commit: "country", params: { sort: "id", values: "id,code,name,en,create_time", }, }, { name: "status", url: "data/Approve_Status/", params: { values: "id,code,name,create_time", }, }, { name: "image", url: "data/Image/", url_detail: "data-detail/Image/", params: {} }, { name: "file", url: "data/File/", url_detail: "data-detail/File/", params: {} }, { name: "filetype", url: "data/File_Type/", url_detail: "data-detail/File_Type/", params: {} }, { name: "news", commit: "updateNews", url: "data/News/", url_detail: "data-detail/News/", params: { values: "id,title,subtitle,create_time" }, }, { name: "category", commit: "updateCategory", url: "data/Category/", url_detail: "data-detail/Category/", params: {}, }, { name: "contract", url: "data/Contract/", url_detail: "data-detail/Contract/", params: { sort: "-id" }, }, { name: "contractstatus", url: "data/Contract_Status/", url_detail: "data-detail/Contract_Status/", params: {}, }, { name: "token", url: "data/Token/", url_detail: "data-detail/Token/", params: { values: "id,token,browser,browser_version,ip,os,platform,expiry,create_time,update_time,user,user__fullname,user__username", sort: "-id", }, }, { name: "authtoken", url: "auth-token/", params: {} }, { name: "notification", commit: "updateNotification", url: "data/Notify/", url_detail: "data-detail/Notify/", params: { values: "id,title,content,image,link,task_log,user,user__username,user__fullname,event,seen,create_time,event__code,event__name,update_time", }, }, { name: "common", commit: "common", url: "data/Biz_Setting/", url_detail: "data-detail/Biz_Setting/", params: { sort: "index" }, }, { name: "upload", url: "upload/", params: {} }, { name: "paymentstatus", url: "data/Payment_Status/", url_detail: "data-detail/Payment_Status/", params: { values: "id,code,name,en,index,create_time", }, }, { name: "paymenttype", url: "data/Payment_Type/", url_detail: "data-detail/Payment_Type/", params: { values: "id,code,name,en,index,create_time", }, }, { name: "paymentmethod", url: "data/Payment_Method/", url_detail: "data-detail/Payment_Method/", params: {} }, { name: "salepolicy", url: "data/Sale_Policy/", url_detail: "data-detail/Sale_Policy/", params: { values: "id,code,name,deposit,method,method__code,method__name,create_time,enable,contract_allocation_percentage,create_time,update_time,index", sort: "index" } }, { name: "paymentplan", url: "data/Payment_Plan/", url_detail: "data-detail/Payment_Plan/", params: { values: "policy__enable,id,policy,policy__code,policy__name,cycle,value,type,days,payment_note,due_note,create_time,update_time", sort: "cycle" }, }, { name: "request", url: "data/Request/", url_detail: "data-detail/Request/", params: {} }, { name: "register", url: "data/Register/", url_detail: "data-detail/Register/", params: {} }, { name: "sendemail", url: "send-email/", path: "etl", params: {} }, { name: "sendemailnow", url: "send-email-now/", path: "etl", params: {} }, { name: "usersession", url: "data/User_Session/", url_detail: "data-detail/User_Session/", params: {} }, { name: "userlog", url: "data/User_Log/", url_detail: "data-detail/User_Log/", params: {} }, { name: "usersetting", url: "data/User_Setting/", url_detail: "data-detail/User_Setting/", params: {} }, { name: "account-entry", url: "/account-entry/", params: {} }, { name: "valuetype", url: "data/Value_Type/", url_detail: "data-detail/Value_Type/", params: { values: "id,code,name,en,index,create_time", sort: "index" }, }, { name: "bizsetting", commit: "bizsetting", url: "data/Biz_Setting/", url_detail: "data-detail/Biz_Setting/", params: {}, }, { name: "discounttype", commit: "discounttype", url: "data/Discount_Type/", url_detail: "data-detail/Discount_Type/", params: { values: 'id,code,name,value,type,type__name,method,method__name', distinct_values: { label: { type: "Concat", field: ["code", "name", "type__name"] }, }, summary: "annotate", }, }, { name: "customer", url: "data/Customer/", url_detail: "data-detail/Customer/", params: { values: "id,update_time,creator,creator__fullname,country,country__name,country__en,issued_date,issued_place,issued_place__name,code,email,fullname,legal_code,phone,legal_type,legal_type__name,address,contact_address,note,type,type__name,updater,updater__fullname,create_time,update_time", distinct_values: { label: { type: "Concat", field: ["code", "fullname", "phone", "legal_code"] }, order: { type: "RowNumber" }, image_count: { type: "Count", field: "id", subquery: { model: "Customer_File", column: "ref" } }, count_note: { type: "Count", field: "id", subquery: { model: "Customer_Note", column: "ref" } }, count_product: { type: "Count", field: "id", subquery: { model: "Product_Booked", column: "transaction__customer" } }, sum_product: { type: "Sum", field: "transaction__sale_price", subquery: { model: "Product_Booked", column: "transaction__customer" } }, sum_receiver: { type: "Sum", field: "transaction__amount_received", subquery: { model: "Product_Booked", column: "transaction__customer" } }, sum_remain: { type: "Sum", field: "transaction__amount_remain", subquery: { model: "Product_Booked", column: "transaction__customer" } } }, summary: "annotate", filter: { deleted: 0 }, sort: "-id", }, }, { name: "transaction", commit: "transaction", url: "data/Transaction/", url_detail: "data-detail/Transaction/", params: { sort: '-date', values: "date,txncurrent__detail,txncurrent__detail__status,customer__type,txncurrent,txncurrent__detail__amount,txncurrent__detail__amount_remaining,txncurrent__detail__status__name,product__zone_type__name,product__trade_code,product__cart__dealer,customer__legal_code,customer__legal_type__name,payment_plan,id,code,customer,customer__code,customer__fullname,customer__phone,product,phase,phase__name,phase__code,policy,policy__code,policy__name,origin_price,discount_amount,sale_price,deposit_amount,deposit_received,deposit_remaining,amount_received,amount_remain,create_time,update_time" } }, { name: "transactionphase", url: "data/Transaction_Phase/", url_detail: "data-detail/Transaction_Phase/", params: { values: "id,code,name,create_time", }, }, { name: "phasedoctype", url: "data/Phase_Doctype/", url_detail: "data-detail/Phase_Doctype/", params: { values: "id,phase,doctype,doctype__code,doctype__name", sort:"doctype__index" } }, { name: "transactiontype", url: "data/Transaction_Type/", url_detail: "data-detail/Transaction_Type/", params: { values: "id,code,name,detail,create_time", }, }, { name: "reservation", commit: "reservation", url: "data/Transaction_Detail/", url_detail: "data-detail/Transaction_Detail/", params: { values: "id,code,date,amount,amount_received,amount_remaining,phase,due_date,transaction,creator,status,approver,approve_time,create_time,update_time", }, }, { name: "transactionfile", commit: "transactionfile", url: "data/Transaction_File/", url_detail: "data-detail/Transaction_File/", params: { values: "id,txn_detail,file,file__name,file__size,file__file,create_time,file__doc_type", }, }, { name: "productbooked", commit: "productbooked", url: "data/Product_Booked/", url_detail: "data-detail/Product_Booked/", params: { }, }, { name: "product", commit: "product", url: "data/Product/", url_detail: "data-detail/Product/", params: { sort: "id", values: "prdbk__transaction__amount_remain,prdbk__transaction,price_excluding_vat,prdbk__transaction__txncurrent__detail__status__name,locked_until,note,cart,cart__name,cart__code,cart__dealer,cart__dealer__code,cart__dealer__name,direction,type,zone_type,dealer,link,type__name,dealer__code,dealer__name,prdbk,prdbk__transaction__customer,prdbk__transaction,prdbk__transaction__policy__code,prdbk__transaction__sale_price,prdbk__transaction__discount_amount,prdbk__transaction__code,prdbk__transaction__customer__code,prdbk__transaction__customer__phone,prdbk__transaction__customer__fullname,prdbk__transaction__customer__legal_code,id,code,trade_code,land_lot_code,zone_code,zone_type__name,lot_area,building_area,total_built_area,number_of_floors,land_lot_size,origin_price,direction__name,villa_model,product_type,template_name,project,project__name,status,status__code,status__name,status__color,status__sale_status,status__sale_status__color,create_time,prdbk__transaction__amount_received", distinct_values: { label: { type: "Concat", field: ["trade_code", "type__name", "land_lot_size", "zone_type__name", "status__name"] }, count_note: { type: 'Count', field: 'prdnote' } }, summary: "annotate", }, }, { name: "productdocument", commit: "productdocument", url: "data/Product_Document/", url_detail: "data-detail/Product_Document/", params: { values: "id,product,product__code,product__type,product__type__code,product__type__name,product__type__en,product__category,product__category__code,product__category__name,document,document__code,document__name,document__en", }, }, { name: "productstatus", url: "data/Product_Status/", url_detail: "data-detail/Product_Status/", params: { sort: "name", values: "id,code,name,color,index,sale_status,create_time", }, }, { name: "producttype", url: "data/Product_Type/", url_detail: "data-detail/Product_Type/", params: { values: "id,code,name,create_time", }, }, { name: "salestatus", url: "data/Sale_Status/", url_detail: "data-detail/Sale_Status/", params: { values: "id,code,name,color,index,create_time", }, }, { name: "project", url: "data/Project/", url_detail: "data-detail/Project/", params: { values: "id,code,name,investor,status,create_time,update_time", }, }, { name: "zonetype", url: "data/Zone_Type/", url_detail: "data-detail/Zone_Type/", params: { values: "id,code,name,create_time", }, }, { name: "direction", url: "data/Direction/", url_detail: "data-detail/Direction/", params: { values: "id,code,name,create_time", }, }, { name: "settingclass", commit: "settingclass", url: "data/Setting_Class/", url_detail: "data-detail/Setting_Class/", params: {}, }, { name: "user", url: "data/User/", url_detail: "data-detail/User/", params: { sort: "-id", values: "id,auth_method__code,blocked,auth_status__code,username,register_method__code,fullname,type,type__code,type__name,create_time,create_time__date,auth_method,auth_status,register_method,create_time,update_time", distinct_values: { label: { type: "Concat", field: ["username", "fullname"] } }, summary: "annotate", }, }, { name: "gethash", url: "get-hash/", params: {} }, { name: "login", url: "login/", params: { values: "id,username,password,avatar,fullname,display_name,type,type__code,type__name,blocked,block_reason,block_reason__code,block_reason__name,blocked_by,last_login,auth_method,auth_method__code,auth_method__name,auth_status,auth_status__code,auth_status__name,register_method,register_method__code,register_method__name,create_time,update_time", }, }, { name: "reservation", commit: "reservation", url: "data/Reservation/", url_detail: "data-detail/Reservation/", params: {}, }, { name: "settingtype", commit: "settingtype", url: "data/Setting_Type/", url_detail: "data-detail/Setting_Type/", params: {}, }, { name: "colorchoice", commit: "colorchoice", url: "data/Color_Choice/", url_detail: "data-detail/Color_Choice/", params: { sort: "id" }, }, { name: "filterchoice", commit: "filterchoice", url: "data/Filter_Choice/", url_detail: "data-detail/Filter_Choice/", params: { sort: "id" }, }, { name: "datatype", commit: "datatype", url: "data/Data_Type/", url_detail: "data-detail/Data_Type/", params: { sort: "id" }, }, { name: "textalign", commit: "textalign", url: "data/Text_Align/", url_detail: "data-detail/Text_Align/", params: { sort: "id" }, }, { name: "placement", commit: "placement", url: "data/Placement/", url_detail: "data-detail/Placement/", params: { sort: "id" }, }, { name: "colorscheme", commit: "colorscheme", url: "data/Color_Scheme/", url_detail: "data-detail/Color_Scheme/", params: { sort: "id" }, }, { name: "textcolor", commit: "textcolor", url: "data/Text_Color/", url_detail: "data-detail/Text_Color/", params: { sort: "id" }, }, { name: "filtertype", commit: "filtertype", url: "data/Filter_Type/", url_detail: "data-detail/Filter_Type/", params: { sort: "id" }, }, { name: "sorttype", commit: "sorttype", url: "data/Sort_Type/", url_detail: "data-detail/Sort_Type/", params: { sort: "id" }, }, { name: "tablesetting", commit: "tablesetting", url: "data/Table_Setting/", url_detail: "data-detail/Table_Setting/", params: { sort: "id", values: "id,code,name,detail" }, }, { name: "settingchoice", commit: "settingchoice", url: "data/Setting_Choice/", url_detail: "data-detail/Setting_Choice/", params: { sort: "id" }, }, { name: "menuchoice", commit: "menuchoice", url: "data/Menu_Choice/", url_detail: "data-detail/Menu_Choice/", params: {}, }, { name: "moneyunit", commit: "moneyunit", url: "data/Money_Unit/", url_detail: "data-detail/Money_Unit/", params: {}, }, { name: "legaltype", commit: "legaltype", url: "data/Legal_Type/", url_detail: "data-detail/Legal_Type/", params: { page: -1 }, }, { name: "sex", commit: "sex", url: "data/Sex/", url_detail: "data-detail/Sex/", params: {} }, { name: "usertype", commit: "UserType", url: "data/User_Type/", url_detail: "data-detail/User_Type/", params: {} }, { name: "executionmethod", commit: "executionmethod", url: "data/Execution_Method/", url_detail: "data-detail/Execution_Method/", params: {}, }, { name: "customerpeople", url: "data/Customer_People/", url_detail: "data-detail/Customer_People/", params: { values: "people__legal_code,id,customer,people,people__code,people__address,people__fullname,people__phone,relation,relation__code,relation__name,relation__en,create_time", }, }, { name: "legalrep", url: "data/Legal_Rep/", url_detail: "data-detail/Legal_Rep/", params: { values: "id,organization,people,people__code,people__address,people__fullname,people__phone,relation,relation__code,relation__name,relation__en,create_time", }, }, { name: "customerfile", url: "data/Customer_File/", url_detail: "data-detail/Customer_File/", params: { values: "id,ref,file,file__name,file__file" }, }, { name: "customertype", url: "data/Customer_Type/", url_detail: "data-detail/Customer_Type/", params: { values: "id,code,name,create_time" }, }, { name: "peoplefile", url: "data/People_File/", url_detail: "data-detail/People_File/", params: { values: "id,ref,file,file__name,file__file" }, }, { name: "collaboratorfile", url: "data/Collaborator_File/", url_detail: "data-detail/Collaborator_File/", params: { values: "id,ref,file,file__name,file__file" }, }, { name: "applicationfile", url: "data/Application_File/", url_detail: "data-detail/Application_File/", params: { values: "id,ref,file,file__name,file__file,file__type__code,file__type__name,file__doc_type__code,file__doc_type__name,file__doc_type__en", }, }, { name: "useraction", url: "data/User_Action/", url_detail: "data-detail/User_Action/", params: { values: "id,action,action__code,action__name,action__message,action__image,action__file,action__link,user,message,image,file,link,create_time", }, }, { name: "relation", commit: "relation", url: "data/Relation/", url_detail: "data-detail/Relation/", params: { sort: "id" }, }, { name: "company", url: "data/Company/", url_detail: "data-detail/Company/", params: { values: "id,country,website,email,code,phone,shortname,fullname,address,create_time,update_time,creator,creator__fullname,updater,updater__fullname", }, }, { name: "exportlog", url: "data/Export_Log/", url_detail: "data-detail/Export_Log/", params: {} }, { name: "bank", url: "data/Bank/", url_detail: "data-detail/Bank/", params: {} }, { name: "exportcsv", url: "exportcsv/", params: {} }, { name: "internalentry", url: "data/Internal_Entry/", url_detail: "data-detail/Internal_Entry/", params: { sort: "-id", values: "product__trade_code,allocation_amount,allocation_remain,allocation_detail,id,customer__fullname,product__trade_code,customer,customer__code,product,product__code,ref,category,category__code,category__name,account__currency__code,balance_before,balance_after,code,account,account__code,account__branch__name,account__type__name,date,amount,content,inputer,inputer__fullname,approver,approver__fullname,create_time,update_time,type,type__code,type__name", }, }, { name: "applicationrights", url: "data/Application_Rights/", url_detail: "data-detail/Application_Rights/", params: { sort: "-id" }, }, { name: "productfile", url: "data/Product_File/", url_detail: "data-detail/Product_File/", params: { values: "id,product,file,create_time" }, }, { name: "Email_Template", url: "data/Email_Template/", url_detail: "data-detail/Email_Template/", params: {}, }, { name: "projectfile", url: "data/Project_File/", url_detail: "data-detail/Project_File/", params: { values: "id,project,file,create_time" }, }, { name: "issuedplace", url: "data/Issued_Place/", url_detail: "data-detail/Issued_Place/", params: { values: "id,code,name,create_time" }, }, { name: "dealer", url: "data/Dealer/", url_detail: "data-detail/Dealer/", params: { values: "id,count_sale,code,name,phone,address,email,create_time,sale_amount,pay_sale,commission_amount,pay_commission,commission_remain,batch_date" }, }, { name: "layersetting", url: "data/Layer_Setting/", url_detail: "data-detail/Layer_Setting/", params: { values: "id,code,name,detail,user,create_time,update_time" } }, { name: "grouprights", commit: "grouprights", url: "data/Group_Rights/", url_detail: "data-detail/Group_Rights/", params: { values: 'id,setting,setting__vi,setting__code,setting__category,group,group__name,is_edit,create_time', sort: '-id' }, }, { name: "discountmethod", commit: "discountmethod", url: "data/Discount_Method/", url_detail: "data-detail/Discount_Method/", params: {sort: '-id'}, }, { name: "emailtemplate", url: "data/Email_Template/", url_detail: "data-detail/Email_Template/", params: { values: "id,name,content,create_time,update_time" } }, { name: "gift", commit: "gift", url: "data/Gift/", url_detail: "data-detail/Gift/", params: {sort: '-id'}, }, { name: "transactiongift", commit: "transactiongift", url: "data/Transaction_Gift/", url_detail: "data-detail/Transaction_Gift/", params: {}, }, { name: "invoice", commit: "invoice", url: "data/Invoice/", url_detail: "data-detail/Invoice/", params: {}, }, ]; const store = useStore(); const { $copy, $clone, $updateSeriesFields, $snackbar, $remove, $dialog } = useNuxtApp(); const requestLogin = function () { store.commit("login", undefined); store.commit("layersetting", undefined); store.commit("lastlegendfiltertab", "Giỏ hàng"); window.location.href = `https://${mode === "dev" ? "dev." : ""}login.utopia.com.vn/signin?module=${module}&link=${window.location.origin}`; }; const getpath = function (name) { return name ? paths.find((v) => v.name === name).url : path; }; const findapi = function (name) { const result = Array.isArray(name) ? apis.filter((v) => name.findIndex((x) => v.name === x) >= 0) : apis.find((v) => v.name === name); return $copy(result); }; const readyapi = function (list) { var array = []; list.forEach((element) => { let found = apis.find((v) => v.name === element); if (found) { let ele = JSON.parse(JSON.stringify(found)); ele.ready = store[element] ? true : false; array.push(ele); } }); return array; }; // get data const getapi = async function (list) { try { let arr = list.map((v) => { let found = apis.find((api) => api.name === v.name); let url = (v.path ? paths.find((x) => x.name === v.path).url : path) + (v.url ? v.url : found.url); let params = v.params ? v.params : found.params === undefined ? {} : found.params; params.login = store.login ? store.login.id : undefined; return { url: url, params: params }; }); //let data = await Promise.all(arr.map(v=>axios.get(v.url, {params: v.params}))) let data = await Promise.all(arr.map((v) => $fetch(v.url, { params: v.params }))); data.map((v, i) => { list[i].data = v; if (list[i].commit) { let data = v.rows ? v.rows : v; store.commit(list[i].commit, data); } }); return list; } catch (err) { console.log(err); return "error"; } }; // insert data const insertapi = async function (name, data, values, notify) { try { let found = findapi(name); let curpath = found.path ? paths.find((x) => x.name === found.path).url : path; var rs; if (!Array.isArray(data)) rs = await axios.post(`${curpath}${found.url}`, data, { params: { values: values } }); else { let params = { action: "import", values: values }; rs = await axios.post(`${curpath}import-data/${found.url.substring(5, found.url.length - 1)}/`, data, { params: params, }); } // update store if (found.commit) { if (store[found.commit]) { let copy = JSON.parse(JSON.stringify(store[found.commit])); let rows = Array.isArray(rs.data) ? rs.data : [rs.data]; rows.map((v) => { if (v.id && !v.error) { let idx = copy.findIndex((x) => x.id === v.id); if (idx >= 0) copy[idx] = v; else copy.push(v); } }); store.commit(found.commit, copy); } } if (notify !== false) { store.lang === "en" ? $snackbar("Data has been successfully saved to the system.", "Success", "Success") : $snackbar("Dữ liệu đã được lưu vào hệ thống", "Thành công", "Success"); } return rs.data; } catch (err) { console.log(err); return "error"; } }; // update api const updateapi = async function (name, data, values, notify) { try { let found = findapi(name); let curpath = found.path ? paths.find((x) => x.name === found.path).url : path; let updateUrl = found.url_detail ? found.url_detail : found.url; let rs = await axios.put(`${curpath}${updateUrl}${data.id}/`, data, { params: { values: values ? values : found.params.values }, }); if (found.commit) { let index = store[found.commit] ? store[found.commit].findIndex((v) => v.id === rs.data.id) : -1; if (index >= 0) { var copy = JSON.parse(JSON.stringify(store[found.commit])); if (Array.isArray(rs.data) === false) copy[index] = rs.data; else { rs.data.forEach((v) => { let index = copy.findIndex((v) => v.id === v.id); if (index >= 0) copy[index] = v; }); } store.commit(found.commit, copy); } } if (notify !== false) { store.lang === "en" ? $snackbar("Data has been successfully saved to the system.", "Success", "Success") : $snackbar("Dữ liệu đã được lưu vào hệ thống", "Thành công", "Success"); } return rs.data; } catch (err) { console.log(err); return "error"; } }; // patch api const patchapi = async function (name, data, values, notify) { try { let found = findapi(name); let curpath = found.path ? paths.find((x) => x.name === found.path).url : path; let updateUrl = found.url_detail ? found.url_detail : found.url; let rs = await axios.patch(`${curpath}${updateUrl}${data.id}/`, data, { params: { values: values ? values : found.params?.values }, }); if (notify !== false) { store.lang === "en" ? $snackbar("Data has been successfully saved to the system.", "Success", "Success") : $snackbar("Dữ liệu đã được lưu vào hệ thống", "Thành công", "Success"); } return rs.data; } catch (err) { console.log(err); return "error"; } }; const findpage = function (arr) { var copy = $copy(store.pagetrack); var doFind = function () { let found = undefined; for (let i = 1; i <= 30; i++) { let name = `pagedata${i}`; if (!copy[name]) { found = name; copy[name] = true; break; } } if (!found) console.log("pagename not found"); return found; }; let result; if (arr) { result = []; arr.map((v) => { result.push({ name: v, value: doFind() }); }); } else { result = doFind(copy); } store.commit("pagetrack", copy); return result; }; const getpage = function (showFilter) { return { data: [], fields: [], filters: [], update: undefined, action: undefined, filterby: undefined, api: { full_data: true }, origin_api: { full_data: true }, tablesetting: undefined, setting: undefined, tabfield: true, setpage: {}, showFilter: !showFilter ? true : showFilter, }; }; const setpage = function (pagename, row, api) { let json = row.detail; let fields = $updateSeriesFields(json.fields); let copy = store[pagename] || getpage(); copy.fields = fields; copy.setting = $copy(row); if (json.filters) copy.filters = $copy(json.filters); if (json.tablesetting) copy.tablesetting = json.tablesetting; if (api) { let copyApi = $copy(api); delete copyApi.data; copyApi.full_data = api.data.full_data; copyApi.total_rows = api.data.total_rows; copy.api = copyApi; copy.origin_api = copy; } store.commit(pagename, copy); return copy; }; const getdata = async function (name, filter, params, first) { let found = findapi(name); if (params) found.params = params; else if (filter) found.params.filter = filter; let rs = await getapi([found]); let data = rs[0].data; if (data) { if (data.rows) { return first ? (data.rows.length > 0 ? data.rows[0] : undefined) : data.rows; } else { let rows = Array.isArray(data) ? data : [data]; return first ? (rows.length > 0 ? rows[0] : data) : data; } } else { let rows = Array.isArray(data) ? data : [data]; return first ? (rows.length > 0 ? rows[0] : data) : data; } }; const subscribe = (name, filter, callback) => { const apiConfig = findapi(name); if (!apiConfig) { console.error(`[subscribe] API config for '${name}' not found.`); return; } const urlParts = apiConfig.url.split('/').filter(p => p); // Capitalize the model name for the backend consumer const modelName = urlParts.length > 1 ? urlParts[1].charAt(0).toUpperCase() + urlParts[1].slice(1) : null; if (!modelName) { console.error(`[subscribe] Could not determine model name from URL for '${name}'.`); return; } const params = $clone(apiConfig.params) || {}; // List of parameters that need to be stringified if they are objects const paramsToJSONify = ['filter_or', 'exclude', 'distinct_values', 'calculation', 'final_filter', 'final_exclude']; // Apply the filter passed to subscribe function if (filter) { params.filter = JSON.stringify(filter); } // Stringify other dictionary-like parameters if they exist and are objects for (const key of paramsToJSONify) { if (params[key] && typeof params[key] === 'object' && !Array.isArray(params[key])) { params[key] = JSON.stringify(params[key]); } } const payload = { name: modelName, params: params }; subscribeToData(payload, callback); }; // insert row var insertrow = async function (name, data, values, pagename, notify) { let result = await insertapi(name, data, values, notify); if (result === "error" || !pagename || !store[pagename]) return result; let copy = $clone(store[pagename]); copy.update = { refresh: true }; store.commit(pagename, copy); return result; }; // update row const updaterow = async function (name, data, values, pagename, notify) { let result = await updateapi(name, data, values, notify); if (result === "error" || !pagename || !store[pagename]) return result; let copy = $clone(store[pagename]); copy.update = { refresh: true }; store.commit(pagename, copy); return result; }; // patch row const patchrow = async function (name, data, values, pagename, notify) { let result = await patchapi(name, data, values, notify); if (result === "error" || !pagename || !store[pagename]) return result; let copy = $clone(store[pagename]); copy.update = { refresh: true }; store.commit(pagename, copy); return result; }; // delete data const deleteapi = async function (name, id) { try { var rs; let found = findapi(name); if (!Array.isArray(id)) rs = await $fetch(`${path}${found.url_detail}${id}`, { method: "delete" }); else { let params = { action: "delete" }; rs = await $fetch(`${path}import-data/${found.url.substring(5, found.url.length - 1)}/`, id, { params: params, }); } if (found.commit) { let copy = JSON.parse(JSON.stringify(store[found.commit])); if (!Array.isArray(id)) { let index = copy.findIndex((v) => v.id === id); if (index >= 0) $remove(copy, index); } else { rs.data.forEach((element) => { let index = copy.findIndex((v) => v.id === element.id); if (index >= 0) $remove(copy, index); }); } store.commit(found.name, copy); console.log("copy", copy); } return id; } catch (err) { console.log(err); if (err.response) { let content = `Đã xảy ra lỗi, xóa dữ liệu không thành công`; if (err.response.data) content += `
${JSON.stringify(err.response.data)}
`; $dialog(content, "Lỗi", "Error"); } return "error"; } }; // delete row const deleterow = async function (name, id, pagename) { let result = await deleteapi(name, id); if (result === "error" || !pagename || !store[pagename]) return result; let copy = $clone(store[pagename]); copy.update = { refresh: true }; store.commit(pagename, copy); return result; }; // update page const updatepage = function (pagename, row, action) { let copy = $clone(store[pagename]); let rows = Array.isArray(row) ? row : [row]; rows.map((x) => { let idx = copy.data.findIndex((v) => v.id === x.id); if (action === "delete") { if (idx >= 0) $remove(copy.data, idx); } else { idx >= 0 ? (copy.data[idx] = x) : copy.data.unshift(x); } }); copy.update = { data: copy.data }; store.commit(pagename, copy); }; const buildFileUrl = (file) => { if (!file || typeof file !== 'string') { console.error(`Invalid file__file: ${file}`) return; } return `${getpath()}static/files/${encodeURIComponent(file)}`; } const generateDocument = async (params) => { const apiBaseUrl = path; const url = new URL(`${apiBaseUrl}generate-document/`); if (params) { for (const key in params) { if (Object.hasOwnProperty.call(params, key)) { const value = params[key]; if (value !== undefined && value !== null) { url.searchParams.append(key, value); } } } } try { const response = await $fetch(url.toString(), { method: "GET", }); if (response && response.pdf) { const pdfUrl = `${apiBaseUrl}static/contract/${response.pdf}`; return { success: true, pdfUrl: pdfUrl, data: response }; } else { console.error("generateDocument: Định dạng phản hồi API không hợp lệ.", response); return { success: false, error: "Định dạng phản hồi API không hợp lệ." }; } } catch (error) { console.error("Lỗi khi tạo tài liệu:", error); return { success: false, error: error.data?.message || error.message }; } }; const accountEntry = async (params) => { const apiBaseUrl = path; try { const response = await $fetch(`${apiBaseUrl}account-entry/`, { method: "POST", body: params, headers: { "Content-Type": "application/json", }, }); if (response) { return { success: true, data: response }; } else { console.error("Định dạng phản hồi API không hợp lệ.", response); return { success: false, error: "Định dạng phản hồi API không hợp lệ." }; } } catch (error) { console.error("Lỗi khi tạo accountEntry:", error); return { success: false, error: error.data?.message || error.message }; } }; /** * @param {'edit' | 'view'} right * @param {{ code?: string, category?: string }} options * `code` & `category` from `Biz_Setting` * - If passed options, returns edit rights for `code` (useful for components used in modals in many different tabs) * - If not passed, returns edit rights for current tab & subtab * @returns {boolean} */ const getEditRights = (right = 'edit', { code, category } = {}) => { if (!['edit', 'view'].includes(right)) throw new Error(`right ${right} is not one of ['edit', 'view']`); const getRight = (rightObj) => { return right === 'edit' ? rightObj && rightObj.is_edit : Boolean(rightObj); } if (store.rights.length === 0) return true; // full rights if (code && category) { // if passed, must pass both const foundRight = store.rights.find(({ setting__category, setting__code }) => setting__category === category && setting__code === code); return getRight(foundRight); } else { const { tab, subtab } = store.tabinfo; let isTabEdit; let isSubTabEdit; const tabRight = store.rights.find(rights => rights.setting === tab.id); isTabEdit = getRight(tabRight); if (!subtab) isSubTabEdit = false; else { const subTabRight = store.rights.find(rights => rights.setting === subtab.id); isSubTabEdit = getRight(subTabRight); } return isTabEdit || isSubTabEdit; } } // --- WebSocket Integration --- let socket = null; const requests = {}; // Store callbacks for subscription responses const connectWebSocket = () => { if (socket && (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING)) { return; } // Use wss for https, ws for http const wsProtocol = window.location.protocol === "https:" ? "wss:" : "wss:"; // Construct base URL without http/https protocol const baseUrl = path.replace(/^https?:\/\//, ''); const wsUrl = `${wsProtocol}//${baseUrl}ws/data/`; socket = new WebSocket(wsUrl); socket.onopen = () => { console.log("WebSocket connection established"); }; socket.onmessage = (event) => { const response = JSON.parse(event.data); // Handle initial subscription responses with specific callbacks if (response.type === 'subscription_response' && response.request_id && requests[response.request_id]) { const callback = requests[response.request_id]; callback(response.data); delete requests[response.request_id]; // Clean up callback after use } else { // For all other messages (like realtime_update), dispatch a global event // This decouples the plugin from the store logic window.dispatchEvent(new CustomEvent('ws_message', { detail: response })); } }; socket.onclose = (event) => { console.log("WebSocket connection closed:", event); socket = null; // Attempt to reconnect after a delay setTimeout(connectWebSocket, 5000); }; socket.onerror = (error) => { console.error("WebSocket error:", error); }; }; const subscribeToData = (payload, callback) => { if (!socket || socket.readyState !== WebSocket.OPEN) { console.warn("WebSocket is not connected. Attempting to connect and retry."); connectWebSocket(); // Retry subscription after a short delay setTimeout(() => subscribeToData(payload, callback), 1000); return; } const requestId = `req-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; if (callback) { requests[requestId] = callback; } const request = { action: "subscribe", request_id: requestId, payload: payload }; socket.send(JSON.stringify(request)); console.log('[WebSocket] Sent subscription request:', request); }; return { provide: { getpath, findapi, readyapi, getapi, getdata, subscribe, insertapi, updateapi, patchapi, updaterow, findpage, getpage, setpage, insertrow, deleteapi, deleterow, updatepage, store, requestLogin, buildFileUrl, generateDocument, accountEntry, getEditRights, connectWebSocket, subscribeToData, mode, }, }; });