iDempiere 経費精算伝票(顧客請求前チェック)の使い方|取引先管理 操作マニュアル・技術仕様
This content is not available in your language yet.
📖 取引先管理の全体像: 取引先管理の全体図 も合わせてご覧ください。
経費精算伝票(Expenses (to be invoiced))は、顧客へまだ請求していない経費・作業時間の明細を、取引先ごとに一覧して確認・修正する照会ウィンドウです。経費報告(Expense Report)から起票された明細のうち、受注伝票がまだ生成されていないものだけが表示されます。
📌 ポイント: このウィンドウは新規の経費を入力する画面ではありません。入力は 経費報告(Expense Report) で行い、こちらは顧客請求へ回す直前の最終チェックに使います。請求価格(
PriceInvoiced)や品目をここで直しておくと、受注伝票生成の結果が正しくなります。
経費精算伝票でできること
Section titled “経費精算伝票でできること”- 顧客へ未請求の経費・作業時間明細を、取引先(得意先)ごとに絞って確認する
- 明細ごとの請求品目(
M_Product_ID)・数量・請求価格を請求前に修正する - 時間単位レポート(
IsTimeReport)と実費経費を区別して確認する - 請求対象の経費金額・換算金額・請求済数量を照会する
- 取引先タブで価格表・支払条件・債権債務残高を確認し、請求条件を事前に検証する
- プロジェクト・フェーズ・タスク・営業活動への紐付けを確認・修正する
親子2タブ構成です。親タブで請求先の取引先を選び、子タブでその取引先の未請求明細を見る、という流れになります。
| タブ名 | テーブル | 項目数 | 役割 |
|---|---|---|---|
| 経費精算伝票 | C_BPartner | 7項目 | 請求対象の得意先を選択(価格表・支払条件・残高を確認) |
| 経費精算伝票明細 | S_TimeExpenseLine | 28項目 | 当該取引先の未請求経費・作業時間明細を照会・修正 |
💡 ヒント: 親タブは取引先マスタ(
C_BPartner)そのものですが、この画面では得意先(IsCustomer)で請求対象となるものに絞った選択用ビューとして機能します。取引先マスタ全体の編集は 取引先マスタ で行ってください。
基本操作手順
Section titled “基本操作手順”graph TD
A["🚀 メニューから開く<br/>取引先管理 > サービス > 経費精算伝票"] --> B["🔍 経費精算伝票タブで<br/>請求対象の得意先を選択"]
B --> C["📋 経費精算伝票明細タブへ移動<br/>未請求の明細一覧を表示"]
C --> D{"明細の内容は正しいか"}
D -->|修正が必要| E["✏️ 品目・数量・請求価格<br/>(PriceInvoiced)を修正"]
D -->|問題なし| F["✅ 請求内容を確定"]
E --> G["💾 保存<br/>(金額が自動再計算される)"]
G --> F
F --> H["🧾 受注伝票の生成処理へ<br/>(経費からの受注生成)"]
アクセス方法(メニューパス)
Section titled “アクセス方法(メニューパス)”メニューから「取引先管理 > サービス > 経費精算伝票」を開きます(AD_Window_ID: 242)。
確認・修正の手順
Section titled “確認・修正の手順”- 「経費精算伝票」タブで請求先の得意先を検索・選択します
- 検索キー / 名称: 取引先の特定に使用
- 価格表: 請求時に適用される売価表
- 支払条件: 請求書に引き継がれる支払条件
- 債権債務残高: 現在の与信状況の確認に使用
- 「経費精算伝票明細」タブに移動し、未請求明細を確認します
- 必要に応じて明細を修正します
- 品目: 請求する品目・サービス
- 数量 / 数量単位: 請求数量
- 請求額(
InvoicePrice): 請求単価。0の場合は価格表の既定価格が使用されます - 説明 / メモ: 請求書に載せる補足
- 「保存」をクリックします
- 保存時に換算金額(
ConvertedAmt)と行合計(LineNetAmt)が自動再計算されます
- 保存時に換算金額(
- 内容確定後、経費から受注伝票を生成する処理を実行します
⚠️ 注意: 親の経費報告(
S_TimeExpense)が既に処理済み(Processed=Y)の場合、その報告に新しい明細を追加することはできません。MTimeExpenseLine.beforeSave()が「ParentComplete」エラーで保存を拒否します。
項目リファレンス
Section titled “項目リファレンス”経費精算伝票タブ(C_BPartner)
Section titled “経費精算伝票タブ(C_BPartner)”| 項目名 | 必須 | 型 | 説明 |
|---|---|---|---|
| 検索キー | 必須 | 文字列 | 取引先コード(一意) |
| 名称 | 必須 | 文字列 | 取引先名 |
| 読み方 | - | 文字列 | 補助名称(カナ等) |
| 得意先 | 必須 | チェック | 得意先かどうか |
| 価格表 | - | 選択 | 請求時に適用する価格表 |
| 支払条件 | - | 選択 | 請求書に適用される支払条件 |
| 債権債務残高 | - | 金額 | 基軸通貨換算の未決済残高 |
経費精算伝票明細タブ(S_TimeExpenseLine)主要項目
Section titled “経費精算伝票明細タブ(S_TimeExpenseLine)主要項目”| 項目名 | 必須 | 型 | 説明 |
|---|---|---|---|
| 経費報告 | 必須 | 検索 | 親となる経費報告(S_TimeExpense) |
| 明細番号 | 必須 | 整数 | 伝票内の一意な行番号(既定は最大値+10) |
| 作業日付 | 必須 | 日付 | 経費・作業の発生日 |
| 取引先 | - | 検索 | 請求先の取引先 |
| 品目 | - | 検索 | 請求対象の品目・サービス |
| 数量 | - | 数量 | 請求数量(既定 1) |
| 数量単位 | - | 選択 | 数量の単位 |
| 経費金額 | - | 金額 | 1単位あたりの経費額 |
| 通貨 | - | 選択 | 経費金額の通貨 |
| 換算金額 | - | 金額 | 報告通貨へ換算した金額(自動計算) |
| 請求額 | - | 単価 | 請求単価。0 で価格表の既定価格を使用 |
| 請求価格 | - | 単価 | 得意先の売価表通貨での請求価格 |
| 請求済数量 | - | 数量 | 既に請求済みの数量 |
| 時間タイプ | - | 選択 | 作業時間の分類(S_TimeType) |
| 時間単位レポート | 必須 | チェック | ON の場合は時間のみの記録(金額は 0 に強制) |
| 請求済み | 必須 | チェック | 請求済みかどうか |
| 受注明細 | - | 検索 | 生成された受注伝票明細への参照 |
| 処理済み | 必須 | チェック | 親伝票が処理済みか |
| プロジェクト | - | 選択 | 紐付け先プロジェクト |
業務フロー上の位置づけ
Section titled “業務フロー上の位置づけ”graph TD
A["経費報告<br/>S_TimeExpense"] --> B["経費明細<br/>S_TimeExpenseLine"]
B --> C{"顧客に請求するか"}
C -->|請求する| D["経費精算伝票<br/>(本ウィンドウ)で内容確認"]
C -->|社内負担| E["経費(未払い)で<br/>従業員へ精算"]
D --> F["受注伝票の生成"]
F --> G["売上請求伝票"]
G --> H["入金消込"]
よくある質問(FAQ)
Section titled “よくある質問(FAQ)”Q. 明細を新規追加しようとすると「ParentComplete」エラーになります
Section titled “Q. 明細を新規追加しようとすると「ParentComplete」エラーになります”親の経費報告(S_TimeExpense)が既に処理済み(Processed=Y)になっています。MTimeExpenseLine.beforeSave() は、新規行の追加時に親伝票が処理済みかどうかを確認し、処理済みなら保存を拒否します。追加が必要な場合は、新しい経費報告を起票してください。
Q. 「時間単位レポート」にチェックを入れると金額が消えるのはなぜですか?
Section titled “Q. 「時間単位レポート」にチェックを入れると金額が消えるのはなぜですか?”beforeSave() の仕様です。IsTimeReport=Y の明細は「作業時間のみの記録で費用を伴わない」という位置づけのため、経費金額(ExpenseAmt)・換算金額(ConvertedAmt)・行合計(LineNetAmt)が強制的に 0 にセットされます。金額を計上したい場合はチェックを外してください。
Q. 換算金額(ConvertedAmt)はいつ再計算されますか?
Section titled “Q. 換算金額(ConvertedAmt)はいつ再計算されますか?”新規登録時、または経費金額(ExpenseAmt)か通貨(C_Currency_ID)が変更されたときに beforeSave() で再計算されます。明細の通貨と報告通貨が同じ場合は経費金額がそのまま入り、異なる場合は MConversionRate.convert() により作業日付(DateExpense)時点のレートで換算されます。
Q. 行合計(LineNetAmt)はどう計算されますか?
Section titled “Q. 行合計(LineNetAmt)はどう計算されますか?”経費金額 × 数量 です。新規登録時、または数量(Qty)・経費金額(ExpenseAmt)が変更されたときに自動再計算されます。手入力しても保存時に上書きされます。
Q. 「経費(未払い)」ウィンドウとの違いは何ですか?
Section titled “Q. 「経費(未払い)」ウィンドウとの違いは何ですか?”本ウィンドウは顧客への請求が目的で、受注伝票がまだ生成されていない明細を対象にします。一方 経費(未払い) は**従業員・仕入先への精算(立替金の払い戻し)**が目的で、仕入請求伝票が未生成の明細を対象にします。同じ S_TimeExpenseLine を別の切り口で見ています。
🛠 技術仕様(開発者向け)
経費精算伝票(AD_Window_ID: 242)は照会・修正型のウィンドウで、親タブに C_BPartner、子タブに S_TimeExpenseLine を持ちます。実体テーブルの新規作成は行わず、経費報告(S_TimeExpense)から起票済みの明細を「顧客未請求」という条件で絞り込んで表示します。明細のロジックは MTimeExpenseLine クラス(360行)が担い、金額計算・リソースアサイン同期・ヘッダー金額の更新を行います。親ヘッダーの MTimeExpense(613行)が伝票処理(DocAction / DocStatus)を持ちますが、このウィンドウには伝票アクションのフィールドは含まれません。
アーキテクチャ概要
Section titled “アーキテクチャ概要”classDiagram
class MTimeExpenseLine {
+getParent() MTimeExpense
+getQtyInvoiced() BigDecimal
+getQtyReimbursed() BigDecimal
+getPriceInvoiced() BigDecimal
+getPriceReimbursed() BigDecimal
+getApprovalAmt() BigDecimal
+getC_Currency_Report_ID() int
+getLaborCost(MAcctSchema) BigDecimal
#beforeSave(boolean) boolean
#afterSave(boolean, boolean) boolean
#afterDelete(boolean) boolean
}
class X_S_TimeExpenseLine {
<<generated>>
}
class PO {
<<abstract>>
}
MTimeExpenseLine --|> X_S_TimeExpenseLine
X_S_TimeExpenseLine --|> PO
MTimeExpenseLine --> MTimeExpense : parent
MTimeExpenseLine --> MResourceAssignment : syncs
MTimeExpenseLine --> MConversionRate : uses
パッケージ: org.compiere.model
ソースファイル: org.adempiere.base/src/org/compiere/model/MTimeExpenseLine.java(親: MTimeExpense.java)
関連DBテーブル
Section titled “関連DBテーブル”S_TimeExpenseLine(経費明細)
Section titled “S_TimeExpenseLine(経費明細)”| カラム名 | 型 | 必須 | 説明 | 備考 |
|---|---|---|---|---|
| S_TimeExpenseLine_ID | ID | PK | 経費明細ID | 主キー |
| AD_Client_ID | TableDirect | Y | クライアント | 既定 @AD_Client_ID@ |
| AD_Org_ID | TableDirect | Y | 組織 | 既定 @AD_Org_ID@ |
| S_TimeExpense_ID | Search | Y | 経費報告FK | 親伝票 |
| Line | Integer | Y | 明細番号 | 既定 SQL(MAX+10) |
| DateExpense | Date | Y | 作業日付 | 既定 @DateExpense@;@DateReport@ |
| C_BPartner_ID | Search | N | 取引先 | 請求先 |
| M_Product_ID | Search | N | 品目 | callout: CalloutTimeExpense.product |
| Qty | Quantity | N | 数量 | 既定 1 / callout: CalloutTimeExpense.amount |
| C_UOM_ID | TableDirect | N | 数量単位 | |
| ExpenseAmt | Amount | N | 経費金額 | callout: CalloutTimeExpense.amount |
| C_Currency_ID | TableDirect | N | 通貨 | 既定 @$C_Currency_ID@ / callout あり |
| ConvertedAmt | Amount | N | 換算金額 | beforeSave で自動算出 |
| LineNetAmt | Amount | N | 行合計 | ExpenseAmt × Qty |
| InvoicePrice | Costs+Prices | N | 請求額 | 0 で価格表既定 |
| PriceInvoiced | Costs+Prices | N | 請求価格 | 得意先 AR 価格表通貨 |
| QtyInvoiced | Quantity | N | 請求済数量 | |
| PriceReimbursed | Costs+Prices | N | 精算価格 | 従業員 AP 価格表通貨 |
| QtyReimbursed | Quantity | N | 精算数量 | |
| IsTimeReport | YesNo | Y | 時間単位レポート | Y なら金額を 0 に強制 |
| IsInvoiced | YesNo | Y | 請求済み | |
| Processed | YesNo | Y | 処理済み | |
| S_TimeType_ID | TableDirect | N | 時間タイプ | |
| S_ResourceAssignment_ID | Assignment | N | リソースアサイン | callout: CalloutAssignment.product |
| C_OrderLine_ID | Search | N | 受注明細 | 生成された受注明細 |
| C_InvoiceLine_ID | Search | N | 仕入請求明細 | 精算側で使用 |
| C_Project_ID / C_ProjectPhase_ID / C_ProjectTask_ID | TableDirect | N | プロジェクト関連 | |
| C_Campaign_ID / C_Activity_ID | TableDirect | N | 営業活動・アクティビティ |
erDiagram
S_TimeExpense ||--o{ S_TimeExpenseLine : "lines"
C_BPartner ||--o{ S_TimeExpenseLine : "billed to"
S_TimeExpenseLine }o--o| M_Product : "product"
S_TimeExpenseLine }o--o| S_TimeType : "time type"
S_TimeExpenseLine }o--o| S_ResourceAssignment : "assignment"
S_TimeExpenseLine }o--o| C_OrderLine : "invoiced via"
S_TimeExpenseLine }o--o| C_Project : "project"
ビジネスロジック
Section titled “ビジネスロジック”beforeSave() の処理順序
Section titled “beforeSave() の処理順序”flowchart TD
A["beforeSave"] --> B{"新規 かつ 親が Processed?"}
B -->|Yes| C["saveError ParentComplete<br/>→ false"]
B -->|No| D{"新規 or ExpenseAmt/通貨 変更?"}
D -->|Yes| E["ConvertedAmt を算出<br/>同一通貨ならそのまま<br/>異なれば MConversionRate.convert"]
D -->|No| F
E --> F{"新規 or Qty/ExpenseAmt 変更?"}
F -->|Yes| G["LineNetAmt = ExpenseAmt × Qty"]
F -->|No| H
G --> H{"IsTimeReport = Y?"}
H -->|Yes| I["ExpenseAmt / ConvertedAmt<br/>/ LineNetAmt を 0 に"]
H -->|No| J["true を返す"]
I --> J
- 親伝票の完了チェック: 新規行かつ
getParent().isProcessed()の場合、ParentCompleteエラーで保存を中止 - 換算金額の算出: 明細通貨と報告通貨(
getC_Currency_Report_ID())が同一ならExpenseAmtをそのままセット。異なる場合はMConversionRate.convert()でDateExpense時点のレートを適用 - 行合計の算出:
LineNetAmt = ExpenseAmt × Qty - 時間レポートの金額ゼロ化:
isTimeReport()が true の場合、経費金額・換算金額・行合計をすべてEnv.ZEROにセット
afterSave() の処理
Section titled “afterSave() の処理”updateHeader()を呼び、親の経費報告のヘッダー金額を再集計- 新規、または
S_ResourceAssignment_IDが変更された場合:- 変更前のリソースアサインが存在すれば
MResourceAssignment.delete()で削除 - 新しいリソースアサインに対し、明細の数量(
Qty)と説明(Description)を同期してsaveEx()
- 変更前のリソースアサインが存在すれば
afterDelete() の処理
Section titled “afterDelete() の処理”updateHeader()でヘッダー金額を再集計- 紐付いていたリソースアサイン(
S_ResourceAssignment_ID)を削除
⚠️ 注意: リソースアサインは明細に従属して削除されます。同一のリソースアサインを他の伝票から参照している設計にすると、明細削除時に予期せず消える可能性があります。
拡張ポイント(カスタマイズ箇所)
Section titled “拡張ポイント(カスタマイズ箇所)”このテーブルに登録されている Callout
Section titled “このテーブルに登録されている Callout”| カラム | Callout クラス |
|---|---|
| ExpenseAmt | org.compiere.model.CalloutTimeExpense.amount |
| Qty | org.compiere.model.CalloutTimeExpense.amount |
| C_Currency_ID | org.compiere.model.CalloutTimeExpense.amount |
| M_Product_ID | org.compiere.model.CalloutTimeExpense.product |
| S_ResourceAssignment_ID | org.compiere.model.CalloutAssignment.product |
品目や数量を変更したときの金額・単価の初期セットはこれらの Callout が行います。入力時の自動セット挙動を変えたい場合は、AD_Column.Callout を独自クラスに差し替えるか、後述の Model Validator で最終値を補正します。
OSGi Model Validator(推奨)
Section titled “OSGi Model Validator(推奨)”請求前チェックの独自ルールは Model Validator で追加できます。
public class CustomTimeExpenseLineValidator implements ModelValidator { @Override public int modelChange(PO po, int type) throws Exception { if (po instanceof MTimeExpenseLine) { MTimeExpenseLine line = (MTimeExpenseLine) po; if (type == TYPE_BEFORE_NEW || type == TYPE_BEFORE_CHANGE) { // 例: 顧客請求する明細は品目必須 if (!line.isTimeReport() && line.getM_Product_ID() == 0) { throw new AdempiereException("請求対象の経費明細には品目を指定してください"); } } } return null; }}請求単価ロジックの拡張
Section titled “請求単価ロジックの拡張”請求価格(PriceInvoiced)は得意先の売価表に基づいて決まります。数量割引や得意先別単価を追加する場合は、価格計算側(IPricingRule の OSGi サービス実装)で対応するとコア改変を避けられます。
関連プロセス
Section titled “関連プロセス”| プロセス名 | 説明 |
|---|---|
| 経費からの受注生成 | 未請求の経費明細から売上側の受注伝票を生成(C_OrderLine_ID がセットされる) |
関連ドキュメント
Section titled “関連ドキュメント”iDempiereカスタマイズのご相談
Section titled “iDempiereカスタマイズのご相談”経費の顧客請求は、請求単価の決定ルールや承認フローに各社固有の要件が出やすい領域です。 Callout と Model Validator を組み合わせることで、コアを変更せずに自社ルールを反映できます。
As-Link株式会社では、OSGiプラグインによる安全なカスタマイズを提供しています。