Compare commits

...

1 Commits
main ... v6

Author SHA1 Message Date
FunctionsAPI
6862b6b6b3 Automatic push from FunctionsAPI 2025-06-12 08:06:10 +00:00
5 changed files with 3933 additions and 1 deletions

3422
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

11
Cargo.toml Normal file
View 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 = "FTHM-12741/adnoc-ingestion" }
pipeline-application = { git = "ssh://git@github.com/fathom-io/pipeline-calculations.git", branch = "FTHM-12741/adnoc-ingestion" }
serde = { version = "1.0.219", features = ["derive"] }
tokio = { version = "1.43.0", features = ["macros", "rt-multi-thread"] }
uuid = { version = "1" }

View File

@ -1,2 +1,65 @@
# 08fec16a203e4af999d114903298d8f1
# 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
- `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 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
curl localhost:8080 -d $(jq '. | tojson' functions/ili_creation/example_input.json)
```

245
example_input.json Normal file
View File

@ -0,0 +1,245 @@
{
"date": "Fri Feb 01 2002",
"file_details": [
{
"fileId": "a2e8295f-3547-47b1-92ae-d5446b081eee",
"revisionId": "2c68f624-2e9b-4c4a-90e0-d0243bd5c541"
}
],
"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"
}

191
src/main.rs Normal file
View File

@ -0,0 +1,191 @@
use fathom_function::{
chrono::NaiveDate,
forms::{TableCellValue, deserialize_date},
tracing,
};
use pipeline_application::application::{
Application, DimensionClass, InlineInspection, InspectionType, ReportType,
Tolerance as ApplicationTolerance, ToleranceAdjustment, ToolTolerances,
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 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,
)
.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,
}
#[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,
}