案件管理と予算管理を使って、営業マン・月毎に予算に対しての達成率を出したいです

いつもお世話になっております。

長文失礼いたします。

 

現状、二つのアプリ(①案件管理②予算管理)を組み合わせて、営業担当者別・月別で予算に対しての達成率を表示したいと考えております。

そこで下記を参考に、②予算管理はフィールドコード"拠点"を営業担当者名の文字フィールドに、また①案件管理ではルックアップで、営業担当者名を予算管理から引っ張ってきておりフィールドコードは"拠点"にしてこれでカスタマイズ表は無事表示されました。

https://developer.cybozu.io/hc/ja/articles/202640870

 

jQuery.noConflict();
(function($) {

“use strict”;
//予算管理アプリを全レコード取得
function fetchRecords(appId, opt_offset, opt_limit, opt_records) {
var app_yosan = kintone.app.getLookupTargetAppId(“拠点”); //予算管理アプリID
var offset = opt_offset || 0;
var limit = opt_limit || 100;
var allRecords = opt_records || [];
var params = {app: app_yosan, query: ‘order by レコード番号 asc limit ’ + limit + ’ offset ’ + offset};
return kintone.api(kintone.api.url(’/k/v1/records’, true), ‘GET’, params).then(function(resp) {
allRecords = allRecords.concat(resp.records);
if (resp.records.length === limit) {
return fetchRecords(appId, offset + limit, limit, allRecords);
}
return allRecords;
});
}
//予実管理データのカスタマイズビュー用データの作成
function makeYojitsuData(records, opt_data, opt_i) {
var i = opt_i || 0; //レコードのカウント
var allData = opt_data || []; //予実の集計結果
var appId = kintone.app.getId(); //実績管理アプリID
var key1, key2, key3, key4, key5;
key1 = records[i][‘拠点’][‘value’];
key1 = key1.replace(/</g, “<”).replace(/>/g, “>”);
key2 = records[i][‘予算’][‘value’];

var params = {‘app’: appId, ‘query’: ‘拠点 = "’ + key1 + ‘"’};
return kintone.api(kintone.api.url(‘/k/v1/records’, true), ‘GET’, params).then(function(resp) {
if (resp.records) {
key3 = 0;
var obj = resp.records;
for (var j = 0; j < obj.length; j++) {
key3 += parseInt(obj[j][‘実績合計’][‘value’], 10);
}
key4 = parseInt(key3, 10) - parseInt(key2, 10);
key5 = parseInt(key3, 10) / parseInt(key2, 10) * 100;
key5 = key5.toFixed(2);
key5 += “%”;
allData.push({segment: key1, budget: key2, results: key3, Difference: key4, AchievementRate: key5});
}else {
event.error = ‘実績管理情報が取得できません。’;
}
i = i + 1;
if (records.length !== i) {
return makeYojitsuData(records, allData, i);
}
return allData;
});
}
//差異のマイナス値を赤色に変更
function cellDesign() {
$(‘#view tr td’).each(function(index, elm) {
if ($(this).hasClass(‘Difference_class’)) {
if ($(this).text().indexOf(“-”) > -1) {
$(this).css(‘color’, ‘#ff0000’);
}
}
});

}
//予実管理のカスタマイズビューを取得
function dispYojitsuCustomizeView(records) {
makeYojitsuData(records).then(function(data) {
//列の設定
var colModelSettings = [
{name: “segment”, index: “segment”, width: 300, align: “center”,
classes: “segment_class”},
{name: “budget”, index: “budget”, width: 200, align: “right”,
classes: “budget_class”, formatter: ‘currency’, sorttype: “float”},
{name: “results”, index: “results”, width: 200, align: “right”,
classes: “results_class”, formatter: ‘currency’, sorttype: “float”},
{name: “Difference”, index: “Difference”, width: 200, align: “right”,
classes: “Difference_class”, formatter: ‘currency’, sorttype: “float”},
{name: “AchievementRate”, index: “AchievementRate”, width: 150, align: “center”,
classes: “AchievementRate_class”, sorttype: “float”}
];
//列の表示名
var colNames = [“氏名”, “予算”, “実績”, “差異”, “達成率”];
$(“#view”).jqGrid({
data: data,
datatype: “local”,
colNames: colNames,
colModel: colModelSettings,
rowNum: 10,
rowList: [1, 10, 20],
caption: “売上”,
height: “auto”,
width: 1100,
pager: ‘pager’,
shrinkToFit: true,
viewrecords: true,
gridComplete: function() {
cellDesign();
}
});
});
}
//イベント処理
kintone.events.on([‘app.record.index.show’], function(event) {
var appId = kintone.app.getId(); //実績管理アプリID
fetchRecords(appId).then(function(records) {
dispYojitsuCustomizeView(records);
});
});

})(jQuery);

 

