How (what design pattern) to handle adding new fields? - oop

I have been doing web app for medical data collection for a long time. Clients always have this kind of request : adding a new field in the form, for example they want add "gender" in demographic form.
Every time they request, I have to
1. Add a new textbox on the page.
2. Add a new field(property) in my demographic form class.
3. Change my business logic for saving the form to DB.
4. Change my business logic for loading the form from DB.
5. Add a new column in the Database table.
6. Alter the Store Procedure for insert and update the demographic table.
I have to make changes on every layer, every module(UI, business layer, data access layer, db), and I feel it is stupid.
How can I handle this kind of change? What pattern should I use?

Something like an ORM would be helpful here. I'll give you an example from Django framework. I am not saying you should use this one in particular, but its tutorial illustrates the concept nicely.
That's our model class:
from django.db import models
class Poll(models.Model):
question = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published)
It generates this DB query:
BEGIN;
CREATE TABLE "polls_poll" (
"id" integer NOT NULL PRIMARY KEY,
"question" varchar(200) NOT NULL,
"pub_date" datetime NOT NULL
);
COMMIT;
Then, you can easily view all of the Polls:
class IndexView(generic.ListView):
model = Poll # specifies model
template_name = 'polls/index.html' # specifies HTML template
Template could look like this:
{% if latest_poll_list %}
<ul>
{% for poll in latest_poll_list %}
<li>{{ poll.question }}</li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
It could use automatic field iteration to display either the data of the inputs, instead. Django automatically chooses appropriate type of input to match the type of data.
Now, when you add a field to Poll class, it automatically propagates to database creation and extraction queries, and the form incorporates the newly added field.
Different frameworks behave slightly differently, of course, so you would need to review them before using. All of them usually supplies you with the tools to solve your problem, and tweak where the generic solutions aren't enough.

Not exactly a pattern but here's an idea:
You could store all the form fields in a map/table/dictionary in your Demographic class.
add the field in the UI
add it's value to the class' map/dictionary for a predefined key
save the map/dictionary to your DB by using each pair's key as a column name
populate the map/dictionary from you DB inserting a pair with the column name as a key
on save check if there is a column for that key. If not - add one
using this approach notify your logic that the map/dictionary was updated and update your CREATE query with the new column (key)

Related

How to create a unique number in Sanity.io?

I have a field of the type number defined on a document in my schema. When the user inputs a number, I want a validation which verifies that no another document of the same type has the same number assigned to this field. How am I able to do this?
There's no out of the box solution to check for uniqueness. Currently the only input that does this is the slug field. However, you can create your own custom validation that uses the client to check for other documents with the same number for the specific field.
You can read more about custom validation in the docs. To import the client, you can add this to the top of your schema import client from 'part:#sanity/base/client'. Then, write a GROQ query to look for the number and validate accordingly.
Hope that helps!

Compute many2many field with values from another model using Odoo developer interface

I need a new field inside Contact model that would hold information about Allowed companies of the related user.
Now there is only field about Currently picked company by that user (and it is not enough for me to make a record rule).
The field I want to copy values from is inside model Users and it is called company_ids.
I’m trying to add this field in the developer mode (Settings > Technical > Fields) like this:
But I’m having trouble with code that would fill my field with values from the another model.
for record in self:
record[("x_company_ids")] = env['res.users'].company_ids
I’m guessing that the record is referring to a record inside Contact model and it does not contain fields from another models like Users. So I can’t figure it out how to reference a field from another model.
Something similar to this: env['res.users'].company_ids?
It is even harder for me because it is many2many field and should always update when the source changes.
Maybe better solution would be to use Automatic action to write values to this field?
I saw some threads like this: Computed many2many field dependencies in Odoo 10.
But it seems like in those cases they had clear connection between the fields and I don't have it. I don't know how to get related user while I'm inside Contact model. I know only how to this oposite way (from user to contact): user.partner_id.id
Here in below given code you haven't specified related user from which you will get company_ids, you have directly accessing company_ids
for record in self:
record[("x_company_ids")] = env['res.users'].company_ids
You can write as following :
for record in self:
record["x_company_ids"] = self.env['res.users'].search([('partner_id','=',record.id)]).company_ids

How to create just a view in odoo9 that does not save data in a model?

I am working in odoo9. Now I needed a view that permits the user to select partner and get his sale history.
Now I created a model "sale.history" but it saves the selected data as a record in db. I really don't need this.
How can I create a view for this.
Please also see this image.
You have two options for such views/reports.
Use TransientModel instead of Model for the model inheritance. Transient model records in database will be deleted by a frequently running cron job. The email message PopUp/Wizard is a nice example for that.
Write your own report (database view) for sales order. Actually there already is one report for that: Reporting/Sales/Sales Analysis. The model for that report is sale.report if you want to know, how it's done.
Aside from using a TransientModel (old api) or AbstractModel (new api)...you can simply set the store property of field to false, that way your field will never be persisted to the database, it will simply be a 'view field'.
class sale_history(model.Model):
_name='sale.history'
partner = fields.Many2one('res.partner', store=False)
The partner field will never get saved to the database
You can use store=False on the field in the model (as danidee suggested).
You can also overwrite the create method on the model.
Question - what is the purpose of the "sale.history" model? If it does not store any data at all then you may be better off creating a new view against "res.partner" rather than creating a new model.

Adding lookups to given view

I'm just getting into Yii. I have a simple relational db. I have a "client" table related to "orders" table (client:id to orders:client_id). If I build my CRUD for orders i naturally see client_id, however I'd rather add a lookup for client name somehow
I have found how to do this on new and update _forms by adding a dropDownList. The list based views seem a little more complex. I can see that actionIndex() in the controller is gathering data and passing it to index.php, finally through to _view, but I can't find any help on where and how I should break into this with my lookup returning the client name
I'd appreciate any help
thanks
Check the Yii documentation about relations. You will need to create a relation in your orders table, lets call it client, Then in your list view where it generates client_id you can put client.name instead. Now you will need to make sure that you have the appropriate label because in the generated model it will only have a label for client_id, and you need a label for client.name. Yii will guess, or you can add it, or you can modify the label for client_id, and instead of using client.name in the view you can use
array(
'name'=>'client_id',
'value'=>$model->client->name,
)
I tend to gravitate towards more explicit definitions rather than shortcuts, but to each his own.

Django queries: how to annotate with a filtered count?

Suppose I have a Book model with a language field and a foreign key to a Publisher model.
Currently I use a Count annotation in a custom Publisher manager to allow me to add to the admin a sortable column with the number of books by each publisher. (see How to add a sortable count column to the Django admin of a model with a many-to-one relation? )
My problem now is that I need to have a different column count for the books published in each language.
Is there any way to make the annotation subject to a filter of the related model?
You can use the double underscore __ for this purpose. Something like this (snippet taken from question linked to by OP):
class PublisherManager(models.Manager):
def get_query_set(self):
return super(PublisherManager,self).get_query_set().annotate(lang_count=Count('book__language'))