
この記事は、プロモーションを含みます。

こんにちは!今回は「自動販売機Webアプリ作成」シリーズの完結編です。
この記事では、商品の在庫管理機能と、おつりを硬貨単位で表示する機能を追加していきます。

いよいよ、自動販売機が完成するんですね。
在庫管理って難しいんじゃないですか?

在庫管理って言葉だけ聞くと難しそうに思うけど、考え方は簡単だよ。
それでは、実際に作っていきましょう。
この記事で学べること
- 在庫管理の考え方、作り方
- おつりに関する考え方、作り方
- 自動販売機を作ろうシリーズの最終的なソースコード
在庫管理を作ろう
在庫管理とは?
現実の自動販売機と同じように、ジュースがなくなったら売れないようにしたいですよね?
それを実現するには、プログラムの中で「各ジュースの在庫数(残り何本あるか)」をしっかり記録して、買われたら1本減らしていく、という処理が必要です。
どんな仕組みを作るの?
機能 | 内容 |
---|---|
在庫を記録する | いちごソーダ:3本、ミルクティー:4本など |
表示する | 「在庫:3本」など画面に見えるようにする |
減らす | 商品が買われたら、在庫を1つ減らす |
売り切れ表示 | 在庫が0になったら「売り切れ」と表示して、購入できないようにする |
「在庫管理」を処理フローに追加してみよう
在庫を減らし、在庫が0個になったら売り切れ表示をして、在庫の表示を更新します。

HTMLの修正
在庫を表示するためのspanタグを追加します。HTMLを以下のように修正してください。
<div class="juice">
<div class="juice-name">
いちごソーダ - 150円
<span id="stock-strawberry">(在庫: 3)</span>
</div>
<button id="btn-strawberry" onclick="buyJuice('いちごソーダ', 150, 'strawberry')">購入</button>
</div>
<div class="juice">
<div class="juice-name">
ももジュース - 130円
<span id="stock-peach">(在庫: 4)</span>
</div>
<button id="btn-peach" onclick="buyJuice('ももジュース', 130, 'peach')">購入</button>
</div>
<div class="juice">
<div class="juice-name">
ミルクティー - 100円
<span id="stock-milk">(在庫: 5)</span>
</div>
<button id="btn-milk" onclick="buyJuice('ミルクティー', 100, 'milk')">購入</button>
</div>
buyJuice関数の第三引数に、在庫数をチェックするキーを追加しています。
JavaScriptの修正
各ジュースの在庫数を管理するため、以下のようなJavaScriptオブジェクトを作成します。これにより、在庫がない商品の購入を防ぐ処理が可能になります。
// 商品ごとの在庫を管理するオブジェクト
const stock = {
strawberry: 3,
peach: 4,
milk: 5
};
/** ジュースの購入ボタンをクリックされた時の処理 **/
function buyJuice(name, price, key) {
const moneyInput = document.getElementById('money');
const message = document.getElementById('message');
const money = Number(moneyInput.value);
// 在庫チェック
if (stock[key] <= 0) {
message.textContent = `${name} は売り切れだよ!`;
return;
}
// 購入制限チェック
if (money < price) {
message.textContent = `ごめんね…あと ${price - money} 円たりないよ。`;
return;
}
stock[key]--;
let zankin = moneyInput.value - price;
moneyInput.value = zankin;
// 在庫数を更新
document.getElementById(`stock-${key}`).textContent = `(在庫: ${stock[key]})`;
// 在庫が0になったらボタン無効化
if (stock[key] === 0) {
document.getElementById(`btn-${key}`).disabled = true;
document.getElementById(`btn-${key}`).textContent = "売り切れ";
}
alert(`${name}:${price}円を購入しました♪`);
}
① 商品の在庫を管理するためのオブジェクトを追加
const stock = {
strawberry: 5,
peach: 3,
milk: 2
};
- それぞれの商品に対して「残り何本あるか」を管理するための在庫オブジェクトを作成。
key
(例:"strawberry"
)を使って在庫数にアクセスします。
② 在庫チェックの処理を追加
if (stock[key] <= 0) {
message.textContent = `${name} は売り切れだよ!`;
return;
}
- 商品の在庫が0以下なら購入をキャンセルし、「売り切れ」メッセージを表示します。
return;
でこの時点で処理を終了しています。
③ 購入成功時に在庫数を1つ減らす処理を追加
stock[key]--;
- 商品が1本売れたので、在庫数を1つ減らします。
④ 在庫表示欄のテキストを更新する処理を追加
document.getElementById(`stock-${key}`).textContent = `(在庫: ${stock[key]})`;
- 画面上に表示されている「在庫:◯本」の数字を、現在の在庫数に書き換えます。
- HTML側で
id="stock-strawberry"
などと記述しておく必要があります。
⑤ 在庫が0になったら購入ボタンを無効化する処理を追加
if (stock[key] === 0) {
document.getElementById(`btn-${key}`).disabled = true;
document.getElementById(`btn-${key}`).textContent = "売り切れ";
}
- 在庫が0になったタイミングで、購入ボタンを押せなくする(
disabled = true
)。 - ボタンのラベルも「売り切れ」に変更して、ユーザーにわかりやすく表示します。
動きを見てみよう
HTMLファイルをダブルクリックして、ブラウザで表示してください。
商品ごとに在庫数が表示されています。

