-
Notifications
You must be signed in to change notification settings - Fork 25
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
feat: metadata import #57
base: main-v13
Are you sure you want to change the base?
Conversation
fix: remove special characters from contact before saving (ParsimonyGit#55)
ContributorsCommit-Lint commandsYou can trigger Commit-Lint actions by commenting on this PR:
|
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.
Hey @batonac, thanks for sending up a contribution! I have some general design notes/questions though:
- I see that you've set it up so that every time a new order is fetched, the system will start populating the "Shipstation Options Import" table.
- Can we request Shipstation to give us all product info with options at once? Rather than having to wait until a product is imported via an order?
- Since this can happen async after the first import, should there be a way (a flag to allow setting up notifications, maybe) to notify users that a new option requires an SO field?
- In your screenshot, I see that you've mapped two options to the same SO field.
- Are the fields coming from different stores, or have alternate names?
- Shouldn't the default behaviour be a 1:1 map? Which option takes precedence between the two if both exist?
- If the expected behaviour is a 1:1 map, then I don't see a real use of the custom fields table. Maybe the two can be merged?
- The custom fields table and create/update custom fields button seem out-of-place for this doctype.
- This behaviour already exists in Customize Form, and custom fields should ideally be handled there instead.
- Suggestion: If we still want to handle it here, I think a better UX might be:
- add a button to show a prompt (as a table, similar to "Update Items" in Sales Order) that lets users view which option fields are missing
- let user decide what each field needs to be in the prompt's table
- add action to have the system create the missing custom fields
- let the user map each option in the table from a dropdown of fields
- For users that are also using the accounting module, I think it might be good to setup the fields in the Sales Invoice and Delivery Note doctypes as well.
Hey @Alchez, thanks for the review! Here are my responses:
I'm not totally following you here... the system does query the "Shipstation Options Import" table when an order is processed, to see if any of the order items have matching metadata/options. It will import an option from Shipstation only if there's a pre-configured match on that table. It never does pull a list of product options from Shipstation, at present. It assumes that you will know the name of the options you want to import and will pre-specify them on the "Shipstation Options Import" table.
I can only speak of Shipstation Woocommerce integration, and my own client's scenario. We are using custom fields/option on our Woocommerce setup, and as such there would be no realistic way (that I know of), to query all the possible options via API ahead of time. The custom options are fed into the metadata on each Woocommerce Order Item, and then passed through to Shipstation as order item options. In a more standardized scenario with parent and variant items, this might be more "doable", though I'm not experienced enough with Shipstation to know how well it supports importing and syncing product variations and attributes across various products. To be even more specific, you, understandably, are probably thinking of "Variable Products", but what we're using is actually Gravity Forms Product Add-ons. This is obviously specific to our e-commerce platform and not Shipstation per-se, but it illustrates why I took the approach I did. Not everyone will have such an unstructured approach, but I assume it won't be totally uncommon. Free-formed product options are definitely a thing. This explains the following as well:
What's actually happening here is that the product options are not completely standardized on the e-commerce side. Thus, this isn't about one product option taking precedent over another, but in being able to scrape options from differently structured products and funnel them into a single/consolidated field in ERPNext. In a perfect world, there would be a 1:1 map, but in my experience, that's expecting a bit too much... (I'm not aware of any widely-adopted standardized schema for product options). In this scenario, we have a wholesale form that names the options differently than our retail form. We could fix/change this if need be, but I would expect some of the same kind of scenarios almost anywhere that local/product-specific options can exist.
I could certainly embrace this approach. As I'm envisioning this solution, the sync engine would add a new entry to the "Shipstation Options Import" table any time it encounters a newly-named option, and let the user select from existing fields from the Order Item table, or create new ones. Something like this?
I'm assuming this would still allow for a break from the "1:1 map" (from the above discussion), is that right?
Interesting. I'm seeing that "make_sales_invoice" is being used from erpnext.selling.doctype.sales_order.sales_order to make the sales invoice, and "make_delivery_note" from erpnext.accounts.doctype.sales_invoice.sales_invoice for the delivery notes. I didn't study either extensively, but are you thinking that it would be as simple as ensuring that all the custom fields are replicated on both those doctypes to allow for the data sync? |
Hey @batonac,
Oh sorry, I might have missed some detail in this part of the code 😅
Yeah, I just browsed through the API, and the item options only seem to be available while importing an order. Oh well.
Okay, I understand now. I had assumed that the options were coming from the same source, but it makes more sense that they're mapping different contexts.
I think you've got it. My only question here would be: is there any additional filters or controls you think a user would want on these new fields? Such as read-only, hidden, in grid view, etc.? If the answer is yes, then I think it would be better to handle it in Customize Form since it allows for larger control over the fields (I think this will also come down to the level of permissions, because adding Custom Fields is a very restricted action). But either way, this could still be a "Quick Entry" way of adding the fields and then modifying them manually later.
Yes, if we take up the prompt approach, then we should be able to arbitrarily map multiple options to the same fields.
Internally, both those functions use a mapper function, which can implicitly map data across doctypes if the fieldnames are the same, so you should be able to just the add the field and be done. |
From my perspective, there are two compelling reasons to retain custom-field creation functionality in this app:
That said, if we are indeed steering away from a 1:1 map, then I'm leaning back towards the initial concept here of two separate child tables for managing custom field creation and shipstation option mapping. I believe the experience could be improved by eliminating the side-by-side view, and hiding the custom field creation behind a conditional checkbox. The custom field creation table could be built out with all the basic field option inputs, as needed. Here's what I'm envisioning currently (with an example in the bottom row): Metadata ImportShipstation Options Import
☑ Create Custom Item Fields Order Item Custom Fields (on Sales Order Item, Sales Invoice Item, and Delivery Note Item Child Tables)
How would you feel about this approach? |
I think it's good UX to allow custom fields to be made in the context of the Shipstation, and I agree with both of your points. My concerns were mostly around duplication and maintenance of features, but that could be a small con against the benefit of being able to create the fields in-place.
Yeah, this design is good. I would just suggest keeping the "Create Custom Item Fields" checkbox as a button from your initial design. That would show the prompt and also let you apply permission levels incase someone needed to put that button behind a role. Speaking of which, we should consider the following:
|
Hey @Alchez, I believe the layout and functionality changes we discussed are all committed and ready to merge.
I believe the only thing we discussed that wasn't touched is the permissions. Since the Shipstation Settings doctype is already limited to "System Manager" or greater, I figured that can be refined down the road if it's necessary to open this up a bit more. Please review! |
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.
@batonac, hey sorry, I haven't had a chance recently to get to this. I haven't done a functional review of the feature yet, but I've added a few comments on the code.
I'll try and get to the functional review sometime in the next 2 weeks.
Can you also please have a look at the Deepsource linter issues for styling?
query: "shipstation_integration.shipstation_integration.doctype.shipstation_settings.shipstation_settings.get_item_fields" | ||
}; | ||
}); | ||
frappe.meta.get_docfield("Shipstation Options Import", "sales_order_item_field", frm.docname).ignore_link_validation = true; |
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.
Can you add a comment here for why we're doing 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.
you have a keen eye @Alchez. both of these code comments are related to the same issue.
I consider the use of a link control for the sales_order_item_field to be a really slick solution, but allowing both DocFields and Custom Field to be selected interchangeably requires a custom query, which throws Frappe into a tizzy when trying to validate the links, even with a "Dynamic Link" populated control.
This was my workaround. If there's a better way to handle this, I'd be glad to know how.
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.
@batonac, I see what you're trying to do. I think we could get away with replacing the Link control with a Select control, which would still let you populate a list to choose from as well as avoid any link validation issues.
The only downside might be the UX, since you would only be able to show the fieldnames in the list, and not the label (unless you add some special processing to separate the two, but that might not be worth it).
I think Link -> Select is a good enough trade-off.
frappe.ui.form.on("Shipstation Options Import", { | ||
sales_order_item_field: (frm, cdt, cdn) => { | ||
const row = locals[cdt][cdn]; | ||
row._ignore_links = true; |
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.
Can you add a comment for adding this flag?
Okay, I tested out the changes, and I think it's almost there! Here's my notes on the feature's UX:
|
c84cd47
to
7304454
Compare
@batonac, just an FYI: we've renamed the default branch from Is there anything left to be done in this PR by you, or should I give it another review? |
Hey @Alchez, that sounds good. v14 compatibility of this app was the last thing I was waiting for before moving my client to that version. In the meantime, I'll try to get the field link fields patched up, and then submit for another review. |
Hey @Alchez! So I just took another stab at the Item Field Linking issue, this time by implementing a Virtual DocType for listing/linking the standard and custom fields available in the Sales Order Item Doctype. I had hoped this would provide an extremely elegant and robust solution, including cleaning up code and dropping workarounds, but alas, it seems that Virtual DocTypes are not very well-supported before Version 14, so the custom I'll await your direction at this point. Is this okay to merge in the v13 branch and then rebase against v14 as a separate PR, or should I rebase this entire PR against that version/branch? |
Ideally I'd like to avoid having to maintain two different versions of the feature code. Do you need this feature for v13?
In either case, I can't guarantee code maintenance, since I haven't worked with Virtual Doctypes much (yet), but PRs are welcome and I wouldn't mind reviewing them. As for your new changes, I'm working on different clients/projects, so it might be sometime before I can get around to properly reviewing it. PS: can you have a look at the Deepsource Python lint errors? I think the JS one can be ignored for now. If you're making this to v14, you can also use the pre-commit hooks defined in the repo. |
Sounds good @Alchez. I'll rebase this against v14 and check out the DeepSource Python errors. As for the Virtual DocType, I don't believe it's quite as "scary" as it seems on the onset. The heart of it is a very simple DocType definition which bypasses the need for a dedicated table and simply operates based on a dedicated get_list function which returns the following dataset:
This should allow for "properly" linking to all available fields in the Sales Order Item DocType (standard and custom) without disabling link validation, creating any other custom query override, or (alternatively) creating a custom function to populate a select field. I trust that, upon review, you will appreciate the elegance of this approach. |
This code closes #52
They say a picture is worth a thousand words, so here goes: