Closed vlad-ed-git closed 1 year ago
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.
@clstaudt
The View
The Intent
The Model (a.k.a data layer)
define the entity
define the entity source (file, remote API, local database, in-memory cache, etc)
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.
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.
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
Thanks for clarifying.
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 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.