Internship (Week 6): MongoDB synchronisation and testing

On the first day, Mr. Peter had provided me several Docker commands for running Mongo Express with different replica sets. After executing the commands, I am able to login the Mongo Express. I then create some databases for users and stores along with their respective collections. Meanwhile, based on the provided “stores” files, I reference it to create users and subsequently build and update the contexts, repositories, services, interfaces and commands. Initially, I populate the MongoDB with sample user data after updates the Mongo connections of environment. I then create a controller and try to get all the user data created. However, there are some issues since the Object value is in different format with “timestamp” and “creationTime”. So I use ToString function in order to retrieve data in string value, and I successfully read all the user data.

After that, Mr. Peter emphasised that the users in MongoDB should be checked against all system databases so that there will be no extra users for new user creation when synchronising. Moreover, I consult with Mr. Peter for a clearer understanding of the concepts discussed yesterday. His clarification helped immensely that I need to retrieve all data and merge them to avoid overlaps, and then compare with MongoDB data to check the users existence before deletion. Then, I continue the manual synchronisation process of creating and updating data and the deleting in MongoDB. However, I face challenges while trying to merge user data. So I do searching about this scenario and understand how to union the data to remove redundant users from MongoDB. As all the manual synchronising successfully, the sense of accomplishment I feel after solving this is very motivating.

Additionally, I move on to mock testing using the “stores” files as references. I encounter an issue while initialising the MongoDB data and try various approaches without success. After discussing it with my colleague, she then provided some useful code snippets that helped me understand the process better. Despite this, I still face difficulties that I couldn’t get the initialised data. Upon consulting Mr. Peter, he identified that the issue was due to using capital letters in the collection name instead of lowercase. Once corrected, everything worked smoothly. In addition, I continue with my testing and fortunately, all the tests passed successfully.

I then update the synchronisation command for the warehouse MongoDB connection, and create another controller to call user data from MongoDB. By reusing the existing code for the retail sync, I could just making minor adjustments which help streamline the process. I successfully sync data from MongoDB to create new users, although I realize later that I had missed implementing the update functionality for changes in MongoDB. I plan to address this the next day. Meanwhile, I refine the mock testing environment for the warehouse and test the original code with initialized data, which worked successfully. Mr. Peter and I also discuss changes in MongoDB collection naming and connection settings.

Mr. Peter requested updates to the user and store contexts for their respective databases. After making the updates and testing them successfully, I proceed with synchronising the other data. The mock testing for sync commands also went well. However, I face challenges when implementing create, update and delete operations due to service issues. Despite adding scopes to the relevant interfaces and repositories, I couldn’t resolve the problem. After consulting Mr. Peter again proved helpful, as he discovered that a persistence configuration was missing during startup. Once fixed, everything functioned as expected. Meanwhile, he suggested using either the override or base method for my logic, which I plan to tackle next week.

Conclusion

This week was a valuable learning experience filled with challenges, problem-solving and significant progress. Each day presented new tasks that deepened my understanding of MongoDB, synchronisation processes and testing environments. I learn a lot and feel a sense of achievement after overcoming each obstacle. The journey reinforced the importance of patience, attention to detail and continuous learning.

Week 6 Internship : Enhancing Data Handling and Create Return Order Page

Optimizing user interface details

In the first three days, Mr. Peter assigned me tasks to optimize user interface details and enhance data handling processes. Firstly, I tried to add a function for validating data to ensure that the main data uploaded is not null. I also added a UI/UX feature that allows users to remove or add images in the payment edit view. After that, I worked on rebuilding the latest API to include a barcode for the store and integrating it into the code. Furthermore, I modified the subtotal printing logic to display 0 instead of NaN when the unit price is null. Additionally, I updated the payment statement to allow users to separate bills.

On the payment page, I enhanced the search bar functionality, enabling users to choose a search type, such as customer name, and various IDs. Besides that, I added hotkey and focus-handling features, allowing users to press the arrow key to select a customer in the POS page. Later on, I modified the network handling functionality to show an alert only when the user tries to call an API. For this, I added a function in the retail API service file to check whether the network is connected.

