Skip to content

Commit

Permalink
feat: expose next possible state [OM-1007] (#2024)
Browse files Browse the repository at this point in the history
  • Loading branch information
turip authored Jan 7, 2025
1 parent 42b83fd commit 41f5fd9
Show file tree
Hide file tree
Showing 8 changed files with 1,047 additions and 802 deletions.
1,484 changes: 756 additions & 728 deletions api/api.gen.go

Large diffs are not rendered by default.

69 changes: 57 additions & 12 deletions api/openapi.cloud.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10775,15 +10775,6 @@ components:
description: External IDs of the invoice in other apps such as Stripe.
readOnly: true
description: Invoice represents an invoice in the system.
InvoiceAction:
type: string
enum:
- advance
- approve
- delete
- retry
- void
description: InvoiceAction represents the actions that can be performed on an invoice.
InvoiceAppExternalIDs:
type: object
properties:
Expand All @@ -10800,6 +10791,61 @@ components:
description: The external ID of the invoice in the payment app if available.
readOnly: true
description: InvoiceAppExternalIDs contains the external IDs of the invoice in other apps such as Stripe.
InvoiceAvailableActionDetails:
type: object
required:
- resultingState
properties:
resultingState:
type: string
description: |-
The state the invoice will reach if the action is activated and
all intermediate steps are successful.

For example advancing a draft_created invoice will result in a draft_manual_approval_needed invoice.
readOnly: true
description: |-
InvoiceAvailableActionInvoiceDetails represents the details of the invoice action for
non-gathering invoices.
InvoiceAvailableActionInvoiceDetails:
type: object
description: |-
InvoiceAvailableActionInvoiceDetails represents the details of the invoice action for
gathering invoices.
InvoiceAvailableActions:
type: object
properties:
advance:
allOf:
- $ref: '#/components/schemas/InvoiceAvailableActionDetails'
description: Advance the invoice to the next status.
readOnly: true
approve:
allOf:
- $ref: '#/components/schemas/InvoiceAvailableActionDetails'
description: Approve an invoice that requires manual approval.
readOnly: true
delete:
allOf:
- $ref: '#/components/schemas/InvoiceAvailableActionDetails'
description: Delete the invoice (only non-issued invoices can be deleted).
readOnly: true
retry:
allOf:
- $ref: '#/components/schemas/InvoiceAvailableActionDetails'
description: Retry an invoice issuing step that failed.
readOnly: true
void:
allOf:
- $ref: '#/components/schemas/InvoiceAvailableActionDetails'
description: Void an already issued invoice.
readOnly: true
invoice:
allOf:
- $ref: '#/components/schemas/InvoiceAvailableActionInvoiceDetails'
description: Invoice a gathering invoice
readOnly: true
description: InvoiceAvailableActions represents the actions that can be performed on the invoice.
InvoiceDocumentRef:
type: object
allOf:
Expand Down Expand Up @@ -11440,9 +11486,8 @@ components:
description: Extended status information for the invoice.
readOnly: true
availableActions:
type: array
items:
$ref: '#/components/schemas/InvoiceAction'
allOf:
- $ref: '#/components/schemas/InvoiceAvailableActions'
description: The actions that can be performed on the invoice.
description: |-
InvoiceStatusDetails represents the details of the invoice status.
Expand Down
69 changes: 57 additions & 12 deletions api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10536,15 +10536,6 @@ components:
description: External IDs of the invoice in other apps such as Stripe.
readOnly: true
description: Invoice represents an invoice in the system.
InvoiceAction:
type: string
enum:
- advance
- approve
- delete
- retry
- void
description: InvoiceAction represents the actions that can be performed on an invoice.
InvoiceAppExternalIDs:
type: object
properties:
Expand All @@ -10561,6 +10552,61 @@ components:
description: The external ID of the invoice in the payment app if available.
readOnly: true
description: InvoiceAppExternalIDs contains the external IDs of the invoice in other apps such as Stripe.
InvoiceAvailableActionDetails:
type: object
required:
- resultingState
properties:
resultingState:
type: string
description: |-
The state the invoice will reach if the action is activated and
all intermediate steps are successful.

For example advancing a draft_created invoice will result in a draft_manual_approval_needed invoice.
readOnly: true
description: |-
InvoiceAvailableActionInvoiceDetails represents the details of the invoice action for
non-gathering invoices.
InvoiceAvailableActionInvoiceDetails:
type: object
description: |-
InvoiceAvailableActionInvoiceDetails represents the details of the invoice action for
gathering invoices.
InvoiceAvailableActions:
type: object
properties:
advance:
allOf:
- $ref: '#/components/schemas/InvoiceAvailableActionDetails'
description: Advance the invoice to the next status.
readOnly: true
approve:
allOf:
- $ref: '#/components/schemas/InvoiceAvailableActionDetails'
description: Approve an invoice that requires manual approval.
readOnly: true
delete:
allOf:
- $ref: '#/components/schemas/InvoiceAvailableActionDetails'
description: Delete the invoice (only non-issued invoices can be deleted).
readOnly: true
retry:
allOf:
- $ref: '#/components/schemas/InvoiceAvailableActionDetails'
description: Retry an invoice issuing step that failed.
readOnly: true
void:
allOf:
- $ref: '#/components/schemas/InvoiceAvailableActionDetails'
description: Void an already issued invoice.
readOnly: true
invoice:
allOf:
- $ref: '#/components/schemas/InvoiceAvailableActionInvoiceDetails'
description: Invoice a gathering invoice
readOnly: true
description: InvoiceAvailableActions represents the actions that can be performed on the invoice.
InvoiceDocumentRef:
type: object
allOf:
Expand Down Expand Up @@ -11201,9 +11247,8 @@ components:
description: Extended status information for the invoice.
readOnly: true
availableActions:
type: array
items:
$ref: '#/components/schemas/InvoiceAction'
allOf:
- $ref: '#/components/schemas/InvoiceAvailableActions'
description: The actions that can be performed on the invoice.
description: |-
InvoiceStatusDetails represents the details of the invoice status.
Expand Down
53 changes: 44 additions & 9 deletions api/spec/src/billing/invoices/invoice.tsp
Original file line number Diff line number Diff line change
Expand Up @@ -198,36 +198,71 @@ model Invoice {
}

/**
* InvoiceAction represents the actions that can be performed on an invoice.
* InvoiceAvailableActions represents the actions that can be performed on the invoice.
*/
@friendlyName("InvoiceAction")
enum InvoiceAction {
@friendlyName("InvoiceAvailableActions")
model InvoiceAvailableActions {
/**
* Advance the invoice to the next status.
*/
advance: "advance",
@visibility(Lifecycle.Read)
advance?: InvoiceAvailableActionDetails;

/**
* Approve an invoice that requires manual approval.
*/
approve: "approve",
@visibility(Lifecycle.Read)
approve?: InvoiceAvailableActionDetails;

/**
* Delete the invoice (only non-issued invoices can be deleted).
*/
delete: "delete",
@visibility(Lifecycle.Read)
delete?: InvoiceAvailableActionDetails;

/**
* Retry an invoice issuing step that failed.
*/
retry: "retry",
@visibility(Lifecycle.Read)
retry?: InvoiceAvailableActionDetails;

/**
* Void an already issued invoice.
*/
`void`: "void",
@visibility(Lifecycle.Read)
`void`?: InvoiceAvailableActionDetails;

/**
* Invoice a gathering invoice
*/
@visibility(Lifecycle.Read)
invoice?: InvoiceAvailableActionInvoiceDetails;
}

/**
* InvoiceAvailableActionInvoiceDetails represents the details of the invoice action for
* non-gathering invoices.
*/
@friendlyName("InvoiceAvailableActionDetails")
model InvoiceAvailableActionDetails {
/**
* The state the invoice will reach if the action is activated and
* all intermediate steps are successful.
*
* For example advancing a draft_created invoice will result in a draft_manual_approval_needed invoice.
*/
@visibility(Lifecycle.Read)
resultingState: InvoiceExtendedStatus;
}

/**
* InvoiceAvailableActionInvoiceDetails represents the details of the invoice action for
* gathering invoices.
*/
// Note: this is a placeholder for future extensibility
@friendlyName("InvoiceAvailableActionInvoiceDetails")
model InvoiceAvailableActionInvoiceDetails {}

/**
* InvoiceStatusDetails represents the details of the invoice status.
*
Expand Down Expand Up @@ -257,7 +292,7 @@ model InvoiceStatusDetails {
/**
* The actions that can be performed on the invoice.
*/
availableActions: InvoiceAction[];
availableActions: InvoiceAvailableActions;
}

// TODO[later]: we can make this an enum, but only if we have reached a stable state with the statuses.
Expand Down
25 changes: 22 additions & 3 deletions openmeter/billing/httpdriver/invoice.go
Original file line number Diff line number Diff line change
Expand Up @@ -361,9 +361,7 @@ func mapInvoiceToAPI(invoice billing.Invoice) (api.Invoice, error) {
Immutable: invoice.StatusDetails.Immutable,
ExtendedStatus: string(invoice.Status),

AvailableActions: lo.Map(invoice.StatusDetails.AvailableActions, func(a billing.InvoiceAction, _ int) api.InvoiceAction {
return api.InvoiceAction(a)
}),
AvailableActions: mapInvoiceAvailableActionsToAPI(invoice.StatusDetails.AvailableActions),
},
Supplier: mapSupplierContactToAPI(invoice.Supplier),
Totals: mapTotalsToAPI(invoice.Totals),
Expand Down Expand Up @@ -478,3 +476,24 @@ func mapTotalsToAPI(t billing.Totals) api.InvoiceTotals {
Total: t.Total.String(),
}
}

