# Japan Supplier Price Impact | 仕入価格改定照合 (`amycole/jp-supplier-price-impact`) Actor

仕入先の価格改定表を商品台帳と厳密照合し、原価・利益の変化と要確認理由をJSON/CSVへ。明示列指定CSV/Excel、既知PDF2様式対応。

- **URL**: https://apify.com/amycole/jp-supplier-price-impact.md
- **Developed by:** [amycole](https://apify.com/amycole) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$200.00 / 1,000 reconciled notice documents

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## 国内仕入価格改定・商品利益影響照合

仕入先から届いた価格改定表を商品台帳へ照合し、商品別の価格差・適用日・利益変化・要確認理由を JSON / CSV で返します。日本国内の EC・卸・小売の業務を自動化する開発者・代行者向けです。

**US$0.20／有効照合を含む通知1文書。商品行数への課金はありません。**

### 料金の数え方

- 最終結果に `matched` または `matched_cost_only` を1行以上含み、結果が保存された文書を1件とします。イベント名は `document-processed`。
- 全件が要確認、未照合、読取り失敗、または空の文書は文書料金0です。
- 一部の商品だけ照合できた通知も1文書です。付随する要確認行に追加料金はありません。
- 値上げがなく「変更なし」と確認できた文書、原価のみ計算できた文書も対象です。
- 起動料・Dataset行課金・プラットフォーム使用量の上乗せは設定しません。10文書なら文書料金は最大US$2です。
- 保存・課金済みの結果があれば、その後の別処理の失敗だけで料金が自動取消しになるわけではありません。新しい実行としてやり直すと、条件を満たす文書は再び課金対象です。
- 実行前に最大料金を設定してください。料金上限不足なら明示的に停止し、勝手に上限を上げません。課金状態は `BILLING` で確認できます。

### 対応範囲

| 入力 | 対応 |
|---|---|
| JSON | 明示した通知行と台帳行 |
| CSV | UTF-8/BOM、または指定したCP932。列対応必須 |
| XLSX | シート名・見出し行・列対応必須。数式は実行しない |
| テキストPDF | `teji_2025_08`、`hermosa_2026` の固定2様式のみ |

画像・スキャンOCR、汎用PDF、商品名だけの推測一致、未知の単位換算は対応しません。同じメーカーでも別レイアウトは保証しません。

入力上限は1ファイル5MB、PDF30ページ、10通知、台帳10,000行です。照合組み合わせ数にも上限があるため、上限エラー時は重複に注意して分割してください。任意URLや手元のパスを直接読み込む機能はありません。ファイルは `content_base64` に入れます。

### すぐ試す：架空の1通知

ApifyのInputをJSON表示にし、以下を入力してください。税抜・1個単位で旧原価100、新原価120、売価150、販売手数料10%、送料5。利益は30→10になります。このサンプルは有効照合を含み、文書料金US$0.20の対象です。実企業の取引条件ではありません。

```json
{
  "schema_version": "0.1",
  "margin_threshold": "0.2",
  "documents": [
    {
      "document_id": "D1",
      "supplier_id": "S1",
      "format": "rows",
      "defaults": {
        "price_basis": "purchase",
        "tax_basis": "exclusive",
        "tax_rate": "0.1",
        "units_per_price": "1",
        "base_unit": "piece",
        "currency": "JPY"
      },
      "rows": [
        {
          "mpn": "A",
          "name": "same",
          "old_price": "100",
          "new_price": "120",
          "effective_date": "2027-01-01"
        }
      ]
    }
  ],
  "ledger_rows": [
    {
      "row_id": "R1",
      "supplier_id": "S1",
      "mpn": "A",
      "name": "same",
      "cost": "100",
      "cost_tax_basis": "exclusive",
      "cost_units": "1",
      "sale": "150",
      "sale_tax_basis": "exclusive",
      "sale_units": "1",
      "currency": "JPY",
      "base_unit": "piece",
      "fee_rate": "0.1",
      "fee_basis": "net_sale",
      "shipping_net_per_base": "5"
    }
  ]
}
```

### 自分のファイルを入力する

通知の `format` を `csv` または `xlsx` とし、`rows` の代わりに `content_base64` と `columns` を指定します。台帳は `ledger_rows` と `ledger_file` のどちらか一方だけです。`columns` の左側は下記の契約フィールド名、右側は実際の見出し名です。JAN・品番・台帳行IDは文字列を使い、先頭0を保持してください。

```python
import base64, json
from pathlib import Path

def encoded(path):
    return base64.b64encode(Path(path).read_bytes()).decode("ascii")

payload = {
  "schema_version": "0.1",
  "documents": [{
    "document_id": "supplier-2027-01",
    "supplier_id": "S1",
    "format": "csv",
    "encoding": "utf-8-sig",
    "content_base64": encoded("notice.csv"),
    "columns": {"mpn": "品番", "old_price": "旧価格", "new_price": "新価格", "effective_date": "適用日"},
    "defaults": {"price_basis": "purchase", "tax_basis": "exclusive", "tax_rate": "0.1", "units_per_price": "1", "base_unit": "piece", "currency": "JPY"}
  }],
  "ledger_file": {
    "format": "csv",
    "encoding": "utf-8-sig",
    "content_base64": encoded("ledger.csv"),
    "columns": {"row_id": "台帳ID", "supplier_id": "仕入先", "mpn": "品番", "cost": "原価", "sale": "売価"},
    "defaults": {"cost_tax_basis": "exclusive", "cost_units": "1", "sale_tax_basis": "exclusive", "sale_units": "1", "base_unit": "piece", "currency": "JPY"}
  }
}
Path("input.json").write_text(json.dumps(payload, ensure_ascii=False), encoding="utf-8")
```

この例の税区分・入数・価格種別は仮の条件です。自社の原本に合わせて変更してください。XLSXの場合は `format: "xlsx"`、`sheet: "価格表"`、`header_row: 1` を指定し、base64にExcelを入れます。台帳側も同じ指定方法です。結合見出しや数式セルは、値を確定した別コピーにしてから利用してください。

PDFの場合は `format: "pdf"`、`profile: "teji_2025_08"` または `"hermosa_2026"`、`content_base64`、`document_id`、`supplier_id` を指定します。税・入数・適用日は確認済みの値だけを `defaults` へ入れます。メーカー原本は配布していません。

### 計算に必要な意味づけ

| フィールド | 意味 |
|---|---|
| supplier_id | 通知と台帳で同じ仕入先ID。同メーカーでも取引条件が異なれば分ける |
| price_basis | purchase＝仕入単価、list＝定価、retail＝販売価格 |
| tax_basis / cost_tax_basis / sale_tax_basis | exclusive＝税抜、inclusive＝税込。税込なら対応するtax_rateも明示 |
| units_per_price / cost_units / sale_units | 価格が何基準単位分か。10個箱価格なら10 |
| base_unit | piece等。異なる意味の単位を自動換算しない |
| purchase_factor / factor_basis | 定価・上代から原価換算する時の確認済み掛率と基準。例0.6とlist |
| fee_rate / fee_basis | 税抜売上に対する料率。非ゼロならfee_basis＝net_sale |
| shipping_net_per_base / fixed_fee_net_per_base | 税抜・基準単位あたりの費用。未指定0 |
| effective_date | YYYY-MM-DD。根拠のない日付を補完しない |

公開された定価は実際の仕入原価ではありません。利益は売価から原価と指定した費用を引いた商品単位の試算で、固定費・人件費等を含む会計上の純利益ではありません。未指定の送料・手数料を0と扱うので、実際の費用があれば入力してください。

### 出力と判断

`OUTPUT` は結果全体のJSONです。`results` に通知行、`documents` に文書の抽出結果、`ledger_unmatched` に台帳側未照合が入ります。Datasetは通知側の結果行です。全体を機械連携する場合はDatasetだけでなくOUTPUTを使ってください。

CSVは `ALL_RESULTS_CSV`、`REVIEWS_CSV`、`NOTICE_UNMATCHED_CSV`、`LEDGER_UNMATCHED_CSV` の4種類です。課金状態は別レコード `BILLING` です。

- `matched`：条件を満たす照合と利益試算。
- `matched_cost_only`：原価まで計算。売価がないなどの理由で利益は未算出。
- `review`：人の確認が必要。`reasons` を確認。
- `unmatched`：通知に対応する台帳が確認できない。
- `run_state: partial`：処理が動いても、確認事項や失敗文書が残る。成功ステータスをそのまま無人の台帳変更許可にしない。

`flags` の `loss_after_change`、`margin_below_threshold` は売価を検討する目印です。`row_id` で台帳へ戻せます。台帳側未照合を「改定なし」と解釈しないでください。CSVは式注入対策により文字列先頭へアポストロフィが付く場合があります。機械連携にはJSONを推奨します。

### よくある要確認・失敗

- `purchase_terms_required`：上代と原価を区別し、確認済み掛率を入力。
- `tax_basis_unknown` / `unit_mismatch_or_missing`：税・入数・単位を明示。
- `old_cost_mismatch`：既に改定済みか、仕入先や入数が違わないか確認。
- `identifier_conflict` / `ambiguous_ledger_match`：JANと品番の矛盾や台帳の重複を解消。名称で決めない。
- `missing_or_duplicate_header`：列名が完全一致するか、同名列がないか確認。
- `identifier_must_be_string`：識別子を文字列として保存。失われた先頭0は復元しない。
- `pdf_table_layout_changed`：対応外のPDF様式。明示列指定のCSVへ変換して利用。
- `comparison_limit_exceeded_split_batch`：同一商品・日付の重複に注意して分割。

### API・n8n

ApifyのAPIタブで同期OUTPUTエンドポイントを取得してください。HTTP POSTで入力JSONを送り、認証はHeader Authの `Authorization: Bearer <自分のAPIキー>` を使います。キーをURL・ワークフロー本文・問い合わせへ貼らないでください。

同期APIの指定例は `outputRecordKey=OUTPUT&timeout=120&memory=1024&maxTotalChargeUsd=0.2` です。これは課金対象1通知の例です。複数通知では料金を確認して上限を自分で指定してください。

n8nのHTTP Requestノードで実行後、`run_state`、`documents`、`results`、`ledger_unmatched` を分岐します。HTTP成功だけで全商品処理成功としないでください。自動再試行は推奨しません。通信切断時は先の実行が続いている可能性があるため、ApifyのRunsを確認してから再実行してください。新しい実行は別の課金単位です。

### データ・サポート・制限

入力と結果はApifyに保存されます。ゼロ保持ではなく、保持期間はアカウント設定等に従います。保存ID・取得リンクを第三者へ共有しないでください。n8nにも入力・結果が保存され得ます。機密資料を使う前に、利用権限と両サービスの保持・アクセス条件を確認してください。

外部LLM/OCRへの送信、任意URL取得、販売管理・台帳・ECの自動更新はありません。利用者自身が結果を確認して次工程へ渡します。

問い合わせはStoreのIssuesから、入力形式・エラー理由・バージョン・匿名化した最小例を送ってください。秘密情報や台帳全体は送らないでください。新しいPDF様式への無期限対応や応答時間保証はありません。

検証は公開PDF2様式と架空台帳、CSV/XLSX、実n8n接続で実施しています。任意PDFや実顧客の全データに対する精度、実際の時間短縮、継続利用は保証しません。入力契約は0.1です。新しい版へ切り替える場合は、利用者の代表入力で事前確認してください。

### English summary

Match Japanese supplier price revisions to a ledger using supplier-scoped exact JAN/product codes. Export effective dates, changes, review reasons and conditional purchase-cost/profit impact. Supports explicitly mapped CSV/XLSX, normalized JSON and only two named text-PDF profiles; no general OCR or fuzzy auto-matching.

Price: US$0.20 per saved notice document containing at least one `matched` or `matched_cost_only` row. All-review, unmatched-only, empty and extraction-failed documents have no document fee. No startup, per-row or usage surcharge. Unchanged-price valid matches are billable; mixed documents are billed once. A new successful run may be charged again. Set your run spending limit. Public list prices are not assumed to be actual purchase costs; explicit terms, tax and units are required.

Outputs are persisted on Apify, not zero-retention. No automated master updates. Treat storage IDs and result links as sensitive. Use the self-contained JSON sample above for your first run and inspect partial/error statuses before downstream use.

# Actor input Schema

## `schema_version` (type: `string`):

Input contract version. Use 0.1.

## `documents` (type: `array`):

1～10文書。formatはrows/csv/xlsx/pdf。ファイルはcontent_base64と列対応columnsを指定、Excelはsheetも必須。PDFはteji_2025_08/hermosa_2026のみ。URL自動取得なし。税・入数・価格種別は確認済みの値を入力。

## `ledger_rows` (type: `array`):

ledger_rowsまたはledger_fileの一方だけ。row_id/supplier_id/品番等は文字列。cost・税区分・入数・単位を明示します。売価省略時は原価のみ。

## `ledger_file` (type: `object`):

CSV/XLSXのcontent_base64とcolumns、XLSXはsheetを指定。使う場合はJSON入力でledger_rows項目を削除し、ledger_fileだけにしてください。作成例はこのActorのREADMEにあります。

## `margin_threshold` (type: `string`):

Contribution-margin threshold as a decimal string from 0 to 1. Example 0.2 means 20 percent.

## Actor input object example

```json
{
  "schema_version": "0.1",
  "documents": [
    {
      "document_id": "D1",
      "supplier_id": "S1",
      "format": "rows",
      "defaults": {
        "price_basis": "purchase",
        "tax_basis": "exclusive",
        "tax_rate": "0.1",
        "units_per_price": "1",
        "base_unit": "piece",
        "currency": "JPY"
      },
      "rows": [
        {
          "mpn": "A",
          "name": "same",
          "old_price": "100",
          "new_price": "120",
          "effective_date": "2027-01-01"
        }
      ]
    }
  ],
  "ledger_rows": [
    {
      "row_id": "R1",
      "supplier_id": "S1",
      "mpn": "A",
      "name": "same",
      "cost": "100",
      "cost_tax_basis": "exclusive",
      "cost_units": "1",
      "sale": "150",
      "sale_tax_basis": "exclusive",
      "sale_units": "1",
      "currency": "JPY",
      "base_unit": "piece",
      "fee_rate": "0.1",
      "fee_basis": "net_sale",
      "shipping_net_per_base": "5"
    }
  ],
  "margin_threshold": "0.2"
}
```

# Actor output Schema

## `output` (type: `string`):

Business results, document errors and unmatched ledger rows. Inspect run_state.

## `all_results_csv` (type: `string`):

All notice-result rows.

## `reviews_csv` (type: `string`):

Rows that require human review.

## `notice_unmatched_csv` (type: `string`):

Notice rows without an exact ledger match.

## `ledger_unmatched_csv` (type: `string`):

Ledger rows not confirmed by this input.

## `billing` (type: `string`):

Eligible-document count and billing state; excludes credentials.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "documents": [
        {
            "document_id": "D1",
            "supplier_id": "S1",
            "format": "rows",
            "defaults": {
                "price_basis": "purchase",
                "tax_basis": "exclusive",
                "tax_rate": "0.1",
                "units_per_price": "1",
                "base_unit": "piece",
                "currency": "JPY"
            },
            "rows": [
                {
                    "mpn": "A",
                    "name": "same",
                    "old_price": "100",
                    "new_price": "120",
                    "effective_date": "2027-01-01"
                }
            ]
        }
    ],
    "ledger_rows": [
        {
            "row_id": "R1",
            "supplier_id": "S1",
            "mpn": "A",
            "name": "same",
            "cost": "100",
            "cost_tax_basis": "exclusive",
            "cost_units": "1",
            "sale": "150",
            "sale_tax_basis": "exclusive",
            "sale_units": "1",
            "currency": "JPY",
            "base_unit": "piece",
            "fee_rate": "0.1",
            "fee_basis": "net_sale",
            "shipping_net_per_base": "5"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("amycole/jp-supplier-price-impact").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "documents": [{
            "document_id": "D1",
            "supplier_id": "S1",
            "format": "rows",
            "defaults": {
                "price_basis": "purchase",
                "tax_basis": "exclusive",
                "tax_rate": "0.1",
                "units_per_price": "1",
                "base_unit": "piece",
                "currency": "JPY",
            },
            "rows": [{
                    "mpn": "A",
                    "name": "same",
                    "old_price": "100",
                    "new_price": "120",
                    "effective_date": "2027-01-01",
                }],
        }],
    "ledger_rows": [{
            "row_id": "R1",
            "supplier_id": "S1",
            "mpn": "A",
            "name": "same",
            "cost": "100",
            "cost_tax_basis": "exclusive",
            "cost_units": "1",
            "sale": "150",
            "sale_tax_basis": "exclusive",
            "sale_units": "1",
            "currency": "JPY",
            "base_unit": "piece",
            "fee_rate": "0.1",
            "fee_basis": "net_sale",
            "shipping_net_per_base": "5",
        }],
}

# Run the Actor and wait for it to finish
run = client.actor("amycole/jp-supplier-price-impact").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "documents": [
    {
      "document_id": "D1",
      "supplier_id": "S1",
      "format": "rows",
      "defaults": {
        "price_basis": "purchase",
        "tax_basis": "exclusive",
        "tax_rate": "0.1",
        "units_per_price": "1",
        "base_unit": "piece",
        "currency": "JPY"
      },
      "rows": [
        {
          "mpn": "A",
          "name": "same",
          "old_price": "100",
          "new_price": "120",
          "effective_date": "2027-01-01"
        }
      ]
    }
  ],
  "ledger_rows": [
    {
      "row_id": "R1",
      "supplier_id": "S1",
      "mpn": "A",
      "name": "same",
      "cost": "100",
      "cost_tax_basis": "exclusive",
      "cost_units": "1",
      "sale": "150",
      "sale_tax_basis": "exclusive",
      "sale_units": "1",
      "currency": "JPY",
      "base_unit": "piece",
      "fee_rate": "0.1",
      "fee_basis": "net_sale",
      "shipping_net_per_base": "5"
    }
  ]
}' |
apify call amycole/jp-supplier-price-impact --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,amycole/jp-supplier-price-impact"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/BrudtKpz2rtY5IZ8m/builds/ks3MAyfpWCbejDfpc/openapi.json