入金額に「1000」を入力し、「いちごソーダ」の購入ボタンをクリックしてください。
在庫数が「2]に減っています。

このまま、あと2回購入して在庫を0にしてください。
購入ボタンが売り切れボタンに変わり、ボタンがクリック出来ないようになりました。

これで、在庫管理の実装が完了です。
おつりを小銭で受け取ろう
おつりボタンを作成し、おつりボタンが押されたら、金額が大きい順に、硬貨の枚数が表示される処理を追加します。
HTMLの修正
ここまでの記事で追加・修正してきた内容をすべてまとめた、完成版のHTMLコードを以下に掲載します。ファイルを一から作成する際にもご活用ください。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>もふもふ自動販売機</title>
<style>
body {
background-color: #fffaf5;
font-family: "Rounded Mplus 1c", "Hiragino Maru Gothic ProN", sans-serif;
text-align: center;
padding: 40px;
}
.vending-machine {
display: inline-block;
background: #ffeef0;
border: 5px solid #f7c5cc;
border-radius: 20px;
padding: 30px 40px;
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
}
h2 {
color: #d35d7c;
margin-bottom: 20px;
font-size: 28px;
}
.money-input {
margin-bottom: 25px;
}
input[type="number"] {
padding: 8px 10px;
font-size: 16px;
border: 2px solid #f7c5cc;
border-radius: 10px;
width: 150px;
}
.juice {
background-color: #fff;
border: 2px solid #f7c5cc;
border-radius: 12px;
padding: 15px;
margin: 15px 0;
}
.juice-name {
font-weight: bold;
font-size: 18px;
color: #333;
}
button {
margin-top: 10px;
padding: 8px 20px;
font-size: 16px;
background-color: #ffd7e0;
border: none;
border-radius: 12px;
cursor: pointer;
transition: background-color 0.3s;
}
button:hover {
background-color: #f7b9c5;
}
#message {
margin-top: 20px;
color: #b85c75;
font-weight: bold;
}
.vending-machine, .change-area {
display: inline-block;
}
.money-input, .change-button {
display: inline-block;
}
</style>
</head>
<body>
<div class="vending-machine">
<h2>もふもふ自動販売機</h2>
<div class="money-input">
<label for="money">お金を入れてください:</label><br>
<input type="number" id="money" placeholder="例:200" min=0 max=1000 />
</div>
<div class="change-button">
<button id="btn-change" onclick="showChange()">おつり</button>
</div>
<p id="message">
<div class="juice">
<div class="juice-name">
いちごソーダ - 150円
<span id="stock-strawberry">(在庫: 3)</span>
</div>
<button id="btn-strawberry" onclick="buyJuice('いちごソーダ', 150, 'strawberry')">購入</button>
</div>
<div class="juice">
<div class="juice-name">
ももジュース - 130円
<span id="stock-peach">(在庫: 4)</span>
</div>
<button id="btn-peach" onclick="buyJuice('ももジュース', 130, 'peach')">購入</button>
</div>
<div class="juice">
<div class="juice-name">
ミルクティー - 100円
<span id="stock-milk">(在庫: 5)</span>
</div>
<button id="btn-milk" onclick="buyJuice('ミルクティー', 100, 'milk')">購入</button>
</div>
<p id="message"></p>
</div>
<!-- おつり表示エリア -->
<div class="change-area">
<h3>おつり</h3>
<div class="coin" id="coin-1000">
1000円札
<span id="change-1000">× 0</span>
</div>
<div class="coin" id="coin-500">
500円硬貨
<span id="change-500">× 0</span>
</div>
<div class="coin" id="coin-100">
100円硬貨
<span id="change-100">× 0</span>
</div>
<div class="coin" id="coin-50">
50円硬貨
<span id="change-50">× 0</span>
</div>
<div class="coin" id="coin-10">
10円硬貨
<span id="change-10">× 0</span>
</div>
</div>
<script src="vendingMachine.js"></script>
</body>
</html>
①おつり表示エリアのレイアウトを設定
.vending-machine, .change-area {
display: inline-block;
}
- 自動販売機の右側におつりの表示クラスを配置する。
②おつりボタンのレイアウトを設定
.money-input, .change-button {
display: inline-block;
}
- 入金額の右側におつりボタンを配置する。
③おつりボタンを作成
<div class="change-button">
<button id="btn-change" onclick="showChange()">おつり</button>
</div>
- クリックされたら関数「showChange()」が呼び出される。
④おつり表示エリアの作成
<!-- おつり表示エリア -->
<div class="change-area">
<h3>おつり</h3>
<div class="coin" id="coin-1000">
1000円札
<span id="change-1000">× 0</span>
</div>
<div class="coin" id="coin-500">
500円硬貨
<span id="change-500">× 0</span>
</div>
<div class="coin" id="coin-100">
100円硬貨
<span id="change-100">× 0</span>
</div>
<div class="coin" id="coin-50">
50円硬貨
<span id="change-50">× 0</span>
</div>
<div class="coin" id="coin-10">
10円硬貨
<span id="change-10">× 0</span>
</div>
</div>
- おつりの表示エリアでは、各金種ごとに「何枚のおつりがあるか」を表示します。
- たとえば「100円硬貨 × 2」と表示されるように、各行にIDを割り当て、JavaScriptから値を動的に反映させる構造になっています。
JavaScriptの修正
ここまでの記事で追加・修正してきた内容をすべてまとめた、完成版のJavaScriptコードを以下に掲載します。ファイルを一から作成する際にもご活用ください。
// 商品ごとの在庫を管理するオブジェクト
const stock = {
strawberry: 3,
peach: 4,
milk: 5
};
/** ジュースの購入ボタンをクリックされた時の処理 **/
function buyJuice(name, price, key) {
const moneyInput = document.getElementById('money');
const message = document.getElementById('message');
const money = Number(moneyInput.value);
// 在庫チェック
if (stock[key] <= 0) {
message.textContent = `${name} は売り切れだよ!`;
return;
}
// 購入制限チェック
if (money < price) {
message.textContent = `ごめんね…あと ${price - money} 円たりないよ。`;
return;
}
stock[key]--;
let zankin = moneyInput.value - price;
moneyInput.value = zankin;
// 在庫数を更新
document.getElementById(`stock-${key}`).textContent = `(在庫: ${stock[key]})`;
// 在庫が0になったらボタン無効化
if (stock[key] === 0) {
document.getElementById(`btn-${key}`).disabled = true;
document.getElementById(`btn-${key}`).textContent = "売り切れ";
}
alert(`${name}:${price}円を購入しました♪`);
}
/** 入力金額チェック(0未満・1000超え) **/
document.addEventListener('DOMContentLoaded', function () {
const moneyInput = document.getElementById('money');
const message = document.getElementById('message');
moneyInput.addEventListener('input', function () {
const money = Number(moneyInput.value);
if (money < 0) {
message.textContent = "0円未満は入力できないよ。";
moneyInput.value = ""
} else if (money > 1000) {
message.textContent = "1000円を超える金額は入力できないよ。";
moneyInput.value = ""
} else {
message.textContent = "";
}
});
});
// おつりを表示する関数
function showChange() {
const moneyInput = document.getElementById("money");
let change = Number(moneyInput.value);
// 各硬貨の枚数を計算(大きい金額優先)
const denominations = [1000, 500, 100, 50, 10];
const changeCounts = {
1000: 0,
500: 0,
100: 0,
50: 0,
10: 0
};
for (let yen of denominations) {
changeCounts[yen] = Math.floor(change / yen);
change -= yen * changeCounts[yen];
}
// 表示を更新
for (let yen of denominations) {
document.getElementById(`change-${yen}`).textContent = `× ${changeCounts[yen]}`;
}
// お金欄をリセット
moneyInput.value = 0;
document.getElementById("message").textContent = "おつりを受け取ったよ♪";
}
① 入力された金額を取得する
const moneyInput = document.getElementById("money");
let change = Number(moneyInput.value);
- ユーザーが入力した金額(残っているお金)を取得します。
Number()
で数値として使えるようにします。- この
change
という変数が、今から分けていく「おつりの合計金額」です。
② おつりの金種(硬貨)とカウントの準備
const denominations = [1000, 500, 100, 50, 10];
const changeCounts = {
1000: 0,
500: 0,
100: 0,
50: 0,
10: 0
};
denominations
は使える金種を大きい順に並べた配列です。changeCounts
は、各金種が**何枚使われたかを記録する箱(オブジェクト)**です。- 最初はすべて0枚で初期化しておきます。
③ 大きい金種から順におつりを計算
for (let yen of denominations) {
changeCounts[yen] = Math.floor(change / yen);
change -= yen * changeCounts[yen];
}
- おつりを大きい金額から優先的に分けていく処理です。
- 例えば、
change
が 1370円 の場合:- 1000円札 ×1(残370円)
- 100円硬貨 ×3(残70円)
- 50円硬貨 ×1(残20円)
- 10円硬貨 ×2(残0円)
Math.floor()
は小数点以下を切り捨てて、整数だけを使います。
④ 画面上におつりの枚数を表示
for (let yen of denominations) {
document.getElementById(`change-${yen}`).textContent = `× ${changeCounts[yen]}`;
}
- HTMLの中の
<span id="change-1000">
などの部分に、計算した枚数を表示します。 - たとえば
× 3
と表示されれば「その金種のおつりが3枚」という意味になります。
⑤ 入金額をリセットし、メッセージを表示
moneyInput.value = 0;
document.getElementById("message").textContent = "おつりを受け取ったよ♪";
- おつりを受け取ったら、残金(
money
)は 0円 にリセット。 - ユーザーに向けて「おつりを受け取ったよ♪」という可愛いメッセージを表示します。
動きを見てみよう
HTMLファイルをダブルクリックして、ブラウザで表示してください。
自動販売機の右下に、おつりの表示エリアが作成されています。

入金額に「1000」を入力し、おつりボタンをクリックしてください。
「1000円札」が1と更新されています。

もう一度、入金額に「1000」を入力し、ももジュースの購入ボタンをクリックしてください。
その後、おつりボタンをクリックしてください。
1000円札以外の硬貨の数字が870円分、更新されていることが確認できました。


自動販売機Webアプリの制作お疲れさまでした。
これで、全工程が終了しました。

ありがとうございました。
Webアプリの作り方が分かるようになりました。

今後も、ツールやゲームのWebアプリを中心に、作り方を公開していこうと思います。是非、他の記事も読んでくださいね♪
ここまで一緒にWebアプリを作ってくれてありがとうございました。
自動販売機のWebアプリだけでは、使っていないJavaScriptの機能は沢山あります。
こちらのJavaScriptに関する書籍を読めば、もっとJavaScriptに詳しくなれるので
よかったら読んでみてください。
コメント