func mapInvoiceAvailableActionsToAPI(actions billing.InvoiceAvailableActions) api.InvoiceAvailableActions {
return api.InvoiceAvailableActions{
Advance: mapInvoiceAvailableActionDetailsToAPI(actions.Advance),
Approve: mapInvoiceAvailableActionDetailsToAPI(actions.Approve),
Delete: mapInvoiceAvailableActionDetailsToAPI(actions.Delete),
Retry: mapInvoiceAvailableActionDetailsToAPI(actions.Retry),
Void: mapInvoiceAvailableActionDetailsToAPI(actions.Void),
Invoice: lo.If(actions.Invoice != nil, &api.InvoiceAvailableActionInvoiceDetails{}).Else(nil),
}
}

func mapInvoiceAvailableActionDetailsToAPI(actions *billing.InvoiceAvailableActionDetails) *api.InvoiceAvailableActionDetails {
if actions == nil {
return nil
}

return &api.InvoiceAvailableActionDetails{
ResultingState: string(actions.ResultingState),
}
}
27 changes: 16 additions & 11 deletions openmeter/billing/invoice.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,20 +321,25 @@ type InvoiceExternalIDs struct {
Payment string `json:"payment,omitempty"`
}

type InvoiceAction string
type InvoiceAvailableActions struct {
Advance *InvoiceAvailableActionDetails `json:"advance,omitempty"`
Approve *InvoiceAvailableActionDetails `json:"approve,omitempty"`
Delete *InvoiceAvailableActionDetails `json:"delete,omitempty"`
Retry *InvoiceAvailableActionDetails `json:"retry,omitempty"`
Void *InvoiceAvailableActionDetails `json:"void,omitempty"`
Invoice *InvoiceAvailableActionInvoiceDetails `json:"invoice,omitempty"`
}

const (
InvoiceActionAdvance InvoiceAction = "advance"
InvoiceActionApprove InvoiceAction = "approve"
InvoiceActionDelete InvoiceAction = "delete"
InvoiceActionRetry InvoiceAction = "retry"
InvoiceActionVoid InvoiceAction = "void"
)
type InvoiceAvailableActionDetails struct {
ResultingState InvoiceStatus `json:"resultingState"`
}

type InvoiceAvailableActionInvoiceDetails struct{}

type InvoiceStatusDetails struct {
Immutable bool `json:"immutable"`
Failed bool `json:"failed"`
AvailableActions []InvoiceAction `json:"availableActions"`
Immutable bool `json:"immutable"`
Failed bool `json:"failed"`
AvailableActions InvoiceAvailableActions `json:"availableActions"`
}

const (
Expand Down
Loading

0 comments on commit 41f5fd9

Please sign in to comment.