const asyncHandler = require("../Middleware/async"); const sequelize = require('sequelize') const StoreModel = require("../Model/StoreModel"); const UserModel = require("../Model/User"); const DataModel = require("../Model/TD_DATA"); const AppModel = require("../Model/AppModel"); const db = require("../Config/db"); const ErrorResponse = require("../utils/errorResponse"); const SuccessResponse = require("../utils/successResponse"); const fs = require('fs'); const dateFormat = require("dateformat"); exports.getStoreInfo = asyncHandler(async (req, res, next) => { console.log("GET STORE INFO EXEC ") try { let store = await StoreModel.findAll() console.log("STORE ", store) if (!store) { return next(new ErrorResponse("No store found", 400)); } res.status(200).send({ success: true, data: store }) } catch (err) { console.log("ERROR GET ALL STORE", err) return next(new ErrorResponse(err, 400)); } }) exports.registerStore = asyncHandler(async (req, res, next) => { var data = JSON.parse(req.body.data) console.log("REQUEST DATA ", data) var photo = req.file.path let imageData = fs.readFileSync(req.file.path) console.log("PHOTO ", photo) const { store_name, username, password, first_name, last_name, phone_number, plan_id, map } = data const t = await db.transaction() try { if (!username || !password || !first_name || !last_name || !store_name || !phone_number) { throw ("Please provide information!") } if (!plan_id) { throw "Please provide subscription plan" } if (!photo) { throw "Please provide store image!" } // check whether store name is existing const existingStore = await StoreModel.findOne({ where: { DB_NAME: store_name } }) if (existingStore) { throw "Store name already exists" // return next(new ErrorResponse("Store name already exists", 400)); } const existingUsername = await UserModel.findOne({ where: { USER_NAME: sequelize.where( sequelize.fn("LOWER", sequelize.col("USER_NAME")), " = ", username.toLowerCase() ) }, order: [["USER_ID"]] }) if (existingUsername) { throw "Username already exists" // return next(new ErrorResponse("Username already exists", 400)); } var date = dateFormat(new Date(), "mm/dd/yyyy"); const nextStoreCode = await generateNextStoreCode() let store = await StoreModel.create( { DB_CODE: nextStoreCode, DB_NAME: store_name, DB_STAT: 'A', DATE_CREA: date, DATE_UPDT: date, DATE_FORMAT: "MM/dd/yyyy", DATE_DEFAULT: 'L', SA_DECIMAL: '2', SB_DECICMA: '2', DEC_SEP: '.', THO_SEP: ',', USER_CREA: "", USER_UPDT: '', MAP: map }, { transaction: t } ) // GET last user id let lastUserID = await UserModel.findOne({ order: [['USER_ID', 'DESC']] }); var newUserID = lastUserID.USER_ID + 1 let user = await UserModel.create({ USER_ID: newUserID, USER_CODE: newUserID, USER_CPAS: 0, APPROVED: 1, APPROVED_BY: "", USER_NAME: username, USER_PASS: UserModel.encryptPass(password), FIRST_NAME: first_name, LAST_NAME: last_name, USER_DESC: last_name + " " + first_name, USER_TYPE: 'A', // A for Admin in POS USER_STATUS: '1', USER_CREDATE: date, FIELD_1: 'ADMIN', FIELD_3: "ADMIN", ROLE_TYPE: "ADMIN", USER_LOG: "" }, { transaction: t } ) let subscriptionPlan = await DataModel.findOne({ where: { DATA_TYPE: 'POS_PLAN', ID: plan_id } }) console.log("PLAN ID ", subscriptionPlan) if (!subscriptionPlan || !subscriptionPlan.DATA_CODE) { throw 'Please provide valid subscription plan' } delete user.dataValues.USER_PASS let folderPath = process.env.STORE_IMAGE_LOCATION if (!fs.existsSync(folderPath)) fs.mkdirSync(folderPath, { recursive: true, }) fs.writeFileSync(folderPath + newUserID + '.jpg', imageData) fs.unlinkSync(req.file.path) // INSERT INTO TDMSAPP let app = AppModel.create({ USER_ID: newUserID, APP_CODE: 'POS', DB_CODE: nextStoreCode, PRESET: subscriptionPlan.DATA_CODE, CREATE_DATE: date }) // await createStoreTables(nextStoreCode, t); await t.commit(); res.status(201).json({ success: true, data: store, app: app }) } catch (err) { fs.unlinkSync(req.file.path) await t.rollback(); return next(new ErrorResponse(err, 400)); } }) async function generateNextStoreCode() { const lastStore = await StoreModel.findOne({ order: [['DB_CODE', 'DESC']] }); if (!lastStore) { return 'AA001'; // Starting point if no stores are present } // use regex to separate letters and numbers let [letters, numbers] = lastStore.DB_CODE.match(/[A-Z]+|\d+/g); // letters -> AA , numbers -> 001 numbers = parseInt(numbers); if (numbers < 999) { numbers++; } else { numbers = 1; letters = incrementLetters(letters); } return letters + numbers.toString().padStart(3, '0'); } function incrementLetters(letters) { const maxLetters = 'ZZ'; if (letters === maxLetters) { throw new Error("Maximum limit reached."); } let firstChar = letters.charCodeAt(0); let secondChar = letters.charCodeAt(1); // if second character is Z, increment first character // and reset second character to A if (secondChar === 90) { firstChar++; secondChar = 65; } else { secondChar++; } return String.fromCharCode(firstChar) + String.fromCharCode(secondChar); } async function createStoreTables(storeCode, transaction) { try { // Table for TDSOHDR const tableTDSOHDR = `${storeCode}TDSOHDR`; await db.query(` IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = '${tableTDSOHDR}') BEGIN CREATE TABLE [dbo].${tableTDSOHDR} ( [REC_TYPE] char(1) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [TRANS_REF] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [HEADER_ID] char(1) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [CUST_CODE] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [DELIV_ADD] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [TRANS_DATE] smalldatetime NOT NULL, [STATUS] char(2) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [TRANS_CD] char(1) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [TRANS_CODE] nvarchar(10) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ORDER_NO] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ORDER_DATE] char(10) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [PRN_DATE] char(10) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [DEL_DATE] char(10) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [INV_DATE] char(10) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [INV_PRD] int NOT NULL, [CUST_REF] nvarchar(25) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [DEL_REF] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [COMMENTS] nvarchar(25) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [TRANS_VAL] numeric(18,5) NOT NULL, [PAY_DATE] char(10) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M0] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M1] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M2] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M3] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M4] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M5] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M6] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M7] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M8] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M9] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [QUOTE_CONVERT] char(1) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [QUOTE_PRINT] char(1) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [QUOTE_EXPIRY] char(10) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [QUOTED_PRD] int NOT NULL, [QUOTATION_REF] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [DATE_QUOTED] nvarchar(10) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [VOID_STATUS] char(1) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [USER_CODE] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, CONSTRAINT [PK_${tableTDSOHDR}] PRIMARY KEY CLUSTERED ([REC_TYPE], [TRANS_REF]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] ALTER TABLE [dbo].${tableTDSOHDR} SET (LOCK_ESCALATION = TABLE) END `, { type: sequelize.QueryTypes.RAW, transaction }); // Table for TDSODET const tableTDSODET = `${storeCode}TDSODET`; await db.query(` IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = '${tableTDSODET}') BEGIN CREATE TABLE [dbo].${tableTDSODET} ( [REC_TYPE] char(1) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [DETAIL_ID] char(1) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [TRANS_TYPE] nvarchar(10) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [TRANS_REF] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [TRANS_LINE] char(5) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [TRANS_CD] char(1) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [LOCATION] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ITEM_CODE] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [DESCRIPTN] nvarchar(50) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [DUE_DATE] char(10) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [STATUS] char(2) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [VALUE_1] numeric(18,5) NOT NULL, [VALUE_2] numeric(18,5) NOT NULL, [VALUE_3] numeric(18,5) NOT NULL, [VALUE_4] numeric(18,5) NOT NULL, [VALUE_5] numeric(18,5) NOT NULL, [VALUE_6] numeric(18,5) NOT NULL, [VALUE_7] numeric(18,5) NOT NULL, [VALUE_8] numeric(18,5) NOT NULL, [VALUE_9] numeric(18,5) NOT NULL, [VALUE_10] numeric(18,5) NOT NULL, [VALUE_11] numeric(18,5) NOT NULL, [VALUE_12] numeric(18,5) NOT NULL, [VALUE_13] numeric(18,5) NOT NULL, [VALUE_14] numeric(18,5) NOT NULL, [VALUE_15] numeric(18,5) NOT NULL, [VALUE_16] numeric(18,5) NOT NULL, [VALUE_17] numeric(18,5) NOT NULL, [VALUE_18] numeric(18,5) NOT NULL, [VALUE_19] numeric(18,5) NOT NULL, [VALUE_20] numeric(18,5) NOT NULL, [UNIT_SALE] nvarchar(5) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ORD_PRD] int NOT NULL, [DEL_DATE] char(10) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [INV_DATE] char(10) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [INV_NO] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [INV_PRD] int NOT NULL, [ACCNT_CODE] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M0] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M1] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M2] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M3] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M4] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M5] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M6] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M7] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M8] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M9] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ASSEMBLY_IND] char(1) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [SPLIT_VAL] int NOT NULL, [CREDIT_STATUS] char(1) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [PRICE_BOOK] nvarchar(10) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [SALE_QTY_VALUE] int NOT NULL, [STK_QTY_VALUE] int NOT NULL, [TOT_VALUE] int NOT NULL, [DISP_VAL_1] int NOT NULL, [DISP_VAL_2] int NOT NULL, [FIXED_VAL] int NOT NULL, [LINE_REF] nvarchar(20) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [USER_CODE] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [USER_INVOICED] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ALLOC_REF] char(20) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [UPDATE_STOCK] char(1) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [FIXED_VAL_2] int NOT NULL, [FIXED_VAL_3] int NOT NULL, CONSTRAINT [PK_${tableTDSODET}] PRIMARY KEY CLUSTERED ([TRANS_REF], [TRANS_LINE]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] ALTER TABLE [dbo].${tableTDSODET} SET (LOCK_ESCALATION = TABLE) END `, { type: sequelize.QueryTypes.RAW, transaction }); // Table for TDINVMOV const tableTDINVMOV = `${storeCode}TDINVMOV`; await db.query(` IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = '${tableTDINVMOV}') BEGIN CREATE TABLE [dbo].${tableTDINVMOV} ( [SEQUENCE] int NOT NULL, [REC_TYPE] char(1) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [MOV_PRD] int NOT NULL, [MOV_REF] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [MOV_LINE] char(4) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [LOCATION] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ITEM_CODE] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [MOV_DATE] char(10) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [STATUS] char(2) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [IR_STAT] char(1) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [BATCH_NO] int NOT NULL, [BATCH_LINE] char(5) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [LINE_REF] nvarchar(20) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [QUANTITY] numeric(18,5) NOT NULL, [COST] numeric(18,5) NOT NULL, [TOTAL] numeric(18,5) NOT NULL, [MOV_UNITS] nvarchar(5) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [MOV_TYPE] nvarchar(10) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [UPDTE_PHYS] char(10) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [UPDTE_ORDR] char(10) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ALLOC_REF] nvarchar(20) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ACCNT_CODE] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ASSET_CODE] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M0] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M1] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M2] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M3] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M4] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M5] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M6] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M7] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M8] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ANAL_M9] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ORIG_LINE_NO] char(5) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [PO_VALUE] numeric(18,5) NOT NULL, [ID_ENTERED] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, [ID_ALLOC] nvarchar(15) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, CONSTRAINT [PK_${tableTDINVMOV}] PRIMARY KEY CLUSTERED ([MOV_REF], [MOV_LINE]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] ALTER TABLE [dbo].${tableTDINVMOV} SET (LOCK_ESCALATION = TABLE) END `, { type: sequelize.QueryTypes.RAW, transaction }); } catch (error) { console.error('Error creating store tables:', error); throw new Error('Failed to create store tables.'); } } async function createUser(username, password, storeCode, first_name, last_name,) { var date = dateFormat(new Date(), "mm/dd/yyyy"); try { user = await UserModel.create({ USER_NAME: username, USER_PASS: UserModel.encryptPass(password), first_name: first_name, last_name: last_name, description: last_name + " " + first_name, USER_TYPE: 'A', // A for Admin in POS USER_STATUS: '1', USER_CREDATE: date, FIELD_1: 'ADMIN', FIELD_3: "ADMIN", ROLE_TYPE: "ADMIN", }) } catch (e) { console.error('Error creating user:', e); throw new Error('Failed to create user.'); } }