Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d4dccb241 |
4595
Cargo.lock
generated
Normal file
4595
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
11
Cargo.toml
Normal file
11
Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
||||
[package]
|
||||
edition = "2024"
|
||||
name = "web"
|
||||
version = "0.1.0"
|
||||
|
||||
[dependencies]
|
||||
fathom-function = { git = "ssh://git@github.com/fathom-io/pipeline-calculations.git", branch = "main" }
|
||||
pipeline-application = { git = "ssh://git@github.com/fathom-io/pipeline-calculations.git", branch = "main" }
|
||||
serde = { version = "1.0.219", features = ["derive"] }
|
||||
tokio = { version = "1.43.0", features = ["macros", "rt-multi-thread"] }
|
||||
uuid = { version = "1" }
|
||||
67
README.md
67
README.md
@ -1,2 +1,67 @@
|
||||
# 870ace1d3a60459f9ca9720b28432fbf
|
||||
# Creation of an ILI report
|
||||
|
||||
A function that will create a ILI report asset and sequence.
|
||||
|
||||
## Input
|
||||
|
||||
### Arguments
|
||||
|
||||
- `org_id`: as string which should be a valid `uuid` for the organization
|
||||
- `project_id`: the id of the data project where the pipeline data is found
|
||||
- `pipeline_id`: a `array` each item of which should be a valid uuid for a pipeline.
|
||||
- `date`: a `string` formatted as an ISO date representing the date of the
|
||||
inspection.
|
||||
- `vendor_name`: a `string` the company who conducted the ILI inspection
|
||||
- `report_type`: a `string` the type of the report possible values:
|
||||
- `final`
|
||||
- `preliminary`
|
||||
- `inspection_type`: a `string` the type of technology used possible values:
|
||||
- `mfl`
|
||||
- `tfi`
|
||||
- `ut`
|
||||
- `emat`
|
||||
- `caliper`
|
||||
- `combo_mfl_and_tfi`
|
||||
- `combo_mfl_and_ut`
|
||||
- `combo_mfl_and_ec`
|
||||
- `file_details`: a `array` of file detail objects
|
||||
- `wall_thickness_source`: optional `string` to configure the wall source in the ILI report calculations
|
||||
- `pipebody_tolerances`: an `object` representing the tolerances for the pipebody
|
||||
- `haz_tolerances`: an `object` representing the tolerances for the heat affected zone (HAZ)
|
||||
|
||||
## Creating the function on the platform
|
||||
|
||||
To create this function on the platform using the `cli` set up the port forwarding as shown in README.
|
||||
|
||||
Then run the following command to create the function.
|
||||
|
||||
```bash
|
||||
cargo run functions create \
|
||||
-f functions/ili_creation \
|
||||
-d "Processes an ILI file and create the sequences and assets associated with that report" \
|
||||
-i org_id=string \
|
||||
-i project_id=string \
|
||||
-i pipeline_id=string \
|
||||
-i date=string \
|
||||
-i vendor_name=string \
|
||||
-i report_type=string \
|
||||
-i wall_thickness_source=string \
|
||||
-i inspection_type=string \
|
||||
-i file_details=object \
|
||||
-i pipebody_tolerances=object \
|
||||
-i haz_tolerances=object
|
||||
```
|
||||
|
||||
## Testing the function locally
|
||||
|
||||
You can run and test the function locally by running
|
||||
|
||||
```bash
|
||||
cargo run
|
||||
```
|
||||
|
||||
Then you can check it work with `curl` as follows
|
||||
|
||||
```bash
|
||||
jq '. | tojson' functions/ili_creation/example_input.json | curl -d '@-' localhost:8080
|
||||
```
|
||||
|
||||
246
example_input.json
Normal file
246
example_input.json
Normal file
@ -0,0 +1,246 @@
|
||||
{
|
||||
"date": "2002-02-01",
|
||||
"file_details": [
|
||||
{
|
||||
"fileId": "a2e8295f-3547-47b1-92ae-d5446b081eee",
|
||||
"revisionId": "2c68f624-2e9b-4c4a-90e0-d0243bd5c541"
|
||||
}
|
||||
],
|
||||
"wall_thickness_source": "as-built",
|
||||
"haz_tolerances": {
|
||||
"axial_grooving": {
|
||||
"depth": {
|
||||
"inputType": "number",
|
||||
"value": 0.15
|
||||
},
|
||||
"length": {
|
||||
"inputType": "number",
|
||||
"value": 20
|
||||
},
|
||||
"sensitivity": {
|
||||
"inputType": "number",
|
||||
"value": 3
|
||||
},
|
||||
"width": {
|
||||
"inputType": "number",
|
||||
"value": 20
|
||||
}
|
||||
},
|
||||
"axial_slotting": {
|
||||
"depth": {
|
||||
"inputType": "number",
|
||||
"value": 0.15
|
||||
},
|
||||
"length": {
|
||||
"inputType": "number",
|
||||
"value": 20
|
||||
},
|
||||
"sensitivity": {
|
||||
"inputType": "number",
|
||||
"value": 3
|
||||
},
|
||||
"width": {
|
||||
"inputType": "number",
|
||||
"value": 20
|
||||
}
|
||||
},
|
||||
"circumferential_grooving": {
|
||||
"depth": {
|
||||
"inputType": "number",
|
||||
"value": 0.15
|
||||
},
|
||||
"length": {
|
||||
"inputType": "number",
|
||||
"value": 20
|
||||
},
|
||||
"sensitivity": {
|
||||
"inputType": "number",
|
||||
"value": 3
|
||||
},
|
||||
"width": {
|
||||
"inputType": "number",
|
||||
"value": 20
|
||||
}
|
||||
},
|
||||
"circumferential_slotting": {
|
||||
"depth": {
|
||||
"inputType": "number",
|
||||
"value": 0.15
|
||||
},
|
||||
"length": {
|
||||
"inputType": "number",
|
||||
"value": 20
|
||||
},
|
||||
"sensitivity": {
|
||||
"inputType": "number",
|
||||
"value": 3
|
||||
},
|
||||
"width": {
|
||||
"inputType": "number",
|
||||
"value": 20
|
||||
}
|
||||
},
|
||||
"general": {
|
||||
"depth": {
|
||||
"inputType": "number",
|
||||
"value": 0.15
|
||||
},
|
||||
"length": {
|
||||
"inputType": "number",
|
||||
"value": 20
|
||||
},
|
||||
"sensitivity": {
|
||||
"inputType": "number",
|
||||
"value": 3
|
||||
},
|
||||
"width": {
|
||||
"inputType": "number",
|
||||
"value": 20
|
||||
}
|
||||
},
|
||||
"pinhole": {
|
||||
"depth": {
|
||||
"inputType": "number",
|
||||
"value": 0.15
|
||||
},
|
||||
"length": {
|
||||
"inputType": "number",
|
||||
"value": 20
|
||||
},
|
||||
"sensitivity": {
|
||||
"inputType": "number",
|
||||
"value": 2
|
||||
},
|
||||
"width": {
|
||||
"inputType": "number",
|
||||
"value": 20
|
||||
}
|
||||
},
|
||||
"pitting": {
|
||||
"depth": {
|
||||
"inputType": "number",
|
||||
"value": 0.15
|
||||
},
|
||||
"length": {
|
||||
"inputType": "number",
|
||||
"value": 20
|
||||
},
|
||||
"sensitivity": {
|
||||
"inputType": "number",
|
||||
"value": 3
|
||||
},
|
||||
"width": {
|
||||
"inputType": "number",
|
||||
"value": 20
|
||||
}
|
||||
}
|
||||
},
|
||||
"inspection_type": "mfl",
|
||||
"pipebody_tolerances": {
|
||||
"axial_grooving": {
|
||||
"depth": {
|
||||
"inputType": "number",
|
||||
"value": 0.2
|
||||
},
|
||||
"length": {
|
||||
"inputType": "number",
|
||||
"value": 13
|
||||
},
|
||||
"width": {
|
||||
"inputType": "number",
|
||||
"value": 15
|
||||
}
|
||||
},
|
||||
"axial_slotting": {
|
||||
"depth": {
|
||||
"inputType": "number",
|
||||
"value": 0.19
|
||||
},
|
||||
"length": {
|
||||
"inputType": "number",
|
||||
"value": 20
|
||||
},
|
||||
"width": {
|
||||
"inputType": "number",
|
||||
"value": 20
|
||||
}
|
||||
},
|
||||
"circumferential_grooving": {
|
||||
"depth": {
|
||||
"inputType": "number",
|
||||
"value": 0.13
|
||||
},
|
||||
"length": {
|
||||
"inputType": "number",
|
||||
"value": 13
|
||||
},
|
||||
"width": {
|
||||
"inputType": "number",
|
||||
"value": 15
|
||||
}
|
||||
},
|
||||
"circumferential_slotting": {
|
||||
"depth": {
|
||||
"inputType": "number",
|
||||
"value": 0.13
|
||||
},
|
||||
"length": {
|
||||
"inputType": "number",
|
||||
"value": 13
|
||||
},
|
||||
"width": {
|
||||
"inputType": "number",
|
||||
"value": 19
|
||||
}
|
||||
},
|
||||
"general": {
|
||||
"depth": {
|
||||
"inputType": "number",
|
||||
"value": 0.15
|
||||
},
|
||||
"length": {
|
||||
"inputType": "number",
|
||||
"value": 19
|
||||
},
|
||||
"width": {
|
||||
"inputType": "number",
|
||||
"value": 19
|
||||
}
|
||||
},
|
||||
"pinhole": {
|
||||
"depth": {
|
||||
"inputType": "number",
|
||||
"value": 0.2
|
||||
},
|
||||
"length": {
|
||||
"inputType": "number",
|
||||
"value": 20
|
||||
},
|
||||
"width": {
|
||||
"inputType": "number",
|
||||
"value": 20
|
||||
}
|
||||
},
|
||||
"pitting": {
|
||||
"depth": {
|
||||
"inputType": "number",
|
||||
"value": 0.13
|
||||
},
|
||||
"length": {
|
||||
"inputType": "number",
|
||||
"value": 13
|
||||
},
|
||||
"width": {
|
||||
"inputType": "number",
|
||||
"value": 15
|
||||
}
|
||||
}
|
||||
},
|
||||
"org_id": "2cbfe270-d195-48ad-aed1-24145924635c",
|
||||
"pipeline_id": [
|
||||
"01966d47-1d4c-7751-a1f1-0617caa3a00d"
|
||||
],
|
||||
"project_id": "680b61b0aedd6f9e639d8699",
|
||||
"report_type": "final",
|
||||
"vendor_name": "ILI-Ros"
|
||||
}
|
||||
224
src/main.rs
Normal file
224
src/main.rs
Normal file
@ -0,0 +1,224 @@
|
||||
use fathom_function::{
|
||||
chrono::NaiveDate,
|
||||
forms::{TableCellValue, deserialize_date},
|
||||
tracing,
|
||||
};
|
||||
use pipeline_application::application::{
|
||||
Application, DimensionClass, ILIConfiguration, InlineInspection, InspectionType, ReportType,
|
||||
Tolerance as ApplicationTolerance, ToleranceAdjustment, ToolTolerances, WallThicknessSource,
|
||||
uom::si::{f64::Length, length::millimeter},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[fathom_function::function]
|
||||
async fn ili_creation(input: Input) -> Result<Output, String> {
|
||||
let reports_details = input.report_details;
|
||||
let tolerances = input.tolerances;
|
||||
let config = input.config;
|
||||
let app = Application::new_from_compile_env(input.org_id, input.project_id).unwrap();
|
||||
|
||||
for (pipeline_id, file_details) in input.pipeline_id.into_iter().zip(input.file_details) {
|
||||
app.process_ili_report(
|
||||
pipeline_id,
|
||||
file_details.file_id,
|
||||
&tolerances,
|
||||
&reports_details,
|
||||
&config,
|
||||
)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
tracing::error!(%pipeline_id, ?err, "Error running ili calculations");
|
||||
format!("{err:?}")
|
||||
})?;
|
||||
}
|
||||
Ok(Output {
|
||||
status: "Success".to_owned(),
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
struct Output {
|
||||
status: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Input {
|
||||
org_id: Uuid,
|
||||
project_id: String,
|
||||
pipeline_id: Vec<Uuid>,
|
||||
file_details: Vec<FileDetails>,
|
||||
#[serde(flatten)]
|
||||
report_details: InspectionReportDetails,
|
||||
#[serde(flatten)]
|
||||
tolerances: CombineTolerances,
|
||||
#[serde(flatten)]
|
||||
config: Config,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Default)]
|
||||
#[serde(default)]
|
||||
struct Config {
|
||||
wall_thickness_source: WTSource,
|
||||
}
|
||||
|
||||
impl From<&Config> for ILIConfiguration {
|
||||
fn from(value: &Config) -> Self {
|
||||
Self::default().with_wall_thickness_source(value.wall_thickness_source)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone, Copy, Default)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
enum WTSource {
|
||||
#[default]
|
||||
AsBuilt,
|
||||
Report,
|
||||
}
|
||||
|
||||
impl From<WTSource> for WallThicknessSource {
|
||||
fn from(value: WTSource) -> Self {
|
||||
match value {
|
||||
WTSource::AsBuilt => Self::AsBuilt,
|
||||
WTSource::Report => Self::Reported,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct CombineTolerances {
|
||||
haz_tolerances: Tolerances<HazTolerance>,
|
||||
pipebody_tolerances: Tolerances<Tolerance>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Tolerances<T> {
|
||||
general: T,
|
||||
pitting: T,
|
||||
axial_grooving: T,
|
||||
circumferential_grooving: T,
|
||||
pinhole: T,
|
||||
axial_slotting: T,
|
||||
circumferential_slotting: T,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Tolerance {
|
||||
depth: TableCellValue,
|
||||
length: TableCellValue,
|
||||
width: TableCellValue,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct HazTolerance {
|
||||
sensitivity: TableCellValue,
|
||||
#[serde(flatten)]
|
||||
tolerance: Tolerance,
|
||||
}
|
||||
|
||||
impl Tolerance {
|
||||
fn to_tolerance(&self, haz_tolerances: &HazTolerance) -> Option<ApplicationTolerance> {
|
||||
Some(ApplicationTolerance::new(
|
||||
Option::<f64>::try_from(&haz_tolerances.sensitivity).ok()??,
|
||||
Option::<ToleranceAdjustment>::from(&haz_tolerances.tolerance)?,
|
||||
Option::<ToleranceAdjustment>::from(self)?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct InspectionReportDetails {
|
||||
#[serde(deserialize_with = "deserialize_date")]
|
||||
date: NaiveDate,
|
||||
vendor_name: String,
|
||||
report_type: ReportType,
|
||||
/// The inspection type and technology used.
|
||||
inspection_type: InspectionType,
|
||||
}
|
||||
|
||||
impl From<&CombineTolerances> for ToolTolerances {
|
||||
fn from(value: &CombineTolerances) -> Self {
|
||||
[
|
||||
(
|
||||
DimensionClass::General,
|
||||
value
|
||||
.pipebody_tolerances
|
||||
.general
|
||||
.to_tolerance(&value.haz_tolerances.general),
|
||||
),
|
||||
(
|
||||
DimensionClass::Pitting,
|
||||
value
|
||||
.pipebody_tolerances
|
||||
.pitting
|
||||
.to_tolerance(&value.haz_tolerances.pitting),
|
||||
),
|
||||
(
|
||||
DimensionClass::AxialGrooving,
|
||||
value
|
||||
.pipebody_tolerances
|
||||
.axial_grooving
|
||||
.to_tolerance(&value.haz_tolerances.axial_grooving),
|
||||
),
|
||||
(
|
||||
DimensionClass::CircumferentialGrooving,
|
||||
value
|
||||
.pipebody_tolerances
|
||||
.circumferential_grooving
|
||||
.to_tolerance(&value.haz_tolerances.circumferential_grooving),
|
||||
),
|
||||
(
|
||||
DimensionClass::Pinhole,
|
||||
value
|
||||
.pipebody_tolerances
|
||||
.pinhole
|
||||
.to_tolerance(&value.haz_tolerances.pinhole),
|
||||
),
|
||||
(
|
||||
DimensionClass::AxialSlotting,
|
||||
value
|
||||
.pipebody_tolerances
|
||||
.axial_slotting
|
||||
.to_tolerance(&value.haz_tolerances.axial_slotting),
|
||||
),
|
||||
(
|
||||
DimensionClass::CircumferentialSlotting,
|
||||
value
|
||||
.pipebody_tolerances
|
||||
.circumferential_slotting
|
||||
.to_tolerance(&value.haz_tolerances.circumferential_slotting),
|
||||
),
|
||||
]
|
||||
.into_iter()
|
||||
.filter_map(|(dc, tol)| tol.map(|tol| (dc, tol)))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Tolerance> for Option<ToleranceAdjustment> {
|
||||
fn from(value: &Tolerance) -> Self {
|
||||
Some(ToleranceAdjustment {
|
||||
depth: Option::<f64>::try_from(&value.depth).ok()??,
|
||||
width: Length::new::<millimeter>(Option::<f64>::try_from(&value.width).ok()??),
|
||||
length: Length::new::<millimeter>(Option::<f64>::try_from(&value.length).ok()??),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&InspectionReportDetails> for InlineInspection {
|
||||
fn from(value: &InspectionReportDetails) -> Self {
|
||||
Self {
|
||||
date: value.date,
|
||||
vendor_name: value.vendor_name.to_owned(),
|
||||
report_type: value.report_type,
|
||||
inspection_type: value.inspection_type,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct FileDetails {
|
||||
pub file_id: Uuid,
|
||||
pub revision_id: Uuid,
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user