Blame | Last modification | View Log | RSS feed
package com.spice.profitmandi.dao.entity.user;import com.spice.profitmandi.dao.enumuration.dtr.LeadCallProvider;import com.spice.profitmandi.dao.enumuration.dtr.LeadCallStatus;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.EnumType;import javax.persistence.Enumerated;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.Table;import javax.persistence.UniqueConstraint;import java.time.LocalDateTime;/*** One dial attempt against an LMS lead (SOP §12) — the call history {@code Lead} cannot hold.** <p>{@code Lead} keeps a single last-write-wins {@code disposition} and {@code recording_url} and has* no call id, duration or direction at all; {@code lead_activity} is an append-only human trail whose* {@code remark} is rendered prose. Neither can answer "how many calls, how long, which recording".* This table can, and {@code lead_activity.lead_call_id} points back at it — the same shape* {@code auth.partner_collection_remark.agent_call_log_id} already uses for collection remarks.** <p>Rows are created by the answer webhook (not by the browser), keyed on the provider's* {@code conversation_uuid}, and then advanced by the event and recording webhooks. Deliberately* separate from {@code cs.agent_call_log}: that table is Knowlarity-shaped, keyed off* {@code sip_master.caller_id}, and shared with the ticket/upsell flows this feature must not disturb.*/@Entity@Table(name = "user.lead_call",uniqueConstraints = {@UniqueConstraint(columnNames = "provider_call_uuid")})public class LeadCall {@Id@Column(name = "id", unique = true, updatable = false)@GeneratedValue(strategy = GenerationType.IDENTITY)private int id;@Column(name = "lead_id")private int leadId;/** The agent who placed the call — {@code auth.auth_user.id}. */@Column(name = "auth_id")private int authId;@Column(name = "provider")@Enumerated(EnumType.STRING)private LeadCallProvider provider;/*** The provider's own id for the agent leg. Null until the provider tells us — the row is created* on the answer webhook, which is the first moment we have a durable handle.*/@Column(name = "provider_call_uuid")private String providerCallUuid;/** Groups both legs of the bridged call; this is the correlation key across webhooks. */@Column(name = "conversation_uuid")private String conversationUuid;/** OUTBOUND for everything today; INBOUND reserved for a future retailer-callback flow. */@Column(name = "direction")private String direction;/** Outbound CLI actually presented to the retailer. */@Column(name = "from_number")private String fromNumber;@Column(name = "to_number")private String toNumber;@Column(name = "started_at")private LocalDateTime startedAt;/** When the retailer picked up. Null on an unanswered call — this is what proves contact. */@Column(name = "answered_at")private LocalDateTime answeredAt;@Column(name = "ended_at")private LocalDateTime endedAt;/** Billed/talk seconds as reported by the provider, not {@code ended - started}. */@Column(name = "duration_seconds")private Integer durationSeconds;@Column(name = "status")@Enumerated(EnumType.STRING)private LeadCallStatus status;/** Provider's recording handle, kept as provenance even after we archive our own copy. */@Column(name = "recording_uuid")private String recordingUuid;/*** Key of our own archived copy in the object store. Null until the archival sweep has stored it.** <p>Deliberately not {@code dtr.document}: that table's {@code path} is VARCHAR(30) and a* recording key is ~58 characters, so routing recordings through it made every upload fail on a* STRICT-mode truncation error.*/@Column(name = "recording_object_key")private String recordingObjectKey;/*** Failed fetch attempts. A call whose audio has expired at the provider can never succeed, and* without a ceiling it would occupy a slot in every batch forever and starve newer recordings.*/@Column(name = "recording_archive_attempts")private int recordingArchiveAttempts;@Column(name = "recording_duration")private Integer recordingDuration;/*** Our archived copy — {@code dtr.document.id}. Null until the archival worker has fetched it;* a null here with a non-null {@code recording_uuid} means "recording exists, not yet pulled".*/@Column(name = "recording_document_id")private Integer recordingDocumentId;/** The trail entry this call produced, once the agent dispositions it. */@Column(name = "lead_activity_id")private Integer leadActivityId;@Column(name = "created_timestamp")private LocalDateTime createdTimestamp;public int getId() {return id;}public void setId(int id) {this.id = id;}public int getLeadId() {return leadId;}public void setLeadId(int leadId) {this.leadId = leadId;}public int getAuthId() {return authId;}public void setAuthId(int authId) {this.authId = authId;}public LeadCallProvider getProvider() {return provider;}public void setProvider(LeadCallProvider provider) {this.provider = provider;}public String getProviderCallUuid() {return providerCallUuid;}public void setProviderCallUuid(String providerCallUuid) {this.providerCallUuid = providerCallUuid;}public String getConversationUuid() {return conversationUuid;}public void setConversationUuid(String conversationUuid) {this.conversationUuid = conversationUuid;}public String getDirection() {return direction;}public void setDirection(String direction) {this.direction = direction;}public String getFromNumber() {return fromNumber;}public void setFromNumber(String fromNumber) {this.fromNumber = fromNumber;}public String getToNumber() {return toNumber;}public void setToNumber(String toNumber) {this.toNumber = toNumber;}public LocalDateTime getStartedAt() {return startedAt;}public void setStartedAt(LocalDateTime startedAt) {this.startedAt = startedAt;}public LocalDateTime getAnsweredAt() {return answeredAt;}public void setAnsweredAt(LocalDateTime answeredAt) {this.answeredAt = answeredAt;}public LocalDateTime getEndedAt() {return endedAt;}public void setEndedAt(LocalDateTime endedAt) {this.endedAt = endedAt;}public Integer getDurationSeconds() {return durationSeconds;}public void setDurationSeconds(Integer durationSeconds) {this.durationSeconds = durationSeconds;}public LeadCallStatus getStatus() {return status;}public void setStatus(LeadCallStatus status) {this.status = status;}public String getRecordingUuid() {return recordingUuid;}public void setRecordingUuid(String recordingUuid) {this.recordingUuid = recordingUuid;}public Integer getRecordingDuration() {return recordingDuration;}public void setRecordingDuration(Integer recordingDuration) {this.recordingDuration = recordingDuration;}public String getRecordingObjectKey() {return recordingObjectKey;}public void setRecordingObjectKey(String recordingObjectKey) {this.recordingObjectKey = recordingObjectKey;}public int getRecordingArchiveAttempts() {return recordingArchiveAttempts;}public void setRecordingArchiveAttempts(int recordingArchiveAttempts) {this.recordingArchiveAttempts = recordingArchiveAttempts;}public Integer getRecordingDocumentId() {return recordingDocumentId;}public void setRecordingDocumentId(Integer recordingDocumentId) {this.recordingDocumentId = recordingDocumentId;}public Integer getLeadActivityId() {return leadActivityId;}public void setLeadActivityId(Integer leadActivityId) {this.leadActivityId = leadActivityId;}public LocalDateTime getCreatedTimestamp() {return createdTimestamp;}public void setCreatedTimestamp(LocalDateTime createdTimestamp) {this.createdTimestamp = createdTimestamp;}@Overridepublic String toString() {return "LeadCall [id=" + id + ", leadId=" + leadId + ", authId=" + authId + ", provider=" + provider+ ", conversationUuid=" + conversationUuid + ", status=" + status+ ", durationSeconds=" + durationSeconds + "]";}}