しかし、これですと、月別などではなく営業マン別のみで延々と数字が積みあがってしまう為、営業マン別で更に月別で表を表示させたいのが願いです。

 

②予算管理には日付フィールド(フィールドも"日付")を作成して

①案件管理側にも日付フィールド(フィールドも"日付")を作成して

カスタマイズ表に表示させたいです。

現状↓

から

変更後↓

 

このような感じにしたいです。

 

なお、案件管理の方の日付フィールドは〇月1日と日付は1日で固定してルール化しております。

 

jsに関して colNamesの追加とkeyの追加は必要だと思うのですが、

そもそも予算管理を現状営業マンの数でレコード数を作っているのですが

このままだと、営業マン数+月別でレコードを作成して、尚且つルックアップしなくてはいけないと思いますので、ルックアップ先でどうしても数が増えてしまう為、懸念しております。

そこで②予算管理での日付と予算フィールドをテーブル化して、参照を行うことはできないでしょうか?

 

ご教示いただけますと幸いです。

 

以上、宜しくお願い致します。

こんにちは。

質問内容に書かれているものも含め、方法論としては3つになると思います。

1)予算管理で1営業マン+1月 で1レコードとする。

2)予算管理で1営業マン+1年 で1レコードとして、月別の予算をテーブル化する

3)予算管理で1営業マン+1年で1レコード。予算金額も1年合計 のままで、最終的な予実集計の時に、1年合計金額を12で割る。

 

1)は今のJSを少し工夫すれば、実現可能ですが、おっしゃる通りレコード数は増えます。

2)は予算管理画面がすっきりしますので、使いやすいと思います。ただ、予実集計の所は、テーブル化にあわせて修正が必要。

3)は若干手抜きですが、実際問題年間の予算を達成できればよく、月別の金額の大小があまり問題にならないのであれば、この方法を取っても良いかもしれません。えてして予算管理って、細かくやりすぎると逆に手間になってしまうので。

 

具体的なコードのアドバイスではないので恐縮ですが、参考になれば幸いです。

追記:コード見ていないので、今の達成率の算出ロジックがわからないので、既にそうなっていたらすみません。

 

4)1月は達成、2月は未達成 ということもあるので、各月で単月予実差異を出しても、あまり意味はなく、大事なのは今日までの累計での予算達成率。という考え方でOKであれば、

氏名、日付、予算、実績、差異、達成率 の現状項目の横に 今月時点 達成率 という項目を追加

 

今月時点達成率の算出は 9月の場合

実績累計 ÷ {年間予算 *  ( 9ヶ月 ÷ 12ヶ月)}

 

※ 雰囲気で計算式書いてるので、違ってたらすみません。意図が伝われば幸いです。

※ つまりちゃんと年末の予算達成に向けて、こつこつやってますか という意味合いの達成率

※ この項目追加だけでOKであれば、JSの修正は最小限でいけると思います。

 

 

上海レンユアー

松村様

 

いつもお世話になっております。

 

ご連絡ありがとうございます。

 

色々な方法のご教示感謝いたします。

