iDempiere 売上請求伝票入金スケジュールの使い方|販売管理 操作マニュアル・技術仕様
📖 販売管理の全体像: 販売管理の全体図 も合わせてご覧ください。
売上請求伝票入金スケジュールは、未入金の売上請求伝票に対して 分割入金の期日と金額を確認・修正する ためのウィンドウです。スケジュールは支払条件から自動生成されますが、個別交渉で入金予定が変わった場合にこの画面で調整できます。
📌 ポイント: スケジュールの金額を変更すると「有効」フラグが自動的に外れます。「バリデート」ボタンで各行の合計と請求伝票の総合計を突き合わせ、一致して初めて有効になります。合計が合わないままだと入金消込で不整合の原因になります。
売上請求伝票入金スケジュールでできること
Section titled “売上請求伝票入金スケジュールでできること”- 未入金の売上請求伝票の抽出と確認
- 支払条件から自動生成された分割入金スケジュールの参照
- 各回の支払期日・満期支払金額の手修正
- 割引日付・割引金額の確認と調整
- スケジュール行の追加・削除による分割回数の変更
- バリデートによる「総合計=各回合計」の検証
- 請求伝票側の「支払スケジュール完成」フラグの更新
入金スケジュールは 2 タブ構成です。ヘッダーは請求伝票の参照用で、実質的な編集は明細タブで行います。
| タブ名 | テーブル | 項目数 | 役割 |
|---|---|---|---|
| 売上請求伝票 | C_Invoice | 18項目 | 未入金請求伝票の選択・内容確認 |
| 入金スケジュール | C_InvoicePaySchedule | 10項目 | 各回の期日・金額・割引の編集 |
graph TD
subgraph "売上請求伝票入金スケジュール(Window ID: 275)"
T1["🧾 売上請求伝票<br/>C_Invoice<br/>18項目<br/>(未入金伝票の選択)"]
T2[" └ 入金スケジュール<br/> C_InvoicePaySchedule<br/> 10項目"]
end
T1 --> T2
💡 ヒント: このウィンドウの請求伝票タブは 未入金の伝票のみ を対象にした選択用ビューです。請求内容そのものの編集は売上請求書画面で行ってください。
基本操作手順
Section titled “基本操作手順”graph TD
A["🚀 メニューから開く<br/>販売管理 > 売上請求管理 > 売上請求伝票入金スケジュール"] --> B["🔍 対象の売上請求伝票を選択<br/>(未入金の伝票のみ表示)"]
B --> C["📋 入金スケジュールタブへ移動"]
C --> D{"スケジュールは存在する?"}
D -->|ない| E["⚠️ 支払条件に分割設定がない<br/>支払条件マスタを確認"]
D -->|ある| F["✏️ 支払期日・満期支払金額を修正"]
F --> G["💾 保存<br/>(有効フラグが自動で外れる)"]
G --> H["✅ バリデートボタンを実行"]
H --> I{"総合計と一致?"}
I -->|不一致| J["❌ 差額メッセージを表示<br/>有効フラグ = OFF のまま"]
J --> F
I -->|一致| K["✔️ 有効フラグ = ON<br/>支払スケジュール完成 = ON"]
K --> L["💰 入出金管理で消込"]
アクセス方法(メニューパス)
Section titled “アクセス方法(メニューパス)”メニューから「販売管理 > 売上請求管理 > 売上請求伝票入金スケジュール」を開きます。
入金スケジュールの確認
Section titled “入金スケジュールの確認”- 請求伝票タブで対象の伝票を検索(伝票番号・取引先・請求日付 など)
- 支払条件・総合計・支払スケジュール完成 フラグを確認
- 「入金スケジュール」タブへ移動し、各回の内容を確認:
- 支払期日: 入金予定日
- 満期支払金額: その回の入金予定額
- 割引日付 / 割引金額: 早期入金割引の適用条件
- 有効: 合計が総合計と一致しているか
入金スケジュールの修正
Section titled “入金スケジュールの修正”- 「入金スケジュール」タブで修正したい行を選択
- 支払期日 または 満期支払金額 を変更
- 「保存」をクリック
- ヘッダーの「バリデート」ボタンを実行して整合性を確認
⚠️ 注意: 満期支払金額(
DueAmt)を変更すると、保存時に「有効」フラグが自動的にfalseになります(MInvoicePaySchedule.beforeSave())。金額調整後は必ずバリデートを実行し、有効フラグを回復させてください。
分割回数の変更
Section titled “分割回数の変更”- 回数を増やす場合: 「新規」で行を追加し、支払期日・満期支払金額・割引日付を入力
- 回数を減らす場合: 不要な行を削除
- 全行の満期支払金額の合計が請求伝票の 総合計 と一致するように調整
- 「バリデート」を実行
💡 ヒント: 端数がある場合は最終回で吸収するのが定石です。1 円でも合計がずれると有効になりません。
バリデートの結果メッセージ
Section titled “バリデートの結果メッセージ”| 結果 | 表示メッセージ | 状態 |
|---|---|---|
| 一致 | OK | 各行の有効=ON、請求伝票の支払スケジュール完成=ON |
| 不一致 | 総合計・合計・差額を表示 | 各行の有効=OFF、支払スケジュール完成=OFF |
項目リファレンス
Section titled “項目リファレンス”売上請求伝票タブ(主要項目)
Section titled “売上請求伝票タブ(主要項目)”| 項目名 | カラム | 必須 | 型 | 説明 |
|---|---|---|---|---|
| 伝票番号 | DocumentNo | 必須 | 文字列 | 請求伝票番号 |
| 伝票タイプ | C_DocType_ID | 必須 | 選択 | 売上請求・貸方メモ等 |
| 伝票状態 | DocStatus | 必須 | リスト | 完了・締切等の伝票状態 |
| 請求日付 | DateInvoiced | 必須 | 日付 | 期日計算の起算日 |
| 取引先 | C_BPartner_ID | 必須 | 選択 | 請求先 |
| 取引先住所 | C_BPartner_Location_ID | 必須 | 選択 | 請求先住所 |
| 支払方法 | PaymentRule | 必須 | リスト | 掛売・口座振替等 |
| 支払条件 | C_PaymentTerm_ID | 必須 | 選択 | スケジュール生成の元 |
| 通貨 | C_Currency_ID | 必須 | 選択 | 請求通貨 |
| 明細行合計 | TotalLines | 必須 | 金額 | 明細金額の合計 |
| 総合計 | GrandTotal | 必須 | 金額 | 税込の請求総額(突合の基準) |
| 支払スケジュール完成 | IsPayScheduleValid | 必須 | チェック | スケジュールが妥当か |
| 社内担当者 | SalesRep_ID | - | 選択 | 営業担当 |
| 受注伝票 | C_Order_ID | - | 選択 | 元の受注伝票 |
入金スケジュールタブ
Section titled “入金スケジュールタブ”| 項目名 | カラム | 必須 | 型 | 説明 |
|---|---|---|---|---|
| 売上請求伝票 | C_Invoice_ID | 必須 | 選択 | 親(請求伝票) |
| 支払スケジュール | C_PaySchedule_ID | - | 選択 | 生成元の支払スケジュール定義 |
| 支払期日 | DueDate | 必須 | 日付 | 入金予定日 |
| 満期支払金額 | DueAmt | 必須 | 金額 | その回の入金予定額(識別子) |
| 割引日付 | DiscountDate | 必須 | 日付 | 割引適用の最終日 |
| 割引金額 | DiscountAmt | 必須 | 金額 | 割引額 |
| バリデート | Processing | - | ボタン | スケジュールの検証実行 |
| 有効 | IsValid | 必須 | チェック | 合計が総合計と一致しているか |
| 有効(アクティブ) | IsActive | 必須 | チェック | 行の有効/無効 |
支払条件からの生成フロー
Section titled “支払条件からの生成フロー”graph TD
A["支払条件<br/>C_PaymentTerm"] --> B["支払スケジュール定義<br/>C_PaySchedule<br/>割合・ネット日数・割引"]
B --> C["売上請求伝票の完了<br/>C_Invoice"]
C --> D["入金スケジュール生成<br/>C_InvoicePaySchedule"]
D --> E["この画面で期日・金額を調整"]
E --> F["バリデート<br/>総合計と突合"]
F --> G["支払スケジュール完成 = ON"]
G --> H["入出金管理で消込<br/>C_Payment / C_AllocationHdr"]
よくある質問(FAQ)
Section titled “よくある質問(FAQ)”Q. 入金スケジュールが 1 行も表示されません。
Section titled “Q. 入金スケジュールが 1 行も表示されません。”請求伝票に適用された支払条件に分割スケジュール(C_PaySchedule)が定義されていない可能性が高いです。単純な期日払いの支払条件では、請求伝票に期日がセットされるだけでスケジュール明細は生成されません。分割入金にしたい場合は支払条件のスケジュールタブで各回の割合を定義してください。
Q. 金額を直しただけで「有効」が外れました。
Section titled “Q. 金額を直しただけで「有効」が外れました。”仕様です。MInvoicePaySchedule.beforeSave() は DueAmt の変更を検知すると IsValid=false をセットします。金額を触った以上、合計の妥当性は再検証が必要という考え方です。修正後に「バリデート」を実行してください。
Q. バリデートで差額が出ます。どこを直せばよいですか?
Section titled “Q. バリデートで差額が出ます。どこを直せばよいですか?”エラーメッセージに「総合計」「合計」「差額」が表示されます。差額分をいずれかの行(通常は最終回)の満期支払金額に加減して合計を総合計に一致させてください。判定は invoice.getGrandTotal().compareTo(total) == 0 と厳密な一致比較のため、1 円のずれも許容されません。
Q. 支払スケジュール完成フラグは何に影響しますか?
Section titled “Q. 支払スケジュール完成フラグは何に影響しますか?”請求伝票の IsPayScheduleValid は、支払期日を単一の期日で扱うか分割スケジュールで扱うかの判断に使われます。フラグが立っていないと、分割スケジュールが正しく認識されず、督促(Dunning)や入金予定の集計が意図しない結果になる可能性があります。
Q. スケジュール行を削除したらどうなりますか?
Section titled “Q. スケジュール行を削除したらどうなりますか?”MInvoicePaySchedule.afterDelete() が親請求伝票の validatePaySchedule() を呼び出し、残った行の合計で妥当性を再判定して請求伝票を保存します。合計が総合計と合わなくなれば IsPayScheduleValid は自動的に外れます。
Q. 期日は何を起点に計算されますか?
Section titled “Q. 期日は何を起点に計算されますか?”自動生成時は 請求日付(DateInvoiced) が起点です。支払期日 = 請求日付 + ネット日数、割引日付 = 請求日付 + 割引日数 として計算されます(MInvoicePaySchedule の親コンストラクタ)。納品後払いなど別の起算日を使いたい場合は支払条件側で設定します。
- 売上請求書(Sales Invoice)の使い方
- 支払条件(Payment Term)の使い方
- 入出金伝票(Payment)の使い方
- 取引先マスタ(Business Partner)の使い方
- 請求スケジュールの使い方
- 画面リファレンス: 売上請求伝票入金スケジュール
🛠 技術仕様(開発者向け)
売上請求伝票入金スケジュールはトランザクション編集型のウィンドウ(AD_Window_ID: 275)で、ヘッダーが C_Invoice(未入金伝票の選択用)、明細が C_InvoicePaySchedule です。C_InvoicePaySchedule は AccessLevel=1(組織レベル)/IsDeleteable=Y。ビジネスロジックは MInvoicePaySchedule(259行)が担い、検証プロセスは InvoicePayScheduleValidate(96行)です。スケジュール行そのものは DocStatus / DocAction を持たない非 Document 型で、状態は IsValid フラグで表現されます。
アーキテクチャ概要
Section titled “アーキテクチャ概要”classDiagram
class MInvoicePaySchedule {
+getInvoicePaySchedule(Properties, int, int, String) MInvoicePaySchedule[]$
+MInvoicePaySchedule(MInvoice, MPaySchedule)
+getParent() MInvoice
+setParent(MInvoice) void
#beforeSave(boolean) boolean
#afterSave(boolean, boolean) boolean
#afterDelete(boolean) boolean
}
class X_C_InvoicePaySchedule {
<<generated>>
}
class PO {
<<abstract>>
}
class InvoicePayScheduleValidate {
<<SvrProcess>>
#doIt() String
}
MInvoicePaySchedule --|> X_C_InvoicePaySchedule
X_C_InvoicePaySchedule --|> PO
MInvoicePaySchedule --> MInvoice : parent
MInvoicePaySchedule --> MPaySchedule : template
MPaymentTerm --> MInvoicePaySchedule : generates
InvoicePayScheduleValidate --> MInvoicePaySchedule : validates
パッケージ: org.compiere.model / org.compiere.process
ソースファイル:
org.adempiere.base/src/org/compiere/model/MInvoicePaySchedule.javaorg.adempiere.base.process/src/org/compiere/process/InvoicePayScheduleValidate.java
関連DBテーブル
Section titled “関連DBテーブル”C_InvoicePaySchedule(売上請求伝票入金スケジュール)
Section titled “C_InvoicePaySchedule(売上請求伝票入金スケジュール)”| カラム名 | 型 | 必須 | 説明 | 備考 |
|---|---|---|---|---|
| C_InvoicePaySchedule_ID | ID | PK | スケジュールID | 主キー |
| C_InvoicePaySchedule_UU | UUID | N | UUID | |
| AD_Client_ID | Table Direct | Y | クライアント | default @AD_Client_ID@ |
| AD_Org_ID | Table Direct | Y | 組織 | default @AD_Org_ID@ |
| C_Invoice_ID | Search | Y | 請求伝票FK | 親(IsParent=Y) |
| C_PaySchedule_ID | Table Direct | N | 支払スケジュール定義 | 生成元テンプレート |
| DueDate | Date | Y | 支払期日 | 請求日付+ネット日数 |
| DueAmt | Amount | Y | 満期支払金額 | 識別子。変更で IsValid=N |
| DiscountDate | Date | Y | 割引日付 | 識別子。請求日付+割引日数 |
| DiscountAmt | Amount | Y | 割引金額 | |
| IsValid | Yes-No | Y | 有効 | 合計=総合計のとき Y |
| IsActive | Yes-No | Y | アクティブ | default Y |
| Processing | Button | N | バリデート | InvoicePayScheduleValidate を起動 |
| Processed | Yes-No | Y | 処理済み |
erDiagram
C_PaymentTerm ||--o{ C_PaySchedule : "defines schedule"
C_PaymentTerm ||--o{ C_Invoice : "applied to"
C_PaySchedule ||--o{ C_InvoicePaySchedule : "template of"
C_Invoice ||--o{ C_InvoicePaySchedule : "payment schedule"
C_Invoice ||--o{ C_InvoiceLine : "lines"
C_Invoice }o--|| C_BPartner : "bill to"
C_Invoice ||--o{ C_AllocationLine : "allocated payments"
ビジネスロジック
Section titled “ビジネスロジック”スケジュールの生成(親コンストラクタ)
Section titled “スケジュールの生成(親コンストラクタ)”MInvoicePaySchedule(MInvoice invoice, MPaySchedule paySchedule) が各回のレコードを組み立てます。
- 端数処理の精度:
MCurrency.getStdPrecision()で請求通貨の標準精度を取得 - 総合計が 0 の場合:
DueAmt = 0/DiscountAmt = 0/IsValid = false - 通常の場合:
DueAmt = GrandTotal × Percentage ÷ 100(RoundingMode.HALF_UP)DiscountAmt = DueAmt × Discount ÷ 100(同上)IsValid = true
- 日付:
DueDate = DateInvoiced + NetDaysDiscountDate = DateInvoiced + DiscountDays
beforeSave()
Section titled “beforeSave()”if (is_ValueChanged("DueAmt")) { setIsValid(false);}return true;満期支払金額が変更された時点で無条件に IsValid=false を立て、再検証を強制します。
afterSave() / afterDelete()
Section titled “afterSave() / afterDelete()”新規作成、または DueAmt / IsActive が変更された場合に、親請求伝票の validatePaySchedule() を呼び出して IsPayScheduleValid を再判定し、saveEx() します。削除時も同じ処理が無条件で走ります。
flowchart TD
A["スケジュール行を保存"] --> B{"DueAmt 変更?"}
B -->|Yes| C["beforeSave: IsValid = false"]
B -->|No| D["そのまま"]
C --> E["DB 更新"]
D --> E
E --> F{"新規 or DueAmt/IsActive 変更?"}
F -->|Yes| G["getParent → MInvoice"]
G --> H["invoice.validatePaySchedule"]
H --> I["invoice.saveEx<br/>IsPayScheduleValid 更新"]
F -->|No| J["何もしない"]
getInvoicePaySchedule()(静的取得)
Section titled “getInvoicePaySchedule()(静的取得)”IsActive='Y' の行を ORDER BY DueDate で取得します。引数は 2 通りの指定に対応しています。
C_Invoice_ID != 0: その請求伝票のスケジュール全件C_Invoice_ID == 0: 指定したC_InvoicePaySchedule_IDと 同じ請求伝票に属する 全件(EXISTS サブクエリ)
後者は、プロセスがボタン押下行の ID しか受け取れない状況で兄弟行をまとめて取得するための実装です。
InvoicePayScheduleValidate(バリデートプロセス)
Section titled “InvoicePayScheduleValidate(バリデートプロセス)”MInvoicePaySchedule[] schedule = MInvoicePaySchedule.getInvoicePaySchedule(getCtx(), 0, getRecord_ID(), null);if (schedule.length == 0) throw new IllegalArgumentException("InvoicePayScheduleValidate - No Schedule");MInvoice invoice = new MInvoice(getCtx(), schedule[0].getC_Invoice_ID(), null);...BigDecimal total = Env.ZERO;for (int i = 0; i < schedule.length; i++) { BigDecimal due = schedule[i].getDueAmt(); if (due != null) total = total.add(due);}boolean valid = invoice.getGrandTotal().compareTo(total) == 0;invoice.setIsPayScheduleValid(valid);invoice.saveEx();for (int i = 0; i < schedule.length; i++) { if (schedule[i].isValid() != valid) { schedule[i].setIsValid(valid); schedule[i].saveEx(); }}処理の要点:
- 押下行と同じ請求伝票のスケジュールを全件取得(0 件なら例外)
DueAmtを合算(nullはスキップ)- 請求伝票の
GrandTotalと 厳密一致(compareTo == 0)で判定 - 判定結果を請求伝票の
IsPayScheduleValidと各行のIsValidへ反映 - 不一致時は
@GrandTotal@ = X <> @Total@ = Y - @Difference@ = Zを返却
⚠️ 注意: このプロセスは
trxNameにnullを渡してMInvoiceを読み書きします(自動コミット)。ロールバック前提の一括処理から呼び出す場合は、トランザクション境界に注意してください。
拡張ポイント(カスタマイズ箇所)
Section titled “拡張ポイント(カスタマイズ箇所)”OSGi Model Validator(推奨)
Section titled “OSGi Model Validator(推奨)”public class CustomInvoicePayScheduleValidator implements ModelValidator { @Override public int modelChange(PO po, int type) throws Exception { if (po instanceof MInvoicePaySchedule) { MInvoicePaySchedule sched = (MInvoicePaySchedule) po; if (type == TYPE_BEFORE_NEW || type == TYPE_BEFORE_CHANGE) { // 例: 支払期日を請求日付より前にできないようにする MInvoice inv = sched.getParent(); if (sched.getDueDate().before(inv.getDateInvoiced())) { throw new AdempiereException("支払期日は請求日付以降にしてください"); } } } return null; }
@Override public String docValidate(PO po, int timing) { // 請求伝票の完了時にスケジュール妥当性を強制したい場合はここで判定 if (po instanceof MInvoice && timing == TIMING_BEFORE_COMPLETE) { MInvoice inv = (MInvoice) po; if (!inv.isPayScheduleValid() && MInvoicePaySchedule.getInvoicePaySchedule(inv.getCtx(), inv.getC_Invoice_ID(), 0, inv.get_TrxName()).length > 0) { return "入金スケジュールの合計が総合計と一致していません"; } } return null; }}Callout
Section titled “Callout”C_InvoicePaySchedule の各カラムには標準の Callout が設定されていません(gw_column.tsv の callout 列がすべて空)。入力中に残差を即時表示したい場合などは IColumnCallout を OSGi サービスとして実装します。
スケジュール生成ロジックの拡張
Section titled “スケジュール生成ロジックの拡張”自動生成は支払条件側(MPaymentTerm.apply(MInvoice))が担っており、この画面は生成済みデータの編集に特化しています。生成ルール自体(例: 取引先グループ別の分割回数)を変えたい場合は、C_Invoice の TIMING_AFTER_COMPLETE で C_InvoicePaySchedule を再構築する Model Validator を実装するのが安全です。
関連プロセス
Section titled “関連プロセス”| プロセス名 | 実装クラス | 説明 |
|---|---|---|
| バリデート(Validate Payment Schedule) | InvoicePayScheduleValidate(96行) | 各回合計と総合計の突合、IsValid の更新 |
| 受注側の同等プロセス | OrderPayScheduleValidate | 受注伝票の支払スケジュール検証 |
関連ドキュメント
Section titled “関連ドキュメント”iDempiereカスタマイズのご相談
Section titled “iDempiereカスタマイズのご相談”分割入金は取引先ごとの個別交渉が入りやすく、標準の「合計一致」検証だけでは運用が回りきらないことがあります。期日ルールの自動化や入金予定表との連携は、Model Validator による拡張で無理なく実現できます。
As-Link株式会社では、OSGiプラグインによる安全なカスタマイズを提供しています。