Checkbox to enable/disable other items when checked - sql

I have this report, every column is generated by the APEX_ITEM package.
APEX_ITEM.CHECKBOX2, APEX_ITEM.DATE_POPUP2
When the checkbox is checked, I would like to enable the DATE_POPUP2 of that row. And disabled it when the checkbox is unchecked.
Is there any way to do this?
Report query:
SELECT APEX_ITEM.CHECKBOX2(1,a.USR_CODIGO,DECODE(NVL((SELECT 1
FROM PROYECTOS_ROLES_USUARIOS pru
WHERE pru.USR_CODIGO = a.USR_CODIGO
AND pru.PRY_ID = :P92_PRY_ID),0),0,'UNCHECKED',1,'CHECKED')) as Incluir,
a.USR_CODIGO as Usuario, APEX_ITEM.SELECT_LIST_FROM_QUERY(2, NVL((SELECT pru.ROL_CODIGO
FROM PROYECTOS_ROLES_USUARIOS pru
WHERE pru.USR_CODIGO = a.USR_CODIGO
AND pru.PRY_ID = :P92_PRY_ID),null), 'SELECT r.ROL_DESCRIPCION, r.ROL_CODIGO
FROM ROLES r WHERE EXISTS (SELECT 1 FROM ROLES_USUARIOS ru
WHERE ru.ROL_CODIGO = r.ROL_CODIGO
AND ru.USR_CODIGO = ''' || a.USR_CODIGO || ''') and r.ROL_CODIGO not in(''MNI_RRHH'',''CAJ_COMPRAS'',''CAJ_VENTAS'',''CTA_CTE_CLIENTES''
,''CTA_CTE_PROVEEDORES'',''TCM_ALQUILERES'',''TCM_COMPRAS'') order by 1', null, 'YES', '%NULL%', '--') as Rol,
NVL((SELECT APEX_ITEM.DATE_POPUP2(3, prus.PRU_FECHA_INICIO, 'dd/mm/yyyy')
from PROYECTOS_ROLES_USUARIOS prus where prus.PRY_ID = :P92_PRY_ID and prus.USR_CODIGO = a.USR_CODIGO),
APEX_ITEM.DATE_POPUP2(3, TO_CHAR(SYSDATE, 'dd/mm/yyyy'), 'dd/mm/yyyy')) as Fecha_Inicio FROM USUARIOS a WHERE a.USR_FECHA_BAJA IS NULL AND exists (SELECT 1
FROM WWV_FLOW_FND_USER
WHERE USER_NAME = a.USR_CODIGO) order by 1;

As Tom suggests in his comment, there are various ways to do this using JavaScript. You could just apply CSS classes to your checkbox and date item and then use some jQuery to perform the action.
Defining this event binding in your page preferences in the 'Execute when page loads' section would do it.
$('input.myCheckBox').click(function() {
var enabled = $(this).prop('checked');
var myDate = $(this).closest('tr').find('input.myDate');
myDate.prop('disabled', !enabled);
if(enabled) {
myDate.next('img').show();
} else {
myDate.next('img').hide();
}
});
With this approach you do not need to apply IDs to your elements. You could also go down the dynamic action route, perhaps triggering a custom event which is interpreted by the dynamic action?

Related

Optimizing EF flattening

I have a similar case to the following:
Say there's a number of jobs to be done and for each job there's a history of workers where only one worker is active per job. There's three tables: the Job itself, a mapping table JobWorkers which holds the history of workers for a given job (including a datetime "To" which indicates whether still active (null) or when assignment was cancelled (end date)) and Workers which have a first and last name.
I'd like to query a list of all jobs and the first and last name of the currently assigned worker as flat model. This is the code I'm executing:
var jobExample = dbContext.Jobs.Select(j => new
{
j.JobId,
// ...some other columns from jobs table
j.JobWorker.FirstOrDefault(jw => jw.To == null).Worker.FirstName, // first name of currently assigned worker
j.JobWorker.FirstOrDefault(jw => jw.To == null).Worker.LastName // last name of currently assigned worker
}).First();
The following SQL query is generated:
SELECT TOP (1)
[Extent1].[JobId] AS [JobId],
[Extent3].[FirstName] AS [FirstName],
[Extent5].[LastName] AS [LastName]
FROM [tables].[Jobs] AS [Extent1]
OUTER APPLY (SELECT TOP (1)
[Extent2].[WorkerId] AS [WorkerId]
FROM [tables].[JobWorkers] AS [Extent2]
WHERE ([Extent1].[JobId] = [Extent2].[JobId]) AND ([Extent2].[To] IS NULL) ) AS [Limit1]
LEFT OUTER JOIN [tables].[Workers] AS [Extent3] ON [Limit1].[WorkerId] = [Extent3].[WorkerId]
OUTER APPLY (SELECT TOP (1)
[Extent4].[WorkerId] AS [WorkerId]
FROM [tables].[JobWorkers] AS [Extent4]
WHERE ([Extent1].[JobId] = [Extent4].[JobId]) AND ([Extent4].[To] IS NULL) ) AS [Limit2]
LEFT OUTER JOIN [tables].[Workers] AS [Extent5] ON [Limit2].[WorkerId] = [Extent5].[WorkerId]
As one can see there're two outer apply/left outer joins that are identical. I'd like to get rid of one of those to make the query more performant.
Note that the select statement is dynamically generated based on what information the user actually wants to query. But even if this didn't apply I'm not sure how to do this without having a hierarchic structure and then only afterwards flatten it in .NET
Thanks for your help and if I can improve this question in any way please comment.
You've probably seen that there are two types of LINQ methods: the ones that return IQueryable<...>, and the other ones.
Methods of the first group use deferred execution. This means, that the query is made, but not executed yet. Your database is not contacted.
Methods of the second group, like ToList(), FirstOrDefault(), Count(), Any(), will execute the query: they will contact the database, and fetch the data that is needed to calculate the result.
This is the reason, that you should try to postpone any method of the second group to as last as possible. If you do it earlier, and you do something LINQy after it, changes are that you fetch to much data, or, as in your case: that you do execute the same code twice.
The solution is: move your FirstOrDefault to a later moment.
var jobExample = dbContext.Jobs.Select(job => new
{
Id = job.JobId,
... // other job properties
ActiveWorker = job.JobWorkers
.Where(jobWorker => jobWorker.To == null)
.Select(worker => new
{
FirstName = worker.FirstName,
LastName = worker.LastName,
})
.FirstOrDefault(),
})
.FirstOrDefault();
The result is slightly different than yours:
Id = 10;
... // other Job properties
// the current active worker:
ActiveWorker =
{
FirstName = "John",
LastName = "Doe",
}
If you really want an object with Id / FirstName / LastName, add an extra Select before your final FirstOrDefault:
.Select(jobWithActiveWorker => new
{
Id = jobWithActiveWorker.Id,
... // other Job properties
// properties of the current active worker
FirstName = jobWithActiveWorker.FirstName,
LastName = jobWithActiveWorker.LastName,
})
.FirstOrDefault();
Personally I think that you should not mix Job properties with Worker properties, so I think the first solution: "Job with its currently active worker" is neater: the Job properties are separated from the Worker properties. You can see why that is important if you also wanted the Id of the active worker:
.Select(job => new
{
Id = job.JobId,
... // other job properties
ActiveWorker = job.JobWorkers
.Where(jobWorker => jobWorker.To == null)
.Select(jobworker => new
{
Id = jobworker.Id,
FirstName = jobworker.FirstName,
LastName = jobworker.LastName,
})
.FirstOrDefault(),
})
.FirstOrDefault();
Try rewriting your query like this:
var query =
from j in dbContext.Jobs
let ws = j.JobWorker
.Where(jw => jw.To == null)
.Select(jw => jw.Worker)
.Take(1)
from w in ws.DefaultIfEmpty()
select new
{
j.JobId,
// other properties
w.FirstName,
w.LastName,
};
The query processor probably could not have optimized any further to know it could use the subquery once.

Magento - SQL - Select all products by attribute and update it

I need to select all products with specific attribute (barcolor) and then update attribute with another value.
EXAMPLE.
I would like to select all SKU with barcolor = LIGHT GREEN and update them to GREEN.
Thanks!
you can do this from backend. you can go to catalog > manage products > select all products > at the right side you can see update attributes option , select that and click on submit and you will redirect to another page and than give the value in required field and save it.
It can be achieve by programming also.
If you have attribute option ID than:
$sAttributeName = 'brands';
$mOptionValueId = 250; // 250 is Id of Brand 1
$newOptionValueId = 255; // 255 is Id of Brand 2
$productsCollection = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect('*')
->addFieldToFilter(
$sAttributeName,
array(
'eq' => $mOptionValueId
)
);
$storeId = Mage::app()->getStore()->getStoreId();
foreach($productsCollection as $product) {
$productId = $product->getId();
Mage::getSingleton('catalog/product_action')->updateAttributes(
array($productId),
array('brands' => $newOptionValueId),
$storeId
);
}
If you do not have attribute option ID than you can use the option value directly as:
$sAttributeName = 'brands';
$mOptionValue = 'Brand 1';
$newOptionValue = 'Brand 2';
$productsCollection = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect('*')
->addFieldToFilter(
$sAttributeName,
array(
'eq' => Mage::getResourceModel('catalog/product')
->getAttribute($sAttributeName)
->getSource()
->getOptionId($mOptionValue)
)
);
$storeId = Mage::app()->getStore()->getStoreId();
foreach($productsCollection as $product) {
$productId = $product->getId();
Mage::getSingleton('catalog/product_action')->updateAttributes(
array($productId),
array('brands' => Mage::getResourceModel('catalog/product')
->getAttribute($sAttributeName)
->getSource()
->getOptionId($newOptionValue)),
$storeId
);
}
If you have the list of the entity_ids for all the products and you are using a custom attribute, you can run an SQL query for each and every product like so:
UPDATE `catalog_product_entity_varchar` SET value = 'NEW BLACK' WHERE entity_id = '12345' AND attribute_id = 'attribute_id_here';
You can also filter the fields by:
SELECT entity_id,value FROM catalog_product_entity_varchar WHERE value LIKE 'something';

(web2py) add extra fields auth_user that reference another field

I am using Web2py and I would like to add extra fields in the auth_user. some of these fields are reference to other table. for example:
auth.settings.extra_fields['auth_user']= [
Field('country', 'reference countries')]
db.define_table(
'countries',
Field('name'),
format = '%(name)s'
)
but I receive this issue:
cannot resolve reference countries in auth_user definition
can any one help me what should I do? how can I link auth_user table with another table???
All the Best
you need to make sure your db.define_table is created before your the auth tables
like this :
db.define_table('bank',
Field('name'),
format = '%(name)s')
auth.settings.extra_fields['auth_user'] =
[Field('bank', 'reference bank',
label = T('Bank'),
notnull = True,
required = True,
requires = IS_IN_DB(db, db.bank.id, '%(name)s') ),
]
auth.define_tables(username = True, signature = True)
custom_auth_table = db[auth.settings.table_user_name]
auth.settings.table_user = custom_auth_table

validate model depending radio button selected

I have install yii-user extension and add some column in tbl_profile table for registration. Registration type are two type: Personal and company
following are the column added:
For company: company_name, comoany_type
For personal: phone
For both personal and company: mobile, fullname, country, states, postal_code, address1, address2
I have use jquery to hide and disable the input field of form according to radio button selection of registration type.
Same goes for country selection for both registration type. Two Options: e.g USA and other country
I am confused that how can I validate the property according to the registration type selected. e.g. If I select the personal then disable the validation for the company property field.
There are two models with their property:
Profile: fullname, company_name, company_type, mobile, phone, firstaddress, secondaddress, country, states, postal_code
RegistrationForm: username, password, email
I have also define rules for those property on corresponding model.
I have tried validating model like this but doesn't works:
if(isset($_POST['RegistrationForm'])) {
if($_POST['Profile']['account_type'] == 'personal')
{
//for personal account
$profile->account_type = $_POST['Profile']['account_type'];
$model->username = $_POST['RegistrationForm']['username'];
$model->password = $_POST['RegistrationForm']['password'];
$model->verifyPassword = $_POST['RegistrationForm']['verifyPassword'];
$model->email = $_POST['RegistrationForm']['email'];
$model->verifyCode = $_POST['RegistrationForm']['verifyCode'];
$model->accept = $_POST['RegistrationForm']['accept'];
$profile->fullname = $_POST['Profile']['fullname'];
$profile->phone = $_POST['Profile']['phone'];
$profile->ext = $_POST['Profile']['ext'];
$profile->mobile = $_POST['Profile']['mobile'];
if($_POST['choose_country'] == 'other')
{
$profile->country = $_POST['choose_country'];
$profile->states = $_POST['profile_states'];
$profile->postalcode = $_POST['Profile']['postalcode'];
$profile->firstaddress = $_POST['Profile']['firstaddress'];
$profile->secondaddress = $_POST['Profile']['secondaddress'];
}
if($_POST['choose_country'] == 'Nepal')
{
$profile->country = $_POST['choose_country'];
$profile->firstaddress = $_POST['Profile']['firstaddress'];
$profile->secondaddress = $_POST['Profile']['secondaddress'];
}
}
if($_POST['Profile']['account_type'] == 'company')
{
//for organization account
$profile->account_type = $_POST['Profile']['account_type'];
$model->username = $_POST['RegistrationForm']['username'];
$model->password = $_POST['RegistrationForm']['password'];
$model->verifyPassword = $_POST['RegistrationForm']['verifyPassword'];
$model->email = $_POST['RegistrationForm']['email'];
$model->verifyCode = $_POST['RegistrationForm']['verifyCode'];
$model->accept = $_POST['RegistrationForm']['accept'];
$profile->fullname = $_POST['Profile']['fullname'];
$profile->ext = $_POST['profile']['ext'];
$profile->mobile = $_POST['Profile']['mobile'];
$profile->company_name = $_POST['Profile']['company_name'];
$profile->company_type = $_POST['Profile']['company_type'];
$profile->designation = $_POST['Profile']['designation'];
if($_POST['choose_country'] == 'Nepal')
{
$profile->country = $_POST['choose_country'];
$profile->states = $_POST['Profile']['states'];
$profile->postalcode = $_POST['Profile']['postalcode'];
$profile->firstaddress = $_POST['profile']['firstaddress'];
$profile->secondaddress = $_POST['profile']['secondaddress'];
}
if($_POST['choose_country'] == 'others')
{
$profile->country = $_POST['profile']['country'];
$profile->firstaddress = $_POST['profile']['firstaddress'];
$profile->secondaddress = $_POST['profile']['secondaddress'];
}
}
//$model->attributes=$_POST['RegistrationForm'];
//$profile->attributes=((isset($_POST['Profile'])?$_POST['Profile']:array()));
if($model->validate()&&$profile->validate())
{
}
}
Problem:
If I select the personal radio button and submit form it still validate the company_name , company type and same for country selection then shows the validation errors. Here what I want is to disable the validation of model depending on selection of radio button either personal or company type.
I never worked with yii-user extension but as a solution I can propose to restrict company and personal validations by setting different scenarios for your $profile model depending on $_POST['Profile']['account_type'] just before assigning values to model from $_POST, e.g.:
if ($_POST['Profile']['account_type'] === "personal")
$profile->scenario = "personal";
else
$profile->scenario = "company";
After that in rules() method of your Profile model you specify corresponding scenario for each account type dependent field:
public function rules() {
return array(
// ...general rules
array("company_name", "validateCompanyName", 'on' => array("company")),
array("company_type", "validateCompanyType", 'on' => array("company")),
array("phone", "validatePersonalPhone", 'on' => array("personal"))
)
}
I believe that this way it will be enough to assign values to models like this:
$model->attributes = $_POST['RegistrationForm'];
$profile->attributes = $_POST['Profile'];

How can I rewrite this SQL into CodeIgniter's Active Records?

SELECT *, SUM(tbl.relevance) AS relevance FROM
(
(
SELECT q_id,
MATCH(a_content) AGAINST ('бутон') AS relevance
FROM answers
WHERE
MATCH(a_content) AGAINST ('бутон')
)
UNION
(
SELECT q_id,
(MATCH(q_content) AGAINST ('бутон')) * 1.5 AS relevance
FROM questions
WHERE
MATCH(q_content) AGAINST ('бутон')
)
) AS tbl
JOIN questions ON questions.q_id = tbl.q_id
GROUP BY tbl.q_id
ORDER BY relevance DESC
Codeigniter currently does not have support for subqueries in its Active Records class.
You'll simply have to use this:
$this->db->query($your_query, FALSE);
Remember to pass that second argument, so that Codeigniter doesn't try to escape your query.
Well there is indeed a simple hack for subqueries in codeigniter. You have to do the following
Go to system/database/DB_active_rec.php
There if you are using version 2.0 or greater change this
public function _compile_select($select_override = FALSE)
public function _reset_select()
Remove public keyword and you will be able to use subqueries
And now
$data = array(
"q_id",
"MATCH(a_content) AGAINST ('?????') AS relevance"
);
$this->db->select($data);
$this->db->from("answers");
$this->db->where("MATCH(a_content) AGAINST ('?????')");
$subQuery1 = $this->db->_compile_select();
// Reset active record
$this->db->_reset_select();
unset($data);
$data = array(
"q_id",
"(MATCH(q_content) AGAINST ('?????')) * 1.5 AS relevance"
);
$this->db->select($data);
$this->db->from("questions");
$this->db->where("MATCH(q_content) AGAINST ('?????')");
$subQuery2 = $this->db->_compile_select();
// Reset active record
$this->db->_reset_select();
unset($data);
$data = array(
"q_id",
"SUM(tbl.relevance) AS relevance"
);
$this->db->select($data);
$this->db->from("$subQuery1 UNION $subQuery2");
$this->db->join("questions","questions.q_id = tbl.q_id");
$this->db->group_by("tbl.q_id");
$this->db->order_by("relevance","desc");
$query = $this->db->get();