私個人的には③④でできたらjsをほとんど触らなくても項目変更したら

できるレベルなので、簡単に実装できるのですが、

恐らく②の形がベストだと思うので。。。

 

再度コード書いてチャレンジしてみます!

以上、宜しくお願い致します。

上海レンユアー

松村様

 

いつもお世話になっております。

 

ご連絡遅くなりまして申し訳ありません。

 

あれから何度かトライしているのですがどうもうまくいかないです。。。

 

予算管理は下記で作成しております。

また、案件実績管理は下記で作成しております。

そして、jsファイルは下記で作成しました。

 

jQuery.noConflict();
(function($) {

“use strict”;
//予算管理アプリを全レコード取得
function fetchRecords(appId, opt_offset, opt_limit, opt_records) {
var app_yosan = kintone.app.getLookupTargetAppId(“拠点”); //予算管理アプリID
var offset = opt_offset || 0;
var limit = opt_limit || 100;
var allRecords = opt_records || [];
var params = {app: app_yosan, query: ‘order by レコード番号 asc limit ’ + limit + ’ offset ’ + offset};
return kintone.api(kintone.api.url(’/k/v1/records’, true), ‘GET’, params).then(function(resp) {
allRecords = allRecords.concat(resp.records);
if (resp.records.length === limit) {
return fetchRecords(appId, offset + limit, limit, allRecords);
}
return allRecords;
});
}
//予実管理データのカスタマイズビュー用データの作成
function makeYojitsuData(records, opt_data, opt_i) {
var i = opt_i || 0; //レコードのカウント
var allData = opt_data || []; //予実の集計結果
var appId = kintone.app.getId(); //実績管理アプリID
var key1, key2, key3, key4, key5, key6;
key1 = records[i][‘拠点’][‘value’];
key1 = key1.replace(/</g, “<”).replace(/>/g, “>”);
key2 = records[i][‘予算’][‘value’];
key6 = records[i][‘日付’][‘value’];

var params = {‘app’: appId, ‘query’: ‘拠点 = "’ + key1 + ‘"’,‘query2’: ‘日付 = "’ + key6 + ‘"’};
return kintone.api(kintone.api.url(‘/k/v1/records’, true), ‘GET’, params).then(function(resp) {
if (resp.records) {
key3 = 0;
var obj = resp.records;
for (var j = 0; j < obj.length; j++) {
key3 += parseInt(obj[j][‘実績合計’][‘value’], 10);
}
key4 = parseInt(key3, 10) - parseInt(key2, 10);
key5 = parseInt(key3, 10) / parseInt(key2, 10) * 100;
key5 = key5.toFixed(2);
key5 += “%”;
allData.push({segment: key1, budget: key2, results: key3, Difference: key4, AchievementRate: key5, monthly: key6});
}else {
event.error = ‘実績管理情報が取得できません。’;
}
i = i + 1;
if (records.length !== i) {
return makeYojitsuData(records, allData, i);
}
return allData;
});
}
//差異のマイナス値を赤色に変更
function cellDesign() {
$(‘#view tr td’).each(function(index, elm) {
if ($(this).hasClass(‘Difference_class’)) {
if ($(this).text().indexOf(“-”) > -1) {
$(this).css(‘color’, ‘#ff0000’);
}
}
});

}
//予実管理のカスタマイズビューを取得
function dispYojitsuCustomizeView(records) {
makeYojitsuData(records).then(function(data) {
//列の設定
var colModelSettings = [
{name: “segment”, index: “segment”, width: 300, align: “center”,
classes: “segment_class”},
{name: “monthly”, index: “monthly”, width: 200, align: “center”,
classes: “segment_class”},
{name: “budget”, index: “budget”, width: 200, align: “right”,
classes: “budget_class”, formatter: ‘currency’, sorttype: “float”},
{name: “results”, index: “results”, width: 200, align: “right”,
classes: “results_class”, formatter: ‘currency’, sorttype: “float”},
{name: “Difference”, index: “Difference”, width: 200, align: “right”,
classes: “Difference_class”, formatter: ‘currency’, sorttype: “float”},
{name: “AchievementRate”, index: “AchievementRate”, width: 150, align: “center”,
classes: “AchievementRate_class”, sorttype: “float”}
];
//列の表示名
var colNames = [“氏名”, “月度”, “予算”, “実績”, “差異”, “達成率”];
$(“#view”).jqGrid({
data: data,
datatype: “local”,
colNames: colNames,
colModel: colModelSettings,
rowNum: 10,
rowList: [1, 10, 20],
caption: “売上”,
height: “auto”,
width: 1100,
pager: ‘pager’,
shrinkToFit: true,
viewrecords: true,
gridComplete: function() {
cellDesign();
}
});
});
}
//イベント処理
kintone.events.on([‘app.record.index.show’], function(event) {
var appId = kintone.app.getId(); //実績管理アプリID
fetchRecords(appId).then(function(records) {
dispYojitsuCustomizeView(records);
});
});

})(jQuery);

 