Thereafter, I redesigned the table alignment in the POS system to improve the layout for better clarity. However, I noticed that when zooming in on the page, the table header would stack with the table itself. I plan to find a better way to resolve this issue and enhance the design further.

Create Return Order Page

After completing these tasks, Mr. Peter assigned me to work on the return order page. This task was quite challenging because it involved multiple APIs. Firstly, I designed the UI page and drew a workflow for it. After that, I added an invoice search dialog as a component and imported it into the return order page. This dialog allows users to click the “Create” button to display a search interface listing all paid invoices that have not been canceled. Once an invoice is selected, all its line items are displayed. The most difficult part was enabling users to select specific items and input the quantity to return, which took me the entire Friday to solve and refine the workflow.

There are still more tasks to complete on this page, such as setting authorization for different user types. For instance, administrators can accept or reject return requests. Different users may have varying privileges to access this page based on their roles.

Conclusion

This week has been a productive and challenging experience, as I worked on enhancing various features and tackling complex tasks, particularly the return order workflow. These assignments helped me develop problem-solving skills and improve my technical abilities, especially in handling APIs and refining the UI/UX.

Enhancing UI Components

Monday, November 25, 2024 – Last week, I focused on refining the user interface of the website I am currently building. A key milestone was improving the breadcrumbs component, which I initially created by referencing a popular tech blog. While the component functioned well, it did not fully accommodate the dynamic routing I had implemented. Additionally, the homepage unnecessarily displayed the “Home” breadcrumb, which was not ideal.

To resolve this, I added a condition within the component to filter out the “Home” breadcrumb when the route was read in the component originated from the homepage. This adjustment worked; however, another challenge arose, displaying the dynamic slug route appropriately within the breadcrumb. Since I used Next.js optional dynamic routing for SEO purposes, the breadcrumb also displayed irrelevant object names instead of just the intended page titles. To address this, I added a filter to clean up the route data, ensuring it displayed the desired output. After some iteration, this solution worked, but I am still reflecting on whether my implementation aligns with clean code principles.

In addition to the breadcrumb enhancements, I revisited the thumbnail gallery component I had previously created. While the design required only minor tweaks, I realized that turning this component function to a client-rendered only on the edge component was essential. The gallery’s functionality relies on a callback to update the main image display when a thumbnail is hovered over. This required using useState, which automatically converted the page to a client-rendered component.

To enable server-side rendering, I refactored the gallery by exporting the main image and thumbnail into their own components. This allowed state changes to be handled outside the page itself. After some trial and error, I successfully implemented this approach.

Throughout the week, I also worked on basic structural components like the navigation bar, footer, and header. While these designs are currently simple, I prioritized practicality to ensure functionality.

Towards the end of the week, I discovered an oversight, one of the pages was still fetching data from a JSON sample file instead of a dummy API. This conflicted with my plan to render the page on the server side. After switching to the API, the page became client-rendered again. I’ve marked this as a task to revisit later, as my focus is currently on completing higher-priority items.

While there’s still much to do, these iterative improvements have brought me closer to achieving goals for the project.

CRUD for user address, password hashing and renaming column

Sixth week as an intern in Tong Hin. A lot of minor changes and implementation this week. The week start off with renaming column and tables as implementing Core Identity meant using the built in default name. After some looking and trying, the name has been renamed.

Moving off with password hashing, the concept of it is to protects a password by turning it into a different and seemingly random string of characters. After looking at articles and tutorials, I implemented it and try it out. All works well.

One of the problems I met for the week is dynamic code as the code can’t get through. After some asking, I get to understand the publishAot was the problem behind all this as I set it true. This little problem involve around a word took my time to solve as if I asked earlier would be solve sooner.

Beside that, I have also commit and push for the 2nd time of my internship. It was a bad practice and commit and push took some time to look at the code and select line by line for the correct name.

Last but not least, CRUD for addresses. Create and delete was fast but read and update took some time as mapping and modifying the code need some logic running around. Test has been done and still read and update haven’t gone through.

