From 74bf8cf802e8df93504429abfb199e1975b83cb4 Mon Sep 17 00:00:00 2001 From: Vernon Keenan Date: Fri, 24 Jul 2026 03:05:55 +0000 Subject: [PATCH] fix: align Asset lifecycle contract --- api/crm/crm_client/assets/assets_client.go | 20 ++--- .../crm_client/assets/put_asset_responses.go | 83 +++++++++++++++++++ api/crm/crm_models/asset.go | 5 +- api/crm/crm_models/asset_contract_test.go | 18 ++++ swagger/defs/asset.yaml | 6 +- 5 files changed, 120 insertions(+), 12 deletions(-) create mode 100644 api/crm/crm_models/asset_contract_test.go diff --git a/api/crm/crm_client/assets/assets_client.go b/api/crm/crm_client/assets/assets_client.go index f49ac41..c21a9ef 100644 --- a/api/crm/crm_client/assets/assets_client.go +++ b/api/crm/crm_client/assets/assets_client.go @@ -72,10 +72,10 @@ type ClientService interface { // GetAssetsContext get a list of assets. GetAssetsContext(ctx context.Context, params *GetAssetsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*GetAssetsOK, error) - // PostAssets add a new asset to salesforce devops net. + // PostAssets add a new asset. PostAssets(params *PostAssetsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*PostAssetsOK, error) - // PostAssetsContext add a new asset to salesforce devops net. + // PostAssetsContext add a new asset. PostAssetsContext(ctx context.Context, params *PostAssetsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*PostAssetsOK, error) // PutAsset update a single asset. @@ -156,7 +156,7 @@ func (a *Client) DeleteAssetContext(ctx context.Context, params *DeleteAssetPara // GetAssets gets a list of assets. // -// Return a list of all available Assets. +// Return tenant-bound Asset records. Requires the exact crm:asset:read scope.. // // This method does not support injected context. // However, timeout and opentracing contexts are honored whenever enabled. @@ -175,7 +175,7 @@ func (a *Client) GetAssets(params *GetAssetsParams, authInfo runtime.ClientAuthI // GetAssetsContext gets a list of assets. // -// Return a list of all available Assets. +// Return tenant-bound Asset records. Requires the exact crm:asset:read scope.. // // Do not use the deprecated [GetAssetsParams.Context] with this method: it would be ignored. func (a *Client) GetAssetsContext(ctx context.Context, params *GetAssetsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*GetAssetsOK, error) { @@ -221,9 +221,9 @@ func (a *Client) GetAssetsContext(ctx context.Context, params *GetAssetsParams, panic(msg) } -// PostAssets adds a new asset to salesforce devops net. +// PostAssets adds a new asset. // -// Asset record to be added. +// Create one tenant-bound Asset with server-owned identity and audit fields.. // // This method does not support injected context. // However, timeout and opentracing contexts are honored whenever enabled. @@ -240,9 +240,9 @@ func (a *Client) PostAssets(params *PostAssetsParams, authInfo runtime.ClientAut return a.PostAssetsContext(ctx, params, authInfo, opts...) } -// PostAssetsContext adds a new asset to salesforce devops net. +// PostAssetsContext adds a new asset. // -// Asset record to be added. +// Create one tenant-bound Asset with server-owned identity and audit fields.. // // Do not use the deprecated [PostAssetsParams.Context] with this method: it would be ignored. func (a *Client) PostAssetsContext(ctx context.Context, params *PostAssetsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*PostAssetsOK, error) { @@ -290,7 +290,7 @@ func (a *Client) PostAssetsContext(ctx context.Context, params *PostAssetsParams // PutAsset updates a single asset. // -// Update a single asset specified by assetId. +// Optimistically update one tenant-bound Asset's authoritative business fields.. // // This method does not support injected context. // However, timeout and opentracing contexts are honored whenever enabled. @@ -309,7 +309,7 @@ func (a *Client) PutAsset(params *PutAssetParams, authInfo runtime.ClientAuthInf // PutAssetContext updates a single asset. // -// Update a single asset specified by assetId. +// Optimistically update one tenant-bound Asset's authoritative business fields.. // // Do not use the deprecated [PutAssetParams.Context] with this method: it would be ignored. func (a *Client) PutAssetContext(ctx context.Context, params *PutAssetParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*PutAssetOK, error) { diff --git a/api/crm/crm_client/assets/put_asset_responses.go b/api/crm/crm_client/assets/put_asset_responses.go index 56d7b73..ea778f8 100644 --- a/api/crm/crm_client/assets/put_asset_responses.go +++ b/api/crm/crm_client/assets/put_asset_responses.go @@ -49,6 +49,12 @@ func (o *PutAssetReader) ReadResponse(response runtime.ClientResponse, consumer return nil, err } return nil, result + case 409: + result := NewPutAssetConflict() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return nil, result case 422: result := NewPutAssetUnprocessableEntity() if err := result.readResponse(response, consumer, o.formats); err != nil { @@ -382,6 +388,83 @@ func (o *PutAssetNotFound) readResponse(response runtime.ClientResponse, consume return nil } +// NewPutAssetConflict creates a PutAssetConflict with default headers values +func NewPutAssetConflict() *PutAssetConflict { + return &PutAssetConflict{} +} + +// PutAssetConflict describes a response with status code 409, with default header values. +// +// Conflict +type PutAssetConflict struct { + AccessControlAllowOrigin string + + Payload *crm_models.Error +} + +// IsSuccess returns true when this put asset conflict response has a 2xx status code +func (o *PutAssetConflict) IsSuccess() bool { + return false +} + +// IsRedirect returns true when this put asset conflict response has a 3xx status code +func (o *PutAssetConflict) IsRedirect() bool { + return false +} + +// IsClientError returns true when this put asset conflict response has a 4xx status code +func (o *PutAssetConflict) IsClientError() bool { + return true +} + +// IsServerError returns true when this put asset conflict response has a 5xx status code +func (o *PutAssetConflict) IsServerError() bool { + return false +} + +// IsCode returns true when this put asset conflict response a status code equal to that given +func (o *PutAssetConflict) IsCode(code int) bool { + return code == 409 +} + +// Code gets the status code for the put asset conflict response +func (o *PutAssetConflict) Code() int { + return 409 +} + +func (o *PutAssetConflict) Error() string { + payload, _ := json.Marshal(o.Payload) + return fmt.Sprintf("[PUT /assets][%d] putAssetConflict %s", 409, payload) +} + +func (o *PutAssetConflict) String() string { + payload, _ := json.Marshal(o.Payload) + return fmt.Sprintf("[PUT /assets][%d] putAssetConflict %s", 409, payload) +} + +func (o *PutAssetConflict) GetPayload() *crm_models.Error { + return o.Payload +} + +func (o *PutAssetConflict) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + + // hydrates response header Access-Control-Allow-Origin + hdrAccessControlAllowOrigin := response.GetHeader("Access-Control-Allow-Origin") + + if hdrAccessControlAllowOrigin != "" { + o.AccessControlAllowOrigin = hdrAccessControlAllowOrigin + } + + o.Payload = new(crm_models.Error) + + // response payload + if err := consumer.Consume(response.Body(), o.Payload); err != nil && !stderrors.Is(err, io.EOF) { + return err + } + + return nil +} + // NewPutAssetUnprocessableEntity creates a PutAssetUnprocessableEntity with default headers values func NewPutAssetUnprocessableEntity() *PutAssetUnprocessableEntity { return &PutAssetUnprocessableEntity{} diff --git a/api/crm/crm_models/asset.go b/api/crm/crm_models/asset.go index ad55f11..69e36a1 100644 --- a/api/crm/crm_models/asset.go +++ b/api/crm/crm_models/asset.go @@ -57,6 +57,9 @@ type Asset struct { // Current Lifecycle End Date CurrentLifecycleEndDate *string `json:"CurrentLifecycleEndDate,omitempty"` + // Current Lifecycle Start Date + CurrentLifecycleStartDate *string `json:"CurrentLifecycleStartDate,omitempty"` + // Current Monthly Recurring Revenue CurrentMrr *float64 `json:"CurrentMrr,omitempty"` @@ -135,7 +138,7 @@ type Asset struct { // Serial Number SerialNumber *string `json:"SerialNumber,omitempty"` - // Status + // Compatibility-only legacy field. The authoritative CRM Asset table does not persist Status; native CRM mutations reject non-null values. Status *string `json:"Status,omitempty"` // Status Reason diff --git a/api/crm/crm_models/asset_contract_test.go b/api/crm/crm_models/asset_contract_test.go new file mode 100644 index 0000000..e251fbc --- /dev/null +++ b/api/crm/crm_models/asset_contract_test.go @@ -0,0 +1,18 @@ +package crm_models + +import ( + "encoding/json" + "testing" +) + +func TestAssetLifecycleStartDateIsInGeneratedJSONContract(t *testing.T) { + start := "2026-07-24T03:00:00Z" + body, err := json.Marshal(&Asset{CurrentLifecycleStartDate: &start}) + if err != nil { + t.Fatal(err) + } + const want = `{"CurrentLifecycleStartDate":"2026-07-24T03:00:00Z"}` + if string(body) != want { + t.Fatalf("got %s, want %s", body, want) + } +} diff --git a/swagger/defs/asset.yaml b/swagger/defs/asset.yaml index a5cfa1e..c2c2234 100644 --- a/swagger/defs/asset.yaml +++ b/swagger/defs/asset.yaml @@ -49,6 +49,10 @@ Asset: description: Current Lifecycle End Date type: string x-nullable: true + CurrentLifecycleStartDate: + description: Current Lifecycle Start Date + type: string + x-nullable: true CurrentMrr: description: Current Monthly Recurring Revenue type: number @@ -150,7 +154,7 @@ Asset: type: string x-nullable: true Status: - description: Status + description: Compatibility-only legacy field. The authoritative CRM Asset table does not persist Status; native CRM mutations reject non-null values. type: string x-nullable: true StatusReason: