Append unit to a XML column value in SQL Server - sql

I have a table with a XML column for storing the file details. Now I want to update the size node in the XML column with KB or MB according to the value.
Sample data:
<FileInfo>
<Field Name="Filename">PV_1_PV_4126_C-482N-25457-005_V1.pdf</Field>
<Field Name="Created">02/21/2017</Field>
<Field Name="Modified">02/21/2017</Field>
<Field Name="Uploaded By">2120</Field>
<Field Name="Uploaded On">02/21/2017</Field>
<Field Name="Size">755</Field>
</FileInfo>
Expected result:
<FileInfo>
<Field Name="Filename">PV_1_PV_4126_C-482N-25457-005_V1.pdf</Field>
<Field Name="Created">02/21/2017</Field>
<Field Name="Modified">02/21/2017</Field>
<Field Name="Uploaded By">2120</Field>
<Field Name="Uploaded On">02/21/2017</Field>
<Field Name="Size">755 KB</Field>
</FileInfo>
Sample data:
<FileInfo>
<Field Name="Filename">PV_1_PV_4126_C-482N-25457-005_V1.pdf</Field>
<Field Name="Created">02/21/2017</Field>
<Field Name="Modified">02/21/2017</Field>
<Field Name="Uploaded By">2120</Field>
<Field Name="Uploaded On">02/21/2017</Field>
<Field Name="Size">1024</Field>
</FileInfo>
Expected result:
<FileInfo>
<Field Name="Filename">PV_1_PV_4126_C-482N-25457-005_V1.pdf</Field>
<Field Name="Created">02/21/2017</Field>
<Field Name="Modified">02/21/2017</Field>
<Field Name="Uploaded By">2120</Field>
<Field Name="Uploaded On">02/21/2017</Field>
<Field Name="Size">1 MB</Field>
</FileInfo>

You can use an updateable CTE
DECLARE #dummy TABLE(YourXMLColumn XML);
INSERT INTO #dummy VALUES
(
N'<FileInfo>
<!--More fields-->
<Field Name="Size">755</Field>
</FileInfo> '
)
,(
N'<FileInfo>
<!--More fields-->
<Field Name="Size">1024</Field>
</FileInfo> '
);
WITH ReplaceValue AS
(
SELECT YourXMLColumn
,ca2.newSize
FROM #dummy AS d
CROSS APPLY(SELECT d.YourXMLColumn.value(N'(/FileInfo/Field[#Name="Size"]/text())[1]',N'int')) AS ca1(size)
CROSS APPLY(SELECT CASE WHEN ca1.size % 1024=0
THEN CAST(ca1.size/1024 AS VARCHAR(10)) + ' MB'
ELSE CAST(ca1.size AS VARCHAR(10)) + ' KB' END) AS ca2(newSize)
)
UPDATE ReplaceValue SET YourXMLColumn.modify(N'replace value of (/FileInfo/Field[#Name="Size"]/text())[1] with sql:column("newSize")');
SELECT * FROM #dummy;
First I read the value of the "Size" field. If it is divideable by 1024 it will be written as "MB", otherwise the value remains as "KB".
The final UPDATE will update the CTE, but this affects the tables column actually. The SELECT shows the modified table data.

Related

Update 3rd level deep field value in an XML using xQuery