この文で、本当は担当者(フィールドコード:拠点)が予算と実績アプリで一致して

なおかつ月度(フィールドコード:日付)が一致する場合、それぞれの月度の行に

売上実績合計が追加される。というのを書きたかったのですが、

 

上記の用にCさんの9月から11月の実績数字にそれぞれ合計値が追加されてしまいました。

本来は下記をイメージしておりました。

 

恐れ入りますが、どこのコードがおかしいのかヒントをご教示願えませんでしょうか?

 

以上、よろしくお願い申し上げます。

岩上様。コード拝見しました。

ポイントになりそうな部分を下記の順番で見ていったところ、気になるところがありました。

他にも何かしらあるかもしれませんが、まずはこの部分を確認してみてください。

 

1.ソースの下記部分で 本来はkey3=0(すなわち実績=0)になってほしいのにkey3に金額が入ってしまっている。という仮説

allData.push({segment: key1, budget: key2, results: key3, Difference: key4, AchievementRate: key5, monthly: key6});

2.その key3 に値が代入されているのはこの場所だが、表記には特に問題なさそう

for (var j = 0; j < obj.length; j++) {
 key3 += parseInt(obj[j]['実績合計']['value'], 10);
}

3。では、値代入前のレコード取得部分で、不要なレコードもまとめて習得しているという仮説。該当箇所がここ。

var params = {'app': appId, 'query': '拠点 = "' + key1 + '"','query2': '日付 = "' + key6 + '"'};

で、恐らくここが問題かなと思います。

query2 というパラメータは存在しないため、実質有効なのはqueryのみとなり、拠点(担当)だけの条件で実績を引っ張ってきてる様子(私が知らないだけで、query2というパラメータが存在したらすみません)。

なので、query に対して 拠点=** and 日付=** みたいな形で、AND条件でつなげた正しいquery分を渡してあげれば、希望通り動く様な気がします。

上海レンユアー

松村様

 

いつもお世話になっております。

 

ご連絡遅くなりまして申し訳ありません。

 

ご返信ありがとうございます!

 

クエリの記述がおかしいという事でご教示いただきましてありがとうございます。

 

今別件が立て込んでおりすぐには対応できないのですが、

落ち着き次第、一度トライしてみます!!

 

また、結果はご報告いたします。

以上、よろしくお願い申し上げます。

上海レンユアー

松村様

 

いつもお世話になっております。

 

ご連絡遅くなりまして申し訳ありません。

 

下記のクエリ条件の記述にすることで無事希望通りの動作が実現しました!

var params = {‘app’: appId, ‘query’:‘拠点 = "’ + key1 + ‘" and 日付 = "’ + key6 + ‘"’};

本当に有難うございます!

 

こちらはもし可能であればなのですが、実績行を合計して累計を作ることは難しいでしょうか?

 

以上、お手数では御座いますが宜しくお願い致します。