CategoryUpdate

This commit is contained in:
Flatlogic Bot 2025-08-24 18:48:46 +00:00
parent 07f3101064
commit 41393cb40c
10 changed files with 553 additions and 23 deletions

5
.gitignore vendored
View File

@ -1,3 +1,8 @@
node_modules/
*/node_modules/
*/build/
**/node_modules/
**/build/
.DS_Store
.env

File diff suppressed because one or more lines are too long

View File

@ -11,6 +11,8 @@ const Notifications = db.notifications;
const Organizations = db.organizations;
const Categories = db.categories;
const DepartmentsData = [
{
name: 'Frontend Team',
@ -35,6 +37,22 @@ const DepartmentsData = [
// type code here for "relation_one" field
},
{
name: 'Threat Intelligence',
// type code here for "relation_one" field
// type code here for "relation_one" field
},
{
name: 'Customer Support',
// type code here for "relation_one" field
// type code here for "relation_one" field
},
];
const DivisionsData = [
@ -67,6 +85,26 @@ const DivisionsData = [
// type code here for "relation_one" field
},
{
name: 'Data Analysis',
// type code here for "relation_one" field
// type code here for "relation_many" field
// type code here for "relation_one" field
},
{
name: 'Technical Support',
// type code here for "relation_one" field
// type code here for "relation_many" field
// type code here for "relation_one" field
},
];
const ExpensesData = [
@ -75,7 +113,7 @@ const ExpensesData = [
amount: 15000,
category: 'Hardware',
category: 'PersonnelCosts',
date_incurred: new Date('2023-10-01T10:00:00Z'),
@ -103,7 +141,7 @@ const ExpensesData = [
amount: 2000,
category: 'PersonnelCosts',
category: 'Telecommunications',
date_incurred: new Date('2023-10-10T09:00:00Z'),
@ -111,6 +149,34 @@ const ExpensesData = [
// type code here for "relation_one" field
},
{
description: 'Employee training program',
amount: 3000,
category: 'Hardware',
date_incurred: new Date('2023-10-15T11:00:00Z'),
// type code here for "relation_one" field
// type code here for "relation_one" field
},
{
description: 'Monthly internet charges',
amount: 800,
category: 'Software',
date_incurred: new Date('2023-10-20T14:00:00Z'),
// type code here for "relation_one" field
// type code here for "relation_one" field
},
];
const NotificationsData = [
@ -143,6 +209,26 @@ const NotificationsData = [
// type code here for "relation_one" field
},
{
message: 'Expense category limit exceeded',
enabled: true,
// type code here for "relation_one" field
// type code here for "relation_one" field
},
{
message: 'New user signup notification',
enabled: true,
// type code here for "relation_one" field
// type code here for "relation_one" field
},
];
const OrganizationsData = [
@ -157,6 +243,56 @@ const OrganizationsData = [
{
name: 'IT Pioneers',
},
{
name: 'Future Tech',
},
{
name: 'Cyber Dynamics',
},
];
const CategoriesData = [
{
// type code here for "relation_one" field
name: 'Stephen Hawking',
// type code here for "relation_one" field
},
{
// type code here for "relation_one" field
name: 'Carl Linnaeus',
// type code here for "relation_one" field
},
{
// type code here for "relation_one" field
name: 'Carl Gauss (Karl Friedrich Gauss)',
// type code here for "relation_one" field
},
{
// type code here for "relation_one" field
name: 'August Kekule',
// type code here for "relation_one" field
},
{
// type code here for "relation_one" field
name: 'Konrad Lorenz',
// type code here for "relation_one" field
},
];
// Similar logic for "relation_many"
@ -194,6 +330,28 @@ async function associateUserWithOrganization() {
if (User2?.setOrganization) {
await User2.setOrganization(relatedOrganization2);
}
const relatedOrganization3 = await Organizations.findOne({
offset: Math.floor(Math.random() * (await Organizations.count())),
});
const User3 = await Users.findOne({
order: [['id', 'ASC']],
offset: 3,
});
if (User3?.setOrganization) {
await User3.setOrganization(relatedOrganization3);
}
const relatedOrganization4 = await Organizations.findOne({
offset: Math.floor(Math.random() * (await Organizations.count())),
});
const User4 = await Users.findOne({
order: [['id', 'ASC']],
offset: 4,
});
if (User4?.setOrganization) {
await User4.setOrganization(relatedOrganization4);
}
}
async function associateDepartmentWithDivision() {
@ -229,6 +387,28 @@ async function associateDepartmentWithDivision() {
if (Department2?.setDivision) {
await Department2.setDivision(relatedDivision2);
}
const relatedDivision3 = await Divisions.findOne({
offset: Math.floor(Math.random() * (await Divisions.count())),
});
const Department3 = await Departments.findOne({
order: [['id', 'ASC']],
offset: 3,
});
if (Department3?.setDivision) {
await Department3.setDivision(relatedDivision3);
}
const relatedDivision4 = await Divisions.findOne({
offset: Math.floor(Math.random() * (await Divisions.count())),
});
const Department4 = await Departments.findOne({
order: [['id', 'ASC']],
offset: 4,
});
if (Department4?.setDivision) {
await Department4.setDivision(relatedDivision4);
}
}
async function associateDepartmentWithOrganization() {
@ -264,6 +444,28 @@ async function associateDepartmentWithOrganization() {
if (Department2?.setOrganization) {
await Department2.setOrganization(relatedOrganization2);
}
const relatedOrganization3 = await Organizations.findOne({
offset: Math.floor(Math.random() * (await Organizations.count())),
});
const Department3 = await Departments.findOne({
order: [['id', 'ASC']],
offset: 3,
});
if (Department3?.setOrganization) {
await Department3.setOrganization(relatedOrganization3);
}
const relatedOrganization4 = await Organizations.findOne({
offset: Math.floor(Math.random() * (await Organizations.count())),
});
const Department4 = await Departments.findOne({
order: [['id', 'ASC']],
offset: 4,
});
if (Department4?.setOrganization) {
await Department4.setOrganization(relatedOrganization4);
}
}
async function associateDivisionWithOrganization() {
@ -299,6 +501,28 @@ async function associateDivisionWithOrganization() {
if (Division2?.setOrganization) {
await Division2.setOrganization(relatedOrganization2);
}
const relatedOrganization3 = await Organizations.findOne({
offset: Math.floor(Math.random() * (await Organizations.count())),
});
const Division3 = await Divisions.findOne({
order: [['id', 'ASC']],
offset: 3,
});
if (Division3?.setOrganization) {
await Division3.setOrganization(relatedOrganization3);
}
const relatedOrganization4 = await Organizations.findOne({
offset: Math.floor(Math.random() * (await Organizations.count())),
});
const Division4 = await Divisions.findOne({
order: [['id', 'ASC']],
offset: 4,
});
if (Division4?.setOrganization) {
await Division4.setOrganization(relatedOrganization4);
}
}
// Similar logic for "relation_many"
@ -336,6 +560,28 @@ async function associateDivisionWithOrganization() {
if (Division2?.setOrganization) {
await Division2.setOrganization(relatedOrganization2);
}
const relatedOrganization3 = await Organizations.findOne({
offset: Math.floor(Math.random() * (await Organizations.count())),
});
const Division3 = await Divisions.findOne({
order: [['id', 'ASC']],
offset: 3,
});
if (Division3?.setOrganization) {
await Division3.setOrganization(relatedOrganization3);
}
const relatedOrganization4 = await Organizations.findOne({
offset: Math.floor(Math.random() * (await Organizations.count())),
});
const Division4 = await Divisions.findOne({
order: [['id', 'ASC']],
offset: 4,
});
if (Division4?.setOrganization) {
await Division4.setOrganization(relatedOrganization4);
}
}
async function associateExpenseWithDepartment() {
@ -371,6 +617,28 @@ async function associateExpenseWithDepartment() {
if (Expense2?.setDepartment) {
await Expense2.setDepartment(relatedDepartment2);
}
const relatedDepartment3 = await Departments.findOne({
offset: Math.floor(Math.random() * (await Departments.count())),
});
const Expense3 = await Expenses.findOne({
order: [['id', 'ASC']],
offset: 3,
});
if (Expense3?.setDepartment) {
await Expense3.setDepartment(relatedDepartment3);
}
const relatedDepartment4 = await Departments.findOne({
offset: Math.floor(Math.random() * (await Departments.count())),
});
const Expense4 = await Expenses.findOne({
order: [['id', 'ASC']],
offset: 4,
});
if (Expense4?.setDepartment) {
await Expense4.setDepartment(relatedDepartment4);
}
}
async function associateExpenseWithOrganization() {
@ -406,6 +674,28 @@ async function associateExpenseWithOrganization() {
if (Expense2?.setOrganization) {
await Expense2.setOrganization(relatedOrganization2);
}
const relatedOrganization3 = await Organizations.findOne({
offset: Math.floor(Math.random() * (await Organizations.count())),
});
const Expense3 = await Expenses.findOne({
order: [['id', 'ASC']],
offset: 3,
});
if (Expense3?.setOrganization) {
await Expense3.setOrganization(relatedOrganization3);
}
const relatedOrganization4 = await Organizations.findOne({
offset: Math.floor(Math.random() * (await Organizations.count())),
});
const Expense4 = await Expenses.findOne({
order: [['id', 'ASC']],
offset: 4,
});
if (Expense4?.setOrganization) {
await Expense4.setOrganization(relatedOrganization4);
}
}
async function associateNotificationWithUser() {
@ -441,6 +731,28 @@ async function associateNotificationWithUser() {
if (Notification2?.setUser) {
await Notification2.setUser(relatedUser2);
}
const relatedUser3 = await Users.findOne({
offset: Math.floor(Math.random() * (await Users.count())),
});
const Notification3 = await Notifications.findOne({
order: [['id', 'ASC']],
offset: 3,
});
if (Notification3?.setUser) {
await Notification3.setUser(relatedUser3);
}
const relatedUser4 = await Users.findOne({
offset: Math.floor(Math.random() * (await Users.count())),
});
const Notification4 = await Notifications.findOne({
order: [['id', 'ASC']],
offset: 4,
});
if (Notification4?.setUser) {
await Notification4.setUser(relatedUser4);
}
}
async function associateNotificationWithOrganization() {
@ -476,6 +788,142 @@ async function associateNotificationWithOrganization() {
if (Notification2?.setOrganization) {
await Notification2.setOrganization(relatedOrganization2);
}
const relatedOrganization3 = await Organizations.findOne({
offset: Math.floor(Math.random() * (await Organizations.count())),
});
const Notification3 = await Notifications.findOne({
order: [['id', 'ASC']],
offset: 3,
});
if (Notification3?.setOrganization) {
await Notification3.setOrganization(relatedOrganization3);
}
const relatedOrganization4 = await Organizations.findOne({
offset: Math.floor(Math.random() * (await Organizations.count())),
});
const Notification4 = await Notifications.findOne({
order: [['id', 'ASC']],
offset: 4,
});
if (Notification4?.setOrganization) {
await Notification4.setOrganization(relatedOrganization4);
}
}
async function associateCategoryWithOrganization() {
const relatedOrganization0 = await Organizations.findOne({
offset: Math.floor(Math.random() * (await Organizations.count())),
});
const Category0 = await Categories.findOne({
order: [['id', 'ASC']],
offset: 0,
});
if (Category0?.setOrganization) {
await Category0.setOrganization(relatedOrganization0);
}
const relatedOrganization1 = await Organizations.findOne({
offset: Math.floor(Math.random() * (await Organizations.count())),
});
const Category1 = await Categories.findOne({
order: [['id', 'ASC']],
offset: 1,
});
if (Category1?.setOrganization) {
await Category1.setOrganization(relatedOrganization1);
}
const relatedOrganization2 = await Organizations.findOne({
offset: Math.floor(Math.random() * (await Organizations.count())),
});
const Category2 = await Categories.findOne({
order: [['id', 'ASC']],
offset: 2,
});
if (Category2?.setOrganization) {
await Category2.setOrganization(relatedOrganization2);
}
const relatedOrganization3 = await Organizations.findOne({
offset: Math.floor(Math.random() * (await Organizations.count())),
});
const Category3 = await Categories.findOne({
order: [['id', 'ASC']],
offset: 3,
});
if (Category3?.setOrganization) {
await Category3.setOrganization(relatedOrganization3);
}
const relatedOrganization4 = await Organizations.findOne({
offset: Math.floor(Math.random() * (await Organizations.count())),
});
const Category4 = await Categories.findOne({
order: [['id', 'ASC']],
offset: 4,
});
if (Category4?.setOrganization) {
await Category4.setOrganization(relatedOrganization4);
}
}
async function associateCategoryWithParent() {
const relatedParent0 = await Categories.findOne({
offset: Math.floor(Math.random() * (await Categories.count())),
});
const Category0 = await Categories.findOne({
order: [['id', 'ASC']],
offset: 0,
});
if (Category0?.setParent) {
await Category0.setParent(relatedParent0);
}
const relatedParent1 = await Categories.findOne({
offset: Math.floor(Math.random() * (await Categories.count())),
});
const Category1 = await Categories.findOne({
order: [['id', 'ASC']],
offset: 1,
});
if (Category1?.setParent) {
await Category1.setParent(relatedParent1);
}
const relatedParent2 = await Categories.findOne({
offset: Math.floor(Math.random() * (await Categories.count())),
});
const Category2 = await Categories.findOne({
order: [['id', 'ASC']],
offset: 2,
});
if (Category2?.setParent) {
await Category2.setParent(relatedParent2);
}
const relatedParent3 = await Categories.findOne({
offset: Math.floor(Math.random() * (await Categories.count())),
});
const Category3 = await Categories.findOne({
order: [['id', 'ASC']],
offset: 3,
});
if (Category3?.setParent) {
await Category3.setParent(relatedParent3);
}
const relatedParent4 = await Categories.findOne({
offset: Math.floor(Math.random() * (await Categories.count())),
});
const Category4 = await Categories.findOne({
order: [['id', 'ASC']],
offset: 4,
});
if (Category4?.setParent) {
await Category4.setParent(relatedParent4);
}
}
module.exports = {
@ -490,6 +938,8 @@ module.exports = {
await Organizations.bulkCreate(OrganizationsData);
await Categories.bulkCreate(CategoriesData);
await Promise.all([
// Similar logic for "relation_many"
@ -512,6 +962,10 @@ module.exports = {
await associateNotificationWithUser(),
await associateNotificationWithOrganization(),
await associateCategoryWithOrganization(),
await associateCategoryWithParent(),
]);
},
@ -525,5 +979,7 @@ module.exports = {
await queryInterface.bulkDelete('notifications', null, {});
await queryInterface.bulkDelete('organizations', null, {});
await queryInterface.bulkDelete('categories', null, {});
},
};

View File

@ -0,0 +1,20 @@
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
const now = new Date();
await queryInterface.bulkInsert('categories', [
{ name: 'Personnel', parentId: null, organizationsId: null, createdAt: now, updatedAt: now },
{ name: 'Hardware', parentId: null, organizationsId: null, createdAt: now, updatedAt: now },
{ name: 'Software', parentId: null, organizationsId: null, createdAt: now, updatedAt: now },
{ name: 'Third-Party', parentId: null, organizationsId: null, createdAt: now, updatedAt: now },
{ name: 'Telecommunications', parentId: null, organizationsId: null, createdAt: now, updatedAt: now },
], {});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.bulkDelete('categories', {
name: ['Personnel', 'Hardware', 'Software', 'Third-Party', 'Telecommunications'],
}, {});
},
};

View File

@ -0,0 +1,49 @@
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
const now = new Date();
// Fetch existing IDs for categories, departments, and organizations
const categories = await queryInterface.sequelize.query(
'SELECT id, name FROM categories',
{ type: queryInterface.sequelize.QueryTypes.SELECT }
);
const departments = await queryInterface.sequelize.query(
'SELECT id FROM departments',
{ type: queryInterface.sequelize.QueryTypes.SELECT }
);
const organizations = await queryInterface.sequelize.query(
'SELECT id FROM organizations',
{ type: queryInterface.sequelize.QueryTypes.SELECT }
);
// Helper to pick random element
const pick = (arr) => arr[Math.floor(Math.random() * arr.length)];
// Generate 100 sample expense records over past 24 months
const records = [];
for (let i = 0; i < 100; i++) {
const monthsAgo = Math.floor(Math.random() * 24);
const date = new Date();
date.setMonth(date.getMonth() - monthsAgo);
records.push({
description: `Sample expense ${i + 1}`,
amount: parseFloat((Math.random() * 10000 + 100).toFixed(2)),
date_incurred: date,
createdAt: now,
updatedAt: now,
departmentId: pick(departments).id,
organizationsId: pick(organizations).id,
// find matching category
categoryId: pick(categories).id,
});
}
await queryInterface.bulkInsert('expenses', records, {});
},
down: async (queryInterface, Sequelize) => {
// Remove all sample expenses
await queryInterface.bulkDelete('expenses', null, {});
},
};

View File

@ -0,0 +1 @@
{}

View File

@ -17,7 +17,7 @@ export default function WebSiteFooter({ projectName }: WebSiteFooterProps) {
const borders = useAppSelector((state) => state.style.borders);
const websiteHeder = useAppSelector((state) => state.style.websiteHeder);
const style = FooterStyle.WITH_PROJECT_NAME;
const style = FooterStyle.WITH_PAGES;
const design = FooterDesigns.DEFAULT_DESIGN;

View File

@ -19,7 +19,7 @@ export default function WebSiteHeader({ projectName }: WebSiteHeaderProps) {
const style = HeaderStyle.PAGES_RIGHT;
const design = HeaderDesigns.DESIGN_DIVERSITY;
const design = HeaderDesigns.DEFAULT_DESIGN;
return (
<header id='websiteHeader' className='overflow-hidden'>
<div

View File

@ -24,7 +24,7 @@ import ContactFormSection from '../components/WebPageComponents/ContactFormCompo
export default function WebSite() {
const cardsStyle = useAppSelector((state) => state.style.cardsStyle);
const bgColor = useAppSelector((state) => state.style.bgLayoutColor);
const projectName = 'App to manage the costs of a companys IT spend';
const projectName = 'App to manage the costs of a company&#39;s IT spend';
useEffect(() => {
const darkElement = document.querySelector('body .dark');
@ -80,12 +80,12 @@ export default function WebSite() {
/>
</Head>
<WebSiteHeader
projectName={'App to manage the costs of a companys IT spend'}
projectName={'App to manage the costs of a company&#39;s IT spend'}
pages={pages}
/>
<main className={`flex-grow ${bgColor} rounded-none `}>
<HeroSection
projectName={'App to manage the costs of a companys IT spend'}
projectName={'App to manage the costs of a company&#39;s IT spend'}
image={['IT budget management dashboard']}
mainText={`Revolutionize IT Spending with ${projectName}`}
subTitle={`Empower your IT department with ${projectName}. Categorize expenses, manage budgets, and ensure compliance effortlessly.`}
@ -94,7 +94,7 @@ export default function WebSite() {
/>
<FeaturesSection
projectName={'App to manage the costs of a companys IT spend'}
projectName={'App to manage the costs of a company&#39;s IT spend'}
image={['Expense tracking dashboard view']}
withBg={0}
features={features_points}
@ -104,7 +104,7 @@ export default function WebSite() {
/>
<AboutUsSection
projectName={'App to manage the costs of a companys IT spend'}
projectName={'App to manage the costs of a company&#39;s IT spend'}
image={['Team collaborating on budget strategy']}
mainText={`Empowering IT Departments with ${projectName}`}
subTitle={`At ${projectName}, we are dedicated to transforming how IT departments manage and optimize their budgets. Our innovative solutions ensure transparency, efficiency, and control over every dollar spent.`}
@ -113,7 +113,7 @@ export default function WebSite() {
/>
<ContactFormSection
projectName={'App to manage the costs of a companys IT spend'}
projectName={'App to manage the costs of a company&#39;s IT spend'}
design={ContactFormDesigns.WITH_IMAGE || ''}
image={['Person typing on a laptop']}
mainText={`Get in Touch with ${projectName} `}
@ -121,7 +121,7 @@ export default function WebSite() {
/>
</main>
<WebSiteFooter
projectName={'App to manage the costs of a companys IT spend'}
projectName={'App to manage the costs of a company&#39;s IT spend'}
pages={pages}
/>
</div>

View File

@ -24,7 +24,7 @@ import ContactFormSection from '../../components/WebPageComponents/ContactFormCo
export default function WebSite() {
const cardsStyle = useAppSelector((state) => state.style.cardsStyle);
const bgColor = useAppSelector((state) => state.style.bgLayoutColor);
const projectName = 'App to manage the costs of a companys IT spend';
const projectName = 'App to manage the costs of a company&#39;s IT spend';
useEffect(() => {
const darkElement = document.querySelector('body .dark');
@ -97,11 +97,11 @@ export default function WebSite() {
/>
</Head>
<WebSiteHeader
projectName={'App to manage the costs of a companys IT spend'}
projectName={'App to manage the costs of a company&#39;s IT spend'}
/>
<main className={`flex-grow ${bgColor} rounded-none `}>
<HeroSection
projectName={'App to manage the costs of a companys IT spend'}
projectName={'App to manage the costs of a company&#39;s IT spend'}
image={['IT services overview illustration']}
mainText={`Transform Your IT Budget Management`}
subTitle={`Discover the comprehensive services offered by ${projectName} to streamline your IT spending. From automated categorization to seamless integrations, we provide solutions tailored to your needs.`}
@ -110,9 +110,9 @@ export default function WebSite() {
/>
<FeaturesSection
projectName={'App to manage the costs of a companys IT spend'}
projectName={'App to manage the costs of a company&#39;s IT spend'}
image={['Feature highlights illustration']}
withBg={0}
withBg={1}
features={features_points}
mainText={`Explore ${projectName} Core Features`}
subTitle={`Unlock the potential of your IT budget with ${projectName}. Our features are designed to enhance efficiency and control over your spending.`}
@ -120,14 +120,14 @@ export default function WebSite() {
/>
<FaqSection
projectName={'App to manage the costs of a companys IT spend'}
projectName={'App to manage the costs of a company&#39;s IT spend'}
design={FaqDesigns.ACCORDION || ''}
faqs={faqs}
mainText={`Frequently Asked Questions about ${projectName} `}
/>
<ContactFormSection
projectName={'App to manage the costs of a companys IT spend'}
projectName={'App to manage the costs of a company&#39;s IT spend'}
design={ContactFormDesigns.HIGHLIGHTED || ''}
image={['Customer support representative']}
mainText={`Connect with ${projectName} Support `}
@ -135,7 +135,7 @@ export default function WebSite() {
/>
</main>
<WebSiteFooter
projectName={'App to manage the costs of a companys IT spend'}
projectName={'App to manage the costs of a company&#39;s IT spend'}
/>
</div>
);