working #18
@@ -5,42 +5,42 @@ Server:
|
|||||||
When a company is created:
|
When a company is created:
|
||||||
Send email -> verify ownership of the email
|
Send email -> verify ownership of the email
|
||||||
|
|
||||||
Need to timeout email reset tokens:
|
Resume:
|
||||||
|
Block API Access as much as possible [ Disallow AI keyword filters ]
|
||||||
|
|
||||||
|
Auth:
|
||||||
|
Make sure autorenew works
|
||||||
|
|
||||||
|
When Job Posting Closes Successful:
|
||||||
|
Update the company rating
|
||||||
|
|
||||||
|
JobCleanupService:
|
||||||
|
Need to update notification email
|
||||||
|
|
||||||
Client:
|
Client:
|
||||||
jobs/new:
|
jobs/new:
|
||||||
Want to add Required skills to help with filtering
|
Job Listing Skills exists but isn't implimented in the UI
|
||||||
When enter is pressed it tries to submit the form
|
Tab doesnt do anything
|
||||||
Should run the whole carosel on enter before the submit is sent
|
|
||||||
Need to validate input before allowing next step
|
|
||||||
Want to add completed job listing preview at end of carosel
|
Want to add completed job listing preview at end of carosel
|
||||||
|
Edit employees not implimented yet
|
||||||
|
|
||||||
|
Jobs/editor:
|
||||||
|
Jobs/editor w/ Querystring JobID=# is not implimented yet
|
||||||
|
Edit employees not implimented yet
|
||||||
|
|
||||||
|
Resume:
|
||||||
|
Resume builder minimal user input [ Dont allow AI input ]
|
||||||
|
Allow company to look up users if their resume is public [ Maybe auto with notify ]
|
||||||
|
Allow multiple resume's for job specific work
|
||||||
|
Create advanced filtering tools for company lookup and resume lookup
|
||||||
|
|
||||||
|
Job Board:
|
||||||
|
Allow users to look up jobs and apply [ Boost visibility | Completely manual ]
|
||||||
|
Mark ghost listings to allow users to be informed and put companies on blast
|
||||||
|
|
||||||
|
CompanyConnect:
|
||||||
|
need to lookup company before making a new one
|
||||||
|
|
||||||
|
|
||||||
database:
|
database:
|
||||||
Add Applied Jobs Table
|
Add Applied Jobs Table
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Task:
|
|
||||||
Block API Access as much as possible [ Rate limit | Auth Req | CORS | Disallow AI keyword filters ]
|
|
||||||
Resume builder minimal user input [ Dont allow AI input ]
|
|
||||||
Auto unlist jobs after a month of no activity [ Multiple offenders marked ]
|
|
||||||
Dont allow external applications for users on company sites from the start
|
|
||||||
Allow company to look up users if their resume is public [ Maybe auto with notify ]
|
|
||||||
Allow users to look up jobs and apply [ Boost visibility | Completely manual ]
|
|
||||||
Allow multiple resume's for job specific work
|
|
||||||
Mark ghost listings to allow users to be informed and put companies on blast
|
|
||||||
Create advanced filtering tools for company lookup and resume lookup
|
|
||||||
|
|
||||||
Create and Auth Database based on the docker compose
|
|
||||||
Create a server table inside the auth database
|
|
||||||
Point all requests after auth to the correct regional server. -> Currently only Mistox-West exists
|
|
||||||
|
|
||||||
CompanyConnect | need to lookup company before making a new one
|
|
||||||
|
|
||||||
Finish Auth setup
|
|
||||||
Make sure autorenew works
|
|
||||||
|
|
||||||
Jobs/editor w/ Querystring JobID=# is not implimented yet
|
|
||||||
Company -> Edit employees not implimented yet
|
|
||||||
|
|
||||||
Resume fields in angular models need to be public
|
|
||||||
+31
-2
@@ -131,6 +131,8 @@ CREATE TABLE IF NOT EXISTS `Company` (
|
|||||||
`EmailVerified` boolean DEFAULT 0,
|
`EmailVerified` boolean DEFAULT 0,
|
||||||
`WebsiteURL` varchar(255) DEFAULT NULL,
|
`WebsiteURL` varchar(255) DEFAULT NULL,
|
||||||
`Logo` mediumblob DEFAULT NULL,
|
`Logo` mediumblob DEFAULT NULL,
|
||||||
|
`JobsClosedSuccessful` int DEFAULT 0,
|
||||||
|
`JobsAutoClosed` int DEFAULT 0,
|
||||||
`Phone` varchar(20) DEFAULT NULL,
|
`Phone` varchar(20) DEFAULT NULL,
|
||||||
`PostalCode` varchar(20) NOT NULL,
|
`PostalCode` varchar(20) NOT NULL,
|
||||||
`Country` char(2) NOT NULL,
|
`Country` char(2) NOT NULL,
|
||||||
@@ -161,9 +163,36 @@ CREATE TABLE IF NOT EXISTS `JobListing` (
|
|||||||
`JobType` varchar(20) NOT NULL,
|
`JobType` varchar(20) NOT NULL,
|
||||||
`Remote` boolean DEFAULT 0,
|
`Remote` boolean DEFAULT 0,
|
||||||
`Description` text NOT NULL,
|
`Description` text NOT NULL,
|
||||||
`CreatedTime` datetime Default NULL,
|
`CreatedTime` datetime DEFAULT NULL,
|
||||||
`ModifiedTime` datetime DEFAULT NULL,
|
`ModifiedTime` datetime DEFAULT NULL,
|
||||||
`IsDeleted` boolean Default 0,
|
`IsDeleted` boolean DEFAULT 0,
|
||||||
PRIMARY KEY (`ID`),
|
PRIMARY KEY (`ID`),
|
||||||
FOREIGN KEY (`CompanyID`) REFERENCES `Company`(`ID`) ON DELETE CASCADE
|
FOREIGN KEY (`CompanyID`) REFERENCES `Company`(`ID`) ON DELETE CASCADE
|
||||||
) AUTO_INCREMENT=1;
|
) AUTO_INCREMENT=1;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `JobListingSkill` (
|
||||||
|
`ID` int NOT NULL AUTO_INCREMENT,
|
||||||
|
`JobListingID` int NOT NULL,
|
||||||
|
`Name` varchar(150) NOT NULL,
|
||||||
|
`Description` text DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`ID`),
|
||||||
|
FOREIGN KEY (`JobListingID`) REFERENCES `JobListing`(`ID`) ON DELETE CASCADE
|
||||||
|
) AUTO_INCREMENT=1;
|
||||||
|
|
||||||
|
-- Application Section
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `JobApplication` (
|
||||||
|
`ID` int NOT NULL AUTO_INCREMENT,
|
||||||
|
`AccountID` int NOT NULL,
|
||||||
|
`ResumeID` int NOT NULL,
|
||||||
|
`JobListingID` int NOT NULL,
|
||||||
|
`ResponseEmail` varchar(255) DEFAULT NULL,
|
||||||
|
`DateApplied` datetime DEFAULT NULL,
|
||||||
|
`ResponseStatus` varchar(50) NOT NULL DEFAULT 'Pending',
|
||||||
|
`HasBeenViewed` boolean DEFAULT 0,
|
||||||
|
`Rating` int DEFAULT NULL,
|
||||||
|
`Notes` text DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`ID`),
|
||||||
|
FOREIGN KEY (`ResumeID`) REFERENCES `Resume`(`ID`) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (`JobListingID`) REFERENCES `JobListing`(`ID`) ON DELETE CASCADE
|
||||||
|
) AUTO_INCREMENT=1;
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
export class Application {
|
||||||
|
public id: number | null = null;
|
||||||
|
public accountID: number = 0;
|
||||||
|
public resumeID: number = 0;
|
||||||
|
public jobListingID: number = 0;
|
||||||
|
public responseEmail: string = "";
|
||||||
|
public dateApplied: Date = new Date();
|
||||||
|
public responseStatus: string = "";
|
||||||
|
public hasBeenViewed: boolean = false;
|
||||||
|
public rating: number = 0;
|
||||||
|
public notes: string = "";
|
||||||
|
}
|
||||||
@@ -5,6 +5,8 @@ export class Company {
|
|||||||
public emailVerified: boolean = false;
|
public emailVerified: boolean = false;
|
||||||
public websiteURL: string = "";
|
public websiteURL: string = "";
|
||||||
public logo: string = "";
|
public logo: string = "";
|
||||||
|
public jobsClosedSuccessful: number = 0;
|
||||||
|
public jobsAutoClosed: number = 0;
|
||||||
public phone: string = "";
|
public phone: string = "";
|
||||||
public postalCode: string = "";
|
public postalCode: string = "";
|
||||||
public country: string = ""; // 2 Letter Country Code
|
public country: string = ""; // 2 Letter Country Code
|
||||||
|
|||||||
@@ -11,7 +11,15 @@ export class JobListing {
|
|||||||
public jobType: string = "";
|
public jobType: string = "";
|
||||||
public remote: boolean = false;
|
public remote: boolean = false;
|
||||||
public description: string = "";
|
public description: string = "";
|
||||||
|
public skills: JobListingSkills[] = [];
|
||||||
public createdTime: Date = new Date();
|
public createdTime: Date = new Date();
|
||||||
public modifiedTime: Date = new Date();
|
public modifiedTime: Date = new Date();
|
||||||
public isDeleted: boolean = false;
|
public isDeleted: boolean = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class JobListingSkills {
|
||||||
|
public id: number | null = null;
|
||||||
|
public jobListingID: number = 0;
|
||||||
|
public name: string = "";
|
||||||
|
public Description: string = "";
|
||||||
|
}
|
||||||
@@ -21,86 +21,86 @@ export class Resume {
|
|||||||
|
|
||||||
export class ResumeExperience {
|
export class ResumeExperience {
|
||||||
public id: number | null = null;
|
public id: number | null = null;
|
||||||
resumeID: number = 0;
|
public resumeID: number = 0;
|
||||||
jobTitle: string = "";
|
public jobTitle: string = "";
|
||||||
company: string = "";
|
public company: string = "";
|
||||||
postalCode: string = "";
|
public postalCode: string = "";
|
||||||
country: string = "";
|
public country: string = "";
|
||||||
stateOrRegion: string = "";
|
public stateOrRegion: string = "";
|
||||||
city: string = "";
|
public city: string = "";
|
||||||
dateStarted: Date = new Date();
|
public dateStarted: Date = new Date();
|
||||||
stillEmployed: boolean = false;
|
public stillEmployed: boolean = false;
|
||||||
dateEnded: Date = new Date();
|
public dateEnded: Date = new Date();
|
||||||
experienceBullets: ResumeExperienceBullet[] = [];
|
public experienceBullets: ResumeExperienceBullet[] = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ResumeExperienceBullet {
|
export class ResumeExperienceBullet {
|
||||||
public id: number | null = null;
|
public id: number | null = null;
|
||||||
resumeID: number = 0;
|
public resumeID: number = 0;
|
||||||
resumeExperienceID: number = 0;
|
public resumeExperienceID: number = 0;
|
||||||
jobFunction: string = "";
|
public jobFunction: string = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ResumeMilitary {
|
export class ResumeMilitary {
|
||||||
public id: number | null = null;
|
public id: number | null = null;
|
||||||
resumeID: number = 0;
|
public resumeID: number = 0;
|
||||||
country: string = "";
|
public country: string = "";
|
||||||
rank: string = "";
|
public rank: string = "";
|
||||||
dateStarted: Date = new Date();
|
public dateStarted: Date = new Date();
|
||||||
stillServing: boolean = false;
|
public stillServing: boolean = false;
|
||||||
dateEnded: Date = new Date();
|
public dateEnded: Date = new Date();
|
||||||
millitaryBullets: ResumeMilitaryBullet[] = [];
|
public millitaryBullets: ResumeMilitaryBullet[] = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ResumeMilitaryBullet {
|
export class ResumeMilitaryBullet {
|
||||||
public id: number | null = null;
|
public id: number | null = null;
|
||||||
resumeID: number = 0;
|
public resumeID: number = 0;
|
||||||
resumeMilitaryID: number = 0;
|
public resumeMilitaryID: number = 0;
|
||||||
achievement: string = "";
|
public achievement: string = "";
|
||||||
description: string = "";
|
public description: string = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ResumeEducation {
|
export class ResumeEducation {
|
||||||
public id: number | null = null;
|
public id: number | null = null;
|
||||||
resumeID: number = 0;
|
public resumeID: number = 0;
|
||||||
degreeType: string = "";
|
public degreeType: string = "";
|
||||||
degreeField: string = "";
|
public degreeField: string = "";
|
||||||
school: string = "";
|
public school: string = "";
|
||||||
postalCode: string = "";
|
public postalCode: string = "";
|
||||||
country: string = "";
|
public country: string = "";
|
||||||
stateOrRegion: string = "";
|
public stateOrRegion: string = "";
|
||||||
city: string = "";
|
public city: string = "";
|
||||||
dateStarted: Date = new Date();
|
public dateStarted: Date = new Date();
|
||||||
stillStudying: boolean = false;
|
public stillStudying: boolean = false;
|
||||||
dateEnded: Date = new Date();
|
public dateEnded: Date = new Date();
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ResumeSkill {
|
export class ResumeSkill {
|
||||||
public id: number | null = null;
|
public id: number | null = null;
|
||||||
resumeID: number = 0;
|
public resumeID: number = 0;
|
||||||
name: string = "";
|
public name: string = "";
|
||||||
description: string = "";
|
public description: string = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ResumeLanguage {
|
export class ResumeLanguage {
|
||||||
public id: number | null = null;
|
public id: number | null = null;
|
||||||
resumeID: number = 0;
|
public resumeID: number = 0;
|
||||||
language: string = "";
|
public language: string = "";
|
||||||
proficiency: string = "";
|
public proficiency: string = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ResumeCertification {
|
export class ResumeCertification {
|
||||||
public id: number | null = null;
|
public id: number | null = null;
|
||||||
resumeID: number = 0;
|
public resumeID: number = 0;
|
||||||
name: string = "";
|
public name: string = "";
|
||||||
verificationURL: string = "";
|
public verificationURL: string = "";
|
||||||
description: string = "";
|
public description: string = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ResumeProject {
|
export class ResumeProject {
|
||||||
public id: number | null = null;
|
public id: number | null = null;
|
||||||
resumeID: number = 0;
|
public resumeID: number = 0;
|
||||||
name: string = "";
|
public name: string = "";
|
||||||
url: string = "";
|
public url: string = "";
|
||||||
description: string = "";
|
public description: string = "";
|
||||||
}
|
}
|
||||||
@@ -30,4 +30,15 @@ button {
|
|||||||
margin: 10px;
|
margin: 10px;
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
color: var(--Mistox-White);
|
||||||
|
}
|
||||||
|
|
||||||
|
.center-item {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center-item img {
|
||||||
|
width: 300px;
|
||||||
}
|
}
|
||||||
@@ -4,11 +4,16 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="content-frame">
|
<div class="content-frame">
|
||||||
<div *ngIf="Comp != null">
|
<div *ngIf="Comp != null">
|
||||||
<h1>{{ Comp.name }}</h1>
|
<div class="center-item">
|
||||||
<h1>{{ Comp.email }}</h1>
|
<div><a [href]="'mailto:' + Comp.email" >{{ Comp.email }}</a></div>
|
||||||
|
<div><h1>{{ Comp.name }}</h1></div>
|
||||||
|
<div><a [href]="Comp.websiteURL">{{ Comp.websiteURL }}</a></div>
|
||||||
|
</div>
|
||||||
|
<div class="center-item">
|
||||||
|
<img [src]="Comp.logo" />
|
||||||
|
</div>
|
||||||
<h1>{{ Comp.emailVerified }}</h1>
|
<h1>{{ Comp.emailVerified }}</h1>
|
||||||
<h1>{{ Comp.websiteURL }}</h1>
|
|
||||||
<h1>{{ Comp.logo }}</h1>
|
|
||||||
<h1>{{ Comp.phone }}</h1>
|
<h1>{{ Comp.phone }}</h1>
|
||||||
<h1>{{ Comp.postalCode }}</h1>
|
<h1>{{ Comp.postalCode }}</h1>
|
||||||
<h1>{{ Comp.country }}</h1>
|
<h1>{{ Comp.country }}</h1>
|
||||||
|
|||||||
@@ -3,6 +3,19 @@
|
|||||||
width: calc(100% - 400px);
|
width: calc(100% - 400px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.center-text {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center-text h1 {
|
||||||
|
font-size: 100px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center-text h2 {
|
||||||
|
margin-bottom: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
.content-frame {
|
.content-frame {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@@ -16,6 +29,7 @@
|
|||||||
|
|
||||||
.floating-frame {
|
.floating-frame {
|
||||||
width: 450px;
|
width: 450px;
|
||||||
|
height: 200px;
|
||||||
background-color: var(--Mistox-Frame);
|
background-color: var(--Mistox-Frame);
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
@@ -41,8 +55,11 @@ hr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.solution-frame {
|
.solution-frame {
|
||||||
height: 200px;
|
|
||||||
background-color: blueviolet;
|
|
||||||
width: calc(100% - 515px);
|
width: calc(100% - 515px);
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border {
|
||||||
|
border-bottom: solid 1px #000;
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,11 @@
|
|||||||
<div class="center-frame">
|
<div class="center-frame">
|
||||||
<div class="content-frame">
|
|
||||||
|
<div class="center-frame center-text border">
|
||||||
|
<h1>Bored Careers</h1>
|
||||||
|
<h2>The Anti-AI Job Board</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content-frame border">
|
||||||
<div class="floating-frame">
|
<div class="floating-frame">
|
||||||
<div class="title-block">
|
<div class="title-block">
|
||||||
<h1>death by a thousand applicants</h1>
|
<h1>death by a thousand applicants</h1>
|
||||||
@@ -11,11 +17,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="solution-frame">
|
<div class="solution-frame">
|
||||||
|
<div>
|
||||||
|
<p><strong>Rate Limiting - </strong>We use strong rate limiting to prevent bot's from flooding applications</p>
|
||||||
|
<p><strong>Strong Authentication - </strong>All API's require authentication and will ban on suspision of bots</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content-frame">
|
<div class="content-frame border">
|
||||||
<div class="floating-frame">
|
<div class="floating-frame">
|
||||||
<div class="title-block">
|
<div class="title-block">
|
||||||
<h1>keyword frenzie</h1>
|
<h1>keyword frenzie</h1>
|
||||||
@@ -27,11 +36,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="solution-frame">
|
<div class="solution-frame">
|
||||||
|
<p><strong>No External Access - </strong>All companies and clients are required to interface with the application. Minimizing the surface for AI resume filters.</p>
|
||||||
|
<p><strong>Skill Based Resumes - </strong>Resume's are skill based not work history based. This allows companies to know what your good at without infering it.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content-frame">
|
<div class="content-frame border">
|
||||||
<div class="floating-frame">
|
<div class="floating-frame">
|
||||||
<div class="title-block">
|
<div class="title-block">
|
||||||
<h1>response black-hole</h1>
|
<h1>response black-hole</h1>
|
||||||
@@ -43,11 +53,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="solution-frame">
|
<div class="solution-frame">
|
||||||
|
<p><strong>Automated Email Notifications - </strong>No longer will you be left in the dark. No matter how the job listing is closed you will be notified</p>
|
||||||
|
<p><strong>More Analytics - </strong>Visibility into if the company has looked at your resume, view your resume score</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content-frame">
|
<div class="content-frame border">
|
||||||
<div class="floating-frame">
|
<div class="floating-frame">
|
||||||
<div class="title-block">
|
<div class="title-block">
|
||||||
<h1>zombie postings</h1>
|
<h1>zombie postings</h1>
|
||||||
@@ -59,7 +70,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="solution-frame">
|
<div class="solution-frame">
|
||||||
|
<p><strong>Job Postings Auto Close - </strong>Job postings auto close 30 days after originally posted. If the company creates a repost habit they will be flagged.</p>
|
||||||
|
<p><strong>Collective Flagging - </strong>Companies hold a reputation on the patform and its visible on all their job postings</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -75,7 +87,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="solution-frame">
|
<div class="solution-frame">
|
||||||
|
<p><strong>Resume Builder - </strong>No staring at a blank sheet trying to build a resume. Use our curated resume builder</p>
|
||||||
|
<p><strong>Companies Search Tools - </strong>Companies can find you with ease with the strong search tools</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
--Mistox-Medium: #890620;
|
--Mistox-Medium: #890620;
|
||||||
--Mistox-Light: #B6465F;
|
--Mistox-Light: #B6465F;
|
||||||
--Mistox-Bright: #FC440F;
|
--Mistox-Bright: #FC440F;
|
||||||
--Mistox-Frame: #FF5A00CC;
|
--Mistox-Frame: #FFE0A5;
|
||||||
--Mistox-Button: #ff9999;
|
--Mistox-Button: #ff9999;
|
||||||
--Mistox-Button-Hover: #ff999977;
|
--Mistox-Button-Hover: #ff999977;
|
||||||
--Mistox-White: #FFF;
|
--Mistox-White: #FFF;
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using BoredCareers.Services.DatabaseService;
|
||||||
|
using BoredCareers.Entities;
|
||||||
|
using System.Web.Http;
|
||||||
|
|
||||||
|
namespace BoredCareers.Controllers {
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/application")]
|
||||||
|
public class ApplicationController : MistoxControllerBase {
|
||||||
|
|
||||||
|
public ApplicationController(DatabaseService db) : base(db) {}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<IActionResult> GetApplication(int ApplicationID) {
|
||||||
|
if (isLoggedIn()) {
|
||||||
|
Application? application = await _databaseService.GetApplication(ApplicationID);
|
||||||
|
if (application != null) {
|
||||||
|
return Ok(application);
|
||||||
|
}
|
||||||
|
return NotFound("Application doesn't exist");
|
||||||
|
}
|
||||||
|
return NotFound("Not logged in");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IActionResult> SetApplication([FromBody] Application application) {
|
||||||
|
if (isLoggedIn()) {
|
||||||
|
if (application.AccountID == getLoggedInUserID()) {
|
||||||
|
await _databaseService.SetApplication(application);
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
return NotFound("Cannot apply for someone else");
|
||||||
|
}
|
||||||
|
return NotFound("Not logged in");
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete]
|
||||||
|
public async Task<IActionResult> DeleteApplication(int ApplicationID) {
|
||||||
|
if (isLoggedIn()) {
|
||||||
|
Application? app = await _databaseService.GetApplication(ApplicationID);
|
||||||
|
if (app != null) {
|
||||||
|
if (app.AccountID == getLoggedInUserID()) {
|
||||||
|
await _databaseService.DeleteApplication(ApplicationID);
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
return NotFound("You cannot delete an app that isnt yours");
|
||||||
|
}
|
||||||
|
return NotFound("Application doesn't exist");
|
||||||
|
}
|
||||||
|
return NotFound("Not logged in");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
namespace BoredCareers.Entities {
|
||||||
|
public class Application {
|
||||||
|
public int? ID { get; set; } // PK
|
||||||
|
public int AccountID { get; set; } // FK
|
||||||
|
public int ResumeID { get; set; } // FK
|
||||||
|
public int JobListingID { get; set; } // FK
|
||||||
|
public string ResponseEmail { get; set; } = "";
|
||||||
|
public DateTime DateApplied { get; set; }
|
||||||
|
public string ResponseStatus { get; set; } = "";
|
||||||
|
public bool HasBeenViewed { get; set; } = false;
|
||||||
|
public int Rating { get; set; }
|
||||||
|
public string Notes { get; set; } = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,8 @@ namespace BoredCareers.Entities {
|
|||||||
public bool EmailVerified { get; set; } = false;
|
public bool EmailVerified { get; set; } = false;
|
||||||
public string WebsiteURL { get; set; } = "";
|
public string WebsiteURL { get; set; } = "";
|
||||||
public string Logo { get; set; } = "";
|
public string Logo { get; set; } = "";
|
||||||
|
public int JobsClosedSuccessful { get; set; }
|
||||||
|
public int JobsAutoClosed { get; set; }
|
||||||
public string Phone { get; set; } = "";
|
public string Phone { get; set; } = "";
|
||||||
public string PostalCode { get; set; } = "";
|
public string PostalCode { get; set; } = "";
|
||||||
public string Country { get; set; } = ""; // 2 Letter Country Code
|
public string Country { get; set; } = ""; // 2 Letter Country Code
|
||||||
|
|||||||
@@ -13,9 +13,17 @@ namespace BoredCareers.Entities {
|
|||||||
public string JobType { get; set; } = "";
|
public string JobType { get; set; } = "";
|
||||||
public bool Remote { get; set; } = false;
|
public bool Remote { get; set; } = false;
|
||||||
public string Description { get; set; } = "";
|
public string Description { get; set; } = "";
|
||||||
|
public JobListingSkill[] Skills { get; set; } = [];
|
||||||
public DateTime CreatedTime { get; set; }
|
public DateTime CreatedTime { get; set; }
|
||||||
public DateTime ModifiedTime { get; set; }
|
public DateTime ModifiedTime { get; set; }
|
||||||
public bool IsDeleted { get; set; } = false;
|
public bool IsDeleted { get; set; } = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class JobListingSkill {
|
||||||
|
public int? ID { get; set; } // PK
|
||||||
|
public int JobListingID { get; set; } // FK
|
||||||
|
public string Name { get; set; } = "";
|
||||||
|
public string Description { get; set; } = "";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+35
-11
@@ -8,11 +8,11 @@ using Microsoft.AspNetCore.Authentication.JwtBearer;
|
|||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
using System.IdentityModel.Tokens.Jwt;
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
using BoredCareers.Services.TimerService;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
// Disable null warnings becuse string.IsNullOrEmpty checks for NULL or Empty
|
// Disable null warnings becuse string.IsNullOrEmpty checks for NULL or Empty
|
||||||
#pragma warning disable CS8600
|
|
||||||
#pragma warning disable CS8604
|
#pragma warning disable CS8604
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
@@ -36,8 +36,9 @@ string? _dbpass = Environment.GetEnvironmentVariable("MySQLPass");
|
|||||||
string dbPass = !string.IsNullOrEmpty(_dbpass) ? _dbpass : "oasv34$8gpv023dd";
|
string dbPass = !string.IsNullOrEmpty(_dbpass) ? _dbpass : "oasv34$8gpv023dd";
|
||||||
|
|
||||||
// Create the database serivice
|
// Create the database serivice
|
||||||
DatabaseService databaseService = new DatabaseService(connectionString: "server=" + dbserver + ";user=" + dbUser + ";database=" + dbdatabase + ";password=" + dbPass + ";port=3306;");
|
builder.Services.AddSingleton<DatabaseService>(sp =>
|
||||||
builder.Services.Add( new ServiceDescriptor( typeof( DatabaseService ), databaseService ) );
|
new DatabaseService("server=" + dbserver + ";user=" + dbUser + ";database=" + dbdatabase + ";password=" + dbPass + ";port=3306;")
|
||||||
|
);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
///////// Email Service ////////
|
///////// Email Service ////////
|
||||||
@@ -135,15 +136,28 @@ builder.Services.AddAuthentication(options => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
builder.Services.AddCors(o => o.AddDefaultPolicy(builder => {
|
////////////////////////////////
|
||||||
builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader(); // No CORS
|
/// Rate Limiting Service ////
|
||||||
}));
|
////////////////////////////////
|
||||||
|
|
||||||
|
List<string> allowedOrigins = new List<string>{ "https://boredcareers.com", "https://www.boredcareers.com" };
|
||||||
|
if (builder.Environment.IsDevelopment()) {
|
||||||
|
allowedOrigins.Add("http://localhost:5000");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Services.AddCors(options => {
|
||||||
|
options.AddDefaultPolicy(policy => {
|
||||||
|
policy.WithOrigins(allowedOrigins.ToArray())
|
||||||
|
.AllowAnyHeader()
|
||||||
|
.AllowAnyMethod()
|
||||||
|
.AllowCredentials();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
builder.Services.AddRateLimiter(options => {
|
builder.Services.AddRateLimiter(options => {
|
||||||
options.AddPolicy("PerUserPolicy", httpContext => {
|
options.AddPolicy("PerUserPolicy", httpContext => {
|
||||||
var userId = httpContext.User.FindFirst(ClaimTypes.NameIdentifier)?.Value
|
var userId = httpContext.User.FindFirst(ClaimTypes.NameIdentifier)?.Value
|
||||||
?? httpContext.User.Identity?.Name
|
?? $"ip:{httpContext.Connection.RemoteIpAddress}";
|
||||||
?? httpContext.Connection.RemoteIpAddress?.ToString();
|
|
||||||
|
|
||||||
return RateLimitPartition.GetTokenBucketLimiter(userId, key => new TokenBucketRateLimiterOptions {
|
return RateLimitPartition.GetTokenBucketLimiter(userId, key => new TokenBucketRateLimiterOptions {
|
||||||
TokenLimit = 10, // max 10 requests
|
TokenLimit = 10, // max 10 requests
|
||||||
@@ -156,9 +170,17 @@ builder.Services.AddRateLimiter(options => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Pages Service
|
////////////////////////////////
|
||||||
|
///// Background Services /////
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
|
builder.Services.AddHostedService<JobCleanupService>();
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
///// ASPNET Core Function /////
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
builder.Services.AddControllers();
|
builder.Services.AddControllers();
|
||||||
builder.Services.AddRazorPages();
|
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
@@ -170,12 +192,14 @@ if( !app.Environment.IsDevelopment() ) {
|
|||||||
app.UseDefaultFiles();
|
app.UseDefaultFiles();
|
||||||
app.UseStaticFiles();
|
app.UseStaticFiles();
|
||||||
|
|
||||||
|
app.UseRateLimiter();
|
||||||
|
|
||||||
app.UseCors();
|
app.UseCors();
|
||||||
|
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
|
|
||||||
app.UseAuthentication();
|
app.UseAuthentication();
|
||||||
app.MapControllers().RequireRateLimiting("perUserPolicy");
|
app.MapControllers();
|
||||||
|
|
||||||
app.MapFallbackToFile("index.html");
|
app.MapFallbackToFile("index.html");
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
using BoredCareers.Entities;
|
||||||
|
|
||||||
|
namespace BoredCareers.Services.TimerService {
|
||||||
|
public class JobCleanupService : BackgroundService {
|
||||||
|
|
||||||
|
private readonly DatabaseService.DatabaseService _db;
|
||||||
|
private readonly EmailService _em;
|
||||||
|
|
||||||
|
public JobCleanupService(DatabaseService.DatabaseService db, EmailService em) {
|
||||||
|
_db = db;
|
||||||
|
_em = em;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
|
||||||
|
while (!stoppingToken.IsCancellationRequested) {
|
||||||
|
try {
|
||||||
|
// Get listing's past expire
|
||||||
|
JobListingDTO[] deletedJobListings = await _db.GetJobListingsPastExipre();
|
||||||
|
|
||||||
|
// Group them by CompanyID, ListingCount
|
||||||
|
Dictionary<int, int> listingsByCompany = deletedJobListings
|
||||||
|
.GroupBy(l => l.CompanyID)
|
||||||
|
.ToDictionary(g => g.Key, g => g.Count());
|
||||||
|
|
||||||
|
// Update each company's rating
|
||||||
|
foreach (KeyValuePair<int, int> kvp in listingsByCompany) {
|
||||||
|
Company? comp = await _db.GetCompany(kvp.Key);
|
||||||
|
if (comp != null) {
|
||||||
|
comp.JobsAutoClosed += kvp.Value;
|
||||||
|
await _db.SetCompany(comp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get each listing
|
||||||
|
foreach (JobListingDTO listing in deletedJobListings) {
|
||||||
|
// Get each Person
|
||||||
|
string[] emails = await _db.GetApplicationResponseEmailFromJobListing(listing.JobListingID);
|
||||||
|
foreach (string email in emails) {
|
||||||
|
// Send Notify Email
|
||||||
|
_em.Send(email, EmailService.JobAutoClosedSubject, EmailService.JobAutoClosedEmail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete Listing's past expire
|
||||||
|
await _db.DeleteJobListingsPastExipre();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Console.WriteLine($"Error: {e.Message}");
|
||||||
|
}
|
||||||
|
await Task.Delay(TimeSpan.FromHours(2), stoppingToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class JobListingDTO {
|
||||||
|
public int JobListingID { get; set; }
|
||||||
|
public int CompanyID { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,216 @@
|
|||||||
|
using BoredCareers.Entities;
|
||||||
|
using MySql.Data.MySqlClient;
|
||||||
|
using System.Data;
|
||||||
|
using System.Data.Common;
|
||||||
|
|
||||||
|
namespace BoredCareers.Services.DatabaseService {
|
||||||
|
public partial class DatabaseService {
|
||||||
|
|
||||||
|
public async Task<Application[]> GetApplcationsFromAccount(int AccountID) {
|
||||||
|
List<Application> applications = new List<Application>();
|
||||||
|
using (MySqlConnection connection = GetConnection()) {
|
||||||
|
await connection.OpenAsync();
|
||||||
|
string command = @"
|
||||||
|
SELECT *
|
||||||
|
FROM JobApplication
|
||||||
|
WHERE AccountID = @AccountID
|
||||||
|
";
|
||||||
|
|
||||||
|
MySqlCommand cmd = new MySqlCommand(command, connection);
|
||||||
|
cmd.Parameters.AddWithValue("@AccountID", AccountID);
|
||||||
|
|
||||||
|
using (DbDataReader reader = await cmd.ExecuteReaderAsync()) {
|
||||||
|
while (await reader.ReadAsync()) {
|
||||||
|
int _id = reader.GetInt32("ID");
|
||||||
|
int _accountid = reader.GetInt32("AccountID");
|
||||||
|
int _resumeid = reader.GetInt32("ResumeID");
|
||||||
|
int _joblistingid = reader.GetInt32("JobListingID");
|
||||||
|
string _responseemail = reader.GetString("ResponseEmail");
|
||||||
|
DateTime _dateapplied = reader.GetDateTime("DateApplied");
|
||||||
|
string _responsestatus = reader.GetString("ResponseStatus");
|
||||||
|
bool _hasbeenviewed = reader.GetBoolean("HasBeenViewed");
|
||||||
|
int _rating = reader.GetInt32("Rating");
|
||||||
|
string _notes = reader.GetString("Notes");
|
||||||
|
|
||||||
|
applications.Add(new Application() {
|
||||||
|
ID = _id,
|
||||||
|
AccountID = _accountid,
|
||||||
|
ResumeID = _resumeid,
|
||||||
|
JobListingID = _joblistingid,
|
||||||
|
ResponseEmail = _responseemail,
|
||||||
|
DateApplied = _dateapplied,
|
||||||
|
ResponseStatus = _responsestatus,
|
||||||
|
HasBeenViewed = _hasbeenviewed,
|
||||||
|
Rating = _rating,
|
||||||
|
Notes = _notes
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return applications.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Application[]> GetApplicationsFromJobListing(int JobListingID) {
|
||||||
|
List<Application> applications = new List<Application>();
|
||||||
|
using (MySqlConnection connection = GetConnection()) {
|
||||||
|
await connection.OpenAsync();
|
||||||
|
string command = @"
|
||||||
|
SELECT *
|
||||||
|
FROM JobApplication
|
||||||
|
WHERE JobListingID = @JobListingID
|
||||||
|
";
|
||||||
|
|
||||||
|
MySqlCommand cmd = new MySqlCommand(command, connection);
|
||||||
|
cmd.Parameters.AddWithValue("@JobListingID", JobListingID);
|
||||||
|
|
||||||
|
using (DbDataReader reader = await cmd.ExecuteReaderAsync()) {
|
||||||
|
while (await reader.ReadAsync()) {
|
||||||
|
int _id = reader.GetInt32("ID");
|
||||||
|
int _accountid = reader.GetInt32("AccountID");
|
||||||
|
int _resumeid = reader.GetInt32("ResumeID");
|
||||||
|
int _joblistingid = reader.GetInt32("JobListingID");
|
||||||
|
string _responseemail = reader.GetString("ResponseEmail");
|
||||||
|
DateTime _dateapplied = reader.GetDateTime("DateApplied");
|
||||||
|
string _responsestatus = reader.GetString("ResponseStatus");
|
||||||
|
bool _hasbeenviewed = reader.GetBoolean("HasBeenViewed");
|
||||||
|
int _rating = reader.GetInt32("Rating");
|
||||||
|
string _notes = reader.GetString("Notes");
|
||||||
|
|
||||||
|
applications.Add(new Application() {
|
||||||
|
ID = _id,
|
||||||
|
AccountID = _accountid,
|
||||||
|
ResumeID = _resumeid,
|
||||||
|
JobListingID = _joblistingid,
|
||||||
|
ResponseEmail = _responseemail,
|
||||||
|
DateApplied = _dateapplied,
|
||||||
|
ResponseStatus = _responsestatus,
|
||||||
|
HasBeenViewed = _hasbeenviewed,
|
||||||
|
Rating = _rating,
|
||||||
|
Notes = _notes
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return applications.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string[]> GetApplicationResponseEmailFromJobListing(int JobListingID) {
|
||||||
|
List<string> emailadds = new List<string>();
|
||||||
|
using (MySqlConnection connection = GetConnection()) {
|
||||||
|
await connection.OpenAsync();
|
||||||
|
string command = @"
|
||||||
|
SELECT ResponseEmail
|
||||||
|
FROM JobApplication
|
||||||
|
WHERE JobListingID = @JobListingID
|
||||||
|
";
|
||||||
|
|
||||||
|
MySqlCommand cmd = new MySqlCommand(command, connection);
|
||||||
|
cmd.Parameters.AddWithValue("@JobListingID", JobListingID);
|
||||||
|
|
||||||
|
using (DbDataReader reader = await cmd.ExecuteReaderAsync()) {
|
||||||
|
while (await reader.ReadAsync()) {
|
||||||
|
string _responseemail = reader.GetString("ResponseEmail");
|
||||||
|
emailadds.Add(_responseemail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return emailadds.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Application?> GetApplication(int ApplicationID) {
|
||||||
|
Application? application = null;
|
||||||
|
using (MySqlConnection connection = GetConnection()) {
|
||||||
|
await connection.OpenAsync();
|
||||||
|
string command = @"
|
||||||
|
SELECT *
|
||||||
|
FROM JobApplication
|
||||||
|
WHERE ID = @ApplicationID
|
||||||
|
";
|
||||||
|
|
||||||
|
MySqlCommand cmd = new MySqlCommand(command, connection);
|
||||||
|
cmd.Parameters.AddWithValue("@ApplicationID", ApplicationID);
|
||||||
|
|
||||||
|
using (DbDataReader reader = await cmd.ExecuteReaderAsync()) {
|
||||||
|
while (await reader.ReadAsync()) {
|
||||||
|
int _id = reader.GetInt32("ID");
|
||||||
|
int _accountid = reader.GetInt32("AccountID");
|
||||||
|
int _resumeid = reader.GetInt32("ResumeID");
|
||||||
|
int _joblistingid = reader.GetInt32("JobListingID");
|
||||||
|
string _responseemail = reader.GetString("ResponseEmail");
|
||||||
|
DateTime _dateapplied = reader.GetDateTime("DateApplied");
|
||||||
|
string _responsestatus = reader.GetString("ResponseStatus");
|
||||||
|
bool _hasbeenviewed = reader.GetBoolean("HasBeenViewed");
|
||||||
|
int _rating = reader.GetInt32("Rating");
|
||||||
|
string _notes = reader.GetString("Notes");
|
||||||
|
|
||||||
|
application = new Application() {
|
||||||
|
ID = _id,
|
||||||
|
AccountID = _accountid,
|
||||||
|
ResumeID = _resumeid,
|
||||||
|
JobListingID = _joblistingid,
|
||||||
|
ResponseEmail = _responseemail,
|
||||||
|
DateApplied = _dateapplied,
|
||||||
|
ResponseStatus = _responsestatus,
|
||||||
|
HasBeenViewed = _hasbeenviewed,
|
||||||
|
Rating = _rating,
|
||||||
|
Notes = _notes
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return application;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SetApplication(Application application) {
|
||||||
|
using (MySqlConnection connection = GetConnection()) {
|
||||||
|
await connection.OpenAsync();
|
||||||
|
string command = @"
|
||||||
|
INSERT INTO JobApplication
|
||||||
|
(ID,AccountID,ResumeID,JobListingID,ResponseEmail,DateApplied,ResponseStatus,HasBeenViewed,Rating,Notes)
|
||||||
|
VALUES
|
||||||
|
(@ID,@AccountID,@ResumeID,@JobListingID,@ResponseEmail,@DateApplied,@ResponseStatus,@HasBeenViewed,@Rating,@Notes)
|
||||||
|
ON DUPLICATE KEY UPDATE
|
||||||
|
AccountID = @AccountID,
|
||||||
|
ResumeID = @ResumeID,
|
||||||
|
JobListingID = @JobListingID,
|
||||||
|
ResponseEmail = @ResponseEmail,
|
||||||
|
ResponseStatus = @ResponseStatus,
|
||||||
|
HasBeenViewed = @HasBeenViewed,
|
||||||
|
Rating = @Rating,
|
||||||
|
Notes = @Notes;
|
||||||
|
";
|
||||||
|
|
||||||
|
MySqlCommand cmd = new MySqlCommand(command, connection);
|
||||||
|
cmd.Parameters.AddWithValue("@ID", application.ID);
|
||||||
|
cmd.Parameters.AddWithValue("@AccountID", application.AccountID);
|
||||||
|
cmd.Parameters.AddWithValue("@ResumeID", application.ResumeID);
|
||||||
|
cmd.Parameters.AddWithValue("@JobListingID", application.JobListingID);
|
||||||
|
cmd.Parameters.AddWithValue("@ResponseEmail", application.ResponseEmail);
|
||||||
|
cmd.Parameters.AddWithValue("@DateApplied", DateTime.UtcNow);
|
||||||
|
cmd.Parameters.AddWithValue("@ResponseStatus", application.ResponseStatus);
|
||||||
|
cmd.Parameters.AddWithValue("@HasBeenViewed", application.HasBeenViewed);
|
||||||
|
cmd.Parameters.AddWithValue("@Rating", application.Rating);
|
||||||
|
cmd.Parameters.AddWithValue("@Notes", application.Notes);
|
||||||
|
|
||||||
|
await cmd.ExecuteNonQueryAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteApplication(int ApplicationID) {
|
||||||
|
using (MySqlConnection connection = GetConnection()) {
|
||||||
|
MySqlCommand cmd;
|
||||||
|
await connection.OpenAsync();
|
||||||
|
string command = @"
|
||||||
|
DELETE FROM JobApplication WHERE ID = @ID;
|
||||||
|
";
|
||||||
|
cmd = new MySqlCommand(command, connection);
|
||||||
|
cmd.Parameters.AddWithValue("@ID", ApplicationID);
|
||||||
|
await cmd.ExecuteNonQueryAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
public async Task<Company?> GetCompany( int CompanyID ) {
|
public async Task<Company?> GetCompany( int CompanyID ) {
|
||||||
Company? company = null;
|
Company? company = null;
|
||||||
using( MySqlConnection connection = GetConnection() ) {
|
using( MySqlConnection connection = GetConnection() ) {
|
||||||
connection.Open();
|
await connection.OpenAsync();
|
||||||
string command = @"
|
string command = @"
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM Company
|
FROM Company
|
||||||
@@ -22,13 +22,14 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
|
|
||||||
using( DbDataReader reader = await cmd.ExecuteReaderAsync() ) {
|
using( DbDataReader reader = await cmd.ExecuteReaderAsync() ) {
|
||||||
while( await reader.ReadAsync() ) {
|
while( await reader.ReadAsync() ) {
|
||||||
if( reader == null ) { break; }
|
|
||||||
int _id = reader.GetInt32("ID");
|
int _id = reader.GetInt32("ID");
|
||||||
string _name = reader.GetString("Name");
|
string _name = reader.GetString("Name");
|
||||||
string _email = reader.GetString("Email");
|
string _email = reader.GetString("Email");
|
||||||
bool _emailVerified = reader.GetBoolean("EmailVerified");
|
bool _emailVerified = reader.GetBoolean("EmailVerified");
|
||||||
string _websiteurl = reader.GetString("WebsiteURL");
|
string _websiteurl = reader.GetString("WebsiteURL");
|
||||||
string _logo = Encoding.UTF8.GetString((byte[])reader["Logo"]);
|
string _logo = Encoding.UTF8.GetString((byte[])reader["Logo"]);
|
||||||
|
int _jobsclosedsuccessful = reader.GetInt32("JobsClosedSuccessful");
|
||||||
|
int _jobsautoclosed = reader.GetInt32("JobsAutoClosed");
|
||||||
string _phone = reader.GetString( "Phone" );
|
string _phone = reader.GetString( "Phone" );
|
||||||
string _postalcode = reader.GetString( "PostalCode" );
|
string _postalcode = reader.GetString( "PostalCode" );
|
||||||
string _country = reader.GetString( "Country" );
|
string _country = reader.GetString( "Country" );
|
||||||
@@ -43,6 +44,8 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
EmailVerified = _emailVerified,
|
EmailVerified = _emailVerified,
|
||||||
WebsiteURL = _websiteurl,
|
WebsiteURL = _websiteurl,
|
||||||
Logo = _logo,
|
Logo = _logo,
|
||||||
|
JobsAutoClosed = _jobsautoclosed,
|
||||||
|
JobsClosedSuccessful = _jobsclosedsuccessful,
|
||||||
Phone = _phone,
|
Phone = _phone,
|
||||||
PostalCode = _postalcode,
|
PostalCode = _postalcode,
|
||||||
Country = _country,
|
Country = _country,
|
||||||
@@ -58,19 +61,20 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
|
|
||||||
public async Task<int> SetCompany( Company company ) {
|
public async Task<int> SetCompany( Company company ) {
|
||||||
using (MySqlConnection connection = GetConnection()) {
|
using (MySqlConnection connection = GetConnection()) {
|
||||||
connection.Open();
|
await connection.OpenAsync();
|
||||||
|
|
||||||
string command = @"
|
string command = @"
|
||||||
INSERT INTO Company
|
INSERT INTO Company
|
||||||
(ID,Name,Email,EmailVerified,WebsiteURL,Logo,Phone,PostalCode,Country,StateOrRegion,City,Description)
|
(ID,Name,Email,EmailVerified,WebsiteURL,Logo,JobsClosedSuccessful,JobsAutoClosed,Phone,PostalCode,Country,StateOrRegion,City,Description)
|
||||||
VALUES
|
VALUES
|
||||||
(@ID,@Name,@Email,@EmailVerified,@WebsiteURL,@Logo,@Phone,@PostalCode,@Country,@StateOrRegion,@City,@Description)
|
(@ID,@Name,@Email,@EmailVerified,@WebsiteURL,@Logo,@JobsClosedSuccessful,@JobsAutoClosed,@Phone,@PostalCode,@Country,@StateOrRegion,@City,@Description)
|
||||||
ON DUPLICATE KEY UPDATE
|
ON DUPLICATE KEY UPDATE
|
||||||
Name = @Name,
|
Name = @Name,
|
||||||
Email = @Email,
|
Email = @Email,
|
||||||
EmailVerified = @EmailVerified,
|
EmailVerified = @EmailVerified,
|
||||||
WebsiteURL = @WebsiteURL,
|
WebsiteURL = @WebsiteURL,
|
||||||
Logo = @Logo,
|
Logo = @Logo,
|
||||||
|
JobsClosedSuccessful = @JobsClosedSuccessful,
|
||||||
|
JobsAutoClosed = @JobsAutoClosed,
|
||||||
Phone = @Phone,
|
Phone = @Phone,
|
||||||
PostalCode = @PostalCode,
|
PostalCode = @PostalCode,
|
||||||
Country = @Country,
|
Country = @Country,
|
||||||
@@ -88,6 +92,8 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
cmd.Parameters.AddWithValue("@EmailVerified", company.EmailVerified);
|
cmd.Parameters.AddWithValue("@EmailVerified", company.EmailVerified);
|
||||||
cmd.Parameters.AddWithValue("@WebsiteURL", company.WebsiteURL);
|
cmd.Parameters.AddWithValue("@WebsiteURL", company.WebsiteURL);
|
||||||
cmd.Parameters.AddWithValue("@Logo", Encoding.UTF8.GetBytes(company.Logo));
|
cmd.Parameters.AddWithValue("@Logo", Encoding.UTF8.GetBytes(company.Logo));
|
||||||
|
cmd.Parameters.AddWithValue("@JobsClosedSuccessful", company.JobsClosedSuccessful);
|
||||||
|
cmd.Parameters.AddWithValue("@JobsAutoClosed", company.JobsAutoClosed);
|
||||||
cmd.Parameters.AddWithValue("@Phone", company.Phone);
|
cmd.Parameters.AddWithValue("@Phone", company.Phone);
|
||||||
cmd.Parameters.AddWithValue("@PostalCode", company.PostalCode);
|
cmd.Parameters.AddWithValue("@PostalCode", company.PostalCode);
|
||||||
cmd.Parameters.AddWithValue("@Country", company.Country);
|
cmd.Parameters.AddWithValue("@Country", company.Country);
|
||||||
@@ -104,7 +110,7 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
public async Task DeleteCompany( int CompanyID ) {
|
public async Task DeleteCompany( int CompanyID ) {
|
||||||
using( MySqlConnection connection = GetConnection() ) {
|
using( MySqlConnection connection = GetConnection() ) {
|
||||||
MySqlCommand cmd;
|
MySqlCommand cmd;
|
||||||
connection.Open();
|
await connection.OpenAsync();
|
||||||
|
|
||||||
string command = @"
|
string command = @"
|
||||||
DELETE FROM Company WHERE ID = @ID;
|
DELETE FROM Company WHERE ID = @ID;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
public async Task<Employee?> GetEmployee( int EmployeeID ) {
|
public async Task<Employee?> GetEmployee( int EmployeeID ) {
|
||||||
Employee? employee = null;
|
Employee? employee = null;
|
||||||
using( MySqlConnection connection = GetConnection() ) {
|
using( MySqlConnection connection = GetConnection() ) {
|
||||||
connection.Open();
|
await connection.OpenAsync();
|
||||||
string command = @"
|
string command = @"
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM Employee
|
FROM Employee
|
||||||
@@ -23,7 +23,6 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
|
|
||||||
using( DbDataReader reader = await cmd.ExecuteReaderAsync() ) {
|
using( DbDataReader reader = await cmd.ExecuteReaderAsync() ) {
|
||||||
while( await reader.ReadAsync() ) {
|
while( await reader.ReadAsync() ) {
|
||||||
if( reader == null ) { break; }
|
|
||||||
int _id = reader.GetInt32("ID");
|
int _id = reader.GetInt32("ID");
|
||||||
int _accountid = reader.GetInt32("AccountID");
|
int _accountid = reader.GetInt32("AccountID");
|
||||||
int _companyid = reader.GetInt32("CompanyID");
|
int _companyid = reader.GetInt32("CompanyID");
|
||||||
@@ -66,7 +65,7 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
public async Task<Employee[]> GetEmployeesFromCompany(int CompanyID) {
|
public async Task<Employee[]> GetEmployeesFromCompany(int CompanyID) {
|
||||||
List<Employee> employees = new List<Employee>();
|
List<Employee> employees = new List<Employee>();
|
||||||
using (MySqlConnection connection = GetConnection()) {
|
using (MySqlConnection connection = GetConnection()) {
|
||||||
connection.Open();
|
await connection.OpenAsync();
|
||||||
string command = @"
|
string command = @"
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM Employee
|
FROM Employee
|
||||||
@@ -79,7 +78,6 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
|
|
||||||
using (DbDataReader reader = await cmd.ExecuteReaderAsync()) {
|
using (DbDataReader reader = await cmd.ExecuteReaderAsync()) {
|
||||||
while (await reader.ReadAsync()) {
|
while (await reader.ReadAsync()) {
|
||||||
if (reader == null) { break; }
|
|
||||||
int _id = reader.GetInt32("ID");
|
int _id = reader.GetInt32("ID");
|
||||||
int _accountid = reader.GetInt32("AccountID");
|
int _accountid = reader.GetInt32("AccountID");
|
||||||
int _companyid = reader.GetInt32("CompanyID");
|
int _companyid = reader.GetInt32("CompanyID");
|
||||||
@@ -122,7 +120,7 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
public async Task<Employee[]> GetEmployeesFromAccount(int AccountID) {
|
public async Task<Employee[]> GetEmployeesFromAccount(int AccountID) {
|
||||||
List<Employee> employees = new List<Employee>();
|
List<Employee> employees = new List<Employee>();
|
||||||
using (MySqlConnection connection = GetConnection()) {
|
using (MySqlConnection connection = GetConnection()) {
|
||||||
connection.Open();
|
await connection.OpenAsync();
|
||||||
string command = @"
|
string command = @"
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM Employee
|
FROM Employee
|
||||||
@@ -135,7 +133,6 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
|
|
||||||
using (DbDataReader reader = await cmd.ExecuteReaderAsync()) {
|
using (DbDataReader reader = await cmd.ExecuteReaderAsync()) {
|
||||||
while (await reader.ReadAsync()) {
|
while (await reader.ReadAsync()) {
|
||||||
if (reader == null) { break; }
|
|
||||||
int _id = reader.GetInt32("ID");
|
int _id = reader.GetInt32("ID");
|
||||||
int _accountid = reader.GetInt32("AccountID");
|
int _accountid = reader.GetInt32("AccountID");
|
||||||
int _companyid = reader.GetInt32("CompanyID");
|
int _companyid = reader.GetInt32("CompanyID");
|
||||||
@@ -177,7 +174,7 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
|
|
||||||
public async Task SetEmployee(Employee employee) {
|
public async Task SetEmployee(Employee employee) {
|
||||||
using (MySqlConnection connection = GetConnection()) {
|
using (MySqlConnection connection = GetConnection()) {
|
||||||
connection.Open();
|
await connection.OpenAsync();
|
||||||
|
|
||||||
string command = @"
|
string command = @"
|
||||||
INSERT INTO Employee
|
INSERT INTO Employee
|
||||||
@@ -201,7 +198,7 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
public async Task DeleteEmployee( int EmployeeID ) {
|
public async Task DeleteEmployee( int EmployeeID ) {
|
||||||
using( MySqlConnection connection = GetConnection() ) {
|
using( MySqlConnection connection = GetConnection() ) {
|
||||||
MySqlCommand cmd;
|
MySqlCommand cmd;
|
||||||
connection.Open();
|
await connection.OpenAsync();
|
||||||
|
|
||||||
string command = @"
|
string command = @"
|
||||||
DELETE FROM Employee WHERE ID = @ID;
|
DELETE FROM Employee WHERE ID = @ID;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using BoredCareers.Entities;
|
using BoredCareers.Entities;
|
||||||
|
using BoredCareers.Services.TimerService;
|
||||||
using MySql.Data.MySqlClient;
|
using MySql.Data.MySqlClient;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Data.Common;
|
using System.Data.Common;
|
||||||
@@ -9,7 +10,7 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
public async Task<JobListing[]> GetJobListingPage(int PageNumber, int CountPerPage) {
|
public async Task<JobListing[]> GetJobListingPage(int PageNumber, int CountPerPage) {
|
||||||
List<JobListing> joblistings = new List<JobListing>();
|
List<JobListing> joblistings = new List<JobListing>();
|
||||||
using (MySqlConnection connection = GetConnection()) {
|
using (MySqlConnection connection = GetConnection()) {
|
||||||
connection.Open();
|
await connection.OpenAsync();
|
||||||
string command = @"
|
string command = @"
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM JobListing
|
FROM JobListing
|
||||||
@@ -24,7 +25,6 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
|
|
||||||
using (DbDataReader reader = await cmd.ExecuteReaderAsync()) {
|
using (DbDataReader reader = await cmd.ExecuteReaderAsync()) {
|
||||||
while (await reader.ReadAsync()) {
|
while (await reader.ReadAsync()) {
|
||||||
if (reader == null) { break; }
|
|
||||||
int _id = reader.GetInt32("ID");
|
int _id = reader.GetInt32("ID");
|
||||||
int _companyid = reader.GetInt32("CompanyID");
|
int _companyid = reader.GetInt32("CompanyID");
|
||||||
string _title = reader.GetString("Title");
|
string _title = reader.GetString("Title");
|
||||||
@@ -37,6 +37,7 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
string _jobtype = reader.GetString("JobType");
|
string _jobtype = reader.GetString("JobType");
|
||||||
bool _remote = reader.GetBoolean("Remote");
|
bool _remote = reader.GetBoolean("Remote");
|
||||||
string _description = reader.GetString("Description");
|
string _description = reader.GetString("Description");
|
||||||
|
JobListingSkill[] _skills = await GetJobListingSkills(_id);
|
||||||
DateTime _createtime = reader.GetDateTime("CreatedTime");
|
DateTime _createtime = reader.GetDateTime("CreatedTime");
|
||||||
DateTime _modifiedtime = reader.GetDateTime("ModifiedTime");
|
DateTime _modifiedtime = reader.GetDateTime("ModifiedTime");
|
||||||
bool _isdeleted = reader.GetBoolean("IsDeleted");
|
bool _isdeleted = reader.GetBoolean("IsDeleted");
|
||||||
@@ -54,6 +55,7 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
JobType = _jobtype,
|
JobType = _jobtype,
|
||||||
Remote = _remote,
|
Remote = _remote,
|
||||||
Description = _description,
|
Description = _description,
|
||||||
|
Skills = _skills,
|
||||||
CreatedTime = _createtime,
|
CreatedTime = _createtime,
|
||||||
ModifiedTime = _modifiedtime,
|
ModifiedTime = _modifiedtime,
|
||||||
IsDeleted = _isdeleted
|
IsDeleted = _isdeleted
|
||||||
@@ -67,7 +69,7 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
public async Task<JobListing[]> GetJobListingFromCompany(int CompanyID) {
|
public async Task<JobListing[]> GetJobListingFromCompany(int CompanyID) {
|
||||||
List<JobListing> joblistings = new List<JobListing>(); ;
|
List<JobListing> joblistings = new List<JobListing>(); ;
|
||||||
using (MySqlConnection connection = GetConnection()) {
|
using (MySqlConnection connection = GetConnection()) {
|
||||||
connection.Open();
|
await connection.OpenAsync();
|
||||||
string command = @"
|
string command = @"
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM JobListing
|
FROM JobListing
|
||||||
@@ -79,7 +81,6 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
|
|
||||||
using (DbDataReader reader = await cmd.ExecuteReaderAsync()) {
|
using (DbDataReader reader = await cmd.ExecuteReaderAsync()) {
|
||||||
while (await reader.ReadAsync()) {
|
while (await reader.ReadAsync()) {
|
||||||
if (reader == null) { break; }
|
|
||||||
int _id = reader.GetInt32("ID");
|
int _id = reader.GetInt32("ID");
|
||||||
int _companyid = reader.GetInt32("CompanyID");
|
int _companyid = reader.GetInt32("CompanyID");
|
||||||
string _title = reader.GetString("Title");
|
string _title = reader.GetString("Title");
|
||||||
@@ -92,6 +93,7 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
string _jobtype = reader.GetString("JobType");
|
string _jobtype = reader.GetString("JobType");
|
||||||
bool _remote = reader.GetBoolean("Remote");
|
bool _remote = reader.GetBoolean("Remote");
|
||||||
string _description = reader.GetString("Description");
|
string _description = reader.GetString("Description");
|
||||||
|
JobListingSkill[] _skills = await GetJobListingSkills(_id);
|
||||||
DateTime _createtime = reader.GetDateTime("CreatedTime");
|
DateTime _createtime = reader.GetDateTime("CreatedTime");
|
||||||
DateTime _modifiedtime = reader.GetDateTime("ModifiedTime");
|
DateTime _modifiedtime = reader.GetDateTime("ModifiedTime");
|
||||||
bool _isdeleted = reader.GetBoolean("IsDeleted");
|
bool _isdeleted = reader.GetBoolean("IsDeleted");
|
||||||
@@ -109,6 +111,7 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
JobType = _jobtype,
|
JobType = _jobtype,
|
||||||
Remote = _remote,
|
Remote = _remote,
|
||||||
Description = _description,
|
Description = _description,
|
||||||
|
Skills = _skills,
|
||||||
CreatedTime = _createtime,
|
CreatedTime = _createtime,
|
||||||
ModifiedTime = _modifiedtime,
|
ModifiedTime = _modifiedtime,
|
||||||
IsDeleted = _isdeleted
|
IsDeleted = _isdeleted
|
||||||
@@ -122,7 +125,7 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
public async Task<JobListing?> GetJobListing(int JobListingID) {
|
public async Task<JobListing?> GetJobListing(int JobListingID) {
|
||||||
JobListing? joblisting = null;
|
JobListing? joblisting = null;
|
||||||
using (MySqlConnection connection = GetConnection()) {
|
using (MySqlConnection connection = GetConnection()) {
|
||||||
connection.Open();
|
await connection.OpenAsync();
|
||||||
string command = @"
|
string command = @"
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM JobListing
|
FROM JobListing
|
||||||
@@ -134,7 +137,6 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
|
|
||||||
using (DbDataReader reader = await cmd.ExecuteReaderAsync()) {
|
using (DbDataReader reader = await cmd.ExecuteReaderAsync()) {
|
||||||
while (await reader.ReadAsync()) {
|
while (await reader.ReadAsync()) {
|
||||||
if (reader == null) { break; }
|
|
||||||
int _id = reader.GetInt32("ID");
|
int _id = reader.GetInt32("ID");
|
||||||
int _companyid = reader.GetInt32("CompanyID");
|
int _companyid = reader.GetInt32("CompanyID");
|
||||||
string _title = reader.GetString("Title");
|
string _title = reader.GetString("Title");
|
||||||
@@ -147,6 +149,7 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
string _jobtype = reader.GetString("JobType");
|
string _jobtype = reader.GetString("JobType");
|
||||||
bool _remote = reader.GetBoolean("Remote");
|
bool _remote = reader.GetBoolean("Remote");
|
||||||
string _description = reader.GetString("Description");
|
string _description = reader.GetString("Description");
|
||||||
|
JobListingSkill[] _skills = await GetJobListingSkills(_id);
|
||||||
DateTime _createtime = reader.GetDateTime("CreatedTime");
|
DateTime _createtime = reader.GetDateTime("CreatedTime");
|
||||||
DateTime _modifiedtime = reader.GetDateTime("ModifiedTime");
|
DateTime _modifiedtime = reader.GetDateTime("ModifiedTime");
|
||||||
bool _isdeleted = reader.GetBoolean("IsDeleted");
|
bool _isdeleted = reader.GetBoolean("IsDeleted");
|
||||||
@@ -164,6 +167,7 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
JobType = _jobtype,
|
JobType = _jobtype,
|
||||||
Remote = _remote,
|
Remote = _remote,
|
||||||
Description = _description,
|
Description = _description,
|
||||||
|
Skills = _skills,
|
||||||
CreatedTime = _createtime,
|
CreatedTime = _createtime,
|
||||||
ModifiedTime = _modifiedtime,
|
ModifiedTime = _modifiedtime,
|
||||||
IsDeleted = _isdeleted
|
IsDeleted = _isdeleted
|
||||||
@@ -174,9 +178,35 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
return joblisting;
|
return joblisting;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SetJobListing( JobListing jobListing ) {
|
public async Task<JobListingDTO[]> GetJobListingsPastExipre() {
|
||||||
using( MySqlConnection connection = GetConnection() ) {
|
List<JobListingDTO> joblistings = new List<JobListingDTO>();
|
||||||
connection.Open();
|
using (MySqlConnection connection = GetConnection()) {
|
||||||
|
await connection.OpenAsync();
|
||||||
|
string command = @"
|
||||||
|
SELECT ID, CompanyID
|
||||||
|
FROM JobListing
|
||||||
|
WHERE IsDeleted = FALSE
|
||||||
|
AND CreatedTime < NOW() - INTERVAL 1 MONTH;
|
||||||
|
";
|
||||||
|
MySqlCommand cmd = new MySqlCommand(command, connection);
|
||||||
|
|
||||||
|
using (DbDataReader reader = await cmd.ExecuteReaderAsync()) {
|
||||||
|
while (await reader.ReadAsync()) {
|
||||||
|
int _id = reader.GetInt32("ID");
|
||||||
|
int _companyid = reader.GetInt32("CompanyID");
|
||||||
|
joblistings.Add(new JobListingDTO() {
|
||||||
|
JobListingID = _id,
|
||||||
|
CompanyID = _companyid
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return joblistings.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SetJobListing(JobListing jobListing) {
|
||||||
|
using (MySqlConnection connection = GetConnection()) {
|
||||||
|
await connection.OpenAsync();
|
||||||
|
|
||||||
string command = @"
|
string command = @"
|
||||||
INSERT INTO JobListing
|
INSERT INTO JobListing
|
||||||
@@ -195,12 +225,11 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
JobType = @JobType,
|
JobType = @JobType,
|
||||||
Remote = @Remote,
|
Remote = @Remote,
|
||||||
Description = @Description,
|
Description = @Description,
|
||||||
CreatedTime = @CreatedTime,
|
|
||||||
ModifiedTime = @ModifiedTime,
|
ModifiedTime = @ModifiedTime,
|
||||||
IsDeleted = @IsDeleted;
|
IsDeleted = @IsDeleted;
|
||||||
";
|
";
|
||||||
|
|
||||||
MySqlCommand cmd = new MySqlCommand( command , connection);
|
MySqlCommand cmd = new MySqlCommand(command, connection);
|
||||||
cmd.Parameters.AddWithValue("@ID", jobListing.ID);
|
cmd.Parameters.AddWithValue("@ID", jobListing.ID);
|
||||||
cmd.Parameters.AddWithValue("@CompanyID", jobListing.CompanyID);
|
cmd.Parameters.AddWithValue("@CompanyID", jobListing.CompanyID);
|
||||||
cmd.Parameters.AddWithValue("@Title", jobListing.Title);
|
cmd.Parameters.AddWithValue("@Title", jobListing.Title);
|
||||||
@@ -213,25 +242,43 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
cmd.Parameters.AddWithValue("@JobType", jobListing.JobType);
|
cmd.Parameters.AddWithValue("@JobType", jobListing.JobType);
|
||||||
cmd.Parameters.AddWithValue("@Remote", jobListing.Remote);
|
cmd.Parameters.AddWithValue("@Remote", jobListing.Remote);
|
||||||
cmd.Parameters.AddWithValue("@Description", jobListing.Description);
|
cmd.Parameters.AddWithValue("@Description", jobListing.Description);
|
||||||
cmd.Parameters.AddWithValue("@CreatedTime", jobListing.CreatedTime.ToUniversalTime());
|
cmd.Parameters.AddWithValue("@CreatedTime", DateTime.UtcNow);
|
||||||
cmd.Parameters.AddWithValue("@ModifiedTime", jobListing.ModifiedTime.ToUniversalTime());
|
cmd.Parameters.AddWithValue("@ModifiedTime", DateTime.UtcNow);
|
||||||
cmd.Parameters.AddWithValue("@IsDeleted", jobListing.IsDeleted);
|
cmd.Parameters.AddWithValue("@IsDeleted", jobListing.IsDeleted);
|
||||||
|
|
||||||
await cmd.ExecuteNonQueryAsync();
|
await cmd.ExecuteNonQueryAsync();
|
||||||
|
|
||||||
|
foreach (JobListingSkill cur in jobListing.Skills) {
|
||||||
|
await SetJobListingSkills(cur);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteJobListingsPastExipre() {
|
||||||
|
using (MySqlConnection connection = GetConnection()) {
|
||||||
|
await connection.OpenAsync();
|
||||||
|
string command = @"
|
||||||
|
UPDATE JobListing
|
||||||
|
SET IsDeleted = TRUE
|
||||||
|
WHERE IsDeleted = FALSE
|
||||||
|
AND CreatedTime < NOW() - INTERVAL 1 MONTH;
|
||||||
|
";
|
||||||
|
MySqlCommand cmd = new MySqlCommand(command, connection);
|
||||||
|
await cmd.ExecuteNonQueryAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteJobListing( int JobListingID ) {
|
public async Task DeleteJobListing(int JobListingID) {
|
||||||
using( MySqlConnection connection = GetConnection() ) {
|
using (MySqlConnection connection = GetConnection()) {
|
||||||
MySqlCommand cmd;
|
MySqlCommand cmd;
|
||||||
connection.Open();
|
await connection.OpenAsync();
|
||||||
|
|
||||||
string command = @"
|
string command = @"
|
||||||
UPDATE JobListing
|
UPDATE JobListing
|
||||||
SET IsDeleted = TRUE
|
SET IsDeleted = TRUE
|
||||||
WHERE ID = @ID;
|
WHERE ID = @ID;
|
||||||
";
|
";
|
||||||
cmd = new MySqlCommand( command, connection );
|
cmd = new MySqlCommand(command, connection);
|
||||||
cmd.Parameters.AddWithValue("@ID", JobListingID);
|
cmd.Parameters.AddWithValue("@ID", JobListingID);
|
||||||
|
|
||||||
await cmd.ExecuteNonQueryAsync();
|
await cmd.ExecuteNonQueryAsync();
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
using BoredCareers.Entities;
|
||||||
|
using MySql.Data.MySqlClient;
|
||||||
|
using System.Data;
|
||||||
|
using System.Data.Common;
|
||||||
|
|
||||||
|
namespace BoredCareers.Services.DatabaseService {
|
||||||
|
public partial class DatabaseService {
|
||||||
|
|
||||||
|
public async Task<JobListingSkill[]> GetJobListingSkills(int JobListingID) {
|
||||||
|
List<JobListingSkill> joblistingskills = new List<JobListingSkill>();
|
||||||
|
using (MySqlConnection connection = GetConnection()) {
|
||||||
|
await connection.OpenAsync();
|
||||||
|
string command = @"
|
||||||
|
SELECT *
|
||||||
|
FROM JobListingSkill
|
||||||
|
WHERE JobListingID = @JobListingID;
|
||||||
|
";
|
||||||
|
|
||||||
|
MySqlCommand cmd = new MySqlCommand(command, connection);
|
||||||
|
cmd.Parameters.AddWithValue("@JobListingID", JobListingID);
|
||||||
|
|
||||||
|
using (DbDataReader reader = await cmd.ExecuteReaderAsync()) {
|
||||||
|
while (await reader.ReadAsync()) {
|
||||||
|
if (reader == null) { break; }
|
||||||
|
int _id = reader.GetInt32("ID");
|
||||||
|
int _joblistingid = reader.GetInt32("JobListingID");
|
||||||
|
string _name = reader.GetString("Name");
|
||||||
|
string _description = reader.GetString("Description");
|
||||||
|
|
||||||
|
joblistingskills.Add(new JobListingSkill() {
|
||||||
|
ID = _id,
|
||||||
|
JobListingID = _joblistingid,
|
||||||
|
Name = _name,
|
||||||
|
Description = _description
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return joblistingskills.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SetJobListingSkills( JobListingSkill jobListingSkill ) {
|
||||||
|
using( MySqlConnection connection = GetConnection() ) {
|
||||||
|
await connection.OpenAsync();
|
||||||
|
string command = @"
|
||||||
|
INSERT INTO JobListing
|
||||||
|
(ID,JobListingID,Name,Description)
|
||||||
|
VALUES
|
||||||
|
(@ID,@JobListingID,@Name,@Description)
|
||||||
|
ON DUPLICATE KEY UPDATE
|
||||||
|
JobListingID = @JobListingID,
|
||||||
|
Name = @Name,
|
||||||
|
Description = @Description;
|
||||||
|
";
|
||||||
|
|
||||||
|
MySqlCommand cmd = new MySqlCommand( command , connection);
|
||||||
|
cmd.Parameters.AddWithValue("@ID", jobListingSkill.ID);
|
||||||
|
cmd.Parameters.AddWithValue("@JobListingID", jobListingSkill.JobListingID);
|
||||||
|
cmd.Parameters.AddWithValue("@Name", jobListingSkill.Name);
|
||||||
|
cmd.Parameters.AddWithValue("@Description", jobListingSkill.Description);
|
||||||
|
|
||||||
|
await cmd.ExecuteNonQueryAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ namespace BoredCareers.Services.DatabaseService {
|
|||||||
public async Task<Resume[]> GetResumes(int AccountID) {
|
public async Task<Resume[]> GetResumes(int AccountID) {
|
||||||
List<Resume> resumes = new List<Resume>();
|
List<Resume> resumes = new List<Resume>();
|
||||||
using (MySqlConnection connection = GetConnection()) {
|
using (MySqlConnection connection = GetConnection()) {
|
||||||
connection.Open();
|
await connection.OpenAsync();
|
||||||
string command = @"
|
string command = @"
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM Resume
|
FROM Resume
|
||||||
|
|||||||
+2
-2
@@ -5,8 +5,8 @@ namespace BoredCareers.Services {
|
|||||||
// @VerifyPassword
|
// @VerifyPassword
|
||||||
// https://mistox.com/api/account/verifyemail?UserName=@UserName&Guid=@VerifyPassword
|
// https://mistox.com/api/account/verifyemail?UserName=@UserName&Guid=@VerifyPassword
|
||||||
|
|
||||||
public static string VerifyEmailSubject = "Verify Your Email Address";
|
public static string JobAutoClosedSubject = "Verify Your Email Address";
|
||||||
public static string VerifyEmailEmail = @"
|
public static string JobAutoClosedEmail = @"
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang=""en"">
|
<html lang=""en"">
|
||||||
<head>
|
<head>
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
namespace BoredCareers.Services {
|
|
||||||
public partial class EmailService {
|
|
||||||
|
|
||||||
// @UserName
|
|
||||||
// @ResetPassWord
|
|
||||||
// https://mistox.com/account/resetpassword?UserName=@UserName&ResetPwd=@ResetPassWord
|
|
||||||
|
|
||||||
public static string ResetPasswordSubject = "Password Reset Request";
|
|
||||||
public static string ResetPasswordEmail = @"
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang=""en"">
|
|
||||||
<head>
|
|
||||||
<meta charset=""UTF-8"">
|
|
||||||
<meta name=""viewport"" content=""width=device-width, initial-scale=1.0"">
|
|
||||||
<title>Password Reset</title>
|
|
||||||
</head>
|
|
||||||
<body style=""font-family: Arial, sans-serif; background-color: #f4f4f4; margin: 0; padding: 0;"">
|
|
||||||
<table role=""presentation"" style=""width: 100%; background-color: #f4f4f4; padding: 20px 0;"">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<table role=""presentation"" style=""max-width: 600px; width: 100%; background-color: #ffffff; margin: 0 auto; border-radius: 8px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);"">
|
|
||||||
<tr>
|
|
||||||
<td style=""padding: 20px; text-align: center; background-color: #4CAF50; color: #ffffff; border-top-left-radius: 8px; border-top-right-radius: 8px;"">
|
|
||||||
<h2>Password Reset Request</h2>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td style=""padding: 20px; text-align: left; font-size: 16px; color: #333333;"">
|
|
||||||
<p>Hi @UserName,</p>
|
|
||||||
<p>We received a request to reset your password. You can reset your password by clicking the button below:</p>
|
|
||||||
<p style=""text-align: center;"">
|
|
||||||
<a href=""https://mistox.com/account/resetpassword?UserName=@UserName&ResetPwd=@ResetPassWord"" style=""background-color: #4CAF50; color: #ffffff; text-decoration: none; padding: 15px 25px; font-size: 16px; border-radius: 5px; display: inline-block;"">Reset Password</a>
|
|
||||||
</p>
|
|
||||||
<p>If you didn't request a password reset, you can safely ignore this email.</p>
|
|
||||||
<p>Best regards</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td style=""padding: 10px; text-align: center; background-color: #f4f4f4; color: #888888; font-size: 12px; border-bottom-left-radius: 8px; border-bottom-right-radius: 8px;"">
|
|
||||||
<p>If you have any questions, feel free to <a href=""mailto:webmaster@mistox.com"" style=""color: #4CAF50; text-decoration: none;"">contact support</a>.</p>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</body>
|
|
||||||
";
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user