Skip to content
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

On Delete item cascading #146

Closed
3 tasks done
vlad-ed-git opened this issue Jan 17, 2023 · 6 comments
Closed
3 tasks done

On Delete item cascading #146

vlad-ed-git opened this issue Jan 17, 2023 · 6 comments
Assignees

Comments

@vlad-ed-git
Copy link
Collaborator

vlad-ed-git commented Jan 17, 2023

  • Test deleting a contact -> what happens to the client holding it
  • Test deleting a client -> what happens with the contract or project referencing it
  • Test deleting a contract -> what happens to the project referencing it
@vlad-ed-git vlad-ed-git converted this from a draft issue Jan 17, 2023
@vlad-ed-git vlad-ed-git added bug Something isn't working and removed bug Something isn't working labels Jan 17, 2023
@vlad-ed-git vlad-ed-git changed the title Bugs: On Delete item cascading On Delete item cascading Jan 17, 2023
@clstaudt
Copy link
Contributor

The logic is straightforward: As long as a Contact is required by a Client, then it cannot be deleted. I think it's clear that the user does not want "cascading" deletion.

So, test for len(contact.invoicing_contact_of) > 0, if true do not allow deletion.

The implementation in the current MVI architecture is not straightforward though. e.g.: Where should this test happen? In the intent or the data source?

I chose the intent layer and implemented it for the deletion of contacts. @vlad-ed-git Please review my implementation.

@vlad-ed-git
Copy link
Collaborator Author

vlad-ed-git commented Jan 18, 2023

@clstaudt

The View

  • builds Ui,
  • reacts to data changes (by updating the Ui)
  • listens for events and forwards them to the Intent

The Intent

  • receives events
  • if some data is affected by the event, figure out which data source corresponds to that data
    - transforms the event data to the data format required by the data source
    - transform returned data source data to the data format required by the Ui
  • else, no data is affected by the event, handle the event (often using a util class).
    an example of this is sending invoices by mail.

The Model (a.k.a data layer)

  • define the entity
  • define the entity source (file, remote API, local database, in-memory cache, etc)
    - if a relational database is used, define the entity's relationship to other entities
    - maintain the integrity of that relation (conflict strategies for insert operations are defined here, and integrity errors are thrown here, for example)
  • define classes that manipulate this source (open, read, write, ....)
  • As you go outer in layers (the outmost layer is the Ui, the innermost is the data layer), communication can occur down_ward across layers, and horizontally (for lack of a better word) BUT a layer cannot skip the layer directly below it. This is to say:

    * Data sources can communicate with each other. Thus `ClientDatasource.delete_client` can call. `ContractDatasource.get_contract ` for example.
    
    * Intents can communicate with each other, and with any data source. Thus `ClientIntent` can call `ContractIntent` or  `ContractDatasource` for example.
    
    • The Ui can communicate with any intent (though often the Ui is tied to only a single intent, and the intent can instead call the 'other' intent). But it cannot communicate with a data source -> this would violate the do not skip layers rule.
  • An inner layer cannot have a dependency on the layer above it. Thus an intent cannot instantiate a Ui class, and a data source cannot instantiate an Intent class.

Image

@vlad-ed-git
Copy link
Collaborator Author

vlad-ed-git commented Jan 18, 2023

  • The above tasks fall under entity integrity management, and should thus be done in the data source.
    @clstaudt

If you are wondering how the intent would know if a delete did not happen because of some other error or because the object being deleted is depended on by another, this is where error_codes typically come in.

The IntentResult can define an error code (Error codes might be wrapped in enums for readability).
So in the case where a deletion fails because the entity being deleted is being used by another entity, the data source will return IntentResult with was_intent_sucessful = False, log_message="...IntegrityError, attempting to delete an entity referenced by another ...", error_code = ErrorCodes.IntegrityError

@clstaudt
Copy link
Contributor

clstaudt commented Jan 18, 2023

Thanks for clarifying.

  • transforms the event data to the data format required by the data source
  • transform returned data source data to the data format required by the Ui

Somewhat missing from the picture is the role of an ORM (Object Relational Mapper). SQLModel already abstracts the concrete database implementation, something that would otherwise be handled by the DataSource. And it seems to me that with SQLModel the data format required by the UI and the data source is often exactly the same. So not much transformation going on in practice.

@clstaudt clstaudt moved this from In Progress to Blocked in Tuttle Dev Jan 18, 2023
@clstaudt clstaudt moved this from Blocked to In Progress in Tuttle Dev Jan 18, 2023
@clstaudt clstaudt moved this from In Progress to Blocked in Tuttle Dev Jan 18, 2023
@clstaudt clstaudt moved this from Blocked to In Progress in Tuttle Dev Jan 19, 2023
@clstaudt
Copy link
Contributor

@vlad-ed-git
Copy link
Collaborator Author

@clstaudt To clarify this, "Somewhat missing from the picture is the role of an ORM (Object Relational Mapper)."

The abstraction that the ORM is doing is not specific to the models of project Tuttle.
It's hence not a replacement for the data source of Tuttle.

In the same way that flet (which abstracts the implementation of a button) is not a replacement for the View layer of Tuttle.
Tuttle's views are aware of how the update profile button looks and what events it listens for, similarly, the data source layer is aware of what updating a user profile entails for a given User model.

On the other hand, flet defines how a generic button looks and what events that button can listen to, and the ORM defines how a generic model can be stored in a table and how updating such a model is done.

@vlad-ed-git vlad-ed-git moved this from In Progress to Todo in Tuttle Dev Jan 21, 2023
@vlad-ed-git vlad-ed-git moved this from Todo to In Progress in Tuttle Dev Jan 22, 2023
@clstaudt clstaudt moved this from In Progress to Blocked in Tuttle Dev Jan 22, 2023
@clstaudt clstaudt moved this from Blocked to In Progress in Tuttle Dev Jan 22, 2023
@github-project-automation github-project-automation bot moved this from In Progress to Done in Tuttle Dev Jan 23, 2023
@clstaudt clstaudt reopened this Jan 23, 2023
@clstaudt clstaudt moved this from Done to Pending Review in Tuttle Dev Feb 9, 2023
@clstaudt clstaudt closed this as completed Apr 8, 2023
@github-project-automation github-project-automation bot moved this from Pending Review to Done in Tuttle Dev Apr 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

No branches or pull requests

2 participants