In summary, I have implement something new and also been solving some problems. I got to proceed the task on week 3. It feels good to see progression and the things I have done for the past weeks. Will continue to keep on learning and doing on next week.

Building a Dynamic Next.js UI with Tailwind CSS

Monday, November 18, 2024 – Last week, I focused on enhancing the user interface of a Next.js website, specifically designing a page where images serve as the main attraction. Before diving into image implementation, I first tackled the challenge of structuring the website path for this page. The goal was to create a dynamic route that incorporated multiple parameters in the URL, ensuring it was both descriptive and SEO-friendly.

To achieve this, I utilized Next.js dynamic routing by wrapping file or folder names in square brackets [segmentName]. However, since the segment combined multiple data points, I initially struggled to retrieve the data correctly. Eventually, I discovered that using Optional Catch-All Segments allowed me to retrieve multiple parameters seamlessly, resolving the issue.

With the routing set up, I shifted my focus to building a thumbnail gallery for the page. As I had limited experience with such implementations, I researched how to achieve this using Tailwind CSS. Initially, I was uncertain whether Tailwind alone could handle the task or if I needed a third-party package for pre-built components. To my surprise, Tailwind proved to be a powerful tool. Its utility-first classes enabled me to design the gallery effectively, including adding hover effects and transitions without needing JavaScript or React hooks for simple interactions. This approach helped keep the page lightweight by minimizing unnecessary client-side rendering. 

During the trial-and-error process of designing the gallery, I referred to a sample website provided by Mr. Peter and explored popular design references online to create a visually appealing layout.

For this page, I also needed icons. At first, I considered using an external icon library. However, I hesitated, as importing a library, especially one that isn’t widely used or actively maintained, might not be ideal for long-term project stability, especially since I only needed a few icons. I then found an alternative: using SVGs as components, which turned out to be a flexible and lightweight solution. By leveraging an AI tool, I generated customizable SVGs that allowed me to adjust their colors and sizes without pixelation issues. These SVGs fit seamlessly into the project.

Throughout the week, I focused on beautifying the thumbnail gallery to enhance the user experience. I implemented hover effects on the images, making interactions more engaging and visually appealing.

Internship (Week 5): Refining synchronisation workflows

Starting the first day, I have a detail discussion with my colleague about best practices for clean and effective testing strategies. It was insightful and gave me some fresh perspectives on structuring tests efficiently as these conversations and learning from others’ experiences, leaving me inspired.

Moreover, I pull the repository and merge the develop branch for both user and retail contexts. I spend time to understand about RabbitMQ’s management interface when running. I also update the MessageQueueService to include new exchanges, queues and Dead Letter Queues (DLQs) for better user synchronisation. Meanwhile, I also ensure that all related tests, controllers and commands in the retail context are updated as well which relate to the new UserInfoDto. However, I also encounter some errors during testing and spend time for debugging after the updates, but then I found out that there some typo errors and some missing part to update. I also try to update the RabbitMQ for the consumer and listener for user synchronisation. Feedback from Mr. Peter on my manual synchronisation efforts was particularly helpful, he suggested me to use hardcoded practice for some cases.

Additionally, I also discuss with my colleague in order to understand RabbitMQ’s publish and listen processes more thoroughly. This discussion help to gain clarity on transaction workflows, especially for creating and publishing messages. We try to publish a message first to the queue before consuming the message. We have try for multiple times to register a new user from the page. However, we failed to and consider that it might be a connection issues. I continue my progress on manual sync in the user context by adding relevant call API that similar in retail context. Although I encounter roadblocks in registering new retail users. Mr.Peter answered me to refer on the register file instead of the commands. I found that file, and try to continue to register new user tomorrow.

Besides that, Mr.Peter assigned me some new tasks in the progress tracker such as manual synchronisation and creating default users for both systems, while ensuring both systems will subscribes the respective events for create, update and delete operations. Handling MongoDB synchronisation for item states and transfer order logs was another critical task. Then, Mr. Peter also raised a critical question about whether our synchronisation process was unnecessarily complex. His suggestion to consider MongoDB as a shared database sparked new ideas. So, I start to explore and search about the MongoDB’s synchronisation features like change streams and note potential approaches. Also, we discussion about the approach and understand about the shared database.

