---
id: object/codeunit/1002
type: object
title: Codeunit 1002 "Job Create-Invoice"
summary: Codeunit 1002 "Job Create-Invoice" in Base Application (Microsoft.Projects.Project.Planning). 13 public procedures, 62 events. Present since at least BC23, still in BC30, changed in BC24-27, BC29.
tier: official
language: en
tags:
  - codeunit
  - base application
versions:
  introduced: null
  last_changed: "29"
  deprecated: null
review:
  state: derived
  by: null
  at: null
  flags: []
generated:
  at: "2026-10-11T00:31:51.816Z"
  pipeline: 0.2.0
  prompts: {}
  input_hash: 731962815bd229b2863c3263c3fc08d7b56f57c8e9350a851bf7c9720e4b6656
evidence:
  - kind: code
    url: https://github.com/microsoft/BCApps/blob/ea08af5ef2d6a9b5c5af4a029288abbe2c883220/src/Layers/W1/BaseApp/Projects/Project/Planning/JobCreateInvoice.Codeunit.al
    title: src/Layers/W1/BaseApp/Projects/Project/Planning/JobCreateInvoice.Codeunit.al (releases/29.x)
    date: null
    commit: ea08af5ef2d6a9b5c5af4a029288abbe2c883220
    t: null
    quote: null
links:
  learn: []
  objects: []
  features: []
  topics: []
  localizations: []
  videos: []
  posts: []
  guidelines: []
  changes:
    - change/bcapps/10361
object_type: codeunit
object_id: 1002
name: Job Create-Invoice
namespace: Microsoft.Projects.Project.Planning
app: Base Application
extends: null
first_version: "23"
last_version: "30"
present_in:
  - "23"
  - "24"
  - "25"
  - "26"
  - "27"
  - "28"
  - "29"
  - "30"
changed_in:
  - "24"
  - "25"
  - "26"
  - "27"
  - "29"
source_major: "29"
obsolete: null
countries: []
ms_search_form_ids: []
counts:
  fields: 0
  procedures: 94
  events: 62
  subscribers: 0
relations:
  out: 0
  referenced_by: 0
  pages: 0
  extended_by: 0
  event_subscribers: 0
  calls: 11
  called_by: 5
  implements: 0
---

# Codeunit 1002 "Job Create-Invoice"

> Codeunit 1002 "Job Create-Invoice" in Base Application (Microsoft.Projects.Project.Planning). 13 public procedures, 62 events. Present since at least BC23, still in BC30, changed in BC24-27, BC29.

