diff --git a/.github/workflows/publish-alpha.yml b/.github/workflows/publish-alpha.yml new file mode 100644 index 0000000..3bb90e8 --- /dev/null +++ b/.github/workflows/publish-alpha.yml @@ -0,0 +1,29 @@ +on: + push: + tags: + - '*-alpha*' + +jobs: + publish-alpha: + name: Publish Alpha + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Node v20 + uses: actions/setup-node@v4 + with: + node-version: 20 + registry-url: 'https://registry.npmjs.org' + - name: Set version from tag + run: | + TAG=${GITHUB_REF#refs/tags/} + VERSION=${TAG#v} + npm version "$VERSION" --no-git-tag-version + - name: Install dependencies + run: npm install + - name: Build + run: npm run build + - name: Publish alpha + run: npm publish --tag alpha --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/docs/BOXCREATEREQUEST.md b/docs/BOXCREATEREQUEST.md new file mode 100644 index 0000000..fe0b7db --- /dev/null +++ b/docs/BOXCREATEREQUEST.md @@ -0,0 +1,199 @@ +# BoxCreateRequest Module + +This document covers the `BoxCreateRequest` model — a change request type for proposing the creation of a new box, optionally with an initial topology/design structure. + +## Models + +### BoxCreateRequest + +```typescript +type BoxCreateRequest = { + // BaseChangeRequest fields + id: string; + createdAt: Date | string; + updatedAt: Date | string; + deletedAt?: Date; + code: string; + applicable?: boolean; + createdBy: string; + review?: { + by: { id: string; name: string; username: string }; + at: Date | string; + }; + observation?: string; + description: string; + // BoxCreate-specific fields + kind: "BoxCreate"; + status: "pending" | "approved" | "rejected"; + element?: { + id?: string; + kind: "box"; + }; + boxData: { + boxType: string; + project: string; + coords: [number, number]; + name?: string; + hierarchyLevel: number; + }; + structure?: { + topology: Topology; + design: BoxDesign; + }; + actions?: ChangeTopologyAction[]; + isStructureEmpty?: boolean; +}; +``` + +### CreateBoxCreateRequestDTO + +```typescript +type CreateBoxCreateRequestDTO = { + kind?: "BoxCreate"; + description: string; + structure?: { + topology: Topology; + design: BoxDesign; + }; + actions?: ChangeTopologyAction[]; + isStructureEmpty?: boolean; + boxData: { + boxType: string; + project: string; + coords: [number, number]; + name?: string; + hierarchyLevel?: number; // min 2 + }; +}; +``` + +### BoxCreateRequestApprove + +Sent when approving a BoxCreateRequest. Optionally overrides box properties at approval time. + +```typescript +type BoxCreateRequestApprove = { + observation?: string; + boxData?: Partial; +}; +``` + +### BoxCreateRequestReject + +```typescript +type BoxCreateRequestReject = { + observation: string; // required, non-empty +}; +``` + +## Example Usage + +### Creating a BoxCreateRequest + +```typescript +import OZMapSDK, { CreateBoxCreateRequestDTO } from 'ozmapsdk'; + +const sdk = new OZMapSDK('ozmapURL', { apiKey: 'yourApiKey' }); + +const dto: CreateBoxCreateRequestDTO = { + description: "New distribution box at Rua das Flores", + boxData: { + boxType: "boxTypeId", + project: "projectId", + coords: [-48.527442, -27.586604], + name: "CTO-01", + hierarchyLevel: 2, + }, +}; + +sdk.boxCreateRequest.create(dto).then((cr) => { + console.log('Box create request created:', cr.id, cr.status); +}); +``` + +### Creating with initial structure + +```typescript +const dto: CreateBoxCreateRequestDTO = { + description: "New CTO with pre-built topology", + boxData: { + boxType: "boxTypeId", + project: "projectId", + coords: [-48.527442, -27.586604], + name: "CTO-02", + }, + structure: { + topology: { + project: "projectId", + splitters: { + "spl1": { + id: "spl1", + name: "Splitter 1:8", + isDrop: false, + implanted: true, + connectables: { input: [null], output: [null, null, null, null, null, null, null, null] }, + ports: [], + isBalanced: true, + orientation: "right", + mostAttenuatedPort: 0, + inputConnectionType: 0, + outputConnectionType: 0, + code: "1:8", + }, + }, + }, + design: { + project: "projectId", + positions: { + splitters: { "spl1": { x: 200, y: 200 } }, + }, + }, + }, +}; + +sdk.boxCreateRequest.create(dto).then((cr) => { + console.log('Created:', cr.id); +}); +``` + +### Approving a BoxCreateRequest + +```typescript +sdk.boxCreateRequest.approveById("requestId", { + observation: "Approved — correct location confirmed", + boxData: { + name: "CTO-01-Final", + }, +}).then((result) => { + console.log('Approved, resulting box:', result); +}); +``` + +### Rejecting a BoxCreateRequest + +```typescript +sdk.boxCreateRequest.rejectById("requestId", { + observation: "Location conflicts with existing infrastructure", +}).then((result) => { + console.log('Rejected:', result); +}); +``` + +### Fetching BoxCreateRequests + +```typescript +// Find all pending +sdk.boxCreateRequest.find({ + filter: [{ property: 'status', value: 'pending', operator: 'eq' }], +}).then((result) => { + console.log('Pending box create requests:', result.rows); +}); + +// Find by ID +sdk.boxCreateRequest.findById("requestId").then((cr) => { + console.log('Request:', cr); +}); + +// Delete +sdk.boxCreateRequest.deleteById("requestId"); +``` diff --git a/docs/BOXDESIGN.md b/docs/BOXDESIGN.md new file mode 100644 index 0000000..af17528 --- /dev/null +++ b/docs/BOXDESIGN.md @@ -0,0 +1,279 @@ +# BoxDesign Module + +This document provides a concise guide to the BoxDesign module, including BoxDesign, Topology, BoxStructure, and their related sub-types. + +## Models + +### BoxDesign + +Defines the visual design/layout of a box, including element positions within the box diagram. + +```typescript +type BoxDesign = { + id?: string | null; + box?: string; + project?: string; + isTemplate?: boolean; + template?: string | null; + positions?: DesignPositions; +}; +``` + +### DesignPositions + +Defines the positions of elements within the box design. + +```typescript +type DesignPositions = { + cables?: Record; + connectors?: Record; + dios?: Record; + drops?: Record; + fusions?: Record; + splitters?: Record; + switches?: Record; + fibers?: Record; + cords?: Record; + passings?: Record; + postits?: PostItPositions; + children?: Record[]; +}; +``` + +### SimplePoint + +```typescript +type SimplePoint = { + x: number; + y: number; +}; +``` + +### ComposedPosition + +```typescript +type ComposedPosition = { + vertices: SimplePoint[]; + labels?: Label[]; +}; +``` + +### Topology + +Defines the logical topology of a box, including all its cables, connectors, splitters, and other network elements. + +```typescript +type Topology = { + box?: string; + project?: string; + id?: string; + cables?: Record; + drops?: Record; + switches?: Record; + connectors?: Record; + splitters?: Record; + passings?: Record; + fusions?: Record; + dios?: Record; + cords?: TopologyCords; + extraData?: any; + checksum?: string; +}; +``` + +### TopologyCables + +```typescript +type TopologyCables = { + id: string; + name: string; + looseNumber: number; + orientation: string; + observation?: string; + implanted: boolean; + fibersColourMap: string[]; + groupsColourMap: string[]; + defaultFiberColor: string; + defaultTubeColor: string; + fibers: string[]; + project: string; + cableType?: string; +}; +``` + +### TopologyDrops + +Extends TopologyCables with property data for drop cables. + +```typescript +type TopologyDrops = TopologyCables & { + propertyData: { + address?: string | null; + coords?: [number, number]; + lat?: number; + lng?: number; + id: string; + observation: string; + client?: TopologyClients | null; + }; +}; +``` + +### TopologyConnectors + +```typescript +type TopologyConnectors = { + id: string; + name: string; + isDrop: boolean; + implanted: boolean; + connectorType?: string; + observation?: string; + connectables: (string | null)[]; +}; +``` + +### TopologySplitter + +```typescript +type TopologySplitter = { + id: string; + name: string; + isDrop: boolean; + implanted: boolean; + connectorType?: string; + observation?: string; + connectables: { + input: (string | null)[]; + output: (string | null)[]; + }; + ports: SplitterPort[]; + isBalanced: boolean; + orientation: string; + mostAttenuatedPort: number; + inputConnectionType: number; + outputConnectionType: number; + code: string; +}; +``` + +### TopologyDIO + +```typescript +type TopologyDIO = { + id: string; + name: string; + isDrop: boolean; + implanted: boolean; + connectorType?: string; + observation?: string; + connectables: { + input: (string | null)[]; + output: (string | null)[]; + }; + tray_number?: number; + input_label?: string[]; + output_label?: string[]; +}; +``` + +### BoxStructure + +Combines topology and design into a single structure. + +```typescript +type BoxStructure = { + topology: Topology; + design: BoxDesign; +}; +``` + +## Example Usage + +### Importing types + +```typescript +import OZMapSDK, { + BoxDesign, + BoxStructure, + Topology, + TopologyCables, + TopologyConnectors, + TopologySplitter, + DesignPositions, +} from 'ozmapsdk'; +``` + +### Getting a Box Structure + +`getStructure` calls the topology and design endpoints in parallel and merges the result into a `BoxStructure`. + +```typescript +import OZMapSDK from 'ozmapsdk'; + +const sdk = new OZMapSDK('ozmapURL', { apiKey: 'yourApiKey' }); + +// Works on both sdk.box and sdk.building +sdk.box.getStructure('boxId').then((structure) => { + console.log('Topology:', structure.topology); + console.log('Design:', structure.design); +}); +``` + +### Updating a Box Structure + +`updateStructure` sends both topology and design together to the `PATCH base-boxes/:id/structure` endpoint. + +```typescript +import OZMapSDK, { BoxStructure } from 'ozmapsdk'; + +const sdk = new OZMapSDK('ozmapURL', { apiKey: 'yourApiKey' }); + +const updatedStructure: BoxStructure = { + topology: { + box: "boxId", + project: "projectId", + cables: { + "cable1": { + id: "cable1", + name: "Cable 1", + looseNumber: 12, + orientation: "left", + implanted: true, + fibersColourMap: ["blue", "orange", "green"], + groupsColourMap: ["blue"], + defaultFiberColor: "blue", + defaultTubeColor: "blue", + fibers: ["fiber1", "fiber2"], + project: "projectId", + }, + }, + connectors: { + "conn1": { + id: "conn1", + name: "Connector 1", + isDrop: false, + implanted: true, + connectables: ["fiber1", null], + }, + }, + }, + design: { + box: "boxId", + project: "projectId", + positions: { + cables: { "cable1": { x: 100, y: 200 } }, + connectors: { "conn1": { x: 150, y: 250 } }, + }, + }, +}; + +sdk.box.updateStructure('boxId', updatedStructure).then(() => { + console.log('Structure updated'); +}); + +// Also works for buildings: +sdk.building.getStructure('buildingId').then((structure) => { + console.log('Building structure:', structure); +}); +``` diff --git a/docs/BOXSTRUCTURECHANGEREQUEST.md b/docs/BOXSTRUCTURECHANGEREQUEST.md new file mode 100644 index 0000000..298678c --- /dev/null +++ b/docs/BOXSTRUCTURECHANGEREQUEST.md @@ -0,0 +1,198 @@ +# BoxStructureChangeRequest Module + +This document covers the `BoxStructureChangeRequest` model — a change request type for modifying the internal structure (topology + design) of an existing box or building. + +## Models + +### BoxStructureChangeRequest + +```typescript +type BoxStructureChangeRequest = { + // BaseChangeRequest fields + id: string; + createdAt: Date | string; + updatedAt: Date | string; + deletedAt?: Date; + code: string; + applicable?: boolean; + createdBy: string; + review?: { + by: { id: string; name: string; username: string }; + at: Date | string; + }; + observation?: string; + description: string; + // BoxStructure-specific fields + kind: "BoxStructure"; + status: "pending" | "approved" | "rejected"; + element: { + id: string; + kind: "box" | "building"; + }; + structure: { + topology: Topology; + design: BoxDesign; + }; + actions: ChangeTopologyAction[]; + isStructureEmpty?: boolean; +}; +``` + +### CreateBoxStructureChangeRequestDTO + +```typescript +type CreateBoxStructureChangeRequestDTO = { + kind?: "BoxStructure"; + element: { + id: string; + kind: "box" | "building"; + }; + description: string; + structure: { + topology: Topology; + design: BoxDesign; + }; + actions?: ChangeTopologyAction[]; + isStructureEmpty?: boolean; +}; +``` + +### ChangeTopologyAction + +Discriminated union of actions that describe topology changes: + +```typescript +// Connect or disconnect two elements +type ConnectDisconnectAction = { + action: "connect" | "disconnect"; + data: { + elementA: ConnectionElement; + elementB: ConnectionElement; + }; +}; + +// Create a new topology element +type CreateElementAction = { + action: "create"; + data: { element: string; identifier: string; kind: ElementKind }; +}; + +// Delete a topology element +type DeleteElementAction = { + action: "delete"; + data: { element: string; identifier: string; kind: ElementKind }; +}; + +// Update a property of a topology element +type UpdateElementAction = { + action: "update"; + data: { + element: string; + identifier: string; + kind: ElementKind; + property: string; + newValue: { value: string | number; identifier?: string }; + oldValue: { value: string | number; identifier?: string }; + }; +}; +``` + +## Example Usage + +### Creating a BoxStructureChangeRequest + +```typescript +import OZMapSDK, { CreateBoxStructureChangeRequestDTO } from 'ozmapsdk'; + +const sdk = new OZMapSDK('ozmapURL', { apiKey: 'yourApiKey' }); + +const dto: CreateBoxStructureChangeRequestDTO = { + element: { + id: "boxId", + kind: "box", + }, + description: "Updating internal fiber connections", + structure: { + topology: { + box: "boxId", + project: "projectId", + cables: {}, + connectors: { + "conn1": { + id: "conn1", + name: "Connector 1", + isDrop: false, + implanted: true, + connectables: ["fiber1", "fiber2"], + }, + }, + }, + design: { + box: "boxId", + project: "projectId", + positions: { + connectors: { "conn1": { x: 150, y: 250 } }, + }, + }, + }, + actions: [ + { + action: "connect", + data: { + elementA: { + element: "connectorId", + identifier: "conn1", + kind: "Connector", + port: 0, + }, + elementB: { + element: "fiberId", + identifier: "fiber1", + kind: "Fiber", + port: 0, + }, + }, + }, + ], +}; + +sdk.boxStructureChangeRequest.create(dto).then((cr) => { + console.log('Change request created:', cr.id, cr.status); +}); +``` + +### Reviewing (Approving / Rejecting) + +```typescript +// Approve +await sdk.boxStructureChangeRequest.reviewById("changeRequestId", { + status: "approved", + observation: "Looks good", +}); + +// Reject +await sdk.boxStructureChangeRequest.reviewById("changeRequestId", { + status: "rejected", + observation: "Connections are incorrect", +}); +``` + +### Fetching BoxStructureChangeRequests + +```typescript +// Find all (paginated) +sdk.boxStructureChangeRequest.find({ + filter: [{ property: 'status', value: 'pending', operator: 'eq' }], +}).then((result) => { + console.log('Pending requests:', result.rows); + console.log('Total:', result.total); +}); + +// Find by ID +sdk.boxStructureChangeRequest.findById("changeRequestId").then((cr) => { + console.log('Change request:', cr); +}); + +// Delete +sdk.boxStructureChangeRequest.deleteById("changeRequestId"); +``` diff --git a/docs/CHANGEREQUEST.md b/docs/CHANGEREQUEST.md new file mode 100644 index 0000000..e6cce4d --- /dev/null +++ b/docs/CHANGEREQUEST.md @@ -0,0 +1,73 @@ +# ChangeRequest Module + +This document covers the base `ChangeRequest` model. For specific change request types, see: +- [BOXSTRUCTURECHANGEREQUEST.md](./BOXSTRUCTURECHANGEREQUEST.md) — modifying an existing box's internal structure +- [BOXCREATEREQUEST.md](./BOXCREATEREQUEST.md) — proposing the creation of a new box + +## Models + +### BaseChangeRequest + +Base model shared by all change request types. + +```typescript +type BaseChangeRequest = { + id: string; + createdAt: Date | string; + updatedAt: Date | string; + deletedAt?: Date; + kind: "BoxStructure" | "BoxCreate"; + status: "pending" | "approved" | "rejected"; + element: { + id: string; + kind: string; + }; + code: string; + applicable?: boolean; + createdBy: string; + review?: { + by: { id: string; name: string; username: string }; + at: Date | string; + }; + observation?: string; + description: string; +}; +``` + +## SDK Proxies + +| Proxy | SDK property | Route | +|---|---|---| +| Base ChangeRequest (read-only) | `sdk.changeRequest` | `change-requests` | +| BoxStructureChangeRequest | `sdk.boxStructureChangeRequest` | `change-requests/box-structures` | +| BoxCreateRequest | `sdk.boxCreateRequest` | `box-create-requests` | + +## Example Usage + +### Fetching all ChangeRequests + +```typescript +import OZMapSDK from 'ozmapsdk'; + +const sdk = new OZMapSDK('ozmapURL', { apiKey: 'yourApiKey' }); + +// Fetch all change requests (all kinds) +sdk.changeRequest.find().then((result) => { + console.log('Change requests:', result.rows); + console.log('Total:', result.total); +}); + +// Find by ID +sdk.changeRequest.findById("changeRequestId").then((cr) => { + console.log('Change request:', cr); +}); + +// Fetch only pending +sdk.changeRequest.find({ + filter: [{ property: 'status', value: 'pending', operator: 'eq' }], +}).then((result) => { + console.log('Pending:', result.rows); +}); +``` +}); +``` diff --git a/docs/POLYGONREPORT.md b/docs/POLYGONREPORT.md new file mode 100644 index 0000000..b3e2668 --- /dev/null +++ b/docs/POLYGONREPORT.md @@ -0,0 +1,393 @@ +# PolygonReport Module + +This document provides a guide to the PolygonReport module, including the main model, report data types, summary types, and custom operations (move, tags, project migration, element reports). + +## Models + +### PolygonReport + +Represents a spatial polygon-based report generated for infrastructure within a geographic area. + +```typescript +type PolygonReport = { + id: string; + createdAt: Date; + updatedAt: Date; + date?: Date; + polygon: { + type: 'Polygon'; + coordinates: number[][][]; + }; + name?: string | null; + project: string; + isGeneralReport: boolean; + data?: PolygonReportData | ReportSummary; +}; +``` + +### CreatePolygonReportDTO + +```typescript +type CreatePolygonReportDTO = { + _id?: string | null; + polygon: { + type: 'Polygon'; + coordinates: number[][][]; + }; + name?: string | null; + project?: string; + isGeneralReport?: boolean | null; + extra?: { + kind?: string; // e.g. 'generaltab', 'boxgrid', 'cablegrid' + force?: boolean; + }; +}; +``` + +### PolygonReportExtraKindReference + +Available `extra.kind` values that map to report kinds on the server: + +```typescript +const PolygonReportExtraKindReference = { + GENERAL_TAB: 'generaltab', // → general (summary) + CABLE_GRID: 'cablegrid', // → cables + BOX_GRID: 'boxgrid', // → boxes + POP_GRID: 'popgrid', // → pops + SHELF_GRID: 'shelfgrid', // → shelfs + SECTOR_GRID: 'sectorgrid', // → sectors + CLIENT_GRID: 'clientgrid', // → clients + PROSPECT_GRID: 'prospectgrid', // → prospects + PROPERTY_GRID: 'propertygrid', // → properties + BUILDING_GRID: 'buildinggrid', // → buildings + POLE_GRID: 'polegrid', // → poles + SPLITTER_GRID: 'splittergrid', // → splitters + PENDENCY_GRID: 'pendencygrid', // → pendencies + REGION_GRID: 'regiongrid', // → regions + JUNCTION_BOX_GRID: 'junctionboxgrid', // → junctionBoxes + DUCT_GRID: 'ductgrid', // → ducts + TOWER_GRID: 'towergrid', // → towers +}; +``` + +### PolygonReportKind + +Available report kinds for filtering report data generation: + +```typescript +const PolygonReportKind = { + ALL: 'all', + GENERAL: 'general', + CABLES: 'cables', + BOXES: 'boxes', + POPS: 'pops', + SHELFS: 'shelfs', + SECTORS: 'sectors', + CLIENTS: 'clients', + PROSPECTS: 'prospects', + PROPERTIES: 'properties', + BUILDINGS: 'buildings', + POLES: 'poles', + SPLITTERS: 'splitters', + PENDENCIES: 'pendencies', + REGIONS: 'regions', + JUNCTION_BOXES: 'junctionBoxes', + DUCTS: 'ducts', + TOWERS: 'torres', +}; +``` + +## Report Data + +When `isGeneralReport` is `false`, the `data` field contains a detailed `PolygonReportData` with arrays of each element type found within the polygon. When `isGeneralReport` is `true`, `data` contains a `ReportSummary` with aggregated counters. + +### PolygonReportData + +```typescript +type PolygonReportData = { + boxes: ReportBox[]; + reserves: ReportReserve[]; + pops: ReportPop[]; + shelfs: ReportShelf[]; + sectors: ReportSector[]; + buildings: ReportBuilding[]; + poles: ReportPole[]; + properties: ReportProperty[]; + points?: ReportPoint[]; + prospects: ReportProspect[]; + cables: ReportCable[]; + clients: ReportClient[]; + junctionBoxes: ReportJunctionBox[]; + ducts: ReportDuct[]; + splitters: ReportConnector[]; + pendencies: ReportPendency[]; + regions: ReportRegion[]; + towers: ReportTower[]; + errors: any[]; +}; +``` + +### ReportSummary (General Report) + +```typescript +type ReportSummary = { + id?: string; + boxes: BoxesSummary[]; + cables: CablesSummary[]; + clients: ClientsSummary[]; + properties: PropertiesSummary[]; + poles: PolesSummary[]; + pops: PopsSummary[]; + pendencies: PendencySummary; + splitters: ReportConnector[]; + buildings: ReportBuilding[]; + errors: ReportError[]; +}; +``` + +### ConnectorAttenuation (Box splitters) + +```typescript +type ConnectorAttenuation = { + id: string; + name: string; + kind: string; + isBalanced: boolean; + parent: string; + project: string; + implanted: boolean; + parentName: string; + isDrop: boolean; + observation: string; + connectorType: string; + connectorTypeCode: string; + input: number; + availability: number; + total: number; + mostAttenuatedPort: number; + min_potency: number; + max_potency: number; + createdAt: Date; +}; +``` + +### PopConnectorAttenuation (POP splitters) + +```typescript +type PopConnectorAttenuation = { + id: string; + name: string; + kind: string; + parent: string; + parentName: string; + project: string; + implanted: boolean; + isDrop: boolean; + observation: string; + connectorType: string; + connectorTypeCode: string; + input: number; + total: number; + createdAt: Date; + size?: string; + fabricationDate?: Date; + radioCapacity?: string; + potency?: number; + autonomy?: string; + serialNumber?: string; + shelf?: string; + tags?: string[]; + posts?: number; +}; +``` + +## Custom Operations + +### MoveReport + +Translates all elements in a polygon report by a coordinate offset. + +```typescript +type MoveReport = { + lat: number; + lng: number; +}; +``` + +### ReportTags + +Add or remove tags from all elements within a report. + +```typescript +type ReportTags = { + tags: string[]; +}; +``` + +### UpdateProject + +Migrates report elements from the current project to a new project. + +```typescript +type UpdateProject = { + project: string; + ids: string[]; +}; +``` + +### ElementsReport + +Generate a complete or count report for specific element IDs. + +```typescript +type ElementsReport = { + elements: { + cableIds?: string[]; + boxIds?: string[]; + popIds?: string[]; + shelfIds?: string[]; + sectorIds?: string[]; + clientIds?: string[]; + prospectIds?: string[]; + propertyIds?: string[]; + buildingIds?: string[]; + poleIds?: string[]; + connectorIds?: string[]; + pendencyIds?: string[]; + regionIds?: string[]; + junctionBoxIds?: string[]; + ductIds?: string[]; + towerIds?: string[]; + }; +}; +``` + +## Example Usage + +### Importing types + +```typescript +import OZMapSDK, { + PolygonReport, + CreatePolygonReportDTO, + PolygonReportKind, + PolygonReportExtraKindReference, + MoveReport, + ReportTags, + ElementsReport, +} from 'ozmapsdk'; +``` + +### Creating a Polygon Report + +```typescript +const sdk = new OZMapSDK('ozmapURL', { apiKey: 'yourApiKey' }); + +const report: CreatePolygonReportDTO = { + polygon: { + type: 'Polygon', + coordinates: [[ + [-48.530045, -27.57414], + [-48.52983, -27.587263], + [-48.523779, -27.587225], + [-48.523264, -27.573645], + [-48.530045, -27.57414], + ]], + }, + name: 'Relatório: 17/03/2026', + project: 'projectId', + isGeneralReport: null, + extra: { + kind: PolygonReportExtraKindReference.GENERAL_TAB, + force: true, + }, +}; + +sdk.polygonReport.create(report).then((created) => { + console.log('Report created:', created.id); +}); +``` + +### Listing Reports + +```typescript +sdk.polygonReport.find().then((result) => { + console.log('Reports:', result.rows); +}); +``` + +### Moving Report Elements + +Translates all elements in a report by a coordinate offset. + +```typescript +sdk.polygonReport.moveById('reportId', { lat: 0.001, lng: -0.002 }).then(() => { + console.log('Elements moved'); +}); +``` + +### Adding Tags + +```typescript +sdk.polygonReport.addTagsById('reportId', { tags: ['tagId1', 'tagId2'] }).then(() => { + console.log('Tags added'); +}); +``` + +### Removing Tags + +```typescript +sdk.polygonReport.removeTagsById('reportId', { tags: ['tagId1'] }).then(() => { + console.log('Tags removed'); +}); +``` + +### Migrating Elements to Another Project + +```typescript +sdk.polygonReport.updateProject({ + project: 'newProjectId', + ids: ['reportId1', 'reportId2'], +}).then((results) => { + results.forEach((r) => { + console.log('Record:', r.record, 'Error:', r.error); + }); +}); +``` + +### Complete Elements Report + +Generate a detailed report for specific element IDs. + +```typescript +sdk.polygonReport.createCompleteElementsReport({ + elements: { + boxIds: ['box1', 'box2'], + cableIds: ['cable1'], + }, +}).then((report) => { + console.log('Complete report:', report); +}); +``` + +### Count Elements Report + +Generate a summary count report for specific element IDs. + +```typescript +sdk.polygonReport.createCountElementsReport({ + elements: { + poleIds: ['pole1', 'pole2'], + }, +}).then((report) => { + console.log('Count report:', report); +}); +``` + +### Deleting a Report + +```typescript +sdk.polygonReport.deleteById('reportId').then(() => { + console.log('Report deleted'); +}); +``` diff --git a/package.json b/package.json index 40a23b4..62de126 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@ozmap/ozmap-sdk", - "version": "1.1.7", + "version": "1.1.8", "description": "Use this sdk to access ozmap plataform and connect it to your own systems. ", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -13,7 +13,9 @@ "lint": "eslint ./src --ext .cjs,.js,.ts", "lint:fix": "eslint ./src --ext .cjs,.js,.ts --fix", "test": "ts-node test", - "publish:alpha": "npm run build && npm publish --tag alpha" + "publish:alpha": "npm run build && npm publish --tag alpha", + "link:local": "npm run build && npm link", + "unlink:local": "npm unlink -g @ozmap/ozmap-sdk" }, "files": [ "dist/**/*" @@ -62,4 +64,4 @@ "tsup": "^8.0.2", "typescript": "^4.9.5" } -} +} \ No newline at end of file diff --git a/src/OZMapSDK.ts b/src/OZMapSDK.ts index 301338f..f997958 100644 --- a/src/OZMapSDK.ts +++ b/src/OZMapSDK.ts @@ -58,6 +58,10 @@ import { DuctTypeProxy, PostProxy, FileProxy, + ChangeRequestProxy, + BoxStructureChangeRequestProxy, + BoxCreateRequestProxy, + PolygonReportProxy, } from './proxy'; class OZMapSDK { @@ -120,6 +124,10 @@ class OZMapSDK { public readonly ductType: DuctTypeProxy; public readonly post: PostProxy; public readonly file: FileProxy; + public readonly changeRequest: ChangeRequestProxy; + public readonly boxStructureChangeRequest: BoxStructureChangeRequestProxy; + public readonly boxCreateRequest: BoxCreateRequestProxy; + public readonly polygonReport: PolygonReportProxy; constructor(ozmapURL: string, options: ConstructorParameters[1]) { this.apiInstance = new Api(ozmapURL, options); @@ -182,6 +190,10 @@ class OZMapSDK { this.ductType = new DuctTypeProxy(this.apiInstance); this.post = new PostProxy(this.apiInstance); this.file = new FileProxy(this.apiInstance); + this.changeRequest = new ChangeRequestProxy(this.apiInstance); + this.boxStructureChangeRequest = new BoxStructureChangeRequestProxy(this.apiInstance); + this.boxCreateRequest = new BoxCreateRequestProxy(this.apiInstance); + this.polygonReport = new PolygonReportProxy(this.apiInstance); } } diff --git a/src/interface/model/BoxStructure/BoxDesign.ts b/src/interface/model/BoxStructure/BoxDesign.ts new file mode 100644 index 0000000..a926532 --- /dev/null +++ b/src/interface/model/BoxStructure/BoxDesign.ts @@ -0,0 +1,33 @@ +import { z } from 'zod'; +import { stringOrObjectId } from '../BaseModel'; +import { PostItPositionsSchema } from './Postit'; +import { ConnectablePositionsSchema, ElementPositionsSchema } from './Positions'; + +const DesignPositionsSchema = z.object({ + cables: ElementPositionsSchema.optional(), + connectors: ElementPositionsSchema.optional(), + dios: ElementPositionsSchema.optional(), + drops: ElementPositionsSchema.optional(), + fusions: ElementPositionsSchema.optional(), + splitters: ElementPositionsSchema.optional(), + switches: ElementPositionsSchema.optional(), + fibers: ConnectablePositionsSchema.optional(), + cords: ConnectablePositionsSchema.optional(), + passings: ConnectablePositionsSchema.optional(), + postits: PostItPositionsSchema.optional(), + children: z.array(z.record(z.unknown())).optional(), +}); + +const BoxDesignSchema = z.object({ + id: z.string().nullable().optional(), + box: stringOrObjectId.optional(), + project: stringOrObjectId.optional(), + isTemplate: z.boolean().optional(), + template: z.string().nullable().optional(), + positions: DesignPositionsSchema.optional(), +}); + +type DesignPositions = z.infer; +type BoxDesign = z.infer; + +export { DesignPositionsSchema, DesignPositions, BoxDesignSchema, BoxDesign }; diff --git a/src/interface/model/BoxStructure/BoxStructure.ts b/src/interface/model/BoxStructure/BoxStructure.ts new file mode 100644 index 0000000..b7f32c9 --- /dev/null +++ b/src/interface/model/BoxStructure/BoxStructure.ts @@ -0,0 +1,12 @@ +import { z } from 'zod'; +import { BoxDesignSchema } from './BoxDesign'; +import { TopologySchema } from './Topology'; + +const BoxStructureSchema = z.object({ + topology: TopologySchema, + design: BoxDesignSchema, +}); + +type BoxStructure = z.infer; + +export { BoxStructureSchema, BoxStructure }; diff --git a/src/interface/model/BoxStructure/Positions.ts b/src/interface/model/BoxStructure/Positions.ts new file mode 100644 index 0000000..4067215 --- /dev/null +++ b/src/interface/model/BoxStructure/Positions.ts @@ -0,0 +1,55 @@ +import { z } from 'zod'; + +const Orientations = ['top', 'bottom', 'left', 'right'] as const; + +const OrientationSchema = z.enum(Orientations); + +const LabelSchema = z.object({ + position: z.object({ + offset: z.number(), + distance: z.number(), + }), +}); + +const SimplePointSchema = z.object({ + x: z.number(), + y: z.number(), +}); + +const OrientedPositionSchema = SimplePointSchema.extend({ + orientation: OrientationSchema.optional(), +}); + +const ComposedPositionSchema = z.object({ + vertices: z.array(SimplePointSchema), + labels: z.array(LabelSchema).optional(), +}); + +const ElementPositionsSchema = z.record(SimplePointSchema); +const ConnectablePositionsSchema = z.record(ComposedPositionSchema); + +type Orientation = z.infer; +type Label = z.infer; +type SimplePoint = z.infer; +type OrientedPosition = z.infer; +type ComposedPosition = z.infer; +type ElementPositions = z.infer; +type ConnectablePositions = z.infer; + +export { + Orientations, + OrientationSchema, + Orientation, + LabelSchema, + Label, + SimplePointSchema, + SimplePoint, + OrientedPositionSchema, + OrientedPosition, + ComposedPositionSchema, + ComposedPosition, + ElementPositionsSchema, + ElementPositions, + ConnectablePositionsSchema, + ConnectablePositions, +}; diff --git a/src/interface/model/BoxStructure/Postit.ts b/src/interface/model/BoxStructure/Postit.ts new file mode 100644 index 0000000..7f17252 --- /dev/null +++ b/src/interface/model/BoxStructure/Postit.ts @@ -0,0 +1,25 @@ +import { z } from 'zod'; +import { SimplePointSchema } from './Positions'; + +const PostItPropsSchema = z.object({ + id: z.string(), + bgcolor: z.string(), + bordercolor: z.string(), + owner: z.string(), + project: z.string(), + text: z.string(), + width: z.number(), + height: z.number(), + createdAt: z.string(), +}); + +const PostItPositionsSchema = z.array( + SimplePointSchema.extend({ + config: PostItPropsSchema, + }), +); + +type PostItProps = z.infer; +type PostItPositions = z.infer; + +export { PostItPropsSchema, PostItProps, PostItPositionsSchema, PostItPositions }; diff --git a/src/interface/model/BoxStructure/Topology.ts b/src/interface/model/BoxStructure/Topology.ts new file mode 100644 index 0000000..7c1448c --- /dev/null +++ b/src/interface/model/BoxStructure/Topology.ts @@ -0,0 +1,40 @@ +import { z } from 'zod'; +import { + TopologyConnectorsSchema, + TopologySplitterSchema, + TopologyDIOSchema, + TopologyPassingSchema, +} from './TopologyConnectors'; +import { TopologyCablesSchema, TopologyDropsSchema } from './TopologyCables'; + +const TopologyCordItemSchema = z.object({ + id: z.string(), + name: z.string().optional(), + connectors: z.array(z.string().nullable()), + observation: z.string().optional(), +}); + +const TopologyCordsSchema = z.record(TopologyCordItemSchema); + +const TopologySchema = z.object({ + box: z.string().optional(), + project: z.string().optional(), + id: z.string().optional(), + cables: z.record(TopologyCablesSchema).optional(), + drops: z.record(TopologyDropsSchema).optional(), + switches: z.record(TopologyConnectorsSchema).optional(), + connectors: z.record(TopologyConnectorsSchema).optional(), + splitters: z.record(TopologySplitterSchema).optional(), + passings: z.record(TopologyPassingSchema).optional(), + fusions: z.record(TopologyConnectorsSchema).optional(), + dios: z.record(TopologyDIOSchema).optional(), + cords: TopologyCordsSchema.optional(), + extraData: z.any().optional(), + checksum: z.string().optional(), +}); + +type TopologyCordItem = z.infer; +type TopologyCords = z.infer; +type Topology = z.infer; + +export { TopologyCordItemSchema, TopologyCordItem, TopologyCordsSchema, TopologyCords, TopologySchema, Topology }; diff --git a/src/interface/model/BoxStructure/TopologyCables.ts b/src/interface/model/BoxStructure/TopologyCables.ts new file mode 100644 index 0000000..25cda55 --- /dev/null +++ b/src/interface/model/BoxStructure/TopologyCables.ts @@ -0,0 +1,53 @@ +import { z } from 'zod'; +import { TopologyClientsSchema } from './TopologyClients'; +import { stringOrObjectId } from '../BaseModel'; + +const TopologyCablesSchema = z.object({ + id: z.string(), + name: z.string(), + looseNumber: z.number(), + orientation: z.string(), + observation: z.string().optional(), + implanted: z.boolean(), + fibersColourMap: z.array(z.string()), + groupsColourMap: z.array(z.string()), + defaultFiberColor: z.string(), + defaultTubeColor: z.string(), + fibers: z.array(z.string()), + project: z.string(), + cableType: stringOrObjectId.optional(), +}); + +const SignalWay = z.enum(['in', 'out']); + +const ExtraFiberDataSchema = z.object({ + name: z.string(), + potency: z.number().optional().nullable(), + split: z.number().optional().nullable(), + way: SignalWay.optional().nullable(), +}); + +const TopologyDropsSchema = TopologyCablesSchema.extend({ + propertyData: z.object({ + address: z.string().nullish(), + coords: z.tuple([z.number(), z.number()]).optional(), + lat: z.number().optional(), + lng: z.number().optional(), + id: z.string(), + observation: z.string(), + client: TopologyClientsSchema.nullish(), + }), +}); + +type TopologyCables = z.infer; +type ExtraFiberData = z.infer; +type TopologyDrops = z.infer; + +export { + TopologyCablesSchema, + TopologyCables, + ExtraFiberDataSchema, + ExtraFiberData, + TopologyDropsSchema, + TopologyDrops, +}; diff --git a/src/interface/model/BoxStructure/TopologyClients.ts b/src/interface/model/BoxStructure/TopologyClients.ts new file mode 100644 index 0000000..e1e775b --- /dev/null +++ b/src/interface/model/BoxStructure/TopologyClients.ts @@ -0,0 +1,16 @@ +import { z } from 'zod'; + +const TopologyClientsSchema = z.object({ + _id: z.string().optional(), + certified: z.boolean(), + implanted: z.boolean(), + status: z.number(), + observation: z.string().optional(), + kind: z.string(), + code: z.string(), + name: z.string().nullish(), +}); + +type TopologyClients = z.infer; + +export { TopologyClientsSchema, TopologyClients }; diff --git a/src/interface/model/BoxStructure/TopologyConnectors.ts b/src/interface/model/BoxStructure/TopologyConnectors.ts new file mode 100644 index 0000000..dd51e95 --- /dev/null +++ b/src/interface/model/BoxStructure/TopologyConnectors.ts @@ -0,0 +1,75 @@ +import { z } from 'zod'; + +const SplitterPortSchema = z.object({ + id: z.string(), + index: z.number(), + blocked: z.boolean().optional(), + tags: z.array(z.string()).optional(), + observation: z.string().optional(), +}); + +const BaseConnectorConnectables = z.array(z.string().nullable()); + +const TopologyBaseConnectorSchema = z.object({ + id: z.string(), + name: z.string(), + isDrop: z.boolean(), + implanted: z.boolean(), + connectorType: z.string().optional(), + observation: z.string().optional(), +}); + +const TopologyConnectorsSchema = TopologyBaseConnectorSchema.extend({ + connectables: BaseConnectorConnectables, +}); + +const TopologyIOConnectorSchema = TopologyBaseConnectorSchema.extend({ + connectables: z.object({ + input: BaseConnectorConnectables, + output: BaseConnectorConnectables, + }), +}); + +const TopologySplitterSchema = TopologyIOConnectorSchema.extend({ + ports: z.array(SplitterPortSchema), + isBalanced: z.boolean(), + orientation: z.string(), + mostAttenuatedPort: z.number(), + inputConnectionType: z.number(), + outputConnectionType: z.number(), + code: z.string(), +}); + +const TopologyDIOSchema = TopologyIOConnectorSchema.extend({ + tray_number: z.number().optional(), + input_label: z.array(z.string()).optional(), + output_label: z.array(z.string()).optional(), +}); + +const TopologyPassingSchema = z.object({ + id: z.string(), + connectables: BaseConnectorConnectables, +}); + +type TopologyBaseConnector = z.infer; +type TopologyConnectors = z.infer; +type TopologyIOConnector = z.infer; +type TopologySplitter = z.infer; +type TopologyDIO = z.infer; +type TopologyPassing = z.infer; + +export { + SplitterPortSchema, + TopologyBaseConnectorSchema, + TopologyBaseConnector, + TopologyConnectorsSchema, + TopologyConnectors, + TopologyIOConnectorSchema, + TopologyIOConnector, + TopologySplitterSchema, + TopologySplitter, + TopologyDIOSchema, + TopologyDIO, + TopologyPassingSchema, + TopologyPassing, +}; diff --git a/src/interface/model/BoxStructure/index.ts b/src/interface/model/BoxStructure/index.ts new file mode 100644 index 0000000..6bf5373 --- /dev/null +++ b/src/interface/model/BoxStructure/index.ts @@ -0,0 +1,8 @@ +export * from './Positions'; +export * from './Postit'; +export * from './TopologyClients'; +export * from './TopologyCables'; +export * from './TopologyConnectors'; +export * from './Topology'; +export * from './BoxDesign'; +export * from './BoxStructure'; diff --git a/src/interface/model/ChangeRequest/BoxCreateRequest.ts b/src/interface/model/ChangeRequest/BoxCreateRequest.ts new file mode 100644 index 0000000..ad2b7c6 --- /dev/null +++ b/src/interface/model/ChangeRequest/BoxCreateRequest.ts @@ -0,0 +1,67 @@ +import { z } from 'zod'; +import { BaseChangeRequestCreateSchema, BaseChangeRequestSchema, changeRequestKind } from './ChangeRequest'; +import { stringOrObjectId } from '../BaseModel'; +import { BoxStructureChangeRequestDataSchema } from './BoxStructureChangeRequest'; +import { CreateBoxDTOSchema } from '../Box'; + +const BoxDataSchema = z.object({ + boxType: stringOrObjectId, + project: stringOrObjectId, + coords: z.tuple([z.number(), z.number()]), + name: z.string().optional(), + hierarchyLevel: z.number().min(2), +}); + +const BoxDataCreateSchema = BoxDataSchema.omit({ hierarchyLevel: true }).extend({ + hierarchyLevel: z.number().min(2).optional(), +}); + +const BoxCreateRequestDataSchema = BoxStructureChangeRequestDataSchema.extend({ + kind: z.literal(changeRequestKind.BoxCreate).optional().default(changeRequestKind.BoxCreate), + element: z + .object({ + id: stringOrObjectId.optional(), + kind: z.literal('box').optional().default('box'), + }) + .optional(), + boxData: BoxDataSchema, + structure: BoxStructureChangeRequestDataSchema.shape.structure.optional(), +}); + +const BoxCreateRequestSchema = BaseChangeRequestSchema.merge(BoxCreateRequestDataSchema); + +const CreateBoxCreateRequestDTOSchema = BaseChangeRequestCreateSchema.merge(BoxCreateRequestDataSchema) + .omit({ element: true, boxData: true }) + .extend({ + boxData: BoxDataCreateSchema, + }); + +const BoxCreateRequestApproveSchema = z.object({ + observation: z.string().optional(), + boxData: CreateBoxDTOSchema.partial().optional(), +}); + +const BoxCreateRequestRejectSchema = z.object({ + observation: z.string().nonempty(), +}); + +type BoxCreateRequestBoxData = z.infer; +type BoxCreateRequest = z.infer; +type CreateBoxCreateRequestDTO = z.infer; +type BoxCreateRequestApprove = z.infer; +type BoxCreateRequestReject = z.infer; + +export { + BoxDataSchema, + BoxDataCreateSchema, + BoxCreateRequestDataSchema, + BoxCreateRequestSchema, + CreateBoxCreateRequestDTOSchema, + BoxCreateRequestApproveSchema, + BoxCreateRequestRejectSchema, + BoxCreateRequestBoxData, + BoxCreateRequest, + CreateBoxCreateRequestDTO, + BoxCreateRequestApprove, + BoxCreateRequestReject, +}; diff --git a/src/interface/model/ChangeRequest/BoxStructureChangeRequest.ts b/src/interface/model/ChangeRequest/BoxStructureChangeRequest.ts new file mode 100644 index 0000000..0ee82b3 --- /dev/null +++ b/src/interface/model/ChangeRequest/BoxStructureChangeRequest.ts @@ -0,0 +1,51 @@ +import { z } from 'zod'; +import { BaseChangeRequestCreateSchema, BaseChangeRequestSchema, changeRequestKind } from './ChangeRequest'; +import { stringOrObjectId } from '../BaseModel'; +import { ChangeTopologyActionSchema } from './ChangeTopologyActions'; +import { TopologyCablesSchema } from '../BoxStructure/TopologyCables'; +import { TopologySchema } from '../BoxStructure/Topology'; +import { BoxDesignSchema } from '../BoxStructure/BoxDesign'; + +const BoxStructureElementKind = z.enum(['box', 'building']); + +const TopologyCablesWithOptionalCableTypeSchema = TopologyCablesSchema.extend({ + cableType: stringOrObjectId.optional(), +}); + +const CustomTopologySchema = TopologySchema.extend({ + cables: z.record(TopologyCablesWithOptionalCableTypeSchema).optional(), +}); + +const CustomBoxStructureSchema = z.object({ + topology: CustomTopologySchema, + design: BoxDesignSchema, +}); + +const BoxStructureChangeRequestDataSchema = z.object({ + kind: z.literal(changeRequestKind.BoxStructure).optional().default(changeRequestKind.BoxStructure), + element: z.object({ + id: stringOrObjectId, + kind: BoxStructureElementKind, + }), + structure: CustomBoxStructureSchema, + actions: z.array(ChangeTopologyActionSchema).default([]), + isStructureEmpty: z.boolean().optional().default(false), +}); + +const BoxStructureChangeRequestSchema = BaseChangeRequestSchema.merge(BoxStructureChangeRequestDataSchema); + +const CreateBoxStructureChangeRequestDTOSchema = BaseChangeRequestCreateSchema.merge( + BoxStructureChangeRequestDataSchema, +); + +type BoxStructureChangeRequest = z.infer; +type CreateBoxStructureChangeRequestDTO = z.infer; + +export { + BoxStructureElementKind, + BoxStructureChangeRequestDataSchema, + BoxStructureChangeRequestSchema, + CreateBoxStructureChangeRequestDTOSchema, + BoxStructureChangeRequest, + CreateBoxStructureChangeRequestDTO, +}; diff --git a/src/interface/model/ChangeRequest/ChangeRequest.ts b/src/interface/model/ChangeRequest/ChangeRequest.ts new file mode 100644 index 0000000..51c41e8 --- /dev/null +++ b/src/interface/model/ChangeRequest/ChangeRequest.ts @@ -0,0 +1,91 @@ +import { z } from 'zod'; +import { BaseModelSchema, stringOrObjectId } from '../BaseModel'; + +const ChangeRequestKinds = ['BoxStructure', 'BoxCreate'] as const; +const ChangeRequestStatuses = ['pending', 'approved', 'rejected'] as const; + +const ChangeRequestStatusSchema = z.enum(ChangeRequestStatuses); +const ChangeRequestKindSchema = z.enum(ChangeRequestKinds); + +const changeRequestKind = ChangeRequestKindSchema.Enum; +const changeRequestStatus = ChangeRequestStatusSchema.Enum; + +const MinimalUserSchema = z.object({ + id: z.string(), + name: z.string(), + username: z.string(), +}); + +const ReviewSchema = z.object({ + by: MinimalUserSchema, + at: z.date().or(z.string()), +}); + +const BaseChangeRequestDataSchema = z.object({ + kind: ChangeRequestKindSchema, + status: ChangeRequestStatusSchema, + element: z.object({ + id: stringOrObjectId, + kind: z.string(), + }), + code: z.string(), + applicable: z.boolean().optional(), + createdBy: stringOrObjectId, + review: ReviewSchema.optional(), + observation: z.string().optional(), + description: z.string().min(5), +}); + +const BaseChangeRequestCreateSchema = z.object({ + kind: ChangeRequestKindSchema, + element: z.object({ + id: stringOrObjectId, + kind: z.string(), + }), + description: z.string().min(5), +}); + +const BaseChangeRequestApproveSchema = z.object({ + elementId: stringOrObjectId, + kind: ChangeRequestKindSchema, + status: z.literal(changeRequestStatus.approved), + observation: z.string().optional(), +}); + +const BaseChangeRequestRejectSchema = z.object({ + elementId: stringOrObjectId, + kind: ChangeRequestKindSchema, + status: z.literal(changeRequestStatus.rejected), + observation: z.string(), +}); + +const BaseChangeRequestSchema = BaseModelSchema.merge(BaseChangeRequestDataSchema); + +type ChangeRequestKind = z.infer; +type ChangeRequestStatus = z.infer; +type BaseChangeRequest = z.infer; +type CreateBaseChangeRequestDTO = z.infer; +type ApproveBaseChangeRequestDTO = z.infer; +type RejectBaseChangeRequestDTO = z.infer; + +export { + ChangeRequestKinds, + ChangeRequestStatuses, + ChangeRequestKindSchema, + ChangeRequestStatusSchema, + changeRequestKind, + changeRequestStatus, + MinimalUserSchema, + ReviewSchema, + BaseChangeRequestDataSchema, + BaseChangeRequestCreateSchema, + BaseChangeRequestApproveSchema, + BaseChangeRequestRejectSchema, + BaseChangeRequestSchema, + ChangeRequestKind, + ChangeRequestStatus, + BaseChangeRequest, + CreateBaseChangeRequestDTO, + ApproveBaseChangeRequestDTO, + RejectBaseChangeRequestDTO, +}; diff --git a/src/interface/model/ChangeRequest/ChangeTopologyActions.ts b/src/interface/model/ChangeRequest/ChangeTopologyActions.ts new file mode 100644 index 0000000..a8694b5 --- /dev/null +++ b/src/interface/model/ChangeRequest/ChangeTopologyActions.ts @@ -0,0 +1,117 @@ +import { z } from 'zod'; +import { stringOrObjectId } from '../BaseModel'; + +const ElementKindsWithoutSide = ['Cable', 'Drop', 'Switch', 'Fusion', 'Connector', 'Passing', 'Cord', 'Fiber'] as const; +const ElementKindsWithSide = ['Splitter', 'DIO'] as const; +const ConnectorSides = ['input', 'output'] as const; + +const ChangeTopologyAction = { + CONNECT: 'connect', + DISCONNECT: 'disconnect', + CREATE: 'create', + DELETE: 'delete', + UPDATE: 'update', +} as const; + +const ElementKindWithoutSideSchema = z.enum(ElementKindsWithoutSide); +const ElementKindWithSideSchema = z.enum(ElementKindsWithSide); +const ElementKindSchema = z.union([ElementKindWithoutSideSchema, ElementKindWithSideSchema]); +const ConnectorSideSchema = z.enum(ConnectorSides); + +const ElementIdentifierSchema = z.object({ + element: stringOrObjectId, + identifier: z.string(), + kind: ElementKindSchema, +}); + +const ConnectionElementWithoutSideSchema = ElementIdentifierSchema.extend({ + kind: ElementKindWithoutSideSchema, + port: z.coerce.number(), +}); + +const ConnectionElementWithSideSchema = ConnectionElementWithoutSideSchema.extend({ + kind: ElementKindWithSideSchema, + side: ConnectorSideSchema, +}); + +const ConnectionElementSchema = z.discriminatedUnion('kind', [ + ConnectionElementWithoutSideSchema, + ConnectionElementWithSideSchema, +]); + +const ConnectionDataSchema = z.object({ + elementA: ConnectionElementSchema, + elementB: ConnectionElementSchema, +}); + +const PropertyValueSchema = z.object({ + value: z.union([z.string(), z.number()]), + identifier: z.string().optional(), +}); + +const UpdateElementPropertySchema = ElementIdentifierSchema.extend({ + property: z.string(), + newValue: PropertyValueSchema, + oldValue: PropertyValueSchema, +}); + +const ConnectDisconnectActionSchema = z.object({ + action: z.enum([ChangeTopologyAction.CONNECT, ChangeTopologyAction.DISCONNECT]), + data: ConnectionDataSchema, +}); + +const CreateElementActionSchema = z.object({ + action: z.literal(ChangeTopologyAction.CREATE), + data: ElementIdentifierSchema, +}); + +const DeleteElementActionSchema = z.object({ + action: z.literal(ChangeTopologyAction.DELETE), + data: ElementIdentifierSchema, +}); + +const UpdateElementActionSchema = z.object({ + action: z.literal(ChangeTopologyAction.UPDATE), + data: UpdateElementPropertySchema, +}); + +const ChangeTopologyActionSchema = z.discriminatedUnion('action', [ + ConnectDisconnectActionSchema, + CreateElementActionSchema, + DeleteElementActionSchema, + UpdateElementActionSchema, +]); + +type ChangeTopologyActionType = z.infer; +type ConnectionAction = z.infer; +type ConnectionElement = z.infer; +type ConnectionElementWithoutSide = z.infer; +type ConnectionElementWithSide = z.infer; +type ConnectionData = z.infer; +type PropertyValue = z.infer; +type CreateElementAction = z.infer; +type DeleteElementAction = z.infer; +type UpdateElementAction = z.infer; +type ElementIdentifier = z.infer; + +export { + ChangeTopologyAction, + ElementKindsWithoutSide, + ElementKindsWithSide, + ConnectorSides, + ChangeTopologyActionSchema, + ChangeTopologyActionType, + ConnectionAction, + ConnectionElement, + ConnectionElementWithoutSide, + ConnectionElementWithSide, + ConnectionData, + PropertyValue, + CreateElementAction, + DeleteElementAction, + UpdateElementAction, + ElementIdentifierSchema, + ElementIdentifier, + PropertyValueSchema, + UpdateElementPropertySchema, +}; diff --git a/src/interface/model/ChangeRequest/index.ts b/src/interface/model/ChangeRequest/index.ts new file mode 100644 index 0000000..0a935a9 --- /dev/null +++ b/src/interface/model/ChangeRequest/index.ts @@ -0,0 +1,4 @@ +export * from './ChangeTopologyActions'; +export * from './ChangeRequest'; +export * from './BoxStructureChangeRequest'; +export * from './BoxCreateRequest'; diff --git a/src/interface/model/PolygonReport/PolygonReport.ts b/src/interface/model/PolygonReport/PolygonReport.ts new file mode 100644 index 0000000..87df1c8 --- /dev/null +++ b/src/interface/model/PolygonReport/PolygonReport.ts @@ -0,0 +1,240 @@ +import { z } from 'zod'; +import { BaseModelSchema, stringOrObjectId } from '../BaseModel'; +import { PolygonReportDataSchema } from './PolygonReportData'; + +const ReportErrorSchema = z.object({ + message: z.string(), + element: z.string(), +}); + +const BoxesSummarySchema = z.object({ + id: z.string(), + implanted: z.number(), + not_implanted: z.number(), + draft: z.number(), + total: z.number(), +}); + +const CablesSummarySchema = z.object({ + id: z.string(), + implanted: z.number(), + not_implanted: z.number(), + total: z.number(), +}); + +const ClientsSummarySchema = z.object({ + id: z.string(), + implanted: z.number(), + not_implanted: z.number(), + total: z.number(), +}); + +const PropertiesSummarySchema = z.object({ + implanted: z.number(), + total: z.number(), +}); + +const PolesSummarySchema = z.object({ + total: z.number(), + used: z.number(), + licensed: z.number(), + licensing: z.number(), + unknown: z.number(), +}); + +const PopsSummarySchema = z.object({ + id: z.string(), + implanted: z.number(), + not_implanted: z.number(), + certified: z.number(), + draft: z.number(), + total: z.number(), +}); + +const PendencySummarySchema = z.object({ + id: z.string(), + solved: z.number(), + not_solved: z.number(), + total: z.number(), +}); + +const ReportSummarySchema = z.object({ + id: z.string().optional(), + boxes: z.array(BoxesSummarySchema), + cables: z.array(CablesSummarySchema), + clients: z.array(ClientsSummarySchema), + properties: z.array(PropertiesSummarySchema), + poles: z.array(PolesSummarySchema), + pops: z.array(PopsSummarySchema), + pendencies: PendencySummarySchema, + splitters: z.array(z.object({}).passthrough()), + buildings: z.array( + z.object({ + id: z.string(), + name: z.string(), + address: z.string(), + properties: z.number(), + clients: z.number(), + createdAt: z.coerce.date(), + tags: z.array(z.string()), + posts: z.number(), + implanted: z.boolean(), + observation: z.string(), + buildingTypeName: z.string().optional(), + color: z.string().optional(), + buildingType: z.string(), + openPendencies: z.number(), + }), + ), + errors: z.array(ReportErrorSchema), +}); + +const PolygonGeoJSONSchema = z.object({ + type: z.enum(['Polygon']), + coordinates: z.array(z.array(z.array(z.number()))), +}); + +const PolygonReportDataFieldSchema = z.object({ + polygon: PolygonGeoJSONSchema, + name: z.string().nullish(), + project: stringOrObjectId, + isGeneralReport: z.boolean().nullable(), +}); + +const PolygonReportSchema = BaseModelSchema.merge(PolygonReportDataFieldSchema).merge( + z.object({ + date: z.coerce.date().optional(), + data: z.union([PolygonReportDataSchema, ReportSummarySchema]).optional(), + }), +); + +const PolygonReportExtraKindReference = { + GENERAL_TAB: 'generaltab', + CABLE_GRID: 'cablegrid', + BOX_GRID: 'boxgrid', + POP_GRID: 'popgrid', + SHELF_GRID: 'shelfgrid', + SECTOR_GRID: 'sectorgrid', + CLIENT_GRID: 'clientgrid', + PROSPECT_GRID: 'prospectgrid', + PROPERTY_GRID: 'propertygrid', + BUILDING_GRID: 'buildinggrid', + POLE_GRID: 'polegrid', + SPLITTER_GRID: 'splittergrid', + PENDENCY_GRID: 'pendencygrid', + REGION_GRID: 'regiongrid', + JUNCTION_BOX_GRID: 'junctionboxgrid', + DUCT_GRID: 'ductgrid', + TOWER_GRID: 'towergrid', +} as const; + +type PolygonReportExtraKindReference = + typeof PolygonReportExtraKindReference[keyof typeof PolygonReportExtraKindReference]; + +const PolygonReportExtraSchema = z.object({ + kind: z.string().optional(), + force: z.boolean().optional(), +}); + +const CreatePolygonReportDTOSchema = z.object({ + _id: stringOrObjectId.nullish(), + polygon: PolygonGeoJSONSchema, + name: z.string().nullish(), + project: stringOrObjectId.optional(), + isGeneralReport: z.boolean().nullable().optional(), + extra: PolygonReportExtraSchema.optional(), +}); + +type PolygonReport = z.infer; +type CreatePolygonReportDTO = z.infer; + +const PolygonReportKind = { + ALL: 'all', + GENERAL: 'general', + CABLES: 'cables', + BOXES: 'boxes', + POPS: 'pops', + SHELFS: 'shelfs', + SECTORS: 'sectors', + CLIENTS: 'clients', + PROSPECTS: 'prospects', + PROPERTIES: 'properties', + BUILDINGS: 'buildings', + POLES: 'poles', + SPLITTERS: 'splitters', + PENDENCIES: 'pendencies', + REGIONS: 'regions', + JUNCTION_BOXES: 'junctionBoxes', + DUCTS: 'ducts', + TOWERS: 'torres', +} as const; + +type PolygonReportKind = typeof PolygonReportKind[keyof typeof PolygonReportKind]; + +const MoveReportSchema = z.object({ + lat: z.number(), + lng: z.number(), +}); + +const ReportTagsSchema = z.object({ + tags: z.array(z.string()), +}); + +const UpdateProjectSchema = z.object({ + project: stringOrObjectId, + ids: z.array(stringOrObjectId), +}); + +const ElementsReportSchema = z.object({ + elements: z.object({ + cableIds: z.array(stringOrObjectId).optional(), + boxIds: z.array(stringOrObjectId).optional(), + popIds: z.array(stringOrObjectId).optional(), + shelfIds: z.array(stringOrObjectId).optional(), + sectorIds: z.array(stringOrObjectId).optional(), + clientIds: z.array(stringOrObjectId).optional(), + prospectIds: z.array(stringOrObjectId).optional(), + propertyIds: z.array(stringOrObjectId).optional(), + buildingIds: z.array(stringOrObjectId).optional(), + poleIds: z.array(stringOrObjectId).optional(), + connectorIds: z.array(stringOrObjectId).optional(), + pendencyIds: z.array(stringOrObjectId).optional(), + regionIds: z.array(stringOrObjectId).optional(), + junctionBoxIds: z.array(stringOrObjectId).optional(), + ductIds: z.array(stringOrObjectId).optional(), + towerIds: z.array(stringOrObjectId).optional(), + }), +}); + +type MoveReport = z.infer; +type ReportTags = z.infer; +type UpdateProject = z.infer; +type ElementsReport = z.infer; + +export { + PolygonReportSchema, + PolygonReport, + CreatePolygonReportDTOSchema, + CreatePolygonReportDTO, + PolygonReportKind, + PolygonReportExtraKindReference, + PolygonReportExtraSchema, + ReportSummarySchema, + ReportErrorSchema, + BoxesSummarySchema, + CablesSummarySchema, + ClientsSummarySchema, + PropertiesSummarySchema, + PolesSummarySchema, + PopsSummarySchema, + PendencySummarySchema, + PolygonGeoJSONSchema, + MoveReportSchema, + MoveReport, + ReportTagsSchema, + ReportTags, + UpdateProjectSchema, + UpdateProject, + ElementsReportSchema, + ElementsReport, +}; diff --git a/src/interface/model/PolygonReport/PolygonReportData.ts b/src/interface/model/PolygonReport/PolygonReportData.ts new file mode 100644 index 0000000..b4fe1b3 --- /dev/null +++ b/src/interface/model/PolygonReport/PolygonReportData.ts @@ -0,0 +1,428 @@ +import { z } from 'zod'; + +// --- Sub-report element schemas --- + +const ReportPointSchema = z.object({ + _id: z.string().optional(), + id: z.string().optional(), + lat: z.number(), + lng: z.number(), + reserve: z.number().optional(), + coords: z.array(z.number()).optional(), +}); + +const ReportCableSchema = z.object({ + id: z.string(), + tags: z.array(z.string()), + name: z.string(), + observation: z.string(), + level: z.string(), + cableType: z.string(), + implanted: z.boolean(), + boxA: z.string(), + boxB: z.string(), + color: z.string(), + project: z.string(), + length: z.number(), + altitude_length: z.number(), + ground_length: z.number(), + poles: z.array(ReportPointSchema), + positions: z + .array( + z.object({ + lat: z.number(), + lng: z.number(), + advancedLat: z.number().optional(), + advancedLng: z.number().optional(), + }), + ) + .optional(), + createdAt: z.coerce.date(), + posts: z.number(), + ducts: z.array(z.string()), + openPendencies: z.number(), +}); + +const ReportPoleSchema = z.object({ + cables: z.union([z.array(z.string()), z.string()]), + id: z.string(), + name: z.string(), + lat: z.number(), + lng: z.number(), + createdAt: z.coerce.date(), + tags: z.array(z.string()), + posts: z.number(), + sumReserves: z.number(), + used: z.boolean(), + licensing_protocol: z.string(), + licensing_status: z.number(), + poleType: z.string(), + observation: z.string(), + color: z.string(), + address: z.string(), + openPendencies: z.number(), +}); + +const ReportBoxSchema = z.object({ + id: z.string(), + name: z.string(), + pole: z.string(), + observation: z.string(), + boxType: z.string(), + level: z.string(), + project: z.string(), + implanted: z.boolean(), + certified: z.boolean(), + draft: z.boolean(), + connectors: z + .array( + z.object({ + name: z.string(), + level: z.string(), + clients: z.number(), + }), + ) + .optional(), + clients: z.number(), + createdAt: z.coerce.date(), + shared: z.boolean(), + tags: z.array(z.string()), + posts: z.number(), + default_reserve: z.number(), + color: z.string(), + fill_color: z.string(), + address: z.string(), + capacity: z.number(), + busyDoors: z.number(), + availableDoors: z.number(), + lat: z.number(), + lng: z.number(), + openPendencies: z.number(), +}); + +const ReportPopSchema = z.object({ + id: z.string(), + name: z.string(), + pole: z.string(), + type: z.string(), + level: z.string(), + observation: z.string(), + project: z.string(), + implanted: z.boolean(), + certified: z.boolean(), + draft: z.boolean(), + lat: z.number(), + lng: z.number(), + connectors: z + .array( + z.object({ + name: z.string(), + level: z.string(), + }), + ) + .optional(), + createdAt: z.coerce.date(), + shared: z.boolean(), + address: z.string(), + tags: z.array(z.string()), + posts: z.number(), + openPendencies: z.number(), +}); + +const ReportShelfSchema = z.object({ + id: z.string(), + name: z.string(), + us: z.number(), + project: z.string(), + createdAt: z.coerce.date(), + parent: z.object({ + _id: z.string(), + name: z.string(), + }), + shelfType: z.string(), + equipmentsCount: z.number(), + equipmentsSize: z.number(), + size: z.number(), + tags: z.array(z.string()), +}); + +const ReportSectorSchema = z.object({ + id: z.string(), + name: z.string(), + pop: z.string(), + tower: z.string(), + project: z.string(), + antenna: z.string(), + link: z.string(), + createdAt: z.coerce.date(), + tags: z.array(z.string()), +}); + +const ReportBaseClientSchema = z.object({ + box: z.string(), + property_observation: z.string(), + property_tags: z.array(z.string()), + pole: z.string(), + project: z.string(), + drop_length: z.union([z.string(), z.number()]), + address: z.string(), + coords: z.tuple([z.number(), z.number()]), + olt: z.string().nullable(), + slot: z.string().nullable(), + pon: z.string().nullable(), + potencyRead: z.number().optional(), + connector: z.string().optional(), + port: z.number().optional(), +}); + +const ReportPropertySchema = ReportBaseClientSchema.extend({ + id: z.string(), + createdAt: z.coerce.date(), + posts: z.number(), + openPendencies: z.number(), +}); + +const ReportClientSchema = ReportBaseClientSchema.extend({ + id: z.string(), + kind: z.string(), + name: z.string(), + certified: z.string(), + property: z.string(), + code: z.string(), + client_observation: z.string(), + implanted: z.boolean(), + status: z.number(), + createdAt: z.coerce.date(), + onu: z.object({}).passthrough(), + tags: z.array(z.string()), + posts: z.number(), + openPendencies: z.number(), +}); + +const ReportBuildingSchema = z.object({ + id: z.string(), + name: z.string(), + address: z.string(), + properties: z.number(), + clients: z.number(), + createdAt: z.coerce.date(), + tags: z.array(z.string()), + posts: z.number(), + implanted: z.boolean(), + observation: z.string(), + buildingTypeName: z.string().optional(), + color: z.string().optional(), + buildingType: z.string(), + openPendencies: z.number(), +}); + +const ReportPendencySchema = z.object({ + id: z.string(), + name: z.string(), + tags: z.array(z.string()), + solved: z.boolean(), + owner: z.string(), + description: z.string(), + pendencyType: z.string(), + responsibles: z.array(z.string()).optional(), + linkedElement: z.object({}).passthrough().nullable(), + populatedLinkedElement: z.object({ name: z.string().optional() }).nullable(), + color: z.string(), + project: z.string(), + lat: z.number(), + lng: z.number(), + createdAt: z.coerce.date().optional(), + posts: z.number(), +}); + +const ReportRegionSchema = z.object({ + id: z.string(), + name: z.string(), + observation: z.string(), + regionType: z.string(), + color: z.string(), + borderColor: z.string(), + tags: z.array(z.string()), + polygon: z.object({ + type: z.enum(['Polygon']), + coordinates: z.array(z.array(z.array(z.number()))), + }), + projects: z.array(z.string()), + createdAt: z.coerce.date(), + posts: z.number(), +}); + +const ReportProspectSchema = z.object({ + id: z.string(), + name: z.string(), + code: z.string(), + tags: z.array(z.string()), + address: z.string(), + createdAt: z.coerce.date(), + observation: z.string(), + lat: z.number(), + lng: z.number(), +}); + +const ReportJunctionBoxSchema = z.object({ + id: z.string(), + name: z.string(), + posts: z.number(), + tags: z.array(z.any()), + junctionBoxType: z.string().optional(), + color: z.string().optional(), + address: z.string().optional(), + observation: z.string().optional(), + junctionBoxTypeName: z.string().optional(), + createdAt: z.coerce.date(), + lat: z.number(), + lng: z.number(), + implanted: z.boolean(), + boxes: z.number(), + project: z.string(), + coords: z.tuple([z.number(), z.number()]).optional(), + _id: z.string().optional(), + openPendencies: z.number(), +}); + +const ReportDuctSchema = z.object({ + id: z.string(), + name: z.string(), + tags: z.array(z.any()), + posts: z.number(), + createdAt: z.coerce.date(), + observation: z.string().optional(), + implanted: z.boolean().optional(), + subDucts: z.number(), + cables: z.number(), + color: z.string().optional(), + edgeA: z.string(), + edgeB: z.string(), + ductType: z.string(), + length: z.number().optional(), + project: z.string().optional(), + openPendencies: z.number(), +}); + +const ReportReserveSchema = z.object({ + cable: z.string(), + lat: z.number(), + lng: z.number(), + reserve: z.number(), + project: z.string(), +}); + +const ReportTowerSchema = z.object({ + id: z.string().optional(), + name: z.string(), + description: z.string(), + tags: z.array(z.string()), + towerType: z.string(), + towerTypeCode: z.string().optional(), + parent: z.string().optional(), + parentName: z.string().optional(), + hierarchyLevelName: z.string().optional(), + lat: z.number().optional(), + lng: z.number().optional(), + coords: z.array(z.number()).optional(), + posts: z.number().optional(), +}); + +const ConnectorAttenuationSchema = z.object({ + id: z.string(), + name: z.string(), + kind: z.string(), + isBalanced: z.boolean(), + parent: z.string(), + project: z.string(), + implanted: z.boolean(), + parentName: z.string(), + isDrop: z.boolean(), + observation: z.string(), + connectorType: z.string(), + connectorTypeCode: z.string(), + input: z.number(), + availability: z.number(), + total: z.number(), + mostAttenuatedPort: z.number(), + min_potency: z.number(), + max_potency: z.number(), + createdAt: z.coerce.date(), +}); + +const PopConnectorAttenuationSchema = z.object({ + id: z.string(), + name: z.string(), + kind: z.string(), + parent: z.string(), + parentName: z.string(), + project: z.string(), + implanted: z.boolean(), + isDrop: z.boolean(), + observation: z.string(), + connectorType: z.string(), + connectorTypeCode: z.string(), + input: z.number(), + total: z.number(), + createdAt: z.coerce.date(), + size: z.string().optional(), + fabricationDate: z.coerce.date().optional(), + radioCapacity: z.string().optional(), + potency: z.number().optional(), + autonomy: z.string().optional(), + serialNumber: z.string().optional(), + shelf: z.string().optional(), + tags: z.array(z.string()).optional(), + posts: z.number().optional(), +}); + +const ReportConnectorSchema = z.union([ConnectorAttenuationSchema, PopConnectorAttenuationSchema]); + +const PolygonReportDataSchema = z.object({ + boxes: z.array(ReportBoxSchema), + reserves: z.array(ReportReserveSchema), + pops: z.array(ReportPopSchema), + shelfs: z.array(ReportShelfSchema), + sectors: z.array(ReportSectorSchema), + buildings: z.array(ReportBuildingSchema), + poles: z.array(ReportPoleSchema), + properties: z.array(ReportPropertySchema), + points: z.array(ReportPointSchema).optional(), + prospects: z.array(ReportProspectSchema), + cables: z.array(ReportCableSchema), + clients: z.array(ReportClientSchema), + junctionBoxes: z.array(ReportJunctionBoxSchema), + ducts: z.array(ReportDuctSchema), + splitters: z.array(ReportConnectorSchema), + pendencies: z.array(ReportPendencySchema), + regions: z.array(ReportRegionSchema), + towers: z.array(ReportTowerSchema), + errors: z.array(z.any()), +}); + +type PolygonReportData = z.infer; + +export { + PolygonReportDataSchema, + PolygonReportData, + ReportCableSchema, + ReportPoleSchema, + ReportBoxSchema, + ReportPopSchema, + ReportShelfSchema, + ReportSectorSchema, + ReportPropertySchema, + ReportClientSchema, + ReportBuildingSchema, + ReportPendencySchema, + ReportRegionSchema, + ReportProspectSchema, + ReportJunctionBoxSchema, + ReportDuctSchema, + ReportReserveSchema, + ReportTowerSchema, + ConnectorAttenuationSchema, + PopConnectorAttenuationSchema, + ReportConnectorSchema, + ReportPointSchema, +}; diff --git a/src/interface/model/PolygonReport/index.ts b/src/interface/model/PolygonReport/index.ts new file mode 100644 index 0000000..d1830c0 --- /dev/null +++ b/src/interface/model/PolygonReport/index.ts @@ -0,0 +1,2 @@ +export * from './PolygonReportData'; +export * from './PolygonReport'; diff --git a/src/interface/model/index.ts b/src/interface/model/index.ts index 3610c08..feb7344 100644 --- a/src/interface/model/index.ts +++ b/src/interface/model/index.ts @@ -57,3 +57,6 @@ export * from './Tag'; export * from './Splitter'; export * from './SplitterType'; export * from './SystemConfig'; +export * from './BoxStructure'; +export * from './ChangeRequest'; +export * from './PolygonReport'; diff --git a/src/proxy/entities/Box.ts b/src/proxy/entities/Box.ts index 720ed4e..ed9795a 100644 --- a/src/proxy/entities/Box.ts +++ b/src/proxy/entities/Box.ts @@ -1,4 +1,4 @@ -import { Box, CreateBoxDTO, CreateBoxDTOSchema, UpdateBoxDTO, UpdateBoxDTOSchema } from '../../interface'; +import { Box, CreateBoxDTO, CreateBoxDTOSchema, UpdateBoxDTO, UpdateBoxDTOSchema, BoxStructure } from '../../interface'; import WritableProxy from '../WritableProxy'; import Api from '../../util/Api'; @@ -23,6 +23,33 @@ class BoxProxy extends WritableProxy { return super.updateById(id, parsedData, options); } + + public async getStructure(id: Box['id'], options?: Parameters[0]['options']): Promise { + const [topology, design] = await Promise.all([ + this.apiInstance.get({ + route: `base-boxes/${id}/topology`, + options, + }), + this.apiInstance.get({ + route: `base-boxes/${id}/design`, + options, + }), + ]); + + return { topology, design }; + } + + public async updateStructure( + id: Box['id'], + data: BoxStructure, + options?: Parameters[0]['options'], + ): Promise { + return this.apiInstance.patch({ + route: `base-boxes/${id}/structure`, + inputData: { structure: data }, + options, + }); + } } export default BoxProxy; diff --git a/src/proxy/entities/Building.ts b/src/proxy/entities/Building.ts index 91c1bbb..c3ddef5 100644 --- a/src/proxy/entities/Building.ts +++ b/src/proxy/entities/Building.ts @@ -4,6 +4,7 @@ import { CreateBuildingDTOSchema, UpdateBuildingDTO, UpdateBuildingDTOSchema, + BoxStructure, } from '../../interface'; import WritableProxy from '../WritableProxy'; @@ -29,6 +30,33 @@ class BuildingProxy extends WritableProxy[0]['options']): Promise { + const [topology, design] = await Promise.all([ + this.apiInstance.get({ + route: `base-boxes/${id}/topology`, + options, + }), + this.apiInstance.get({ + route: `base-boxes/${id}/design`, + options, + }), + ]); + + return { topology, design }; + } + + public async updateStructure( + id: Building['id'], + data: BoxStructure, + options?: Parameters[0]['options'], + ): Promise { + return this.apiInstance.patch({ + route: `base-boxes/${id}/structure`, + inputData: { structure: data }, + options, + }); + } } export default BuildingProxy; diff --git a/src/proxy/entities/PolygonReport.ts b/src/proxy/entities/PolygonReport.ts new file mode 100644 index 0000000..e0fa413 --- /dev/null +++ b/src/proxy/entities/PolygonReport.ts @@ -0,0 +1,110 @@ +import { + PolygonReport, + CreatePolygonReportDTO, + CreatePolygonReportDTOSchema, + MoveReport, + MoveReportSchema, + ReportTags, + ReportTagsSchema, + UpdateProject, + UpdateProjectSchema, + ElementsReport, + ElementsReportSchema, +} from '../../interface'; +import WritableProxy from '../WritableProxy'; +import Api from '../../util/Api'; +import { BaseModel } from '../../interface'; + +class PolygonReportProxy extends WritableProxy { + protected get _route(): string { + return 'reports/polygon'; + } + + private get _reportsRoute(): string { + return 'reports'; + } + + public async create( + data: CreatePolygonReportDTO, + options?: Parameters[0]['options'], + ): Promise { + const parsedData = CreatePolygonReportDTOSchema.parse(data); + return super.create(parsedData, options); + } + + public async moveById( + reportId: BaseModel['id'], + data: MoveReport, + options?: Parameters[0]['options'], + ): Promise { + const parsedData = MoveReportSchema.parse(data); + return this.apiInstance.post({ + route: `${this._reportsRoute}/${reportId}/move`, + inputData: parsedData, + options, + }); + } + + public async addTagsById( + reportId: BaseModel['id'], + data: ReportTags, + options?: Parameters[0]['options'], + ): Promise { + const parsedData = ReportTagsSchema.parse(data); + return this.apiInstance.post({ + route: `${this._reportsRoute}/${reportId}/tags`, + inputData: parsedData, + options, + }); + } + + public async removeTagsById( + reportId: BaseModel['id'], + data: ReportTags, + options?: Parameters[0]['options'], + ): Promise { + const parsedData = ReportTagsSchema.parse(data); + return this.apiInstance.delete({ + route: `${this._reportsRoute}/${reportId}/tags`, + options: { ...options, data: parsedData }, + }); + } + + public async updateProject( + data: UpdateProject, + options?: Parameters[0]['options'], + ): Promise<{ record: Record; error: string }[]> { + const parsedData = UpdateProjectSchema.parse(data); + return this.apiInstance.post({ + route: `${this._reportsRoute}/project`, + inputData: parsedData, + options, + }); + } + + public async createCompleteElementsReport( + data: ElementsReport, + options?: Parameters[0]['options'], + ): Promise { + const parsedData = ElementsReportSchema.parse(data); + return this.apiInstance.post({ + route: `${this._reportsRoute}/elements/complete`, + inputData: parsedData, + options, + }); + } + + public async createCountElementsReport( + data: ElementsReport, + options?: Parameters[0]['options'], + ): Promise { + const parsedData = ElementsReportSchema.parse(data); + return this.apiInstance.post({ + route: `${this._reportsRoute}/elements/count`, + inputData: parsedData, + options, + }); + } +} + +export default PolygonReportProxy; diff --git a/src/proxy/entities/changeRequest/BoxCreateRequest.ts b/src/proxy/entities/changeRequest/BoxCreateRequest.ts new file mode 100644 index 0000000..ec52d77 --- /dev/null +++ b/src/proxy/entities/changeRequest/BoxCreateRequest.ts @@ -0,0 +1,54 @@ +import { + BoxCreateRequest, + CreateBoxCreateRequestDTO, + CreateBoxCreateRequestDTOSchema, + BoxCreateRequestApprove, + BoxCreateRequestApproveSchema, + BoxCreateRequestReject, + BoxCreateRequestRejectSchema, +} from '../../../interface'; +import WritableProxy from '../../WritableProxy'; +import Api from '../../../util/Api'; +import { BaseModel } from '../../../interface'; + +class BoxCreateRequestProxy extends WritableProxy { + protected get _route(): string { + return 'box-create-requests'; + } + + public async create( + data: CreateBoxCreateRequestDTO, + options?: Parameters[0]['options'], + ): Promise { + const parsedData = CreateBoxCreateRequestDTOSchema.parse(data); + return super.create(parsedData, options); + } + + public async approveById( + requestId: BaseModel['id'], + data?: BoxCreateRequestApprove, + options?: Parameters[0]['options'], + ): Promise { + const parsedData = data ? BoxCreateRequestApproveSchema.parse(data) : {}; + return this.apiInstance.post({ + route: `${this._route}/${requestId}/approve`, + inputData: parsedData, + options, + }); + } + + public async rejectById( + requestId: BaseModel['id'], + data: BoxCreateRequestReject, + options?: Parameters[0]['options'], + ): Promise { + const parsedData = BoxCreateRequestRejectSchema.parse(data); + return this.apiInstance.post({ + route: `${this._route}/${requestId}/reject`, + inputData: parsedData, + options, + }); + } +} + +export default BoxCreateRequestProxy; diff --git a/src/proxy/entities/changeRequest/BoxStructureChangeRequest.ts b/src/proxy/entities/changeRequest/BoxStructureChangeRequest.ts new file mode 100644 index 0000000..e08b54b --- /dev/null +++ b/src/proxy/entities/changeRequest/BoxStructureChangeRequest.ts @@ -0,0 +1,40 @@ +import { + BoxStructureChangeRequest, + CreateBoxStructureChangeRequestDTO, + CreateBoxStructureChangeRequestDTOSchema, +} from '../../../interface'; +import WritableProxy from '../../WritableProxy'; +import Api from '../../../util/Api'; +import { BaseModel } from '../../../interface'; + +class BoxStructureChangeRequestProxy extends WritableProxy< + BoxStructureChangeRequest, + CreateBoxStructureChangeRequestDTO, + never +> { + protected get _route(): string { + return 'change-requests/box-structures'; + } + + public async create( + data: CreateBoxStructureChangeRequestDTO, + options?: Parameters[0]['options'], + ): Promise { + const parsedData = CreateBoxStructureChangeRequestDTOSchema.parse(data); + return super.create(parsedData, options); + } + + public async reviewById( + id: BaseModel['id'], + data: { status: 'approved' | 'rejected'; observation?: string }, + options?: Parameters[0]['options'], + ): Promise { + return this.apiInstance.patch({ + route: `${this._route}/${id}/review`, + inputData: data, + options, + }); + } +} + +export default BoxStructureChangeRequestProxy; diff --git a/src/proxy/entities/changeRequest/ChangeRequest.ts b/src/proxy/entities/changeRequest/ChangeRequest.ts new file mode 100644 index 0000000..e11df78 --- /dev/null +++ b/src/proxy/entities/changeRequest/ChangeRequest.ts @@ -0,0 +1,10 @@ +import { BaseChangeRequest } from '../../../interface'; +import ReadableProxy from '../../ReadableProxy'; + +class ChangeRequestProxy extends ReadableProxy { + protected get _route(): string { + return 'change-requests'; + } +} + +export default ChangeRequestProxy; diff --git a/src/proxy/entities/changeRequest/index.ts b/src/proxy/entities/changeRequest/index.ts new file mode 100644 index 0000000..bac68a7 --- /dev/null +++ b/src/proxy/entities/changeRequest/index.ts @@ -0,0 +1,3 @@ +export { default as ChangeRequestProxy } from './ChangeRequest'; +export { default as BoxStructureChangeRequestProxy } from './BoxStructureChangeRequest'; +export { default as BoxCreateRequestProxy } from './BoxCreateRequest'; diff --git a/src/proxy/entities/index.ts b/src/proxy/entities/index.ts index 52c0600..767f8a3 100644 --- a/src/proxy/entities/index.ts +++ b/src/proxy/entities/index.ts @@ -56,3 +56,5 @@ export { default as SwitchTypeProxy } from './SwitchType'; export { default as TagProxy } from './Tag'; export { default as UserProxy } from './User'; export { default as SystemConfigProxy } from './SystemConfig'; +export * from './changeRequest'; +export { default as PolygonReportProxy } from './PolygonReport';