In addition, I also try to continue about my manual sync for main system. I successfully call the API to compare, but stuck in registering new user for retail user, I will try to finish by tomorrow. Apart from that, I also pull the latest develop branch and merge updates from Mr.Peter. I also spend time understanding new files about MongoDB, so that I could refine the user creation and synchronisation process. I then create some files for user synchronisation on MongoDB by referring the store files. Meanwhile, I continue refining the manual synchronisation for the user context and successfully achieve a sync between the systems, it was a satisfying milestone. However, the satisfaction of reaching this point was slightly dampen by new issues reveal during testing.

Conclusion

This week was a blend of deep learning, collaboration and problem-solving while debugging errors and tackling testing challenges tested my patience. The experiences of syncing systems and brainstorming innovative approaches with Mr. Peter made it worthwhile. I am getting my knowledge in understanding of RabbitMQ and MongoDB.

Internship Week 5: Enhance Order Page UI and Create Tax Dropdown

In this week, Mr. Peter gave me a task to work on enhancing the order page. Since this page is related to many files and functions, it took me four days to complete. Firstly, I created a tax dropdown to let the user choose different types of tax rates for each item. After that, I combined it with the order page line items and tried to fix the bug that did not show the tax dynamically after selecting the desired tax rate. Additionally, I redesigned the entire order page UI and set a user default store to ensure users have a great experience using it.

Secondly, I redesigned the payment UI by adjusting the spacing between payment types and other CSS styles. I also fixed the bug that allowed users to click on full payment an unlimited number of times. I set it so that users can only click once when the pop-up window is first shown or when the amount is cleared. Afterward, I worked on fixing bugs related to payment types. For non-cash payment types, I enhanced the conditional statements to validate data integrity and correctness, ensuring that a reference number and image are required. After these fixes, users can make payments and complete orders more smoothly.

Lastly, since Mr. Peter mentioned that my solution for fixing the cookie session was incomplete, I continued to work on this problem. I had only implemented checking whether the token was still valid, but not addressing expired cookie sessions or handling network disconnections. I set a timer for 30 minutes for the cookie session, so when it expires, users are forced to log out and log in again. Since the cookie session was not being triggered when users logged in, I added a reload function to the login page to ensure that the cookie session starts after the page refreshes. For network status detection, I referred to a blog that explained real-time network detection. I set up a general alert that displays “connection lost” with a retry button until the connection is restored, preventing users from losing unsaved data. Additionally, I added a network status indicator next to the username to show if the network is connected.

In conclusion, this week, I learned many new things, such as how to change all data dynamically when part of the data changes, and how to detect network status and handle cookie session timing.

Add claims, refresh token and authorize

Fifth week as an intern in Tong Hin. After some simple implementation on last Friday to test out with the bare minimum requirement, the week start with implementing claim and necessary column for the Web project. Claiming additional user details as claims in a token helps streamline processing. It also enhance security as claiming unique value in the token.

Some continuous testing on access token was done by Monday and it works through. Continuing with refresh token on Tuesday, it is a bit different than access token. The concept of refresh token is to generate a new access token when the access token is expired as the refresh token is set to be live longer than access token. After some research and coding, it worked after testing out with access token.

Continuing with update with authorize, I need to do authorization for the update command by sending the access token together with the detail to change . If the detail of the token is not the same as the registered detail of the database, it will be denied unless it is a privileged account. I did not think of sending the access token in the body at first and after some help from Mr. Peter, the task is done.

After an amount of time of trying out new concept and try to implementing new idea in the sandbox, Mr. Peter asked me to implement in the main project instead of sandbox. Everything work through except for 1 or 2 test and will continue it on next week. It is happy to see progression.

In summary, I have done different learning and implementing on new concept for me this week. For the past 2 week, I have been doing with Core Identity, JWT token and claims. I got a better understanding of every part of the code. It is indeed happy to keep on learning and doing as after doing 1 task, there will be another task to continue.

