Last active
June 4, 2022 10:57
-
-
Save hrdtbs/533980dfd21414e7dd6682ff609133e5 to your computer and use it in GitHub Desktop.
jobcanの交通費明細で有効なCSV形式
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// source: https://ssl.wf.jobcan.jp/static/wf/scripts/controllers/create_request/expense_specifics_transport_controllers.js?ci-build-64159.444028469786320462 | |
(function() { | |
'use strict'; | |
angular | |
.module('WfApp.create_request_controllers') | |
.controller('ExpenseSpecificsTransportController', ExpenseSpecificsTransportController); | |
ExpenseSpecificsTransportController.$inject = [ | |
'$http', | |
'$scope', | |
'$rootScope', | |
'$uibModal', | |
'gettextCatalog', | |
'notifyService', | |
'NorikaeService', | |
'Const', | |
'CreateRequestExpenseSpecificsService', | |
]; | |
/** | |
* 経費精算 交通費明細 | |
* @param {Object} $http | |
* @param {Object} $scope | |
* @param {Object} $rootScope | |
* @param {Object} $uibModal | |
* @param {Object} gettextCatalog | |
* @param {Object} notifyService | |
* @param {Object} NorikaeService | |
* @param {Object} Const | |
* @param {Object} CreateRequestExpenseSpecificsService | |
*/ | |
function ExpenseSpecificsTransportController( | |
$http, $scope, $rootScope, $uibModal, gettextCatalog, | |
notifyService, NorikaeService, Const, CreateRequestExpenseSpecificsService) { | |
$scope.selectICcardHistoryCSV = selectICcardHistoryCSV; | |
$scope.selectICcardHistoryFelica = selectICcardHistoryFelica; | |
$scope.showNorikaeDialog = showNorikaeDialog; | |
$scope.showSelectStationDialog = showSelectStationDialog; | |
$scope.changeStation = changeStation; | |
$scope.changeRoundTrip = changeRoundTrip; | |
$scope.changeTransportRow = changeTransportRow; | |
$scope.isValidStationName = isValidStationName; | |
$scope.existInRequest = existInRequest; | |
$scope.isDraftRequest = isDraftRequest; | |
$scope.getProgressRequestUrl = getProgressRequestUrl; | |
$scope.isTrafficWayRequired = isTrafficWayRequired; | |
$scope._ = _; | |
// definitions // | |
/** | |
* ICカード利用履歴csvアップロード | |
* @param {Object} file | |
* @param {Object} sheet | |
*/ | |
function selectICcardHistoryCSV(file, sheet) { | |
var error_message = gettextCatalog.getString( | |
'エラーが発生しました。<br>ICカードリーダーから読み込んだCSVファイルを選択してください。'); | |
if (!file) { | |
return; | |
} | |
// 拡張子がcsv以外の場合 | |
var reg=/(.*)(?:\.([^.]+$))/; | |
var extension = file.name.match(reg)[file.name.match(reg).length-1]; | |
if (extension !== 'csv') { | |
notifyService.showNotify(error_message, 'alert-danger'); | |
return; | |
} | |
var params = {}; | |
var list = []; | |
// ここだけPapaをESLint許容する。 | |
// eslint-disable-next-line no-undef | |
Papa.parse(file, { | |
header: true, | |
encoding: 'Shift-JIS', | |
complete: function(results) { | |
// 正しいCSVファイルかを確認する | |
if (!results.data[0].hasOwnProperty('__parsed_extra') || | |
results.data[0]['__parsed_extra']['0'] !== '定期') { | |
notifyService.showNotify(error_message, 'alert-danger'); | |
return; | |
} | |
// 最初のヘッダーは削除する | |
results.data.splice(0, 1); // ヘッダー行削除 | |
angular.forEach(results.data, function(record) { | |
if (record['__parsed_extra']) { | |
// バス(メモにバス/路面等が入ってる場合) | |
if (record['__parsed_extra'][8].match(/バス\/路面等/)) { | |
list.push({ | |
start_place: record['__parsed_extra'][8], | |
goal_place: record['__parsed_extra'][8], | |
amount: record['__parsed_extra'][6], | |
allocation_date: record[Object.keys(record)[0]], | |
check_flg: false, | |
}); | |
} | |
// 電車(出発駅、到着駅が入ってる場合) | |
if (record['__parsed_extra'][2] !== '' && record['__parsed_extra'][5] !== '') { | |
list.push({ | |
start_place: record['__parsed_extra'][2], | |
goal_place: record['__parsed_extra'][5], | |
amount: record['__parsed_extra'][6], | |
allocation_date: record[Object.keys(record)[0]], | |
check_flg: false, | |
}); | |
} | |
} | |
}); | |
// 古い順に並び替え | |
params.iccard_history = list.reverse(); | |
// 基本的には↑の reverse にて古い順になっているものの、 | |
// CSVをユーザーが勝手に編集した場合などがあるため、allocation_date で再度並び替えておく。 | |
// (注:allocation_date の並び替えだけでは、同一日内での順序は古い順にはならない。 | |
// 同一日内での順序は、生CSVの順序に頼るしかない。) | |
params.iccard_history.sort(function(a, b) { | |
return Date.parse(a['allocation_date']) - Date.parse(b['allocation_date']); | |
}); | |
params.sheet = sheet; | |
params.default_group = $scope.form_data.group; | |
params.default_project = _getProjectForSpecificsRow(); | |
$uibModal.open({ | |
templateUrl: '../static/wf/views/create_request/dialogs/iccard_history_templ.html', | |
controller: 'ICcardHistoryDialogCtrl', | |
resolve: { | |
params: function() { | |
return params; | |
}, | |
}, | |
}); | |
}, error: function() {}, | |
}); | |
} | |
/** | |
* 勤怠打刻時の交通費履歴選択 | |
* @param {Object} sheet | |
*/ | |
function selectICcardHistoryFelica(sheet) { | |
var params = {}; | |
params.sheet = sheet; | |
params.all_sheets = $scope.form_data.expense.request_expense_specifics; | |
params.default_group = $scope.form_data.group; | |
params.default_project = _getProjectForSpecificsRow(); | |
params.is_felica = true; | |
$http.get('/api/v1/felica/').then(function(res) { | |
params.iccard_history = res.data; | |
$uibModal.open({ | |
templateUrl: '../static/wf/views/create_request/dialogs/iccard_history_templ.html', | |
controller: 'ICcardHistoryDialogCtrl', | |
resolve: { | |
params: function() { | |
return params; | |
}, | |
}, | |
}); | |
}); | |
} | |
/** | |
* 経費・支払明細のプロジェクト用オブジェクトを返却する | |
* @return {null|{id: *, name: *, project_code: *}} | |
* @private | |
*/ | |
function _getProjectForSpecificsRow() { | |
var project_obj; | |
if (angular.isUndefinedOrNull($scope.form_data.project)) { | |
project_obj = null; | |
} else { | |
project_obj = {id: $scope.form_data.project, | |
name: $scope.form_data.project_name, | |
project_code: $scope.form_data.project_code}; | |
} | |
return project_obj; | |
} | |
/** | |
* 交通費明細 乗換案内ダイアログ | |
* @param {Object} row | |
* @param {Object} station_kind | |
* @param {Object} sheet 明細 | |
* @param {Number} index 明細行のインデックス | |
*/ | |
function showNorikaeDialog(row, station_kind, sheet, index) { | |
if (angular.isUndefinedOrNull(station_kind)) { | |
station_kind = 'start'; | |
} | |
// ICリーダーの明細では、基本的に当関数は呼ばれることはなく、 | |
// 駅名不明の場合のみ当関数を呼び出すことができる。 | |
// 駅名不明の場合は、経路検索ではなく、直接、駅名検索を行う。 | |
if (row.is_icreader) { | |
$scope.showSelectStationDialog(row, station_kind); | |
return; | |
} | |
// 乗換案内は無料制限ではないこと | |
$http.get('/api/v1/check_current_subscription/').then(function(res) { | |
if (res.data.subscription_flg) { | |
var params = { | |
allocation_date: row.allocation_date, | |
start_station_detail: row.start_station_detail, | |
goal_station_detail: row.goal_station_detail, | |
start_station_name: row.start_place, | |
goal_station_name: row.goal_place, | |
via_station_name: row.via_place, | |
station_kind: station_kind, | |
traffic_way: row.traffic_way || '', | |
pay_content: row.pay_content || '', | |
group: row.group || '', | |
project: row.project || '', | |
specifics_group_setting: sheet.specifics_group_setting, | |
specifics_project_setting: sheet.specifics_project_setting, | |
}; | |
if (!angular.isUndefinedOrNull($scope.requester_id)) { | |
// 代理申請の場合 | |
params.user_id = $scope.requester_id; | |
} else if (!angular.isUndefinedOrNull($scope.form_data.request_user)) { | |
// 修正の場合 | |
params.user_id = $scope.form_data.request_user.id; | |
} | |
var size = ''; | |
if ($rootScope.is_mobile) { | |
size = 'mobile'; | |
} | |
var modalInstance = $uibModal.open({ | |
templateUrl: '../static/wf/views/create_request/dialogs/norikae_templ.html', | |
controller: 'norikaeDialogCtrl', | |
size: size, | |
resolve: { | |
params: function() { | |
return params; | |
}, | |
}}); | |
modalInstance.result.then(function(norikae_datas) { | |
var base_row = sheet.request_expense_specifics_rows[index]; | |
norikae_datas.forEach(function(norikae_data, data_index) { | |
if (data_index) { | |
$scope.addSpecificsDetail(sheet, index + data_index - 1); | |
} | |
row = sheet.request_expense_specifics_rows[index + data_index]; | |
row.allocation_date = norikae_data.allocation_date; | |
row.start_place = norikae_data.start_place; | |
row.goal_place = norikae_data.goal_place; | |
row.via_place = norikae_data.via_place; | |
row.round_trip_flg = base_row.round_trip_flg; | |
row.traffic_way = norikae_data.traffic_way; | |
row.pay_content = norikae_data.pay_content || ''; | |
if (norikae_data.group || row.group) { | |
row.group = norikae_data.group; | |
} | |
if (norikae_data.project || row.project) { | |
row.project = norikae_data.project; | |
} | |
if (norikae_data.is_manual_input === | |
Const.miscellaneous.NORIKAE_ICON_EXCLAMATION.MANUAL_INPUT | |
) { | |
$scope.changeTransportRow(row); | |
row.amount = null; | |
} else { | |
row.start_station_detail = norikae_data.start_station_detail; | |
row.goal_station_detail = norikae_data.goal_station_detail; | |
// 往復が指定されている場合は倍にして返す | |
row.amount = (row.round_trip_flg === 1)? norikae_data.amount * 2: norikae_data.amount; | |
row.is_lowprice = Number(norikae_data.is_lowprice); | |
row.is_early = Number(norikae_data.is_early); | |
row.is_iccard = Number(norikae_data.is_iccard); | |
row.is_teiki = Number(norikae_data.is_teiki); | |
row.is_norikae_input = 1; | |
row.is_manual_input = Const.miscellaneous.NORIKAE_ICON_EXCLAMATION.AUTO_INPUT; | |
row.is_icreader = 0; | |
} | |
}); | |
$scope.checkExtraFlow('amount', null); | |
}).catch(function() { | |
}); | |
} else { | |
notifyService.showNotify(gettextCatalog.getString('無料プランのため、乗換案内機能はご利用できません。'), 'alert-danger'); | |
} | |
}); | |
} | |
/** | |
* 駅名検索ダイアログ | |
* @param {Object} row | |
* @param {Object} kind | |
*/ | |
function showSelectStationDialog(row, kind) { | |
var modalInstance = NorikaeService.openStationSearchDialog('', $rootScope.is_mobile); | |
modalInstance.result.then(function(station_detail) { | |
if (kind === 'start') { | |
row.start_station_detail = station_detail; | |
row.start_place = station_detail.name; | |
} else if (kind === 'goal') { | |
row.goal_station_detail = station_detail; | |
row.goal_place = station_detail.name; | |
} | |
}, function() { | |
}); | |
} | |
/** | |
* 駅名の手動変更の際の、乗換案内データのクリア | |
* @param {Object} row | |
* @param {Object} station_type | |
*/ | |
function changeStation(row, station_type) { | |
if (station_type === 'start') row.start_station_detail = null; | |
if (station_type === 'goal') row.goal_station_detail = null; | |
$scope.changeTransportRow(row); | |
} | |
/** | |
* 交通手段の必須確認 | |
* @param {Object} requestForm | |
* @return {boolean} | |
* @param {Object} sheet | |
* @param {Object} sheet_idx | |
* @param {Object} index | |
*/ | |
function isTrafficWayRequired(requestForm, sheet, sheet_idx, index) { | |
var formSheetKey = 'expenseSpecificsForm_' + sheet_idx; | |
var trafficWayKey = 'traffic_way_' + sheet_idx + '_' + index; | |
return formSheetKey in requestForm | |
&& trafficWayKey in requestForm[formSheetKey] | |
&& $scope.clicked_confirm | |
&& sheet.validate_error | |
&& requestForm[formSheetKey][trafficWayKey].$invalid === true; | |
} | |
/** | |
* 交通費明細 片道 <-> 往復 の変更時の金額自動変更 | |
* @param {Object} row | |
*/ | |
function changeRoundTrip(row) { | |
if (row.is_credit_card) { | |
return; | |
} | |
calcAmountWithRoundTrip(row); | |
$scope.checkExtraFlow('amount', null); | |
} | |
/** | |
* 交通費 片道 <->往復変更時の金額計算処理 | |
* @param {Object} row | |
*/ | |
function calcAmountWithRoundTrip(row) { | |
// 片道 -> 往復 | |
if (row.round_trip_flg) { | |
row.amount *= 2; | |
} | |
// 往復 -> 片道 | |
else { | |
row.amount /= 2; | |
} | |
} | |
/** | |
* 交通費明細を手動入力した場合の各種マーク変更 | |
* @param {Object} row | |
*/ | |
function changeTransportRow(row) { | |
row.is_lowprice = 0; | |
row.is_early = 0; | |
row.is_iccard = 0; | |
row.is_teiki = 0; | |
row.is_icreader = 0; | |
row.is_norikae_input = 0; | |
row.is_manual_input = Const.miscellaneous.NORIKAE_ICON_EXCLAMATION.MANUAL_INPUT; | |
row.progress_request = null; // コピー申請で進行中交通費申請が紐付いている場合も、行コピー時には無効化する | |
} | |
/** | |
* 正しい駅名ならtrue、駅名不明ならfalseを返す | |
* @param {String} station_name | |
* @return {boolean} | |
*/ | |
function isValidStationName(station_name) { | |
var is_not_valid = | |
station_name === Const.miscellaneous.UNKNOWN_STATION_BUS || // バス停の場合 | |
station_name === Const.miscellaneous.UNKNOWN_STATION_TRAIN || // 勤怠からの交通費連携で、駅名がDBに無い場合 | |
station_name === ''; | |
return !is_not_valid; | |
} | |
/** | |
* 勤怠からの交通費連携で、申請済の交通費での明細行あれば true を返す | |
* 交通費選択ダイアログではこのような交通費は選択できないが、コピー申請にてこのような明細行が発生しうる | |
* @param {Object} row 行オブジェクト | |
* @return {boolean} | |
*/ | |
function existInRequest(row) { | |
return CreateRequestExpenseSpecificsService.existInRequest(row); | |
} | |
/** | |
* 行に書かれた交通費の情報がまだ下書きの申請のものであればtrueを返す | |
* @param {Object} row 行オブジェクト | |
* @return {boolean} | |
*/ | |
function isDraftRequest(row) { | |
return CreateRequestExpenseSpecificsService.isDraftRequest(row); | |
} | |
/** | |
* その行の交通費データを使っている申請へのURLを取得する | |
* @param {Object} row 行オブジェクト | |
* @return {string} | |
*/ | |
function getProgressRequestUrl(row) { | |
return CreateRequestExpenseSpecificsService.getProgressRequestUrl(row); | |
} | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
以下の形式はjobcanの交通費明細で有効
encoding: Shift-JIS