Base Application · Microsoft.Projects.Project.Planning · BC23-30 · [source at ea08af5e](https://github.com/microsoft/BCApps/blob/ea08af5ef2d6a9b5c5af4a029288abbe2c883220/src/Layers/W1/BaseApp/Projects/Project/Planning/JobCreateInvoice.Codeunit.al) · facts from BC29

## Events published

- `OnAfterCreateSalesInvoiceLines(var SalesHeader: Record "Sales Header"; NewInvoice: Boolean)` (integration)
- `OnBeforeCreateSalesHeader(Job: Record Job; PostingDate: Date; var SalesHeader2: Record "Sales Header"; var JobPlanningLine: Record "Job Planning Line")` (integration)
- `OnBeforeCreateSalesLine(var JobPlanningLine: Record "Job Planning Line"; var SalesHeader: Record "Sales Header"; var SalesHeader2: Record "Sales Header"; var JobInvCurrency: Boolean)` (integration)
- `OnAfterCreateSalesLine(var SalesLine: Record "Sales Line"; SalesHeader: Record "Sales Header"; Job: Record Job; var JobPlanningLine: Record "Job Planning Line")` (integration)
- `OnAfterUpdateSalesHeader(var SalesHeader: Record "Sales Header"; Job: Record Job)` (integration)
- `OnBeforeCreateNewInvoice(var JobTask: Record "Job Task"; InvoicePerTask: Boolean; var OldJobNo: Code[20]; var OldJobTaskNo: Code[20]; LastJobTask: Boolean; var NewInvoice: Boolean; var IsHandled: Boolean; var TempJobPlanningLine: Record "Job Planning Line" temporary)` (integration)
- `OnBeforeCreateSalesInvoiceLines(var JobPlanningLine: Record "Job Planning Line"; InvoiceNo: Code[20]; NewInvoice: Boolean; PostingDate: Date; CreditMemo: Boolean; var NoOfSalesLinesCreated: Integer; var SkipClear: Boolean)` (integration)
- `OnBeforeCreateSalesInvoiceJobTask(var JobTask2: Record "Job Task"; PostingDate: Date; InvoicePerTask: Boolean; var NoOfInvoices: Integer; var OldJobNo: Code[20]; var OldJobTaskNo: Code[20]; LastJobTask: Boolean; var IsHandled: Boolean)` (integration)
- `OnBeforeDeleteSalesLine(var SalesLine: Record "Sales Line"; var IsHandled: Boolean)` (integration)
- `OnBeforeGetInvoiceNo(var JobPlanningLine: Record "Job Planning Line"; Done: Boolean; NewInvoice: Boolean; PostingDate: Date; var InvoiceNo: Code[20]; var IsHandled: Boolean)` (integration)
- `OnBeforeGetCrMemoNo(var JobPlanningLine: Record "Job Planning Line"; Done: Boolean; NewInvoice: Boolean; PostingDate: Date; var InvoiceNo: Code[20]; var IsHandled: Boolean)` (integration)
- `OnBeforeInsertSalesHeader(var SalesHeader: Record "Sales Header"; Job: Record Job; JobPlanningLine: Record "Job Planning Line")` (integration)
- `OnBeforeModifySalesHeader(var SalesHeader: Record "Sales Header"; Job: Record Job; JobPlanningLine: Record "Job Planning Line")` (integration)
- `OnBeforeInsertSalesLine(var SalesLine: Record "Sales Line"; var SalesHeader: Record "Sales Header"; Job: Record Job; JobPlanningLine: Record "Job Planning Line"; JobInvCurrency: Boolean)` (integration)
- `OnBeforeModifySalesLine(var SalesLine: Record "Sales Line"; SalesHeader: Record "Sales Header"; Job: Record Job; JobPlanningLine: Record "Job Planning Line")` (integration)
- `OnBeforeOpenSalesInvoice(var JobPlanningLineInvoice: Record "Job Planning Line Invoice"; var IsHandled: Boolean)` (integration)
- `OnBeforeTestSalesHeader(var SalesHeader: Record "Sales Header"; Job: Record Job; var IsHandled: Boolean; var JobPlanningLine: Record "Job Planning Line")` (integration)
- `OnBeforeTransferLine(var JobPlanningLine: Record "Job Planning Line"; var IsHandled: Boolean; var Result: Boolean)` (integration)
- `OnBeforeUpdateSalesHeader(var SalesHeader: Record "Sales Header"; Job: Record Job; var IsHandled: Boolean)` (integration)
- `OnAfterOpenSalesInvoice(var JobPlanningLineInvoice: Record "Job Planning Line Invoice")` (integration)
- `OnAfterTestSalesHeader(var SalesHeader: Record "Sales Header"; Job: Record Job; JobPlanningLine: Record "Job Planning Line")` (integration)
- `OnBeforeCheckJobBillToCustomer(JobPlanningLineSource: Record "Job Planning Line"; Job: Record Job; var IsHandled: Boolean)` (integration)
- `OnBeforeFindInvoices(var TempJobPlanningLineInvoice: Record "Job Planning Line Invoice" temporary; JobNo: Code[20]; JobTaskNo: Code[20]; JobPlanningLineNo: Integer; DetailLevel: Option; var IsHandled: Boolean)` (integration)
- `OnBeforeShowMessageLinesTransferred(var JobPlanningLine: Record "Job Planning Line"; CrMemo: Boolean; var IsHandled: Boolean)` (integration)
- `OnBeforeTestExchangeRate(var JobPlanningLine: Record "Job Planning Line"; PostingDate: Date; var UpdateExchangeRates: Boolean; var CurrencyExchangeRate: Record "Currency Exchange Rate")` (integration)
- `OnBeforeTestTransferred(var JobPlanningLine: Record "Job Planning Line"; SalesHeader: Record "Sales Header"; var IsHandled: Boolean)` (integration)
- `OnCreateSalesLineOnAfterCalcShouldUpdateCurrencyFactor(var JobPlanningLine: Record "Job Planning Line"; var Job: Record Job; var SalesHeader: Record "Sales Header"; var SalesHeader2: Record "Sales Header"; var JobInvCurrency: Boolean; var ShouldUpdateCurrencyFactor: Boolean)` (integration)
- `OnCreateSalesHeaderOnBeforeUpdateSalesHeader(var SalesHeader: Record "Sales Header"; var Job: Record Job; var IsHandled: Boolean; JobPlanningLine: Record "Job Planning Line")` (integration)
- `OnCreateSalesLineOnBeforeSalesCheckIfAnyExtText(var JobPlanningLine: Record "Job Planning Line"; var SalesLine: Record "Sales Line"; var IsHandled: Boolean)` (integration)
- `OnCreateSalesLineOnBeforeValidateSalesLineNo(var JobPlanningLine: Record "Job Planning Line"; var SalesLine: Record "Sales Line"; var IsHandled: Boolean)` (integration)
- `OnCreateSalesLineOnAfterSalesLineModify(var SalesLine: Record "Sales Line"; SalesHeader: Record "Sales Header"; Job: Record Job; JobPlanningLine: Record "Job Planning Line")` (integration)
- `OnCreateSalesInvoiceLinesOnAfterValidateJobPlanningLine(var JobPlanningLine: Record "Job Planning Line"; var LastError: Text)` (integration)
- `OnCreateSalesInvoiceLinesOnBeforeJobPlanningLineFindSet(var JobPlanningLine: Record "Job Planning Line"; InvoiceNo: Code[20]; NewInvoice: Boolean; PostingDate: Date; CreditMemo: Boolean)` (integration)
- `OnCreateSalesInvoiceLinesOnBeforeJobPlanningLineModify(var JobPlanningLine: Record "Job Planning Line")` (integration)
- `OnCreateSalesInvoiceLinesOnBeforeCreateSalesLine(var JobPlanningLine: Record "Job Planning Line"; SalesHeader: Record "Sales Header"; SalesHeader2: Record "Sales Header"; NewInvoice: Boolean; var NoOfSalesLinesCreated: Integer; var SkipCreateSalesLine: Boolean)` (integration)
- `OnCreateSalesInvoiceLinesOnBeforeTestJob(var Job: Record Job)` (integration)
- `OnCreateSalesInvoiceJobTaskOnAfterLinesCreated(var SalesHeader: Record "Sales Header"; var Job: Record Job; InvoicePerTask: Boolean; LastJobTask: Boolean)` (integration)
- `OnCreateSalesInvoiceJobTaskOnBeforeTempJobPlanningLineFind(var JobTask: Record "Job Task"; var SalesHeader: Record "Sales Header"; InvoicePerTask: Boolean; var TempJobPlanningLine: Record "Job Planning Line" temporary)` (integration)
- `OnCreateSalesInvoiceJobTaskOnBeforeCreateSalesLine(var JobPlanningLine: Record "Job Planning Line"; SalesHeader: Record "Sales Header"; SalesHeader2: Record "Sales Header"; var NoOfSalesLinesCreated: Integer)` (integration)
- `OnCreateSalesInvoiceJobTaskTestJob(var Job: Record Job; var JobPlanningLine: Record "Job Planning Line"; PostingDate: Date)` (integration)
- `OnDeleteSalesLineOnBeforeJobPlanningLineModify(var JobPlanningLine: Record "Job Planning Line")` (integration)
- `OnCreateSalesInvoiceJobTaskOnBeforeJobPlanningLineInvoiceInsert(var JobPlanningLineInvoice: Record "Job Planning Line Invoice")` (integration)
- `OnCreateSalesInvoiceOnBeforeRunReport(var JobPlanningLine: Record "Job Planning Line"; var Done: Boolean; var NewInvoice: Boolean; var PostingDate: Date; var InvoiceNo: Code[20]; var IsHandled: Boolean; CrMemo: Boolean)` (integration)
- `OnFindInvoicesOnBeforeTempJobPlanningLineInvoiceInsert(var TempJobPlanningLineInvoice: Record "Job Planning Line Invoice"; JobPlanningLineInvoice: Record "Job Planning Line Invoice")` (integration)
- `OnFindInvoicesOnBeforeTempJobPlanningLineInvoiceModify(var TempJobPlanningLineInvoice: Record "Job Planning Line Invoice"; JobPlanningLineInvoice: Record "Job Planning Line Invoice")` (integration)
- `OnCreateSalesHeaderOnBeforeCheckBillToCustomerNo(var SalesHeader: Record "Sales Header"; Job: Record Job; JobPlanningLine: Record "Job Planning Line"; var IsHandled: Boolean)` (integration)
- `OnCreateSalesInvoiceLinesOnBeforeJobPlanningLineCopy(Job: Record Job; var JobPlanningLineSource: Record "Job Planning Line"; PostingDate: Date)` (integration)
- `OnBeforeUpdateSalesLineDimension(var SalesLine: Record "Sales Line"; JobPlanningLine: Record "Job Planning Line"; var IsHandled: Boolean)` (integration)
- `OnCreateSalesInvoiceLinesOnAfterSetJobInvCurrency(Job: Record Job; var JobInvCurrency: Boolean)` (integration)
- `OnCreateSalesLineOnBeforeValidateCurrencyCode(var IsHandled: Boolean; SalesLine: Record "Sales Line"; JobPlanningLine: Record "Job Planning Line")` (integration)
- `OnCreateSalesInvoiceLinesOnAfterSetSalesDocumentType(var SalesHeader: Record "Sales Header")` (integration)
- `OnBeforeGetJobPlanningLineInvoices(JobPlanningLine: Record "Job Planning Line")` (integration)
- `OnCreateSalesInvoiceJobTaskOnAfterJobPlanningLineSetFilters(var JobPlanningLine: Record "Job Planning Line"; var JobTask2: Record "Job Task")` (integration)
- `OnCreateSalesLineOnBeforeCheckPricesIncludingVATAndSetJobInformation(var SalesLine: Record "Sales Line"; JobPlanningLine: Record "Job Planning Line"; var IsHandled: Boolean)` (integration)
- `OnDeleteSalesLineOnBeforeGetJobPlanningLine(JobPlanningLineInvoice: Record "Job Planning Line Invoice")` (integration)
- `OnBeforeGetCustomerNo(var Job: Record Job; var JobPlanningLine: Record "Job Planning Line"; SellToCustomerNo: Boolean; var CustomerNo: Code[20])` (integration)
- `OnBeforeFindJobPlanningLineInvoice(JobTask: Record "Job Task"; var JobPlanningLineInvoice: Record "Job Planning Line Invoice"; var SalesHeader: Record "Sales Header"; var ExitValue: Boolean; var IsHandled: Boolean)` (integration)
- `OnTestExchangeRateOnBeforeValidateCurrencyDate(var JobPlanningLine: Record "Job Planning Line"; PostingDate: Date; var CurrencyExchangeRate: Record "Currency Exchange Rate"; var ShouldValidateCurrencyCode: Boolean)` (integration)
- `OnCreateSalesInvoiceLinesOnBeforeNoSalesLineCreatedError(var SkipError: Boolean)` (integration)
- `OnCreateSalesInvoiceLinesOnBeforeJobPlanningLineInvoiceInsert(var JobPlanningLineInvoice: Record "Job Planning Line Invoice")` (integration)
- `OnCreateSalesInvoiceOnBeforeFindJobPlanningLines(var JobPlanningLine: Record "Job Planning Line")` (integration)
- `OnCreateSalesInvoiceOnBeforeCommit(var JobPlanningLine: Record "Job Planning Line"; var SkipCommit: Boolean)` (integration)

## Procedures

- `CreateSalesInvoice(var JobPlanningLine: Record "Job Planning Line"; CrMemo: Boolean)`
- `CreateSalesInvoiceLines(JobNo: Code[20]; var JobPlanningLineSource: Record "Job Planning Line"; InvoiceNo: Code[20]; NewInvoice: Boolean; PostingDate: Date; DocumentDate: Date; CreditMemo: Boolean)`
- `DeleteSalesInvoiceBuffer()`
- `CreateSalesInvoiceJobTask(var JobTask2: Record "Job Task"; PostingDate: Date; DocumentDate: Date; InvoicePerTask: Boolean; var NoOfInvoices: Integer; var OldJobNo: Code[20]; var OldJobTaskNo: Code[20]; LastJobTask: Boolean)`
- `CreateNewInvoice(var JobTask: Record "Job Task"; InvoicePerTask: Boolean; var OldJobNo: Code[20]; var OldJobTaskNo: Code[20]; LastJobTask: Boolean): Boolean`
- `CreateSalesHeader(Job: Record Job; JobPlanningLine: Record "Job Planning Line"; PostingDate: Date; DocumentDate: Date)`
- `CreateSalesLine(var JobPlanningLine: Record "Job Planning Line")`
- `TransferLine(var JobPlanningLine: Record "Job Planning Line"): Boolean`
- `DeleteSalesLine(SalesLine: Record "Sales Line")`
- `FindInvoices(var TempJobPlanningLineInvoice: Record "Job Planning Line Invoice" temporary; JobNo: Code[20]; JobTaskNo: Code[20]; JobPlanningLineNo: Integer; DetailLevel: Option All,"Per Job","Per Job Task","Per Job Planning Line")`
- `GetJobPlanningLineInvoices(JobPlanningLine: Record "Job Planning Line")`
- `OpenSalesInvoice(JobPlanningLineInvoice: Record "Job Planning Line Invoice")`
- `TestExchangeRate(var JobPlanningLine: Record "Job Planning Line"; PostingDate: Date)`

Plus 19 local procedures.

## Triggers

OnRun

## Calls

From the extracted call graph of BC29 (graphify-al on the snapshot checkout): calls whose target is known from a declared type or an `Object::"Name"` argument. Interface dispatch and calls through events are not counted, so the list is not complete.

- [Codeunit 408 "DimensionManagement"](../codeunit/408.md) (3 calls: `UpdateSalesLineDimension → CreateDimForSalesLineWithHigherPriorities`, `UpdateSalesLineDimension → CreateDimSetFromJobTaskDim`, `UpdateSalesLineDimension → GetCombinedDimensionSetID`)
- [Codeunit 378 "Transfer Extended Text"](../codeunit/378.md) (2 calls: `CreateSalesLine → InsertSalesExtText`, `CreateSalesLine → SalesCheckIfAnyExtText`)
- [Codeunit 365 "Format Address"](../codeunit/365.md) (1 call: `UpdateSalesHeader → UseCounty`)
- [Codeunit 46 "SelectionFilterManagement"](../codeunit/46.md) (1 call: `SalesInvoiceExistForMultipleCustomerBillingMethod → GetSelectionFilter`)
- [Codeunit 60 "Sales-Calc. Discount"](../codeunit/60.md) (1 call: `CalculateInvoiceDiscount → (object)`)
- [Codeunit 701 "Data Type Management"](../codeunit/701.md) (1 call: `ReturnJobDataDependingOnTaskBillingMethod → FindFieldByName`)
- [Page 1029 "Job Invoices"](../page/1029.md) (1 call: `GetJobPlanningLineInvoices → (object)`)
- [Page 132 "Posted Sales Invoice"](../page/132.md) (1 call: `OpenSalesInvoice → (object)`)
- [Page 134 "Posted Sales Credit Memo"](../page/134.md) (1 call: `OpenSalesInvoice → (object)`)
- [Page 43 "Sales Invoice"](../page/43.md) (1 call: `OpenSalesInvoice → (object)`)
- [Page 44 "Sales Credit Memo"](../page/44.md) (1 call: `OpenSalesInvoice → (object)`)

## Called by

- [Codeunit 1033 "Job-Process Plan. Lines"](../codeunit/1033.md) (1 call: `CreateInvLines → CreateSalesInvoiceLines`)
- [Page 1007 "Job Planning Lines"](../page/1007.md) (1 call: `CreateSalesInvoice → CreateSalesInvoice`)
- [Page 1029 "Job Invoices"](../page/1029.md) (1 call: `OnOpenPage → FindInvoices`)
- [Report 1093 "Job Create Sales Invoice"](../report/1093.md) (1 call: `OnPreReport → DeleteSalesInvoiceBuffer`)
- [Table 37 "Sales Line"](../table/37.md) (1 call: `OnDelete → DeleteSalesLine`)

## Recent changes

- 2026-08-31 [#10361 [main] Line Discount Amount Rounding Discrepancy When Transferring Project Planning Lines to Sales Invoice](../../changes/bcapps/10361.md) (main, BC30, fix)

## Across versions

- Present in: BC23-30
- Changed (declaration) in: BC24-27, BC29

Source: AL metadata extracted from the code (names, ids, signatures, properties); no code bodies (D10).

## Ask your agent

Procedure bodies are not stored here (D10). The call sections above are our own, per object, from the BC29 call graph. For a procedure body or the calls of one procedure, ask bc-code-atlas (external, by Stefan Maron, MIT; default corpus w1-28), which the bc-observatory plugin connects: `bcatlas_resolve_node(object_type: "codeunit", object_name: "Job Create-Invoice")`, then `bcatlas_get_procedure_body` or `bcatlas_get_neighbors` on the returned id.
