diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..54f336f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/Resources.md +/temp.md \ No newline at end of file diff --git a/README.md b/README.md index 1a7c26e..abb1fd9 100644 --- a/README.md +++ b/README.md @@ -1 +1,94 @@ # πŸ”– Online Bookstore Management System (OBMS) + +## πŸ“ [`TO-DO`](https://mastekgroup.sharepoint.com/:x:/r/sites/DSAR/_layouts/15/Doc.aspx?sourcedoc=%7B2848B15B-01BB-4355-A183-606D3EB11455%7D&file=Participantlist.xlsx&action=default&mobileredirect=true) + +![image](https://github.com/Ayon-SSP/Ayon-SSP/assets/80549753/8c5630bf-8343-48ca-aba4-e9b7d6759666) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Online Bookstore Management System
ProcessStepDescription
Book Catalog Management1Admin adds new books to the catalog, specifying details such as title, author, genre, price, etc.
2System updates the book inventory and displays new additions on the website.
Order Processing1Customers browse the bookstore website and add books to their shopping cart.
2Upon checkout, system calculates the total cost, applies discounts (if any), and generates an order confirmation.
3Admin processes orders, updates inventory, and notifies customers about order status (shipping details, delivery estimates, etc.).
+ + +## 🌲Project Structure +```css +online-bookstore-ms/ + +|__ README.md +|__ LICENSE +|__ .gitignore + +|__ docs/ + |__ requirements.md + |__ architecture.md + |__ system-design.md + |__ database-schema.sql + |__ er-diagram.png + |__ class-diagram.uml + |__ sequence-diagram.uml + |__ other-diagrams.uml (optional) + +|__ src/ + |__ backend/ + |__ java/ + |__ com.example.bookstore + |__ model/ + |__ service/ + |__ repository/ + |__ util/ + |__ resources/ + |__ application.properties + |__ database.properties + |__ frontend/ + |__ static/ + |__ css/ + |__ img/ + |__ js/ + |__ index.html + |__ components/ + |__ pages/ + |__ other-folders (optional) + +|__ db/ + |__ init.sql + |__ test-data.sql (optional) + +|__ tests/ + |__ backend/ + |__ unit/ + |__ integration/ + |__ frontend/ + |__ unit/ + |__ integration/ +``` \ No newline at end of file diff --git a/docs/OBMS ER Diagram v2.pdf b/docs/OBMS ER Diagram v2.pdf new file mode 100644 index 0000000..d348b0c Binary files /dev/null and b/docs/OBMS ER Diagram v2.pdf differ diff --git a/docs/OBMS-ER-Diagram-v2.png b/docs/OBMS-ER-Diagram-v2.png new file mode 100644 index 0000000..a63d0fe Binary files /dev/null and b/docs/OBMS-ER-Diagram-v2.png differ diff --git a/docs/db-notes/conventional-commits.md b/docs/db-notes/conventional-commits.md new file mode 100644 index 0000000..21fac63 --- /dev/null +++ b/docs/db-notes/conventional-commits.md @@ -0,0 +1 @@ +### [πŸ”— Conventional Commits](https://github.com/Ayon-SSP/all-git/blob/b1/Conventional%20Commits.md) -\- [conventionalcommits.org/en/v1.0.0/](conventionalcommits.org) \ No newline at end of file diff --git a/docs/db-notes/need-to-know.md b/docs/db-notes/need-to-know.md new file mode 100644 index 0000000..46ab056 --- /dev/null +++ b/docs/db-notes/need-to-know.md @@ -0,0 +1,7 @@ +#### **SYS & SYSTEM :** [sys-and-system-accounts-in-oracle-database](https://medium.com/@ykods/sys-and-system-accounts-in-oracle-database-6113c3a29765) +1. **SYS:** `superuser` (system administrator account) && `highest level of privileges` +2. both created automatically during the database installation, AND account is used for performing critical administrative tasks and managing the Oracle Database instance itself. +3. privileges: creating and modifying database structures managing, memory and storage, and creating and managing other database users. +4. **SYSTEM**: `another administrative account` && `fewer privileges` compared to SYS. +5. privileges: system-related tasks +6. used for day-to-day management activities and is typically used for managing database schema objects, security, and application-related tasks \ No newline at end of file diff --git a/docs/db-notes/sql-style-guide.md b/docs/db-notes/sql-style-guide.md new file mode 100644 index 0000000..3807ce8 --- /dev/null +++ b/docs/db-notes/sql-style-guide.md @@ -0,0 +1,29 @@ +### πŸ’₯ Examples of SQL Conventional [Link](https://github.com/Ayon-SSP/SQL/blob/main/B%5D_PL-SQL%20(Oracle)/Oracle%20Notes/1%5D_Oracle%20baby/README.md) + +> 1. **Consistency**: Use consistent formatting and naming conventions throughout your code. +> 2. **Readability**: Write clear and concise code that is easy to understand. +> 3. **Maintainability**: Make your code easy to modify and extend. +> 4. **Performance**: Consider performance implications when writing queries. [πŸ”‘ Key Points](https://gemini.google.com/app/88fb0a8eb06acc68) + +### 24 Rules to the SQL Formatting Standard [Link](https://learnsql.com/blog/24-rules-sql-code-formatting-standard/) +- **Avoid** table/column in the plural βœ… `employee` instead of ❌`employees` +- **CamelCase style || using '_' || paka more than one word**: eg: employee_city, employee_name +- Check that the name is not already used as a keyword in SQL +- For the primary key column avoid the name id. A good idea is to combine id with the name of a table, for example: id_employee. + +### SQL Style Guide [Link](https://handbook.gitlab.com/handbook/business-technology/data-team/platform/sql-style-guide/) + + +### Trigger naming convention + +Certainly! Here are some more naming conventions for triggers in Oracle databases: + +TRG__: Naming convention where refers to the table associated with the trigger and represents the database event that triggers the action, such as INSERT, UPDATE, or DELETE. For example, TRG_EMPLOYEE_INSERT or TRG_ORDER_UPDATE. + +__TRG: Naming convention where represents the action that triggers the event, such as BEFORE or AFTER, and refers to the associated table. For example, BEFORE_EMPLOYEE_UPDATE_TRG or AFTER_ORDER_INSERT_TRG. + +_TRG_: Naming convention where represents the database event and refers to the table associated with the trigger. For example, INSERT_TRG_EMPLOYEE or UPDATE_TRG_ORDER. + +__TRIGGER: Naming convention where refers to the associated table, and represents the action that triggers the event. For example, EMPLOYEE_BEFORE_INSERT_TRIGGER or ORDER_AFTER_UPDATE_TRIGGER. + +_: Customized naming convention where is a descriptive prefix indicating the type of trigger (e.g., BEF for BEFORE triggers, AFT for AFTER triggers), and provides a brief description of the trigger's purpose. For example, BEF_EMPLOYEE_INSERT_CHECK or AFT_ORDER_UPDATE_AUDIT. \ No newline at end of file diff --git a/docs/er-documentation.md b/docs/er-documentation.md new file mode 100644 index 0000000..3a44e32 --- /dev/null +++ b/docs/er-documentation.md @@ -0,0 +1,244 @@ +# πŸ›’οΈ Database Documentation + +![OBMS-ER-dIAGRAM-V2](OBMS-ER-dIAGRAM-V2.png) +## 1. tbl_author +> Stores information about book authors. + +**Columns:** +- `author_id`: Unique identifier for the author (VARCHAR2(10), Not Null, Primary Key) +- `author_name`: Name of the author (VARCHAR2(50), Not Null) +- `author_bio`: Short biography of the author (VARCHAR2(1000)) +- `author_score`: Score assigned to the author (based on reviews or ratings) (NUMBER) +- `author_image`: URL of the author's image (VARCHAR2(255)) +- `author_birth_date`: Date of birth of the author (DATE) + +**Constraints:** +- `pk_author`: Primary key constraint on author_id +- `ck_author_id`: Ensures author_id starts with "au" followed by five digits +- `ck_author_score`: Ensures author_score is between 0 and 5 + +## 2. tbl_book_category +> Stores information about book categories. + +**Columns:** +- `category_id`: Unique identifier for the category (VARCHAR2(10), Not Null, Primary Key) +- `category_name`: Name of the category (VARCHAR2(50), Not Null) +- `category_description`: Description of the category (VARCHAR2(1000)) +- `category_image`: URL of the category image (VARCHAR2(255)) + +**Constraints:** +- `pk_book_category`: Primary key constraint on category_id +- `ck_category_id`: Ensures category_id starts with "bc" followed by five digits + +## 3. tbl_genre +> Stores information about book genres. + +**Columns:** +- `genre_id`: Unique identifier for the genre (VARCHAR2(10), Not Null, Primary Key) +- `genre_name`: Name of the genre (VARCHAR2(50), Not Null) +- `genre_description`: Description of the genre (VARCHAR2(1000)) +- `genre_image`: URL of the genre image (VARCHAR2(255)) + +**Constraints:** +- `pk_genre`: Primary key constraint on genre_id +- `ck_genre_id`: Ensures genre_id starts with "ge" followed by five digits + +## 4. tbl_book +> Stores information about books. + +**Columns:** +- `book_id`: Unique identifier for the book (VARCHAR2(10), Not Null, Primary Key) +- `author_id`: Foreign key referencing tbl_author.author_id (VARCHAR2(10), Not Null) +- `category_id`: Foreign key referencing tbl_book_category.category_id (VARCHAR2(10), Not Null) +- `genre_ids`: Nested table type for storing genre ids (GENRE_ID_LIST) +- `book_title`: Title of the book (VARCHAR2(100), Not Null) +- `book_description`: Description of the book (VARCHAR2(1000)) +- `book_publish_date`: Date when the book was published (DATE) +- `book_price`: Price of the book (NUMBER) +- `discontinued`: Discontinued status of the book (NUMBER, Default 0, Not Null) +- `book_pages`: Number of pages in the book (NUMBER) +- `book_discount`: Discount on the book (NUMBER, Default 0) +- `available_quantity`: Available quantity of the book (NUMBER) +- `book_language`: Language of the book (VARCHAR2(100)) +- `book_publisher`: Publisher of the book (VARCHAR2(100)) +- `book_isbn`: ISBN of the book (VARCHAR2(13)) +- `book_cover_image`: URL of the book cover image (VARCHAR2(255)) + +**Constraints:** +- `pk_book`: Primary key constraint on book_id +- `ck_book_id`: Ensures book_id starts with "bo" followed by five digits +- `ck_book_book_price`: Ensures book_price is greater than 0 +- `ck_discontinued`: Ensures discontinued is 0 or 1 +- `ck_book_pages`: Ensures book_pages is greater than or equal to 0 +- `ck_book_discount`: Ensures book_discount is between 0 and 1 +- `ck_available_quantity`: Ensures available_quantity is greater than or equal to 0 +- `fk_book_author`: Foreign key constraint referencing tbl_author.author_id. On delete cascade ensures that if an author is deleted, all associated books are also deleted. +- `fk_book_category`: Foreign key constraint referencing tbl_book_category.category_id. On delete cascade ensures that if a category is deleted, all associated books are also deleted. + +## 5. tbl_customer +> Stores information about customers. + +**Columns:** +- `customer_id`: Unique identifier for the customer (VARCHAR2(10), Not Null, Primary Key) +- `customer_name`: Name of the customer (VARCHAR2(30)) +- `customer_email`: Email of the customer (VARCHAR2(100)) +- `customer_phone1`: Primary phone number of the customer (VARCHAR2(24), Not Null) +- `password_hash`: Hashed password of the customer (VARCHAR2(100)) + +**Constraints:** +- `pk_customer`: Primary key constraint on customer_id +- `ck_customer_id`: Ensures customer_id starts with "cu" followed by five digits + +## 6. tbl_customer_address +> Stores information about customer addresses. + +**Columns:** +- `customer_address_id`: Unique identifier for the customer address (VARCHAR2(10), Not Null, Primary Key) +- `address_type`: Type of address (VARCHAR2(16), Not Null) +- `customer_id`: Foreign key referencing tbl_customer.customer_id (VARCHAR2(10), Not Null) +- `address_line1`: Address line 1 (VARCHAR2(255)) +- `address_line2`: Address line 2 (VARCHAR2(255)) +- `address_line3`: Address line 3 (VARCHAR2(255)) +- `city`: City (VARCHAR2(100)) +- `state`: State (VARCHAR2(100)) +- `country`: Country (VARCHAR2(100)) +- `postalcode`: Postal code (VARCHAR2(6)) +- `landmark`: Landmark (VARCHAR2(255)) +- `phone`: Phone number (VARCHAR2(24)) + +**Constraints:** +- `pk_customer_address`: Primary key constraint on customer_address_id +- `ck_customer_address_id`: Ensures customer_address_id starts with "ca" followed by five digits +- `ck_address_type_customer_id`: Unique constraint on (address_type, customer_id) +- `fk_customer_address_customer`: Foreign key constraint referencing tbl_customer.customer_id. On delete cascade ensures that if a customer is deleted, all associated addresses are also deleted. + +## 7. tbl_subscription +> Stores information about subscription plans offered by the library. + +**Columns:** +- `subscription_status_id`: Unique identifier for the subscription status (VARCHAR2(10), Not Null, Primary Key) +- `subscription_name`: Name of the subscription plan (VARCHAR2(30)) +- `subscription_description`: Description of the subscription plan (VARCHAR2(1000)) +- `subscription_price`: Price of the subscription plan (NUMBER) +- `subscription_duration`: Duration of the subscription plan (NUMBER) +- `subscription_discount_on_order`: Discount offered on book orders for subscribers (NUMBER, Default 0) + +**Constraints:** +- `pk_subscription`: Primary key constraint on subscription_status_id +- `ck_subscription_status_id`: Ensures subscription_status_id starts with "su" followed by five digits +- `ck_subscription_price`: Ensures subscription_price is greater than 0 +- `ck_subscription_discount_on_order`: Ensures subscription_discount_on_order is between 0 and 1 + +## 8. tbl_subscription_log_history +> Stores historical information about customer subscriptions. + +**Columns:** +- `subscription_log_id`: Unique identifier for the subscription log (VARCHAR2(10), Not Null, Primary Key) +- `customer_id`: Foreign key referencing tbl_customer.customer_id (VARCHAR2(10), Not Null) +- `subscription_status_id`: Foreign key referencing tbl_subscription.subscription_status_id (VARCHAR2(10), Not Null) +- `subscription_start_date`: Start date of the subscription (DATE) +- `subscription_end_date`: End date of the subscription (DATE) + +**Constraints:** +- `pk_subscription_log_history`: Primary key constraint on subscription_log_id +- `ck_subscription_log_id`: Ensures subscription_log_id starts with "sl" followed by five digits +- `fk_subscription_log_history_customer`: Foreign key constraint referencing tbl_customer.customer_id. On delete cascade ensures that if a customer is deleted, all associated subscription logs are also deleted. +- `fk_subscription_log_history_subscription`: Foreign key constraint referencing tbl_subscription.subscription_status_id. On delete cascade ensures that if a subscription plan is deleted, all associated subscription logs are also deleted. + +## 9. tbl_shopping_cart +> Stores information about customer shopping carts. + +**Columns:** +- `customer_id`: Foreign key referencing tbl_customer.customer_id (VARCHAR2(10), Not Null) +- `book_id`: Foreign key referencing tbl_book.book_id (VARCHAR2(10), Not Null) +- `quantity`: Quantity of the book in the shopping cart (NUMBER, Not Null) + +**Constraints:** +- `pk_shopping_cart`: Primary key constraint on customer_id and book_id +- `ck_quantity`: Ensures quantity is greater than 0 +- `fk_shopping_cart_customer`: Foreign key constraint referencing tbl_customer.customer_id. On delete cascade ensures that if a customer is deleted, all associated shopping cart items are also deleted. +- `fk_shopping_cart_book`: Foreign key constraint referencing tbl_book.book_id. On delete cascade ensures that if a book is deleted, the associated shopping cart items are also deleted. + +## 10. tbl_wishlist +> Stores information about customer wishlists. + +**Columns:** +- `customer_wishlist_id`: Unique identifier for the customer wishlist (VARCHAR2(10), Not Null) +- `customer_id`: Foreign key referencing tbl_customer.customer_id (VARCHAR2(10), Not Null) +- `book_id`: Foreign key referencing tbl_book.book_id (VARCHAR2(10), Not Null) +- `wishlist_name`: Name of the wishlist (VARCHAR2(50)) +- `wishlist_description`: Description of the wishlist (VARCHAR2(1000)) +- `wishlist_image`: URL of the wishlist image (VARCHAR2(255)) + +**Constraints:** +- `pk_wishlist`: Primary key constraint on customer_wishlist_id and customer_id +- `ck_wishlist_customer_wishlist_id`: Ensures customer_wishlist_id starts with "wi" followed by five digits +- `fk_wishlist_customer`: Foreign key constraint referencing tbl_customer.customer_id. On delete cascade ensures that if a customer is deleted, all associated wishlists are also deleted. +- `fk_wishlist_book`: Foreign key constraint referencing tbl_book.book_id. On delete cascade ensures that if a book is deleted, the associated wishlist items are also deleted. + +## 11. tbl_wishlist_item +> Stores information about customer wishlist items. + +**Columns:** +- `customer_wishlist_id`: Foreign key referencing tbl_wishlist.customer_wishlist_id (VARCHAR2(10), Not Null) +- `customer_id`: Foreign key referencing tbl_customer.customer_id (VARCHAR2(10), Not Null) +- `book_id`: Foreign key referencing tbl_book.book_id (VARCHAR2(10), Not Null) + +**Constraints:** +- `pk_wishlist_item`: Primary key constraint on customer_wishlist_id, customer_id, and book_id +- `fk_wishlist_item_wishlist`: Foreign key constraint referencing tbl_wishlist.customer_wishlist_id and tbl_wishlist.customer_id. On delete cascade ensures that if a wishlist is deleted, all associated wishlist items are also deleted. +- `fk_wishlist_item_book`: Foreign key constraint referencing tbl_book.book_id. On delete cascade ensures that if a book is deleted, the associated wishlist items are also deleted. + + +## 12. tbl_user_review +> Stores information about customer reviews on books. + +**Columns:** +- `book_id`: Foreign key referencing tbl_book.book_id (VARCHAR2(10), Not Null) +- `customer_id`: Foreign key referencing tbl_customer.customer_id (VARCHAR2(10), Not Null) +- `book_rating`: Rating given by the customer for the book (NUMBER) +- `book_review`: Review text given by the customer for the book (VARCHAR2(1000)) +- `review_date`: Date when the review was submitted (DATE) + +**Constraints:** +- `pk_book_rating`: Primary key constraint on book_id and customer_id +- `ck_book_rating`: Ensures book_rating is between 0 and 5 +- `fk_book_rating_book`: Foreign key constraint referencing tbl_book.book_id. On delete cascade ensures that if a book is deleted, all associated reviews are also deleted. +- `fk_book_rating_customer`: Foreign key constraint referencing tbl_customer.customer_id. On delete cascade ensures that if a customer is deleted, all associated reviews are also deleted. + +## 13. tbl_orders +> Stores information about customer orders. + +**Columns:** +- `order_id`: Unique identifier for the order (VARCHAR2(10), Not Null, Primary Key) +- `customer_id`: Foreign key referencing tbl_customer.customer_id (VARCHAR2(10), Not Null) +- `address_type`: Type of address for shipping (VARCHAR2(16), Not Null) +- `order_date`: Date when the order was placed (DATE) +- `shipped_date`: Date when the order was shipped (DATE) +- `order_discount`: Discount applied to the order (NUMBER, Not Null) +- `order_total_cost`: Total cost of the order (NUMBER, Not Null) +- `order_status`: Status of the order (VARCHAR2(16)) + +**Constraints:** +- `pk_order`: Primary key constraint on order_id +- `ck_order_id`: Ensures order_id starts with "or" followed by five digits +- `fk_order_customer_address_customer`: Foreign key constraint referencing tbl_customer.customer_id and tbl_customer_address.address_type. On delete cascade ensures that if a customer or address is deleted, all associated orders are also deleted. +- `ck_customer_address_type`: Checks that the address_type is one of the predefined values ('Home', 'Office', 'Work', 'Other'). +- `ck_order_discount`: Ensures order_discount is between 0 and 1 +- `ck_order_total_cost`: Ensures order_total_cost is greater than or equal to 0 + +## 14. tbl_order_detail +> Stores detailed information about items in customer orders. + +**Columns:** +- `order_id`: Foreign key referencing tbl_orders.order_id (VARCHAR2(10), Not Null) +- `book_id`: Foreign key referencing tbl_book.book_id (VARCHAR2(10), Not Null) +- `book_price`: Price of the book at the time of the order (NUMBER) +- `quantity`: Quantity of the book in the order (NUMBER, Default 1, Not Null) + +**Constraints:** +- `pk_order_detail`: Primary key constraint on order_id and book_id +- `ck_book_price`: Ensures book_price is greater than or equal to 0 +- `ck_order_detail_quantity`: Ensures quantity is greater than or equal to 1 +- `fk_OrderDetails_Orders`: Foreign key constraint referencing tbl_orders.order_id. On delete cascade ensures that if an order is deleted, all associated order details are also deleted. +- `fk_OrderDetails_Products`: Foreign key constraint referencing tbl_book.book_id. On delete cascade ensures that if a book is deleted, the associated order details are also deleted. diff --git a/requirements.md b/requirements.md new file mode 100644 index 0000000..6a56a7b --- /dev/null +++ b/requirements.md @@ -0,0 +1,11 @@ +## β˜• Requirements +- [ ] Database Schema + - [ ] Database Normalization + - [ ] ER Diagram @vishveshrathore20 + - [x] Database Schema + - [ ] sys & system accounts in Oracle Database + - [ ] SQL Queries @Ayon-SSP + - [ ] DDL + - [ ] Triggers (insert) + - [ ] Insert Data @GauravBohra2001 + - [ ] ... \ No newline at end of file diff --git a/tests/docs/er-diagram.jpg b/tests/docs/er-diagram.jpg new file mode 100644 index 0000000..761ab51 Binary files /dev/null and b/tests/docs/er-diagram.jpg differ diff --git a/tests/docs/er-diagram.md b/tests/docs/er-diagram.md new file mode 100644 index 0000000..a90957e --- /dev/null +++ b/tests/docs/er-diagram.md @@ -0,0 +1,698 @@ +## ER Diagram +``` +1. check all not null, `check` constraints and `unique` constraints +2. check all foreign keys & primary keys +3. check all unique constraints +4. check id datatypes +5. there are many mistakes + + +FORMAT SQL OBJECT FILE +change NUMBER -> VARCHAR2(10) for id's +CHECK REGEXP FOR ID'S +``` + +### author +- author_id [PK] +- author_name +- author_bio +- author_score +- [auto calculate average ratings of all books] +- author_image +- author_birth_date + - Optional: + - author_email + - author_death_date + - author_country + +```sql +CREATE TABLE author +( + author_id NUMBER NOT NULL, + author_name VARCHAR2(50) NOT NULL, + author_bio VARCHAR2(300), + author_score NUMBER, + author_image VARCHAR2(255), + author_birth_date DATE, +CONSTRAINT PK_author + PRIMARY KEY (author_id) +CONSTRAINT CK_author_score CHECK ((author_score >= 0 AND author_score <= 5)) +) +/ + +-- CREATE A TRIGGER ON USER_REVIEW TABLE SO WHEN A NEW ROCORD IS INSERTED, UPDATED AND DELETED INTO THE TABLE, THE AUTHOR_SCORE IS UPDATED.(For this we will create a main package for calculation and in that package we will create a function to calulate average_author_rating and then we will create an insert trigger to calculate the average_author_rating when a new record is inserted into the user_review table by calling the function from that package.) + +``` + +### book_category +- category_id [PK] +- category_name (like magazine, novel, etc) +- category_description + - Optional: + - category_image + +```sql +CREATE TABLE book_category +( + category_id NUMBER NOT NULL, + category_name VARCHAR2(50) NOT NULL, + category_description VARCHAR2(300), + category_image VARCHAR2(255), +CONSTRAINT PK_book_category + PRIMARY KEY (category_id), +) +/ + +``` + +### genre +- genre_id [PK] +- genre_name +- genre_description +- genre_image + - Optional: + +```sql +CREATE TABLE genre +( + genre_id NUMBER GENERATED BY DEFAULT AS IDENTITY + START WITH 101 NOT NULL, + genre_name VARCHAR2(50) NOT NULL, + genre_description VARCHAR2(300), + genre_image VARCHAR2(255), +CONSTRAINT PK_genre + PRIMARY KEY (genre_id) +) +/ +``` + +### book +- book_id [PK] +- book_title +- book_description +- book_publish_date +- author_id [FK-> author.author_id] +- category_id [FK-> book_category.category_id] +- book_price [check >=0] +- book_discount [0.0 - 1.0] +- available_quantity [check >=0] +- discontinued [Default: false] +- book_cover_image +- book_publisher +- book_language +- book_pages +- book_isbn + - Optional: + - book_rating + - total_book_reviews + +-- + +```SQL +CREATE OR REPLACE + TYPE genre_id_list AS TABLE OF NUMBER; -- Define a nested table type for genre IDs + +CREATE TABLE book +( + book_id NUMBER NOT NULL, + book_title VARCHAR2(40) NOT NULL, + book_description VARCHAR2(300), + book_publish_date DATE, + author_id NUMBER NOT NULL, + category_id NUMBER NOT NULL, + genre_ids genre_id_list, -- Define the column as the nested table type + book_price NUMBER, + book_discount NUMBER(1) DEFAULT 0 NOT NULL, + available_quantity NUMBER, + discontinued NUMBER(1) NOT NULL, + book_cover_image VARCHAR2(255), + book_publisher VARCHAR2(100), + book_language VARCHAR2(100), + book_pages NUMBER, + book_isbn VARCHAR2(13) UNIQUE, +CONSTRAINT PK_book + PRIMARY KEY (book_id), +CONSTRAINT CK_book_book_price CHECK ((book_price > 0)), +CONSTRAINT CK_book_discount CHECK ((book_discount >= 0 AND book_discount <= 1)), +CONSTRAINT CK_book_pages CHECK ((book_pages >= 0)), +CONSTRAINT CK_discontinued CHECK ((discontinued = 0 or discontinued = 1)), +CONSTRAINT CK_available_quantity CHECK ((available_quantity >= 0)), +CONSTRAINT FK_book_author FOREIGN KEY (author_id) REFERENCES author(author_id), +CONSTRAINT FK_book_category FOREIGN KEY (category_id) REFERENCES book_category(category_id) +) +/ + +DECLARE + v_genre_ids genre_id_list; +BEGIN + -- Initialize the genre IDs for a specific book + v_genre_ids := genre_id_list(1, 3, 5); -- Example genre IDs + + -- Insert data into the book table + INSERT INTO book ( + book_id, + book_title, + book_description, + book_publish_date, + author_id, + category_id, + genre_ids, + book_price, + available_quantity, + discontinued, + book_cover_image, + book_publisher, + book_language, + book_pages, + book_isbn + ) VALUES ( + 1, -- Example book_id + 'Example Book Title', + 'This is an example book description.', + TO_DATE('2024-03-05', 'YYYY-MM-DD'), -- Example publish date + 1, -- Example author_id + 1, -- Example category_id + v_genre_ids, -- Use the variable containing genre IDs + 10.99, -- Example book price + 100, -- Example available quantity + 0, -- Example discontinued + 'example_cover_image.jpg', + 'Example Publisher', + 'English', + 250, -- Example number of pages + '9781234567890' -- Example ISBN + ); +END; +/ + + + + +-- OTHER EXAMPLES TO INSERT + +-- write a simple plsql code to create and insert where using PL/SQL Nested Tables a table contains a column of nested table type. +-- + +CREATE OR REPLACE TYPE nested_table AS TABLE OF VARCHAR2(100); +/ + +CREATE TABLE employees ( + employee_id NUMBER, + employee_name VARCHAR2(100), + employee_address nested_table +) +NESTED TABLE employee_address STORE AS employee_address_tab; + +INSERT INTO employees VALUES (1, 'John', nested_table('Address1', 'Address2')); +INSERT INTO employees VALUES (2, 'Smith', nested_table('Address3', 'Address4')); + + +``` + +TODO: suggest subscription names +### subscription - ⚠️ suggest a table name +- subscription_status_id (1, 2, 3 ...) +- subscription_name (Gold, Silver, Bronze ...) TODO: suggest subscription names (royalmember, ) +- subscription_description (description about the subscription type) +- subscription_price (149, 199, 249 ...) +- subscription_duration (3M, 6M, 12M) x all are of 1M +- subscription_discount (0.1, 0.2, 0.3) - 10%, 20%, 30% + - Optional: + +```sql +CREATE TABLE subscription +( + subscription_status_id NUMBER NOT NULL, + subscription_name VARCHAR2(30), + subscription_description VARCHAR2(300), + subscription_price NUMBER, + subscription_duration VARCHAR2(3), + subscription_discount NUMBER(1, 2), +CONSTRAINT PK_subscription + PRIMARY KEY (subscription_status_id), +CONSTRAINT CK_subscription_price CHECK ((subscription_price > 0)), +CONSTRAINT CK_subscription_discount CHECK ((subscription_discount >= 0 AND subscription_discount <= 1)) +) +/ +``` + + +### customer +- customer_id [PK] +- customer_name +- customer_email +- customer_phone1 +- customer_phone2 +- password_hash + + + - Optional: + - join_date + - subscription_expire_date + + +```sql +CREATE TABLE customer +( + customer_id NUMBER NOT NULL, + customer_name VARCHAR2(30), + customer_email VARCHAR2(100), + customer_phone1 VARCHAR2(24) NOT NULL, + customer_phone2 VARCHAR2(24), + password_hash VARCHAR2(100), + -- subscription_status_id NUMBER NOT NULL, + -- premium_expire_date DATE, +CONSTRAINT PK_customer + PRIMARY KEY (customer_id), +-- CONSTRAINT FK_customer_customer_address FOREIGN KEY (subscription_status_id) REFERENCES customer_address(subscription_status_id) +) +/ + +-- need to update the subscription_expire_date when the premium_expire_date is expired +``` + + +### customer_address +- customer_address_id [/PK] customer_address_id -> (customer_id, address_type) +- address_type (home, office, etc) [PK] +- customer_id [FK-> customer.customer_id] [PK] +- address_line1 [not null] +- address_line2 +- address_line3 +- city +- state [not null] +- country +- pincode (or postalcode) [not null] - ⚠️ suggest a name +- landmark +- phone [not null] + - Optional: + - country + + +```sql +CREATE TABLE customer_address ( + address_type VARCHAR2(16) NOT NULL, + customer_id NUMBER NOT NULL, + address_line1 VARCHAR2(255), + address_line2 VARCHAR2(255), + address_line3 VARCHAR2(255), + city VARCHAR2(100), + state VARCHAR2(100), + country VARCHAR2(100), + postalcode VARCHAR2(6), + landmark VARCHAR2(255), + phone VARCHAR2(24), +CONSTRAINT PK_customer_address + PRIMARY KEY (address_type, customer_id), +CONSTRAINT FK_customer_address_customer FOREIGN KEY (customer_id) REFERENCES customer(customer_id) +) +/ + +-- triggere if phone is null then set phone = customer.phone +``` + + +### subscription_log_history +- subscription_log_id [PK] +- customer_id [FK-> customer.customer_id] +- subscription_status_id [FK-> subscription.subscription_status_id] +- subscription_start_date -- sysdate +- subscription_end_date -- sysdate + 6M + - Optional: + - subscription_cancel_date + - subscription_cancel_reason + +```sql +CREATE TABLE subscription_log_history +( + subscription_log_id NUMBER NOT NULL, + customer_id NUMBER NOT NULL, + subscription_status_id VARCHAR2(10) NOT NULL, + subscription_start_date DATE, + subscription_end_date DATE, +CONSTRAINT PK_subscription_log_history + PRIMARY KEY (subscription_log_id), +CONSTRAINT FK_subscription_log_history_customer + FOREIGN KEY (customer_id) + REFERENCES customer(customer_id) + ON DELETE CASCADE, +CONSTRAINT FK_subscription_log_history_subscription + FOREIGN KEY (subscription_status_id) + REFERENCES subscription(subscription_status_id) + ON DELETE CASCADE +) +/ +``` + + + +### shopping_cart +- customer_id [FK-> customer.customer_id] [PK] +- book_id [FK-> book.book_id] [PK] +- quantity + - Optional: + - added_date + - removed_date + +```sql +CREATE TABLE shopping_cart +( + customer_id NUMBER NOT NULL, + book_id NUMBER NOT NULL, + quantity NUMBER NOT NULL, +CONSTRAINT PK_shopping_cart + PRIMARY KEY (customer_id, book_id), +CONSTRAINT CK_quantity CHECK ((quantity > 0)), +CONSTRAINT FK_shopping_cart_customer FOREIGN KEY (customer_id) REFERENCES customer(customer_id), +CONSTRAINT FK_shopping_cart_book FOREIGN KEY (book_id) REFERENCES book(book_id) +) +/ +``` + + +### wishlist +- customer_id [FK-> customer.customer_id] [PK] +- customer_wishlist_id [PK] +- book_id [FK-> book.book_id] [PK] +- wishlist_name +- wishlist_description +- wishlist_image +- date_added +- removed_date + - Optional: + +```sql +CREATE TABLE wishlist +( + customer_id NUMBER NOT NULL, + customer_wishlist_id NUMBER NOT NULL, + book_id NUMBER NOT NULL, + wishlist_name VARCHAR2(50), + wishlist_description VARCHAR2(300), + wishlist_image VARCHAR2(255), + date_added DATE, + removed_date DATE, +CONSTRAINT PK_wishlist + PRIMARY KEY (customer_id, customer_wishlist_id, book_id), +CONSTRAINT FK_wishlist_customer FOREIGN KEY (customer_id) REFERENCES customer(customer_id), +CONSTRAINT FK_wishlist_book FOREIGN KEY (book_id) REFERENCES book(book_id) +) +/ + +``` + + +### user_review +- book_id [FK-> book.book_id] [PK] +- customer_id [FK-> customer.customer_id] [PK] +- book_rating [0-5] +- book_review +- review_date + - Optional: + - user_liked (-1, 0, 1) (disliked, neutral, liked) + +```sql +CREATE TABLE user_review +( + book_id NUMBER NOT NULL, + customer_id NUMBER NOT NULL, + book_rating NUMBER(1, 1), + book_review VARCHAR2(300), + review_date DATE, +CONSTRAINT PK_book_rating + PRIMARY KEY (book_id, customer_id), +CONSTRAINT CK_book_rating CHECK ((book_rating >= 0 and book_rating <= 5)), +CONSTRAINT FK_book_rating_book FOREIGN KEY (book_id) REFERENCES book(book_id), +CONSTRAINT FK_book_rating_customer FOREIGN KEY (customer_id) REFERENCES customer(customer_id) +) +/ + +``` + +### order +> πŸ€–-> from shopping cart +- order_id [PK] +- customer_id [FK-> customer.customer_id] +- address_type (customer_id & customer_address_type) -> Delivery Address [FK-> customer_addressaddress_type] +- order_date [auto calculated current date] +- shipped_date (basic algorithm to calculate the shipping date) +- order_discount (applying discount by customer's subscription status) (initial random data insertion) "function" to calculate the total price with discount with 10 or 20% discount [auto calculated SUM(order_detail.book_price) WHERE order_id = order_detail.order_id] +- order_total_cost (calculating with the book_price & book_discount) [auto calculated/PLSQL] + - ( SUM(order_detail.book_price * (1 - order_detail.book_discount) * order_detail.quantity) * (1 - order_discount) ) WHERE order_id = order.order_id `Order Processing (point 2` +- order_status (pending, processing, shipped, delivered, cancelled, returned, etc.) + - Optional: + - required_date + - salesman_id + + +```sql +CREATE TABLE order +( + order_id NUMBER NOT NULL, + customer_id NUMBER NOT NULL, + address_type VARCHAR2(16) NOT NULL, + order_date DATE, + shipped_date DATE, + order_discount NUMBER NOT NULL, -- get from customer subscription status + order_total_cost NUMBER, -- this will be calculated + order_status VARCHAR2(16), +CONSTRAINT PK_order + PRIMARY KEY (order_id), +CONSTRAINT FK_order_customer FOREIGN KEY (customer_id) REFERENCES customer(customer_id), +CONSTRAINT FK_order_customer FOREIGN KEY (address_type) REFERENCES customer_address(address_type), +CONSTRAINT CK_order_discount CHECK ((order_discount >= 0 AND order_discount <= 1)), +CONSTRAINT CK_order_total_cost CHECK ((order_total_cost >= 0)) +) +-- create a insert trigger to calculate the order_total_cost -> cancelled +``` + + +### order_detail +- order_id [FK-> order.order_id] [PK] +- book_id [FK-> book.book_id] [PK] +- book_price [auto calculated book.book_price] +- quantity + - Optional: + +```sql +CREATE TABLE order_detail +( + order_id NUMBER NOT NULL, + book_id NUMBER NOT NULL, + book_price NUMBER NOT NULL, + quantity NUMBER NOT NULL, +CONSTRAINT PK_order_detail + PRIMARY KEY (order_id, book_id), +CONSTRAINT CK_book_price CHECK ((book_price >= 0)), +CONSTRAINT CK_quantity CHECK ((quantity > 0)), +CONSTRAINT FK_OrderDetails_Orders FOREIGN KEY (order_id) REFERENCES order(order_id), +CONSTRAINT FK_OrderDetails_Products FOREIGN KEY (book_id) REFERENCES book(book_id) +) + +-- create a insert trigger to calculate the book_price +-- create a avalable stock count trigger +-- create a update trigger to update the available stock count -... +``` + +## Ignore +- Publishers(Optional) + +Id's starts with + genre_id: Gen100 101 ... + author_id: Auth200 201 ... + book_id: Boo300 301 ... + subscription_status_id: Sub400 401 ... + customer_id: cus500 501 ... + shopping_cart_id: sho800 801 ... + order_id: ord600 601 ... + address_id: add700 701 ... + wishlist_id: wis900 901 ... + user_review_id: rev1000 1001 ... + SUBSCRIPTION_ID: SUB100 101 ... + +## T0do +- TODO: auto increment id's ❌ +- TODO: Think about the how to give custome names to id columns DONE: +- TODO: add the triggers AND exceptions and packages + - author: au00001 + - book_category: bc00001 + - genre: ge00001 + - book: bo00001 + - subscription: su00001 + - customer: cu00001 + - order: or00001 + - customer_address: ca00001 + - wishlist: wi00001 + - order_detail: od00001 + - subscription_log_history: sl00001 + +- TODO: DISIDE THE largest limit for the id columns. +- USING PACKAGES +- pls_integer insted of NUMBER +- +- designing all the triggers + +# login logout triggers, History of login and logout +# history of every eddits made database and schema level triggers. +# startup and shutdown triggers + +----------------------------------------------------------------------------------------------------------- +### PACKAGE_CALCULATE +- TRIGGER(FUNCTION return calculate.get_avg_author_rating) + + + + + + +### PACKAGE_OPERATIONS +- Procedure(Book Table[price] perform update operation using DML statement operatins.set_book_discount(author_id, discount) +- Procedure(Book Table[available_quantity] +- increase the book count on book stock update + - operation.add_book_quantity(book_id, quantity) +- decrement the book count on book sale (triggers) + - operation.decrement_book_quantity(book_id, quantity) + + + + +### Packages +#### Operation + - decrement the book quantity on book sale procedure + - operation.pr_decrement_book_count(book_id, quantity) + - book order cancled so decrement the book_quantity of a book + - operation.pr_increment_book_count(book_id, quantity) + - function to calculate the price of a book_id with discount + - operation.fn_get_book_price(book_id) + +#### Calculate + - procedure to update the author_score + - operation.pr_update_author_score(author_id, book_rating) + +### Trigger + +- book_sale_trigger on order_detail -> decrement the book count on book sale + +- create a trigger on table user_review on insert delete and update to updat the author.author_score by calculating the average rating of all the books of the author. + - tr_set_author_score on user_review -> update author.author_score + +- triggered cart -> on order_details(auto insert the new order_id in order table) -> update book_price in order_detail using book_price +- + + + + + + + + + + + + + + +_______________________________________________________________________________________________ + + + + +-- Create Tables +CREATE TABLE Authors ( + AuthorID INT PRIMARY KEY, + AuthorName VARCHAR(100) +); + +CREATE TABLE Books ( + BookID INT PRIMARY KEY, + Title VARCHAR(255), + AuthorID INT, + Price DECIMAL(10,2), + StockQuantity INT, + FOREIGN KEY (AuthorID) REFERENCES Authors(AuthorID) +); + +CREATE TABLE Customers ( + CustomerID INT PRIMARY KEY, + FirstName VARCHAR(100), + LastName VARCHAR(100), + Email VARCHAR(255), + Address VARCHAR(255) +); + +CREATE TABLE Orders ( + OrderID INT PRIMARY KEY, + CustomerID INT, + OrderDate DATE, + TotalAmount DECIMAL(10,2), + FOREIGN KEY (CustomerID) REFERENCES Customers(CustomerID) +); + +CREATE TABLE OrderDetails ( + OrderDetailID INT PRIMARY KEY, + OrderID INT, + BookID INT, + Quantity INT, + Price DECIMAL(10,2), + FOREIGN KEY (OrderID) REFERENCES Orders(OrderID), + FOREIGN KEY (BookID) REFERENCES Books(BookID) +); + +-- Create Triggers (Example: Update StockQuantity after an order) +CREATE TRIGGER UpdateStockQuantity +AFTER INSERT ON OrderDetails +FOR EACH ROW +BEGIN + UPDATE Books + SET StockQuantity = StockQuantity - NEW.Quantity + WHERE BookID = NEW.BookID; +END; + +-- Create Procedures (Example: PlaceOrder) +DELIMITER // +CREATE PROCEDURE PlaceOrder( + IN custID INT, + IN bookID INT, + IN qty INT +) +BEGIN + DECLARE totalAmount DECIMAL(10,2); + DECLARE price DECIMAL(10,2); + + SELECT Price INTO price FROM Books WHERE BookID = bookID; + SET totalAmount = price * qty; + + INSERT INTO Orders (CustomerID, OrderDate, TotalAmount) + VALUES (custID, CURDATE(), totalAmount); + + INSERT INTO OrderDetails (OrderID, BookID, Quantity, Price) + VALUES (LAST_INSERT_ID(), bookID, qty, price); +END// +DELIMITER ; + +-- Create Functions (Example: CalculateTotalPrice) +CREATE FUNCTION CalculateTotalPrice(bookID INT, qty INT) RETURNS DECIMAL(10,2) +BEGIN + DECLARE price DECIMAL(10,2); + SELECT Price INTO price FROM Books WHERE BookID = bookID; + RETURN price * qty; +END; + +-- Create Packages (Example: BookstoreManagement) +CREATE PACKAGE BookstoreManagement AS + PROCEDURE PlaceOrder(custID INT, bookID INT, qty INT); + FUNCTION CalculateTotalPrice(bookID INT, qty INT) RETURNS DECIMAL(10,2); +END BookstoreManagement; +/ + +CREATE PACKAGE BODY BookstoreManagement AS + PROCEDURE PlaceOrder(custID INT, bookID INT, qty INT) AS + -- implementation details + END PlaceOrder; + + FUNCTION CalculateTotalPrice(bookID INT, qty INT) RETURNS DECIMAL(10,2) AS + -- implementation details + END CalculateTotalPrice; +END BookstoreManagement; +/ + diff --git a/tests/frontend/obms_home.jpg b/tests/frontend/obms_home.jpg new file mode 100644 index 0000000..57307e2 Binary files /dev/null and b/tests/frontend/obms_home.jpg differ