// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package google.cloud.talent.v4;

import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/cloud/talent/v4/common.proto";
import "google/protobuf/timestamp.proto";

option go_package = "cloud.google.com/go/talent/apiv4/talentpb;talentpb";
option java_multiple_files = true;
option java_outer_classname = "JobProto";
option java_package = "com.google.cloud.talent.v4";
option objc_class_prefix = "CTS";

// A Job resource represents a job posting (also referred to as a "job listing"
// or "job requisition"). A job belongs to a
// [Company][google.cloud.talent.v4.Company], which is the hiring entity
// responsible for the job.
message Job {
  option (google.api.resource) = {
    type: "jobs.googleapis.com/Job"
    pattern: "projects/{project}/tenants/{tenant}/jobs/{job}"
  };

  // Application related details of a job posting.
  message ApplicationInfo {
    // Use this field to specify email address(es) to which resumes or
    // applications can be sent.
    //
    // The maximum number of allowed characters for each entry is 255.
    repeated string emails = 1;

    // Use this field to provide instructions, such as "Mail your application
    // to ...", that a candidate can follow to apply for the job.
    //
    // This field accepts and sanitizes HTML input, and also accepts
    // bold, italic, ordered list, and unordered list markup tags.
    //
    // The maximum number of allowed characters is 3,000.
    string instruction = 2;

    // Use this URI field to direct an applicant to a website, for example to
    // link to an online application form.
    //
    // The maximum number of allowed characters for each entry is 2,000.
    repeated string uris = 3;
  }

  // Derived details about the job posting.
  message DerivedInfo {
    // Structured locations of the job, resolved from
    // [Job.addresses][google.cloud.talent.v4.Job.addresses].
    //
    // [locations][google.cloud.talent.v4.Job.DerivedInfo.locations] are exactly
    // matched to [Job.addresses][google.cloud.talent.v4.Job.addresses] in the
    // same order.
    repeated Location locations = 1;

    // Job categories derived from [Job.title][google.cloud.talent.v4.Job.title]
    // and [Job.description][google.cloud.talent.v4.Job.description].
    repeated JobCategory job_categories = 3;
  }

  // Options for job processing.
  message ProcessingOptions {
    // If set to `true`, the service does not attempt to resolve a
    // more precise address for the job.
    bool disable_street_address_resolution = 1;

    // Option for job HTML content sanitization. Applied fields are:
    //
    // * description
    // * applicationInfo.instruction
    // * incentives
    // * qualifications
    // * responsibilities
    //
    // HTML tags in these fields may be stripped if sanitiazation isn't
    // disabled.
    //
    // Defaults to
    // [HtmlSanitization.SIMPLE_FORMATTING_ONLY][google.cloud.talent.v4.HtmlSanitization.SIMPLE_FORMATTING_ONLY].
    HtmlSanitization html_sanitization = 2;
  }

  // Required during job update.
  //
  // The resource name for the job. This is generated by the service when a
  // job is created.
  //
  // The format is
  // "projects/{project_id}/tenants/{tenant_id}/jobs/{job_id}". For
  // example, "projects/foo/tenants/bar/jobs/baz".
  //
  // Use of this field in job queries and API calls is preferred over the use of
  // [requisition_id][google.cloud.talent.v4.Job.requisition_id] since this
  // value is unique.
  string name = 1;

  // Required. The resource name of the company listing the job.
  //
  // The format is
  // "projects/{project_id}/tenants/{tenant_id}/companies/{company_id}". For
  // example, "projects/foo/tenants/bar/companies/baz".
  string company = 2 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = { type: "jobs.googleapis.com/Company" }
  ];

  // Required. The requisition ID, also referred to as the posting ID, is
  // assigned by the client to identify a job. This field is intended to be used
  // by clients for client identification and tracking of postings. A job isn't
  // allowed to be created if there is another job with the same
  // [company][google.cloud.talent.v4.Job.name],
  // [language_code][google.cloud.talent.v4.Job.language_code] and
  // [requisition_id][google.cloud.talent.v4.Job.requisition_id].
  //
  // The maximum number of allowed characters is 255.
  string requisition_id = 3 [(google.api.field_behavior) = REQUIRED];

  // Required. The title of the job, such as "Software Engineer"
  //
  // The maximum number of allowed characters is 500.
  string title = 4 [(google.api.field_behavior) = REQUIRED];

  // Required. The description of the job, which typically includes a
  // multi-paragraph description of the company and related information.
  // Separate fields are provided on the job object for
  // [responsibilities][google.cloud.talent.v4.Job.responsibilities],
  // [qualifications][google.cloud.talent.v4.Job.qualifications], and other job
  // characteristics. Use of these separate job fields is recommended.
  //
  // This field accepts and sanitizes HTML input, and also accepts
  // bold, italic, ordered list, and unordered list markup tags.
  //
  // The maximum number of allowed characters is 100,000.
  string description = 5 [(google.api.field_behavior) = REQUIRED];

  // Strongly recommended for the best service experience.
  //
  // Location(s) where the employer is looking to hire for this job posting.
  //
  // Specifying the full street address(es) of the hiring location enables
  // better API results, especially job searches by commute time.
  //
  // At most 50 locations are allowed for best search performance. If a job has
  // more locations, it is suggested to split it into multiple jobs with unique
  // [requisition_id][google.cloud.talent.v4.Job.requisition_id]s (e.g. 'ReqA'
  // becomes 'ReqA-1', 'ReqA-2', and so on.) as multiple jobs with the same
  // [company][google.cloud.talent.v4.Job.company],
  // [language_code][google.cloud.talent.v4.Job.language_code] and
  // [requisition_id][google.cloud.talent.v4.Job.requisition_id] are not
  // allowed. If the original
  // [requisition_id][google.cloud.talent.v4.Job.requisition_id] must be
  // preserved, a custom field should be used for storage. It is also suggested
  // to group the locations that close to each other in the same job for better
  // search experience.
  //
  // Jobs with multiple addresses must have their addresses with the same
  // [LocationType][google.cloud.talent.v4.Location.LocationType] to allow
  // location filtering to work properly. (For example, a Job with addresses
  // "1600 Amphitheatre Parkway, Mountain View, CA, USA" and "London, UK" may
  // not have location filters applied correctly at search time since the first
  // is a
  // [LocationType.STREET_ADDRESS][google.cloud.talent.v4.Location.LocationType.STREET_ADDRESS]
  // and the second is a
  // [LocationType.LOCALITY][google.cloud.talent.v4.Location.LocationType.LOCALITY].)
  // If a job needs to have multiple addresses, it is suggested to split it into
  // multiple jobs with same LocationTypes.
  //
  // The maximum number of allowed characters is 500.
  repeated string addresses = 6;

  // Job application information.
  ApplicationInfo application_info = 7;

  // The benefits included with the job.
  repeated JobBenefit job_benefits = 8;

  // Job compensation information (a.k.a. "pay rate") i.e., the compensation
  // that will paid to the employee.
  CompensationInfo compensation_info = 9;

  // A map of fields to hold both filterable and non-filterable custom job
  // attributes that are not covered by the provided structured fields.
  //
  // The keys of the map are strings up to 64 bytes and must match the
  // pattern: `[a-zA-Z][a-zA-Z0-9_]*`. For example, key0LikeThis or
  // KEY_1_LIKE_THIS.
  //
  // At most 100 filterable and at most 100 unfilterable keys are supported.
  // For filterable `string_values`, across all keys at most 200 values are
  // allowed, with each string no more than 255 characters. For unfilterable
  // `string_values`, the maximum total size of `string_values` across all keys
  // is 50KB.
  map<string, CustomAttribute> custom_attributes = 10;

  // The desired education degrees for the job, such as Bachelors, Masters.
  repeated DegreeType degree_types = 11;

  // The department or functional area within the company with the open
  // position.
  //
  // The maximum number of allowed characters is 255.
  string department = 12;

  // The employment type(s) of a job, for example,
  // [full time][google.cloud.talent.v4.EmploymentType.FULL_TIME] or
  // [part time][google.cloud.talent.v4.EmploymentType.PART_TIME].
  repeated EmploymentType employment_types = 13;

  // A description of bonus, commission, and other compensation
  // incentives associated with the job not including salary or pay.
  //
  // The maximum number of allowed characters is 10,000.
  string incentives = 14;

  // The language of the posting. This field is distinct from
  // any requirements for fluency that are associated with the job.
  //
  // Language codes must be in BCP-47 format, such as "en-US" or "sr-Latn".
  // For more information, see
  // [Tags for Identifying Languages](https://tools.ietf.org/html/bcp47){:
  // class="external" target="_blank" }.
  //
  // If this field is unspecified and
  // [Job.description][google.cloud.talent.v4.Job.description] is present,
  // detected language code based on
  // [Job.description][google.cloud.talent.v4.Job.description] is assigned,
  // otherwise defaults to 'en_US'.
  string language_code = 15;

  // The experience level associated with the job, such as "Entry Level".
  JobLevel job_level = 16;

  // A promotion value of the job, as determined by the client.
  // The value determines the sort order of the jobs returned when searching for
  // jobs using the featured jobs search call, with higher promotional values
  // being returned first and ties being resolved by relevance sort. Only the
  // jobs with a promotionValue >0 are returned in a FEATURED_JOB_SEARCH.
  //
  // Default value is 0, and negative values are treated as 0.
  int32 promotion_value = 17;

  // A description of the qualifications required to perform the
  // job. The use of this field is recommended
  // as an alternative to using the more general
  // [description][google.cloud.talent.v4.Job.description] field.
  //
  // This field accepts and sanitizes HTML input, and also accepts
  // bold, italic, ordered list, and unordered list markup tags.
  //
  // The maximum number of allowed characters is 10,000.
  string qualifications = 18;

  // A description of job responsibilities. The use of this field is
  // recommended as an alternative to using the more general
  // [description][google.cloud.talent.v4.Job.description] field.
  //
  // This field accepts and sanitizes HTML input, and also accepts
  // bold, italic, ordered list, and unordered list markup tags.
  //
  // The maximum number of allowed characters is 10,000.
  string responsibilities = 19;

  // The job [PostingRegion][google.cloud.talent.v4.PostingRegion] (for example,
  // state, country) throughout which the job is available. If this field is
  // set, a [LocationFilter][google.cloud.talent.v4.LocationFilter] in a search
  // query within the job region finds this job posting if an exact location
  // match isn't specified. If this field is set to
  // [PostingRegion.NATION][google.cloud.talent.v4.PostingRegion.NATION] or
  // [PostingRegion.ADMINISTRATIVE_AREA][google.cloud.talent.v4.PostingRegion.ADMINISTRATIVE_AREA],
  // setting job [Job.addresses][google.cloud.talent.v4.Job.addresses] to the
  // same location level as this field is strongly recommended.
  PostingRegion posting_region = 20;

  // Deprecated. The job is only visible to the owner.
  //
  // The visibility of the job.
  //
  // Defaults to
  // [Visibility.ACCOUNT_ONLY][google.cloud.talent.v4.Visibility.ACCOUNT_ONLY]
  // if not specified.
  Visibility visibility = 21 [deprecated = true];

  // The start timestamp of the job in UTC time zone. Typically this field
  // is used for contracting engagements. Invalid timestamps are ignored.
  google.protobuf.Timestamp job_start_time = 22;

  // The end timestamp of the job. Typically this field is used for contracting
  // engagements. Invalid timestamps are ignored.
  google.protobuf.Timestamp job_end_time = 23;

  // The timestamp this job posting was most recently published. The default
  // value is the time the request arrives at the server. Invalid timestamps are
  // ignored.
  google.protobuf.Timestamp posting_publish_time = 24;

  // Strongly recommended for the best service experience.
  //
  // The expiration timestamp of the job. After this timestamp, the
  // job is marked as expired, and it no longer appears in search results. The
  // expired job can't be listed by the
  // [ListJobs][google.cloud.talent.v4.JobService.ListJobs] API, but it can be
  // retrieved with the [GetJob][google.cloud.talent.v4.JobService.GetJob] API
  // or updated with the
  // [UpdateJob][google.cloud.talent.v4.JobService.UpdateJob] API or deleted
  // with the [DeleteJob][google.cloud.talent.v4.JobService.DeleteJob] API. An
  // expired job can be updated and opened again by using a future expiration
  // timestamp. Updating an expired job fails if there is another existing open
  // job with same [company][google.cloud.talent.v4.Job.company],
  // [language_code][google.cloud.talent.v4.Job.language_code] and
  // [requisition_id][google.cloud.talent.v4.Job.requisition_id].
  //
  // The expired jobs are retained in our system for 90 days. However, the
  // overall expired job count cannot exceed 3 times the maximum number of
  // open jobs over previous 7 days. If this threshold is exceeded,
  // expired jobs are cleaned out in order of earliest expire time.
  // Expired jobs are no longer accessible after they are cleaned
  // out.
  //
  // Invalid timestamps are ignored, and treated as expire time not provided.
  //
  // If the timestamp is before the instant request is made, the job
  // is treated as expired immediately on creation. This kind of job can
  // not be updated. And when creating a job with past timestamp, the
  // [posting_publish_time][google.cloud.talent.v4.Job.posting_publish_time]
  // must be set before
  // [posting_expire_time][google.cloud.talent.v4.Job.posting_expire_time]. The
  // purpose of this feature is to allow other objects, such as
  // [ApplicationInfo][google.cloud.talent.v4.Job.ApplicationInfo], to refer a
  // job that didn't exist in the system prior to becoming expired. If you want
  // to modify a job that was expired on creation, delete it and create a new
  // one.
  //
  // If this value isn't provided at the time of job creation or is invalid,
  // the job posting expires after 30 days from the job's creation time. For
  // example, if the job was created on 2017/01/01 13:00AM UTC with an
  // unspecified expiration date, the job expires after 2017/01/31 13:00AM UTC.
  //
  // If this value isn't provided on job update, it depends on the field masks
  // set by
  // [UpdateJobRequest.update_mask][google.cloud.talent.v4.UpdateJobRequest.update_mask].
  // If the field masks include
  // [job_end_time][google.cloud.talent.v4.Job.job_end_time], or the masks are
  // empty meaning that every field is updated, the job posting expires after 30
  // days from the job's last update time. Otherwise the expiration date isn't
  // updated.
  google.protobuf.Timestamp posting_expire_time = 25;

  // Output only. The timestamp when this job posting was created.
  google.protobuf.Timestamp posting_create_time = 26
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. The timestamp when this job posting was last updated.
  google.protobuf.Timestamp posting_update_time = 27
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Display name of the company listing the job.
  string company_display_name = 28 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. Derived details about the job posting.
  DerivedInfo derived_info = 29 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Options for job processing.
  ProcessingOptions processing_options = 30;
}