I have the following sample XML and I am looking to Update:
AttendeeID to 7878 (will be a sql variable) where sequence = 1 (will be a sql variable)
Expected output is to see 7878 in the AttendeeID field's value. When I run any of the 2 options I tried, it does not yield the correct result. For Eg. Delete works but the element is not added. Replace value does not update the value.
Any inputs are highly appreciated. Thank you.
--------XML ---------------------------
DECLARE #cartXML XML =
'<OBJECT CLASS="Test1" ID="-1" FULL="FULL" VERSION="1">
<FIELD NAME="OrderDate">20220619</FIELD>
<FIELD NAME="OrderParty">Individual</FIELD>
<FIELD NAME="ShipToID">34567</FIELD>
<FIELD NAME="ShipToAddress1">123 Test Street</FIELD>
<FIELD NAME="ShipToCity">TestCity</FIELD>
<FIELD NAME="ShipToState">IL</FIELD>
<FIELD NAME="ShipTocountry">USA</FIELD>
<FIELD NAME="TaxNumber">444</FIELD>
<FIELD NAME="DiscountCode">Summer22</FIELD>
<SUBTYPE NAME="SubType1">
<OBJECT NAME="SubType111" ID="-1">
<FIELD NAME="TestID">-1</FIELD>
<FIELD NAME="Sequence">1</FIELD>
<FIELD NAME="ParentSequence">-1</FIELD>
<FIELD NAME="ExtID">-1</FIELD>
<FIELD NAME="ExtName">ABC</FIELD>
</OBJECT>
<OBJECT NAME="SubType111" ID="-1">
<FIELD NAME="TestID">-1</FIELD>
<FIELD NAME="Sequence">2</FIELD>
<FIELD NAME="ParentSequence">1</FIELD>
<FIELD NAME="ExtID">-1</FIELD>
<FIELD NAME="ExtName">DEF</FIELD>
<FIELD NAME="__ExtendedData"><OBJECT
CLASS="Meet123" ID="-1" FULL="FULL"
VERSION="1"><FIELD
NAME="OrderDetailID">-1</FIELD><FIELD
NAME="OrderID">-1</FIELD><FIELD
NAME="Sequence">0</FIELD><FIELD
NAME="AttendeeID">123</FIELD><FIELD NAME="AttendeeID_Name">Test, Mark/I
H 6</FIELD><FIELD
NAME="ShowList">1</FIELD><FIELD
NAME="BdgeName">Mark</FIELD><FIELD
NAME="BadgeCompanyName">I H 6</FIELD>
</OBJECT></FIELD>
</OBJECT>
<OBJECT NAME="SubType111" ID="-1">
<FIELD NAME="TestID">-1</FIELD>
<FIELD NAME="Sequence">3</FIELD>
<FIELD NAME="ParentSequence">1</FIELD>
<FIELD NAME="ExtID">-1</FIELD>
<FIELD NAME="ExtName">GHI</FIELD>
</OBJECT>
</SUBTYPE>
<SUBTYPE NAME="SubType2"/>
<SUBTYPE NAME="SubType3"/>
</OBJECT>';
-----------------------SQL -----------------------
select #cartXML as originalXML
DECLARE #ID as int ,#productID as int, #attendeeId as int = 7878,
#sequenceId as int, #orderLineXML as XML , #ExtendedAttrDetail as XML
SET #sequenceId = 2
select #orderlineXML = c.query('.'), #ExtendedAttrDetail = w.query('.') from
#cartXML.nodes('/OBJECT/SUBTYPE/OBJECT[FIELD[#NAME="Sequence"]/text()=sql:variable("#sequenceId")]') t1(c)
Cross APPLY (VALUES(TRY_CAST(c.query('FIELD[#NAME="__ExtendedData"]').value('.','NVARCHAR(MAX)') AS XML)))AS t2(w)
-----This works..But I am looking to alter #cartXML as it contains the entire XML
SET #ExtendedAttrDetail.modify('replace value of
(/OBJECT/FIELD[#NAME="AttendeeID"]/text())[1]
with sql:variable("#attendeeId")')
--select #ExtendedAttrDetail
------- Option 1( Preferred)---does not work--
SET #cartXML.modify ('replace value of
(/OBJECT/SUBTYPE/OBJECT[FIELD[#NAME="Sequence"]/text()=sql:variable("#sequenceId")]/FIELD[#NAME="__ExtendedData"]/OBJECT/FIELD[#NAME="AttendeeID"]/text())[1] with sql:variable("#attendeeId")')
select #cartXML as ModifiedDirectly
---Option 2 (Insert does not add correctly )
--SET #cartXML.modify('delete
--/OBJECT/SUBTYPE/OBJECT[FIELD[#NAME="Sequence"]/text()=sql:variable("#sequenceId")]
--/FIELD[#NAME="__ExtendedData"]');
--SET #cartXML.modify('insert sql:variable("#ExtendedAttrDetail") into
--(/OBJECT/SUBTYPE/OBJECT[FIELD[#NAME="Sequence"]/text()=sql:variable("#sequenceId")])
--[1]');
--SELECT #cartXML as UpdatedXL;
Please try the following solution.
The issue is that the XML fragment in question is encoded.
SQL
DECLARE #cartXML XML =
N'<OBJECT CLASS="Test1" ID="-1" FULL="FULL" VERSION="1">
<FIELD NAME="OrderDate">20220619</FIELD>
<FIELD NAME="OrderParty">Individual</FIELD>
<FIELD NAME="ShipToID">34567</FIELD>
<FIELD NAME="ShipToAddress1">123 Test Street</FIELD>
<FIELD NAME="ShipToCity">TestCity</FIELD>
<FIELD NAME="ShipToState">IL</FIELD>
<FIELD NAME="ShipTocountry">USA</FIELD>
<FIELD NAME="TaxNumber">444</FIELD>
<FIELD NAME="DiscountCode">Summer22</FIELD>
<SUBTYPE NAME="SubType1">
<OBJECT NAME="SubType111" ID="-1">
<FIELD NAME="TestID">-1</FIELD>
<FIELD NAME="Sequence">1</FIELD>
<FIELD NAME="ParentSequence">-1</FIELD>
<FIELD NAME="ExtID">-1</FIELD>
<FIELD NAME="ExtName">ABC</FIELD>
</OBJECT>
<OBJECT NAME="SubType111" ID="-1">
<FIELD NAME="TestID">-1</FIELD>
<FIELD NAME="Sequence">2</FIELD>
<FIELD NAME="ParentSequence">1</FIELD>
<FIELD NAME="ExtID">-1</FIELD>
<FIELD NAME="ExtName">DEF</FIELD>
<FIELD NAME="__ExtendedData"><OBJECT
CLASS="Meet123" ID="-1" FULL="FULL"
VERSION="1"><FIELD
NAME="OrderDetailID">-1</FIELD><FIELD
NAME="OrderID">-1</FIELD><FIELD
NAME="Sequence">0</FIELD><FIELD
NAME="AttendeeID">123</FIELD><FIELD NAME="AttendeeID_Name">Test, Mark/I
H 6</FIELD><FIELD
NAME="ShowList">1</FIELD><FIELD
NAME="BdgeName">Mark</FIELD><FIELD
NAME="BadgeCompanyName">I H 6</FIELD>
</OBJECT></FIELD>
</OBJECT>
<OBJECT NAME="SubType111" ID="-1">
<FIELD NAME="TestID">-1</FIELD>
<FIELD NAME="Sequence">3</FIELD>
<FIELD NAME="ParentSequence">1</FIELD>
<FIELD NAME="ExtID">-1</FIELD>
<FIELD NAME="ExtName">GHI</FIELD>
</OBJECT>
</SUBTYPE>
<SUBTYPE NAME="SubType2"/>
<SUBTYPE NAME="SubType3"/>
</OBJECT>';
DECLARE #ExtendedData XML
, #attendeeId INT = 770;;
-- Step #1: select XML fragment in question as real XML data type
SELECT #ExtendedData = w
FROM #cartxml.nodes('/OBJECT/SUBTYPE/OBJECT[#ID="-1"]') as t1(c)
CROSS APPLY (VALUES(TRY_CAST(c.query('FIELD[#NAME="__ExtendedData"]').value('.','NVARCHAR(MAX)') AS XML))) AS t2(w)
WHERE w.exist('/OBJECT[#CLASS="Meet123"]') = 1;
-- Step #2: remove encoded XML fragment
SET #cartXML.modify('replace value of (/OBJECT/SUBTYPE[#NAME="SubType1"]/OBJECT/FIELD[#NAME="__ExtendedData"]/text())[1]
with ""');
-- Step #3: modify AttendeeID
SET #ExtendedData.modify('replace value of
(/OBJECT/FIELD[#NAME="AttendeeID"]/text())[1]
with sql:variable("#attendeeId")');
-- Step #4: insert real XML fragment
SET #cartXML.modify('insert sql:variable("#ExtendedData") into
(/OBJECT/SUBTYPE[#NAME="SubType1"]/OBJECT/FIELD[#NAME="__ExtendedData"])[1]');
-- test
SELECT #cartXML;

Convert nested XML via XQuery to flat xml

I've a nested piece of XML i want to insert in to SQL.
Import XML:
<RECORD>
<RECID>118810</RECID>
<FIELD TYPE="C">
<NAME>proj_code</NAME>
<VALUE>118810</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>sub_nr</NAME>
<VALUE>99900</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>proj_desc</NAME>
<VALUE>Nagekomen kosten Oktober 2018</VALUE>
</FIELD>
<FIELD TYPE="N">
<NAME>pro_stat</NAME>
<VALUE>9</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>comment</NAME>
<VALUE></VALUE>
</FIELD>
</RECORD>
I want to convert via XQuery it into:
<RECORD>
<RECID>118810</RECID>
<proj_code>118810</proj_code>
<sub_nr>99900</sub_nr>
<proj_desc>Nagekomen kosten Oktober 2018</proj_desc>
<pro_stat>9</pro_stat>
<comment></comment>
</RECORD>
so i can import it into SQL.
Any thoughts?
As Martin Honnen pointed out, MS SQL Server XQuery doesn't support computed dynamic element names, just literals. Unfortunately, including even the latest SQL Server 2019. Here is an ugly solution.
SQL
DECLARE #xml XML = N'<root>
<RECORD>
<RECID>118810</RECID>
<FIELD TYPE="C">
<NAME>proj_code</NAME>
<VALUE>118810</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>sub_nr</NAME>
<VALUE>99900</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>proj_desc</NAME>
<VALUE>Nagekomen kosten Oktober 2018</VALUE>
</FIELD>
<FIELD TYPE="N">
<NAME>pro_stat</NAME>
<VALUE>9</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>comment</NAME>
<VALUE></VALUE>
</FIELD>
</RECORD>
<RECORD>
<RECID>118811</RECID>
<FIELD TYPE="C">
<NAME>proj_code</NAME>
<VALUE>118811</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>sub_nr</NAME>
<VALUE>99901</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>proj_desc</NAME>
<VALUE>Nagekomen kosten November 2019</VALUE>
</FIELD>
<FIELD TYPE="N">
<NAME>pro_stat</NAME>
<VALUE>19</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>comment</NAME>
<VALUE>wow</VALUE>
</FIELD>
</RECORD>
</root>';
DECLARE #tbl TABLE (ID INT IDENTITY(1,1) PRIMARY KEY, RECID VARCHAR(10), [col_name] VARCHAR(20), [col_value] VARCHAR(100));
INSERT INTO #tbl
SELECT c.value('(../RECID/text())[1]', 'VARCHAR(100)') AS [RECID]
, c.value('(NAME/text())[1]', 'VARCHAR(30)') AS [name]
, c.value('(VALUE/text())[1]', 'VARCHAR(100)') AS [value]
FROM #xml.nodes('root/RECORD/FIELD') AS t(c);
DECLARE #RowCount INT = (SELECT MAX(ID) FROM #tbl)
, #recID varchar(10) = (SELECT TOP(1) RECID FROM #tbl WHERE ID = 1)
, #xml_data VARCHAR(MAX) = '<root><RECORD>';
WHILE #RowCount > 0 BEGIN
SELECT #xml_data += IIF(#recID != RECID, '</RECORD><RECORD>', '') +
--'<' + [col_Name] + '>' + COALESCE([col_value],'') + '</' + [col_Name] + '>'
CONCAT('<',[col_Name],'>',[col_value],'</',[col_Name],'>')
, #recID = RECID
FROM #tbl
ORDER BY ID DESC OFFSET #RowCount - 1 ROWS FETCH NEXT 1 ROWS ONLY;
SET #RowCount -= 1;
END;
SET #xml_data += '</RECORD></root>';
SELECT CAST(#xml_data AS XML);
Simply map each RECORD to a new one where you map all FIELDs to elements with the name from NAME and the value from VALUE:
RECORD !
<RECORD>
{
RECID,
FIELD ! element { NAME } { data(VALUE) }
}
</RECORD>
https://xqueryfiddle.liberty-development.net/nbUY4kB
For XQuery 1 you would need to use for return instead of the map operator !:
for $record in //RECORD
return
<RECORD>
{
$record/RECID,
for $field in $record/FIELD
return element { $field/NAME } { data($field/VALUE) }
}
</RECORD>
https://xqueryfiddle.liberty-development.net/nbUY4kB/1
I tried this:
DECLARE #xml xml;
SET #xml =N'
<RECORD>
<RECID>118810</RECID>
<FIELD TYPE="C">
<NAME>proj_code</NAME>
<VALUE>118810</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>sub_nr</NAME>
<VALUE>99900</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>proj_desc</NAME>
<VALUE>Nagekomen kosten Oktober 2018</VALUE>
</FIELD>
<FIELD TYPE="N">
<NAME>pro_stat</NAME>
<VALUE>9</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>comment</NAME>
<VALUE></VALUE>
</FIELD>
</RECORD>
<RECORD>
<RECID>118811</RECID>
<FIELD TYPE="C">
<NAME>proj_code</NAME>
<VALUE>118811</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>sub_nr</NAME>
<VALUE>99900</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>proj_desc</NAME>
<VALUE>Nagekomen kosten November 2018</VALUE>
</FIELD>
<FIELD TYPE="N">
<NAME>pro_stat</NAME>
<VALUE>9</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>comment</NAME>
<VALUE></VALUE>
</FIELD>
</RECORD>
';
SELECT #xml.query('
for $record in //RECORD
return
<RECORD>
{
$record/RECID,
for $field in $record/FIELD
return element { $field/NAME } { data($field/VALUE) }
}
</RECORD>
' ) as result
But i get an error on the return element part:
XQuery [query()]: Only constant expressions are supported for the name expression of computed element and attribute constructors.
This is the final version with select for inserting it into SQL:
DECLARE #xml XML = N'
<AVXML>
<SIGNONMSGRS>
<DTSERVER>2019-09-10T15:54:32</DTSERVER>
<APPID>ACCOUNTVIEW</APPID>
<APPVER>0908-</APPVER>
</SIGNONMSGRS>
<EBUSMSGSRS>
<EBUSQRYRS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<RECORD>
<RECID>118810</RECID>
<FIELD TYPE="C">
<NAME>proj_code</NAME>
<VALUE>118810</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>sub_nr</NAME>
<VALUE>99900</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>proj_desc</NAME>
<VALUE>Nagekomen kosten Oktober 2018</VALUE>
</FIELD>
<FIELD TYPE="N">
<NAME>pro_stat</NAME>
<VALUE>9</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>comment</NAME>
<VALUE></VALUE>
</FIELD>
</RECORD>
<RECORD>
<RECID>118811</RECID>
<FIELD TYPE="C">
<NAME>proj_code</NAME>
<VALUE>118811</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>sub_nr</NAME>
<VALUE>99901</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>proj_desc</NAME>
<VALUE>Nagekomen kosten November 2019</VALUE>
</FIELD>
<FIELD TYPE="N">
<NAME>pro_stat</NAME>
<VALUE>19</VALUE>
</FIELD>
<FIELD TYPE="C">
<NAME>comment</NAME>
<VALUE>wow</VALUE>
</FIELD>
</RECORD>
</EBUSQRYRS>
</EBUSMSGSRS>
</AVXML>
';
DECLARE #tbl TABLE (ID INT IDENTITY(1,1) PRIMARY KEY, RECID VARCHAR(10), [col_name] VARCHAR(20), [col_value] VARCHAR(100));
INSERT INTO #tbl
SELECT c.value('(../RECID/text())[1]', 'VARCHAR(100)') AS [RECID]
, c.value('(NAME/text())[1]', 'VARCHAR(30)') AS [name]
, c.value('(VALUE/text())[1]', 'VARCHAR(500)') AS [value]
FROM #xml.nodes('//RECORD/FIELD') AS t(c);
DECLARE #RowCount INT = (SELECT MAX(ID) FROM #tbl)
, #recID varchar(10) = (SELECT TOP(1) RECID FROM #tbl WHERE ID = 1)
, #xml_data VARCHAR(MAX) = '<root><RECORD>';
WHILE #RowCount > 0 BEGIN
SELECT #xml_data +=
IIF(#recID != RECID,
'<RECID>' + #recID + '</RECID>' +
'</RECORD><RECORD>',
'') +
CONCAT('<',[col_Name],'>',[col_value],'</',[col_Name],'>')
, #recID = RECID
FROM #tbl
ORDER BY ID DESC OFFSET #RowCount - 1 ROWS FETCH NEXT 1 ROWS ONLY;
SET #RowCount -= 1;
END;
SET #xml_data += '<RECID>' + #recID + '</RECID>' + '</RECORD></root>';
DECLARE #handler int;
exec sys.sp_xml_preparedocument #handler OUTPUT, #xml_data;
--print #xml_data
select *
from OPENXML(#handler,'/root/RECORD',11)
WITH
(
id nvarchar(50) 'RECID',
proj_code nvarchar(50) 'proj_code',
sub_nr nvarchar(50) 'sub_nr',
proj_desc nvarchar(1000) 'proj_desc',
pro_stat nvarchar(50) 'pro_stat',
comment nvarchar(50) 'comment'
)
exec sys.sp_xml_removedocument #handler

Odoo. Tree/form display field data

I have some problem with tree/form view in Odoo.
My model have such classes: https://yadi.sk/d/sCLVo3gHtbVEu
class URLList(models.Model):
_name = 'webvisitorcalc.url_list'
url = fields.Char(string="URL", required=True)
url_parametes = fields.Char(string="URL parameters") #пераметры URLб всё что идёт после ?
target_session_id = fields.One2many('webvisitorcalc.session_visitor', 'target_url_ids', string='Target URL')
site_trip_prevouse_id = fields.One2many('webvisitorcalc.site_trip', 'url_prevouse_ids', string='Prevouse URL')
site_trip_current_id = fields.One2many('webvisitorcalc.site_trip', 'url_current_ids', string='Current URL')
remote_sites_id = fields.One2many('webvisitorcalc.remote_sites', 'site_url_ids', string='Remote site page with URL')
remote_sites_target_url_id = fields.One2many('webvisitorcalc.remote_sites', 'target_url_ids', string='URL on remote site page')
#api.multi
def url_exist(self, cr, SUPERUSER_ID, urlForCheck):
_logger.error("Check URL exist in DB ")
result = False
if (self.search_count(cr, SUPERUSER_ID, [('url', '=', urlForCheck)])>0):
result = True
return result
class SiteTrip(models.Model):
_name = 'webvisitorcalc.site_trip'
session_ids = fields.Many2one('webvisitorcalc.session_visitor', string='Session ID', index=True)
url_prevouse_ids = fields.Many2one('webvisitorcalc.url_list', string='Prevouse URL', index=True)
url_current_ids = fields.Many2one('webvisitorcalc.url_list', string='Current URL', index=True)
Template for this model: https://yadi.sk/d/Ob0o65PutbVFA
<record model="ir.actions.act_window" id="site_trip_list_action">
<field name="name">Site trip</field>
<field name="res_model">webvisitorcalc.site_trip</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">Create the first record for site trip
</p>
</field>
</record>
<record model="ir.actions.act_window" id="url_list_list_action">
<field name="name">URL list</field>
<field name="res_model">webvisitorcalc.url_list</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">Create the first url
</p>
</field>
</record>
<record model="ir.ui.view" id="site_trip_tree_view">
<field name="name">site_trip.tree</field>
<field name="model">webvisitorcalc.site_trip</field>
<field name="arch" type="xml">
<tree string="URL list tree">
<field name="session_ids"/>
<field name="url_prevouse_ids" string="PrevURL">
</field>
<!--<field name="url_prevouse_ids"/>-->
<field name="url_current_ids"/>
</tree>
</field>
</record>
<record model="ir.ui.view" id="url_list_tree_view">
<field name="name">url_list.tree</field>
<field name="model">webvisitorcalc.url_list</field>
<field name="arch" type="xml">
<tree string="URL list tree">
<field name="url"/>
<field name="url_parametes"/>
</tree>
</field>
</record>
<menuitem id="site_trip_menu" name="Site trip" parent="webvisitorcalc_menu"
action="site_trip_list_action"/>
<menuitem id="url_list_menu" name="URL list" parent="webvisitorcalc_menu"
action="url_list_list_action"/>
Screenshots are here:
Tree view for class SiteTrip
http://i.stack.imgur.com/FjRDK.png
Form view for class SiteTrip
http://i.stack.imgur.com/uDbOp.png
Tree view for class URLList
http://i.stack.imgur.com/tXzqL.png
Form view for class URLList
http://i.stack.imgur.com/oVnqg.png
As you see URLList displayed fine. For class SiteTrip present problem. Field is displaying not data from URLList. This is field stored element such webvisitorcalc.url_list.ID (array?). How I can display real data in this field (for example URL: http://some-site.com/page.html)?
URL in URLList must be uniq. SiteTrip must have stored only ID of URLList record.
UPD:
class RemoteSites(models.Model):
_name = 'webvisitorcalc.remote_sites'
site_id = advert_company_id = fields.One2many('webvisitorcalc.site_list', 'remote_sites_ids', string='Site')
site_url_ids = fields.Many2one('webvisitorcalc.url_list', string='URL page ')
target_url_ids = fields.Many2one('webvisitorcalc.url_list', string='URL target page')
You obviously have no name field on your webvisitorcalc.url_list model. Odoo needs this to use it as name in webclient wherever you use this model as e.g. many2one field or in the breadcrumb navigation.
So either you define a name field or you set _name on your class with another field identifier.
You can also (re-)define the method display_name on your model (enough examples in Odoo code) where you can do more cool stuff with the record display name :-)

How to update automatically other fields when quantity on hand get increase or decrease odoo?

I need to update automatically this field(qty_available_onhand) either when quantity on hand get increase or decrease below i have mentioned my code.
Current below code working perfectly but only when i fill this field(squ_meter) as i'm entering in this field get multiplied to field(qty_avl) which is qty_avl is nothing but it is actually quantity on hand.
Any answer would be much appreciated
class product_template(osv.osv):
_name = "product.template"
_inherit = "product.template"
_columns = {
'squ_meter':fields.float('Square Meter'),
'qty_available_onhand': fields.float(
'Qty Sqm Available',
compute='_compute_qty_available_onhand',
require = True
),
'qty_avl':fields.related(
'virtual_available',
relation='product.product',
string='Quantity on Hand'
),
}
#api.depends('qty_avl', 'squ_meter')
def _compute_qty_available_onhand(self):
for record in self:
record.qty_available_onhand = record.qty_avl * record.squ_meter
view.xml
<field name="name">product.product.inherited</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_form_view"/>
<field name="type">form</field>
<field name="arch" type="xml">
<xpath expr="//field[#name='active']" position="after">
<field name="qty_available_onhand"/>
<field name="qty_avl" invisible='1'/>
<field name="squ_meter"/>
</xpath>

Master-detail relation, variable scope, passing variables, etc in openerp

I'm writing a warehouse management module and I came to the inventory step.
I need to make an inventory every now and then for each warehouse separately and each inventory operation will be kept in the database as a master-detail relation,
ie:
one record for the basic data such as id, date, warehouse_id etc. and
this will be recorded in a table created by (inventory) object.
many records will keep the details of the operation (one record for each material) recording the material id, inventory id, balance, etc. and this will be recorded in the table (inventory_lines).
During the data entry, when the user selects a material, I need to check its current balance and display it in the balance field. In order to do this, I'll need to know the warehouse id because every warehouse shall have separate inventories.
I have many materials stored in many warehouses.
For example: I can have a quantity of 5 pens in warehouse A and 10 pens in warehouse B and 6 pens in warehouse C.
First, I select the warehouse (A or B or C) --- let's say warehouse B
Then I select the material (Pen or notebook or whatever) --- let's say Pen
Now, I want to search the database to find the balance of (Pen) in (Warehouse B)
I can write something like this:
select balance from inventory_lines where material_id=mmmmmm and warehouse_id=wwwwww
So, I need to get the material id (mmmmm) and the warehouse id (wwwww)
And that will be done with each material I choose.
The warehouse id is in the column: inventory_id in the object: inventory
'warehouse_id' : fields.many2one('makhazen.warehouse', 'Warehouse Name',required=True),
The material id is in the column: material_id of the object inventory_line as in the picture in the question
'material_id' : fields.many2one('makhazen.material' ,'Material Name'),
I faced the following problem:
I could use the (on_change) method in the form view on the material_id field and could trigger a method to search for the balance in the database but I needed the warehouse_id which I couldn't get.
The questions are:
- How are this master-detail relationship is handled in openerp? how values are passed between the master table and the details table?
- How can we extend the scope of the warehouse_id so that it can be seen from any method in the module?
- I could change the values of the fields by calling a method and returning the desired values in a dictionary, but how to do the opposite (read them)?
It's very critical matter to me.
Firstly, you don't need the warehouse_id field in the wh_inventory_line class. You can always access it trough the the parent object:
inventory_line = self.pool.get('wh.inventory.line').browse(cr, uid, line_id)
wharehouse_id = inventory_line.inventory_id.warehouse_id.id
Secondly, in your case you can just pass the warehouse_id value as parameter to your onchange method. Something like this:
<field name="material_id"
on_change="onchange_material_id(material_id, warehouse_id)"/>
or, if you follow my first advice and remove the warehouse_id from wh_inventory_line:
<field name="material_id"
on_change="onchange_material_id(material_id, parent.warehouse_id)"/>
EDIT
After testing on OpenERP 6.0 I found some errors in your code. I'm just wondering how did you manage to run it.
First, you missed a quote (\') on the warehouse_id column definition of your wh.inventory model:
_columns = {
'date': fields.datetime('Date'),
'warehouse_id': fields.many2one('wh.warehouse', 'Warehouse Name, required=True),
Second, the fields.char() field definition takes at least size parameter additionally to the supplied Field Name. Again, you missed a quote on the following line:
'notes': fields.char('Notes),
Not an error but something you should consider too - you tagged your question with the openerp-7 tag. In OpenERP v7 inheriting from osv.osv is deprecated. Inherit from osv.Model instead.
If I insist on your errors it's because the solution I proposed to you is working fine on my side. So there must be some little error somewhere that prevents your code for doing what is expected.
Here is my test code. You can try it:
wh.py
# -*- encoding: utf-8 -*-
import netsvc
import pooler
from osv import fields, osv
class wh_warehouse(osv.osv):
_name = 'wh.warehouse'
_columns = {
'name': fields.char('Name', 128),
}
wh_warehouse()
class wh_material(osv.osv):
_name = 'wh.material'
_columns = {
'name': fields.char('Name', 128),
}
wh_material()
class wh_inventory(osv.osv):
_name = 'wh.inventory'
_columns = {
'date': fields.datetime('Date'),
'warehouse_id': fields.many2one('wh.warehouse', 'Warehouse Name', required=True),
'inventory_line_ids': fields.one2many('wh.inventory.line', 'inventory_id', 'Inventory'),
'notes': fields.char('Notes', 512),
'balance_track': fields.boolean('Balance Track'),
}
wh_inventory()
class wh_inventory_line(osv.osv):
_name = 'wh.inventory.line'
_columns = {
'inventory_id': fields.many2one('wh.inventory', 'Inventory'),
'material_id': fields.many2one('wh.material', 'Material'),
'balance': fields.float('Balance'),
'previous_balance': fields.float('Previous Balance'),
'notes': fields.char('Notes', 512),
}
def onchange_material_id(self, cr, uid, ids, material_id, warehouse_id):
return = {'value': {
'notes': 'Selected material {0} and warehouse {1}'.format(material_id, warehouse_id), }
}
wh_inventory_line()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
wh_view.xml
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_wh_inventory_form" model="ir.ui.view">
<field name="name">wh.inventory.form</field>
<field name="model">wh.inventory</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Warehouse Inventory">
<field name="date"/>
<field name="warehouse_id" widget="selection"/>
<field name="notes"/>
<field name="balance_track"/>
<field colspan="4" name="inventory_line_ids" widget="one2many_list">
<tree string="Details" editable="bottom">
<field name="material_id" widget="selection"
on_change="onchange_material_id(material_id, parent.warehouse_id)"/>
<field name="balance"/>
<field name="previous_balance"/>
<field name="notes"/>
</tree>
</field>
</form>
</field>
</record>
<record id="view_wh_inventory_tree" model="ir.ui.view">
<field name="name">wh.inventory.tree</field>
<field name="model">wh.inventory</field>
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Warehouse Inventory">
<field name="date"/>
<field name="warehouse_id" widget="selection"/>
<field name="notes"/>
<field name="balance_track"/>
</tree>
</field>
</record>
<record id="action_wh_inventory_form" model="ir.actions.act_window">
<field name="name">Warehouse Inventory</field>
<field name="res_model">wh.inventory</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_wh_inventory_tree"/>
</record>
<menuitem
action="action_wh_inventory_form"
id="menu_wh_inventory_form"
parent="account.menu_finance"
/>
<!-- Sample data -->
<record id="warehouse_1" model="wh.warehouse">
<field name="name">Warehouse 1</field>
</record>
<record id="warehouse_2" model="wh.warehouse">
<field name="name">Warehouse 2</field>
</record>
<record id="warehouse_3" model="wh.warehouse">
<field name="name">Warehouse 3</field>
</record>
<record id="material_1" model="wh.material">
<field name="name">Material 1</field>
</record>
<record id="material_2" model="wh.material">
<field name="name">Material 2</field>
</record>
<record id="material_3" model="wh.material">
<field name="name">Material 3</field>
</record>
</data>
</openerp>