📖
smartHRから部署をツリー構造で取得する
はじめに
特定の条件に当てはまる部署を検知することになった。親部署や子部署も確認しなければならないため、ツリー構造で部署を集めることにした。ただし、smartHRのAPIは現状部署がない。(人の部署は取れる)。そのため
- 人の情報をAPIで取得
- 部署をツリー構造で編集する
- 特定条件に合致した場合通知する
を行う
code
main.js
function main(){
// crew取得処理は省略
const crewList = getCrewListFromSheet();
const depertmentList = crewList.reduce((depertmentList, crew) => {
crew.getDepertmentList().forEach(depertment => {
if(!depertment.name) return;
depertment.name.split(DEPERTMENT.route.spliter).reduce((routeList, depertmentName) => {
routeList.push(depertmentName);
const depertment = new Depertment([].concat(routeList), crew);
!depertmentList.length
? depertmentList.push(depertment)
: depertmentList.some(bd => bd.findSet(depertment, crew));
return routeList;
}, []);
});
return depertmentList;
}, []);
const findSetReplenishmentPosition = positionName => {
return depertmentList.forEach(depertment => {
depertment.findSetReplenishmentPosition(positionName, depertment.getCrewListholdPosition(positionName));
});
};
findSetReplenishmentPosition('取締役');
findSetReplenishmentPosition('役員');
findSetReplenishmentPosition('部長');
}
crew.js
const CREW = {
status: {
valid: '有効',
},
position: {
ceo: '社長',
board: '役員',
generalManager: '部長',
manager: 'マネージャー',
member: 'メンバー',
}
};
class Crew{
constructor(){
this.email;
this.name;
this.id;
this.emp_code;
this.departmentList = [];
}
setDataFromSheet(row){
this.id = row[SHEET.crew.column.id - 1];
this.email = row[SHEET.crew.column.email - 1];
}
setDataFromSmartHRCrew(crew){
this.name = crew.getName();
this.email = crew.getEmail();
this.emp_code = crew.getEmpCode();
this.departmentList = crew.getDepartmentList();
}
addDepertmentList(departmentList){
this.departmentList = this.departmentList.concat(departmentList);
}
isSameEmail(email){
return this.email === email;
}
isNoId(){
return this.id === undefined;
}
isPosition(positionName){
return this.departmentList.some(d => d.position.includes(positionName));
}
findSetId(crewList){
this.id = crewList.find(bc => this.isSameEmail(bc.email))?.id;
}
getDepertmentList(){
return this.departmentList;
}
getEmail(){
return this.email;
}
getOutList(){
// 以下参照
}
}
depertment.js
const DEPERTMENT = {
route: {
spliter: '/',
},
};
class Depertment{
constructor(routeList, crew){
this.routeList = routeList;
this.crewList = [crew];
this.childrenDepertmentList = [];
}
findSet(depertment, crew){
if(!depertment.getRouteText().includes(this.getRouteText()))return false;
if(this.isSame(depertment)){
this.crewList.push(crew);
return true;
}
if(this.childrenDepertmentList.some(cd => cd.findSet(depertment, crew))) return true;
this.childrenDepertmentList.push(depertment);
return true;
}
findSetReplenishmentPosition(positionName, crewListWithPositionFromParentDepertment){
crewListWithPositionFromParentDepertment = crewListWithPositionFromParentDepertment.filter(c => {
return c.getDepertmentList().every(d => d.name === '' || !(d.position.includes(positionName) && this.getRouteText().includes(d.name)));
});
if(!this.getCrewListholdPosition(positionName).length && crewListWithPositionFromParentDepertment.length){
Logger.log(crewListWithPositionFromParentDepertment.map(c => c.getEmail()));
return;
}
this.childrenDepertmentList.forEach(cd => cd.findSetReplenishmentPosition(positionName, this.getCrewListholdPosition(positionName)));
}
getCrewListholdPosition(positionName){
return this.crewList.filter(crew => crew.isPosition(positionName));
}
isSame(depertment){
return this.getRouteText() === depertment.getRouteText();
}
getRouteList(){
return this.routeList;
}
getRouteText(){
return this.routeList.join(DEPERTMENT.route.spliter);
}
}
Discussion