Internship (Week 4): Compare logic and mock testing

This week, I will continue on completing the compare logic for synchronisation and the mock testings. I attempt to call the API from the retail to retrieve user details but encounter some issues. Initially, I try inserting data into the retail database and executing actions through Swagger, but the API calls consistently failed. Meanwhile, I also have no clue about how can I compare the logic, I consulted with Mr. Peter about it, he then introduced me to Postman to test API calls. He firstly guided me on calling the warehouse database to retrieve user details that we created previous week. Despite this, there were errors fetching user details, Mr. Peter decide to address these issues later that evening.

Moreover, Mr. Peter left a message of instructions for using Postman to call APIs and guided me further on API calls through Postman. After manually syncing and clicking “continue” to execute the API calls, I could retrieve the user details for both lists and specific details by ID. Following his instructions and using breakpoints, I understand how the code execute step by step. I then create a new command and handler, “SyncUser,” but encounter errors with API calls from the retail database as well. I try to debug with breakpoints but couldn’t locate the issue.

Besides that, I continue developing the compare logic, created service and controller to distinguish different function calls from user query of retail. I add two controllers to retrieve user lists and specific usernames by user ID from the warehouse. However, API calls from retail still face errors. My colleague and I try in troubleshooting but couldn’t identify the problem, so I consult Mr. Peter again. He then detected a connection error with the PostgreSQL database and guided me on debugging methods like F10 and F11 for stepping through code. Together, we identified several issues such as typos, incorrect password and capitalisation errors. After resolving these and setting PublishAot library to false, we achieved a successful connection.

Apart from that, I face challenges creating the sync command and handler. I initially try to store each call detail into a file or in a table database, and fetch the retail data and compare them foreach. But then I find out it was unnecessary, as it was only for synchronisation. With guidance from my colleague, I restructure the compare logic by deleting and redoing the sync command and handler. I try Meanwhile, my friends also encountered similar API call issues, we discussed together and found out it also a connection error. In addition, Mr. Peter advised me to keep the sync task simple and also guided me on mock testing.

Additionally, I creat a new sync command and handler, I successfully synchronise user data and implement the compare logic. I’m grateful for my colleague and Mr. Peter guidance and patience on teaching me. Mr. Peter further assisted me with mock tests and emphasised the importance of documentation for code consistency. He then recommended reading Clean Code to deepen my understanding and improve my skills.

Conclusion

This week, I focus on troubleshooting API call and connection issues between the warehouse and retail databases, working through synchronisation and compare logic for user data. With guidance from Mr. Peter and support from colleagues, I improve my debugging skills, use tools like Postman and implement effective mock testing.

SQL Querying for CRUD Operations

Last week, I continued working on CRUD operations for an API, specifically focusing on retrieving lists from a newly created entity. The task was progressing smoothly until I reached the SQL query part. As someone new to writing SQL queries, I felt uncertain about the best approach to querying across multiple databases. In my previous experience with EF Core, I could simply use the Include() function to fetch data from related tables. However, doing the same in raw SQL required a different approach.

To handle data from multiple tables, I quickly realized that JOIN statements would be essential, so I dove into learning SQL joins. Although it seemed complex initially, I found that retrieving columns from multiple tables was not as difficult as I anticipated. Using SQL joins allowed me to efficiently pull data across related tables, achieving similar functionality to what Include() provides in EF Core but with SQL-specific syntax and nuances.

After grasping the join concepts, I moved on to testing and refining the query based on errors that emerged during execution, which helped me improve the overall structure. Once the read operation was stable, I developed the create operation for the entity and wrote tests to validate it. Although this entity will have additional table relationships that shall be integrated later, the essential read and create API functionality was successfully implemented. For now, I skipped implementing a delete operation, as it doesn’t align with the entity’s purpose; however, further discussion shall be made.

Toward the end of the week, I returned to my Next.js work, focusing on SEO-friendly dynamic routing for the project. I’m exploring the updated dynamic route handling introduced in Next.js 13, which differs from previous versions. Though I haven’t achieved the desired setup yet, I plan to continue refining this next week.