経済対策で消費税減税とかあり得ないよと言う話し

消費税現在が叫ばれているが、消費税を勘違いしている人が存外多いので、簡単に纏めておく。

消費税に良くある誤解

企業は消費税をほとんど負担していない

企業も物を仕入れたり、経費をつかったりすると、消費税を支払います。例えば900万円で仕入れたなら、消費税90万円を含む990万円を支払うこととなる。この時の消費税90万円を、経理上は仮払消費税として別途集計しておきます。

逆に企業が物を売ったりすると、消費税を受け取ります。例えば1000万円の売上なら、消費税100万円を加えて、1100万円を受け取る。この時の消費税100万円を、経理上は仮受消費税として別途集計しておきます。

そして決算時に仮受消費税の合計額から、仮払消費税の合計額を引いた、残りを消費税額を消費税納税額として申告します。つまり仮払消費税が90万円、仮受け消費税が100万円なら、納税する消費税は10万円です。この納税する分の10万円は一括で支払う訳では無く、翌年に月々分割で納税していうことになります。

このように消費税は最終消費者が10%の消費税を負担する仕組みになっています。企業は経費として一旦は仮払消費税を払いますが、最後はお客様から頂いた仮受消費税と相殺します。したがって企業側は消費税負が殆ど無い(交際費など一部の経費は消費税を負担している)のです。

取引の度に消費税が積み上がるので、最終消費者の実質負担は10%ではなく数十%になる・・・と言う誤解を時折見かけます。そんな事は無いのです。

税率が変わった後も旧税率での売上や支払が起こる

税率の変更日以降の取引において消費税率が変わります。逆に言えば、変更日以前に1年単位あるいはもっと長期にわたる契約を取り交わしていた場合には、変更日以後も旧税率での取引が発生します。良くあるのは年単位の保守契約や賃借契約で代金を前払いしている場合です。長い場合には10年以上にわたって旧税率での取引が残ることもあります。(※実際には様々な特例規定が設けられてます。)

そのため企業の情報システムは税率変更後も旧税率の取引を、今後何年間にもわたって取り扱えなくてはなりません。場合によっては旧々税率の取引も扱う必要があります。だからこそ多大なシステム改修が発生するのです。

レジの消費税率変更はマニュアルを見れば誰でも簡単にできる・・・と言われる方がいますが、レジの消費税率設定は、消費税にかかわるシステムの一部に過ぎないのです。

税率変更に伴う価格改定作業は意外と時間がかかる

国が総額表示(内税価格での表示)を義務づけています。そのために店頭の価格表示は原則として総額表示です。税率改定時には旧税率総額表示になっている価格を全て外税表示に差し替え、税率変更日以後に改めて新税率の総額表示に差し替えるという作業をおこなっています。

食品スーパーなどはオンラインで表示価格を変更できる電子棚札を用いていますが、それ以外の小売業は紙に印刷していることが殆どです。これらを全て差し替えるには、仕事の合間を縫いながら何週間もかけて実施しています。

消費税減税は増税よりも難しい

消費税減税の告知により買い控えが発生する

消費税率変更にはシステム改修を避けられません。そのため、消費税率を下げる場合でも数年前からの告知が必要不可欠です。数年後に消費税率が大幅に下がるとなれば、広範囲で買い控えが発生するのを避けられません。

地方税収入が減額される

消費税10%のうち、7.8%が国税、2.2%は地方税となっています。地方自治体の税収源は限られており、また国債の発行などにより赤字を埋め合わせるのかも難しいのです。予算的な埋め合わせを考えずに消費税減税だけを実施すれば、元々余裕のない地方自治体の財政が破綻する可能性もあります。

上記のことを踏まえると、仮に消費税減税を実施するにしても「20年計画で2年ごとに1%づつ下げる」ような非常にゆっくりとした減税にするほか無く、緊急の経済対策として機能しうる物では無いです。

もし経済対策として行える可能性があるとしたら、消費税率を一度にゼロまで下げる事です。殆どのシステムは非課税(税率ゼロ)の取引を扱うことが出来るはずです。したがって税率をゼロにするならシステム改修は数ヶ月で済むと思われます。ただし、その数ヶ月間は個人消費が恐ろしく落ち込むので、同時に相当の財政出動を行わないと、多くの企業が破綻するでしょうけど。

.NET COREでLinuxで動作するサービスを作成する

.NET Core + C#でLinuxのDeamon作れないかなと思ったら、思ったより簡単に作れるようになっていたので覚え書き。Program.csとDaemonService.csの中味はほぼ定型なのでサンプルからそのまま流用します。

以下のサンプルは.NET Core 3.1で記述しています。

// Program.cs

using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace DaemonSample
{
    class Program
    {
        public static async Task Main(string[] args)
        {
            var builder = new HostBuilder()
                .ConfigureAppConfiguration((hostingContext, config) =>
                {
                    config.AddEnvironmentVariables();

                    if (args != null)
                    {
                        config.AddCommandLine(args);
                    }
                })
                .ConfigureServices((hostContext, services) =>
                {
                    services.AddOptions();
                    services.Configure<DaemonConfig>(hostContext.Configuration.GetSection("Daemon"));

                    services.AddSingleton<IHostedService, DaemonService>();
                })
                .ConfigureLogging((hostingContext, logging) => {
                    logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
                    logging.AddConsole();
                });

            await builder.RunConsoleAsync();
        }
    }
}
// DaemonService.cs

using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace DaemonSample
{
    class DaemonService : IHostedService, IDisposable
    {
        private readonly ILogger _logger;
        private readonly IOptions<DaemonConfig> _config;
        public DaemonService(ILogger<DaemonService> logger, IOptions<DaemonConfig> config)
        {
            _logger = logger;
            _config = config;
        }

        public Task StartAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation("Starting daemon: " + _config.Value.DaemonName);
            _logger.LogInformation("arg1:{0}", _config.Value.arg1);
            _logger.LogInformation("arg2:{0}", _config.Value.arg2);

            // ここでサーバー本体の処理をTaskとして起動します。

            return Task.CompletedTask;
        }

        public Task StopAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation("Stopping daemon.");
            return Task.CompletedTask;
        }

        public void Dispose()
        {
            _logger.LogInformation("Disposing....");
        }
    }
}
// DaemonConfig.cs

using System;
using System.Collections.Generic;
using System.Text;

namespace DaemonSample
{
    class DaemonConfig
    {
        public string DaemonName { get; set; }
        public string arg1{ get; set; }
        public string arg2{ get; set; }
    }
}

起動時のコマンドラインは下記の通り。コマンドライン引数の受け渡し方が非常に独特です。

/usr/bin/dotnet run --project deamonsample --configuration Release --Daemon:DaemonName="Sample Daemon" Daemon:arg1="argument 1" Daemon:arg2="argument 2"

Demonとして起動するにはsystemdを使用します。/etc/systemd/systemにdeamonsample.serviceファイルを作成し、下記の様に記述します。

[Unit]
Description=deamon sample
After=network.target

[Service]
ExecStart=/usr/bin/dotnet run --project atozipsrv --configuration Release --Daemon:DaemonName="deamonsample " Daemon:arg1="argument 1" Daemon:arg2="argument 2"
WorkingDirectory=/usr/src/deamonsample
Restart=always
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=atozip
Environment=DOTNET_CLI_HOME=/var/src/deamonsample

[Install]
WantedBy=multi-user.target

後は通常のsystemdのDeamon同様に以下のコマンドで起動します。

$ systemctl start deamonsample

参考:Creating a Daemon with .NET Core (Part 1)