একটি জাপানি ক্লায়েন্টের এন্টারপ্রাইজ HR প্ল্যাটফর্ম — ছুটি, হাজিরা, খরচ, ওয়ার্ক লগ ও কমপ্লায়েন্স — প্রথমে GeneXus + WorkWithPlus-এ তৈরি, পরে ক্লায়েন্টের পাশে থেকে React, FastAPI ও PostgreSQL-এ রি-প্ল্যাটফর্ম করা, একটা রেকর্ডও না হারিয়ে।
→ পুরনো সিস্টেম থেকে ৯২,৫৭৯টি রেকর্ড মাইগ্রেট, আর্থিক হিসাব হুবহু মিলিয়ে দেখা হয়েছে
ELM হলো একটি জাপানি এন্টারপ্রাইজ ক্লায়েন্টের প্রতিদিনের HR ও অপারেশনস প্ল্যাটফর্ম: ছুটি, হাজিরা, খরচ, ওয়ার্ক লগ, প্রতিষ্ঠানের ডিরেক্টরি, ঘোষণা আর অভ্যন্তরীণ অ্যাডমিনিস্ট্রেশন — ইংরেজি ও জাপানি দুই ভাষায়।
এই সিস্টেমে আমি দুইবার কাজ করেছি। প্রথমে আমরা এটা GeneXus + WorkWithPlus-এ তৈরি করি, যে লো-কোড স্ট্যাকে ক্লায়েন্টের ইকোসিস্টেম আগে থেকেই চলত। পরে সিস্টেমটা যখন সেই প্ল্যাটফর্মের সীমা ছাড়িয়ে গেল, তখন আমি এটাকে আধুনিক স্ট্যাকে রি-প্ল্যাটফর্ম করার নেতৃত্ব দিই — সামনে React ও TypeScript, পেছনে FastAPI ও PostgreSQL — আর পুরো সময় ক্লায়েন্ট সিস্টেমটা ব্যবহার করে গেছে।
দ্বিতীয় ধাপটাই আমার কাছে সবচেয়ে গর্বের, কারণ এটা কোডের চেয়ে বেশি ছিল কাজের ধরন নিয়ে: ক্লায়েন্টের কাছাকাছি থেকে, ফিচার ধরে ধরে, পথে কিছু না হারিয়ে।
ধাপ ১: GeneXus + WorkWithPlus-এ তৈরি
GeneXus দিয়ে ছোট একটা টিম দ্রুত বড় একটা সিস্টেম শিপ করতে পেরেছিল: ছুটির নীতি ও অনুমোদন, মাসিক হাজিরা পরিকল্পনা, খরচের আবেদন, কাজের রেজিস্ট্রেশন, রিপোর্ট আর ইমেইল টেমপ্লেট। যেখানে বিল্ট-ইন কম্পোনেন্ট যথেষ্ট ছিল না, সেখানে আমি JavaScript লাইব্রেরি দিয়ে কাস্টম GeneXus ইউজার কন্ট্রোল বানিয়েছি — Gantt চার্ট, Kanban বোর্ড আর রিচ-টেক্সট এডিটর — যার কয়েকটা এখন ওপেন সোর্স।
সিস্টেমটা কাজ করত, মানুষ এর ওপর নির্ভর করত। কিন্তু সময়ের সাথে সীমাবদ্ধতা চোখে পড়ল:
অ্যাক্সেস কন্ট্রোল ছিল একটা মাত্র "user type" নম্বর। প্রতিটা নতুন অনুমতির নিয়ম মানে আরেকটা বিশেষ কেস।
কোনো পরিবর্তনের ইতিহাস নেই। "কে এটা বদলেছে, আগে কী ছিল?" — কেউ বলতে পারত না।
নোটিফিকেশন আলাদা মেইল আর পুশ টেবিলে ভাগ করা ছিল।
ভাষা হার্ড-কোড করা, প্রতিটা ইউজারের জন্য আলাদা বাছাই করা যেত না।
সেশন প্ল্যাটফর্মের বিল্ট-ইন অ্যাক্সেস ম্যানেজারের ওপর নির্ভর করত।
এগুলোর কোনোটাই বাগ ছিল না। এগুলো ছিল প্ল্যাটফর্মের সীমা।
লক্ষ্য ছিল না "React-এ নতুন করে লেখা"। লক্ষ্য ছিল: একই মানুষদের আরও ভালো একটা সিস্টেম দেওয়া, প্রথম দিনেই তাদের কাজের ধরন না বদলে, আর কিছু না হারিয়ে।
আগে হুবহু মিল, তারপর উন্নতি
ইউজারদের বছরের পর বছর পুরনো স্ক্রিনে অভ্যাস তৈরি হয়েছিল। তাই প্রথম নিয়ম ছিল হুবহু মিল: কাজের সময়ের হিসাব, নোটিফিকেশনের টাইপ নম্বর, ছুটির নিয়ম, এমনকি ডাউনলোড করা রসিদের নামও পুরনো সিস্টেমের মতোই রাখা হয়েছে, আর প্রতিটা সিদ্ধান্ত লিখে রাখা হয়েছে। হুবহু মিলের পরে উন্নতি এসেছে, একটা একটা করে, প্রতিটা আলাদা টাস্ক হিসেবে — শুধু ইউজার গাইডেই প্রায় ৬০টা।
তথ্য বদলালে পরিকল্পনাও বদলাও
শুরুর ডিজাইনে ELM-কে একটা মাল্টি-কোম্পানি SaaS প্রোডাক্ট ধরা হয়েছিল — টেন্যান্ট, সাবস্ক্রিপশন আর বিলিং সহ। ক্লায়েন্টের সাথে কাজ করে পরিষ্কার হলো এটার দরকার নেই: সিস্টেমটা চালাবে একটাই কোম্পানি। তাই ২০২৬-এর সেপ্টেম্বরে পুরো সেই অংশটা সরিয়ে ফেলা হয়। কম কোড, কম স্ক্রিন, এমন কিছু রক্ষণাবেক্ষণের দরকার নেই যা কেউ ব্যবহার করবে না।
মাইগ্রেট করো, তারপর প্রমাণ করো
ডেটা সরানোটাই ছিল সবচেয়ে ঝুঁকির অংশ। ইউজার, ছুটির বরাদ্দ ও আবেদন, হাজিরার ইতিহাস, খরচ, ওয়ার্ক লগ, ঘোষণা, রিলিজ নোট আর নোটিফিকেশন আর্কাইভ — মোট ৯২,৫৭৯টি রেকর্ড — মাইগ্রেট করা হয়েছে, আর পুরনো সিস্টেমের সাথে আর্থিক হিসাব হুবহু মিলিয়ে দেখা হয়েছে।
দুটো জিনিস ইচ্ছা করেই রেখে আসা হয়েছে: পুরনো লগইন-সেশনের ইতিহাস, আর কাঁচা পাঞ্চ রেকর্ড যেগুলো পুরনো সিস্টেম নিজেই আগে বাতিল করে দিয়েছিল। কী মাইগ্রেট করা হয়নি তা পরিষ্কার বলা, কী করা হয়েছে তার মতোই গুরুত্বপূর্ণ।
ক্লায়েন্টের জন্য কী বদলেছে
বিষয়
GeneXus সংস্করণ
আধুনিক ELM
অ্যাক্সেস কন্ট্রোল
একটা user-type নম্বর
সূক্ষ্ম অনুমতি দিয়ে গড়া ৮টি নামযুক্ত রোল, সাথে কাস্টম রোল
পরিবর্তনের ইতিহাস
নেই
প্রতিটা তৈরি, আপডেট ও মুছে ফেলা অপরিবর্তনীয় অডিট লগে রেকর্ড
পড়ার ইতিহাস
নেই
কে সংবেদনশীল রেকর্ড দেখেছে তার আলাদা লগ (GDPR / PDPA ধাঁচে)
সাইন-ইন
ইউজারনেম ও পাসওয়ার্ড
ইমেইল ও পাসওয়ার্ড, অথবা কোম্পানি অ্যাকাউন্টের জন্য Google সাইন-ইন; স্বল্পমেয়াদি রোটেটিং টোকেন
নোটিফিকেশন
আলাদা মেইল ও পুশ টেবিল
একটা ইনবক্স ও আউটবক্স, ইউজার অনুযায়ী ভাষা, Slack ইন্টিগ্রেশন
ভাষা
হার্ড-কোড করা EN / JA
প্রতিটা ইউজারের পছন্দমতো EN / JA, নাম দেখানোর ধরনসহ
কমপ্লায়েন্স
হাতে হাতে
জাপানের Article 36 ওভারটাইম সীমা ট্র্যাক করে রিপোর্টে চিহ্নিত
খরচ
হাতে এক্সপোর্ট
তৈরি করা PDF সারাংশ আর রসিদের বাল্ক ZIP ডাউনলোড
টেকনিক্যাল স্ট্যাক
ফ্রন্টএন্ড: React, TypeScript, সার্ভার থেকে নিয়ন্ত্রিত রোল-ভিত্তিক রাউটিং ও মেনু
ব্যাকএন্ড: Python, FastAPI, ইমেইল, Slack ও নির্ধারিত কাজের জন্য ব্যাকগ্রাউন্ড ওয়ার্কার
ডেটা: আইডেন্টিটি, HR ডেটা আর অডিটের জন্য আলাদা স্কিমাসহ PostgreSQL; ডেটাবেস ট্রিগার অডিট লগ লেখে
ক্যাশিং: বেশি পড়া হয় এমন পথে Redis cache-aside, Redis বন্ধ থাকলে PostgreSQL-এ ফিরে যায়
ইনফ্রাস্ট্রাকচার: লোকাল ডেভেলপমেন্ট ও সার্ভিসের জন্য Docker
পুরনো "user type" নম্বর হয়ে গেছে leave:approve বা expense:process-এর মতো অনুমতি-কী দিয়ে গড়া নামযুক্ত রোল। প্রতিটা রোল কী দেখবে তা সার্ভার ঠিক করে, হোম পেজে কোন ব্লক দেখাবে সেটা পর্যন্ত — তাই ফ্রন্টএন্ডকে কখনো আন্দাজ করতে হয় না।
এমন অডিট লগ যা কেউ বদলাতে পারে না
অডিট রেকর্ড শুধু যোগ করা যায়, আর সেগুলো অ্যাপ্লিকেশন কোড নয়, ডেটাবেস ট্রিগার লেখে — তাই API-তে বাগ থাকলেও সেগুলো বাদ পড়ে না বা বদলায় না। সংবেদনশীল রেকর্ড পড়ার তথ্য যায় দ্বিতীয় একটা লগে। দুটো মিলে সেই প্রশ্নগুলোর উত্তর দেয় যা পুরনো সিস্টেম কখনো দিতে পারত না।
কোডের সাথে মিলিয়ে দেখা ডকুমেন্টেশন
ইউজার গাইড নির্দিষ্ট কমিটের সাথে মিলিয়ে দেখা হয়, আর যা নতুন করে যাচাই হয়নি তা সেভাবেই চিহ্নিত থাকে। যে ক্লায়েন্ট তাদের HR ডেটা নিয়ে নতুন সিস্টেমে ভরসা রাখছে, তার কাছে আজ ঠিক কী সত্যি তা জানাও প্রোডাক্টেরই অংশ।
ফলাফল
২০২৬-এ ক্লায়েন্ট পুরো ইতিহাস অক্ষত রেখে পুরনো প্ল্যাটফর্ম ছেড়েছে: ৯২,৫৭৯টি রেকর্ড, আর্থিক হিসাব হুবহু মেলানো।
রিলিজের প্রতিটা স্ক্রিন কাজ করে; কোনো ফাঁকা প্লেসহোল্ডার পেজ নেই।
সিস্টেমে এখন সেই অডিট ট্রেইল, অ্যাক্সেস কন্ট্রোল আর ইউজার-ভিত্তিক ভাষা আছে যা পুরনো প্ল্যাটফর্ম দিতে পারত না।
ক্লায়েন্টের নাম ও কিছু বিবরণ গোপন রাখা হয়েছে। আর্কিটেকচার ও মাইগ্রেশনের পদ্ধতি নিয়ে আলাপে আরও বিস্তারিত বলতে পারি।