-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
6650 rename requisition line transformation and expose plugin data query to plugins #6684
base: 5837-requisition-line-column-and-plugin-data
Are you sure you want to change the base?
Conversation
@@ -173,7 +173,7 @@ You can work on plugins as if they were part of the app (types should be shared, | |||
|
|||
```bash | |||
# From server directory | |||
cargo run --bin remote_server_cli -- generate-plugin-bundle -i ../client/packages/plugins/mynewplugin/frontend -o pluginbundle.json | |||
cargo run --bin remote_server_cli -- generate-plugin-bundle -i ../client/packages/plugins/myPluginBundle/frontend -o pluginbundle.json |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
decided to change this since submodule example in readme uses myPluginBundle as plugin name
@@ -83,6 +85,9 @@ export const RequestLineEdit = ({ | |||
?.sort((a, b) => a.name.name.localeCompare(b.name.name)) | |||
.sort((a, b) => b.amcInUnits - a.amcInUnits) | |||
.sort((a, b) => b.stockInUnits - a.stockInUnits); | |||
|
|||
const line = lines.find(line => line.id === draft?.id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For fragment to be available to editViewColumns plugin interface
pub enum PluginType { | ||
Amc, | ||
TransformRequisitionLines, | ||
AverageMonthlyConsumption, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was not necessary, but not a huge change, sorry for the extra diff
@@ -8,10 +8,10 @@ use diesel_derive_enum::DbEnum; | |||
use serde::{Deserialize, Serialize}; | |||
|
|||
#[derive(Clone, Eq, PartialEq, Debug, Serialize, Deserialize)] | |||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")] | |||
#[serde(rename_all = "snake_case")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
snake case now because this maps directly to main plugins type now, made comments in types/mod.rs
pub struct EqualFilter<T> | ||
where | ||
T: 'static, | ||
{ | ||
#[ts(optional)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without optional Option is treated as null, with optional treated as undefined (with former have to list all fields ..)
pub(crate) fn call_plugin<I, O>( | ||
input: I, | ||
name: &str, | ||
r#type: &PluginType, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this change even though it's a little bit out of scope, it avoids having to hard code string and makes PluginType source of truth
Bundle size differenceComparing this PR to
|
let Some(arg) = args.get(index) else { | ||
return Err(Error::NoArgumentAtIndex(index)); | ||
}; | ||
let arg = args.get(index).ok_or(Error::NoArgumentAtIndex(index))?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry again refactor, i added new method below which uses ok_or so thought to keep consistent, subjectively no difference in readability Β―_(γ)_/Β―
SerdeError(#[from] serde_json::Error), | ||
} | ||
|
||
pub(super) fn get_serde_argument<D: DeserializeOwned>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is used to get of plugin data filter
@@ -30,6 +31,10 @@ pub trait Trait: Send + Sync { | |||
// TODO as macro ? Can do types here too | |||
impl self::Trait for PluginInstance { | |||
fn call(&self, input: Input) -> PluginResult<Output> { | |||
Ok(call_plugin(input, "average_monthly_consumption", self)?) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shows why PluginType is used now, rather then a string
@@ -127,6 +129,7 @@ fn generate( | |||
store_id, | |||
&requisition_row, | |||
items_ids_not_in_requisition, | |||
HashMap::new(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is the change for item to new line id mapping, see generate_requisition_lines
let types = PluginTypes(vec![PluginType::Amc, PluginType::Amc]); | ||
let types = PluginTypes(vec![ | ||
PluginType::AverageMonthlyConsumption, | ||
PluginType::AverageMonthlyConsumption, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit, but should we use the TransformRequestRequisitionLines here now?
|
||
let key = js_string!(name); | ||
let key = js_string!(r#type.as_str()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How come this one not using plugin_type_to_string
?
JsString::from("get_plugin_data"), | ||
0, | ||
NativeFunction::from_copy_closure(move |_, args, mut ctx| { | ||
// TODO Is this actually safe ? (need to check reference counts after plugin has run) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would like to know about this before we merge..?
|
||
// TODO pagination or restrictions ? | ||
let plugin_data: Vec<PluginDataRow> = PluginDataRepository::new(&connection) | ||
.query_by_filter(filter) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does feel pretty loose, had same thought with transform_lines
as plugin... would like to hear more about how much we intend to trust the plugins?
@@ -46,6 +49,8 @@ pub fn generate_requisition_lines( | |||
store_id: &str, | |||
requisition_row: &RequisitionRow, | |||
item_ids: Vec<String>, | |||
// Need for plugins since sometimes we set id passed in as parameter in graphql |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, the insert_request_requisition_line
that does this is only used from batch mutation, which is not used by our frontend? Do you know if there is an integration that we need to support here, or should we remove the batch mutation and then wouldn't need to do this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I TAKE IT BACK IM BAD AT SEARCHING IT IS INDEED USED
Looking good, would like to know about the todos you left, will test properly in the morning π |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Requesting changes at least until hear from you what we do now vs added to carryover:
- Currently
transform_request_requisition_lines
is not called byupdate_request_requisition_line
but it is byupdate_request_requisition
- should be added to line update too I think- If plugin interface/capability is as generic as "transform" then I think should be called in all cases
- As discussed, could pass an ActionType enum into plugin, for plugin to determine if runs on all calls, only create etc.
- Other places currently not using plugin that probably should in this case: R&R form, processors, fine grained calls like
use_suggested_quantity
(+ maybe more?? see below, I'm worried about this, how do we ensure we don't miss any?)
- Backend plugin helper methods have:
// TODO Is this actually safe ? (need to check reference counts after plugin has run)
... can we remove this if you are happy it is safe? - Back and frontend plugins should have same code in package.json
- I wonder if common frontend should expose
usePluginData
hook rather than implementing for each plugin- This can extract pluginCode from the plugin itself?
- Query and mutate should only be able to access plugin data for that plugin code
- restrict
get_plugin_data
- Maybe
call_plugin
method supports returning of plugin_data rows, can then get processed and plugin code applied, before returned to service call for saving? Though probs requires a second kind ofcall_plugin_with_data_output
or something....
- restrict
- I wonder if common frontend should expose
- For thought - best practices to ensure plugin calls aren't missed in future core dev? Should live in mod file, as generic place as possible... are there better patterns to support the plugin architecture?
FYI at one point you mentioned update would be creating duplicate plugin data, but looks like backend plugin that isn't happening anymore. I wonder about frontend though, whether we should expose upsert plugin data mutation rather than 2 separately
@@ -213,6 +218,10 @@ export const RequestLineEdit = ({ | |||
label={t('label.amc')} | |||
sx={{ marginBottom: 1 }} | |||
/> | |||
{line && | |||
plugins.requestRequisitionColumn?.editViewColumns?.map( | |||
(Column, index) => <Column key={index} line={line} /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should call this Field
, and editViewFields
? Column
has me thinking I should be defining a column definition with cell/accessor etc..
Fixes #6650
π©π»βπ» What does this PR do?
Sorry I did a bit more then specified by the issue.
Renamed transform_requisition_line to transform_request_requisition_line, while renaming I decided to use PluginType as source of truth, this also included updating types in the backend plugin package.json (see example branch mentioned in testing)
Added get plugin data method that is exposed now to plugins
Exposed request edit line in front end to also have columns shown
I found a bug where plugin data is set for wrong id, because id is overwritten after generating requisition line (since we are using id generated on front end), this was fixed by providing item_id -> id mapping to generate requisition line
π Any notes for the reviewer?
Plugin data filter is exposed to plugin, we starting to expose types that are deep in our code, which is very convenient but would require testing strategy, which will be implemented for CIV plugins.
π§ͺ Testing
Use this branch of examples: msupply-foundation/open-msupply-plugins#11
Create internal order, see aggregate AMC value appearing in table and edit lines view. Delete a line with 0 aggregate amc. Create manual response requisition with that item, set amc. Insert that one line again in internal order, see aggregate amc change having value. Aggregate AMC should be sum of all of the latest response requisition line AMC for that item in that store