Odoo 13: How do I print the move_id (payment number) in an invoice? - invoice

I want to add move_id (credit name) or payment_id name from the payments journal to the invoice in report_invoice_document_with_payments or through the payments widget. I have tried several ways without luck and have read payments_ids would work but perhaps the change in Odoo 13 from account.invoice to account.move is the problem since the field is not recognized.
I would like to get something like:
CSH1/2019/0002 Paid on 12/11/2019 $500.00
CSH1/2019/0003 Paid on 12/12/2019 $100.00
The closest I have been is <t t-esc="payment_vals['payment_id']"/> in:
<xpath expr="//div[#id='total']/div/table" position="inside">
<t t-set="payments_vals" t-value="o._get_reconciled_info_JSON_values()"/>
<t t-foreach="payments_vals" t-as="payment_vals">
<tr>
<td>
<small><i class="oe_form_field text-right oe_payment_label">Paid on <t t-esc="payment_vals['date']"/>,<t t-esc="payment_vals['move_id']"/></i></small>
</td>
<td class="text-right">
<span t-esc="payment_vals['amount']" t-options="{"widget": "monetary", "display_currency": o.currency_id}"/>
</td>
</tr>
</t>
<t t-if="len(payments_vals) > 0">
<tr class="border-black">
<td><strong>Amount Due</strong></td>
<td class="text-right">
<span t-field="o.amount_residual"/>
</td>
</tr>
</t>
</xpath>
<xpath expr="." position="attributes"><attribute name="t-name">account.report_invoice_document_with_payments</attribute></xpath></data>```

Finally I was able to do it using "ref" (<i class="oe_form_field text-right oe_payment_label">Paid on <t t-esc="payment_vals['date']"/>,<t t-esc="payment_vals['ref']"/></I>).
I figured out from account_invoice.py
payment_vals.append({
'name': payment.name,
'journal_name': payment.journal_id.name,
'amount': amount_to_show,
'currency': currency_id.symbol,
'digits': [69, currency_id.decimal_places],
'position': currency_id.position,
'date': payment.date,
'payment_id': payment.id,
'account_payment_id': payment.payment_id.id,
'invoice_id': payment.invoice_id.id,
'move_id': payment.move_id.id,
'ref': payment_ref,
})
return payment_vals

Related

Extract text from a specific row in the table with Capybara

Friends for me to finish my test and I just need to extract the text of the tooltip from the specific line of the table. Thomas Walpole has helped me a lot. Now I can read the excel spreadsheet and I will validate with each line of the application.
****** I read excel and get the first line *************
Spreadsheet.client_encoding = 'UTF-8'
book = Spreadsheet.open('c:/temp/Pasta1.xls', "r")
sheet = book.worksheet 0
#sheet.each do |row|
pp hydrometer = sheet.row(1)
****** reading the specific row of the table *************
I just need to extract this text save in a variable and validate with the hydrometer variable that stores the row of my excel sheet
expect(page).to have_css('tr.tvRow:nth-child(2) .tvCell:nth-child(6) img[tooltip="Invisível"]')
see the code
<tr oncontextmenu="if(!this.cancelEvent) {sendEvent(0,event,this,true,0,'TVXWFMTGINSTATOCE','bdb','BtnDropDownRow#',1,'','','');return false;} delete this.cancelEvent;" onclick="if(notSelecting()) sendEvent(0,event,this,true,0,'TVXWFMTGINSTATOCE','bdb','Select#',1,'','','');" onmousedown="if(event.ctrlKey) this.cancelEvent=true;" class="tvRow tvRowEven tvRoll tvRowSelected" style="cursor:pointer;">
<td valign="center" align="left" class="tvCell">XWFMSLETMATRICOLA_E</td>
<td valign="center" align="left" class="tvCell"> Nº Hidrômetro</td>
<td align="left" class="tvCell" valign="center" nowrap=""></td>
<td valign="center" align="left" class="tvCell"></td>
<td align="left" width="1" class="tvCell" valign="center" tooltip="[AIMPMATRICOLA]">
<button onclick="event.cancelBubble=true;sendEvent(0,event,this,searchImage(this),0,'','bdb','AUTOFILLBTN#',1,'','','','');" class="but butAct" tabindex="0" tooltip="Preenchimento automático ativado" type="BUTTON">
<div><img src="r/std/icons/checkboxselected64.png" class="icon" draggable="false" align="absmiddle"></div>
</button>
</td>
<td valign="center" align="center" class="tvCell"><img tooltip="Invisível" src="r/std/static/minus16.gif"></td>
<td align="center" width="30" style="line-height:1px;padding:0px;" class="tvCell" valign="center">
<div onclick="event.cancelBubble=true;sendEvent(0,event,this,searchImage(this),0,'','bdb','BtnDropDownRow#',1,'','','','');" class="but">
<div><img src="r/std/icons/menu64.png" class="icon" draggable="false" align="absmiddle"></div>
</div>
</td>
</tr>
<tr oncontextmenu="if(!this.cancelEvent) {sendEvent(0,event,this,true,0,'TVXWFMTGINSTATOCE','bdb','BtnDropDownRow#',2,'','','');return false;} delete this.cancelEvent;" onclick="if(notSelecting()) sendEvent(0,event,this,true,0,'TVXWFMTGINSTATOCE','bdb','Select#',2,'','','');" onmousedown="if(event.ctrlKey) this.cancelEvent=true;" class="tvRow tvRowOdd tvRoll" style="cursor:pointer;">
<td valign="center" align="left" class="tvCell">XWFMSLETLETTURA_E</td>
<td valign="center" align="left" class="tvCell"> Leitura</td>
<td align="left" class="tvCell" valign="center" nowrap=""></td>
<td valign="center" align="left" class="tvCell"></td>
<td align="left" width="1" class="tvCell" valign="center" tooltip=""></td>
<td valign="center" align="center" class="tvCell"><img tooltip="Invisível" src="r/std/static/minus16.gif"></td>
<td align="center" width="30" style="line-height:1px;padding:0px;" class="tvCell" valign="center">
<div onclick="event.cancelBubble=true;sendEvent(0,event,this,searchImage(this),0,'','bdb','BtnDropDownRow#',2,'','','','');" class="but">
<div><img src="r/std/icons/menu64.png" class="icon" draggable="false" align="absmiddle"></div>
</div>
</td>
</tr>
If hydrometer contains the text you're checking for just interpolate it in the CSS selector you're using
expect(page).to have_css("tr.tvRow:nth-child(2) .tvCell:nth-child(6) img[tooltip='#{hydrometer}']")
Since your going through a loop you'd probably also want to interpolate the row number but I don't know what variable you have that in
expect(page).to have_css("tr.tvRow:nth-child(#{row_number}) .tvCell:nth-child(6) img[tooltip='#{hydrometer}']")
If you really want to get the tooltip text for a specific row you would do
text = find("tr.tvRow:nth-child(2) .tvCell:nth-child(6) img[tooltip]")[:tooltip] # get the tooltip attribute value from the 2nd row
but doing that and then comparing it to some other string is bad practice and will lead to flaky tests. It is much better to do the have_css shown above

Table dropdown with bootstrap 5 not working

I am trying to show product items when button order detail is pressed, but its not working in any way I tried, it's possible to make it work with bootstrap 5 or I have to do it with javascript ?
Useless information for "It looks like your post is mostly code; please add some more details." : In the first foreach I am displaying information from the order, then the second foreach is retrieving product id and quantity from a different table that contain order id and the third foreach is getting product where id from the second foreach in order to display product details
<table class="table border">
<thead>
<tr>
<th class="h4" style="width: 18%">Order Number</th>
<th class="h4">Date</th>
<th class="h4">Total</th>
<th class="h4">Status</th>
<th class="h4"></th>
<td></td>
</tr>
</thead>
<tbody>
<tr>
<?php
foreach ($order as $row_order) {
$order_status = intval($row_order->status);
?>
<td class="fw-bold">{{ $row_order->id }}</td>
<td class="fw-bold">{{ $row_order->added_on }}</td>
<td class="fw-bold">{{ $row_order->order_total }} $</td>
<td class="fw-bold"><?php if($order_status == 0){ ?>
Not Paid
<?php }elseif ($order_status == 1) { ?>
Paid
<?php }elseif ($order_status == 2) { ?>
Shipped
<?php }elseif ($order_status == 3) { ?>
Delivered
<?php } ?>
</td>
<td></td>
{{-- <td><a class="btn btn-primary" href="">Order Detail</a></td> --}}
<div class="btn-group">
<td>
<button class="btn btn-primary dropdown-toggle" type="button" id="dropdownMenuButton" data-bs-toggle="dropdown" aria-expanded="false">
Order Detail
</button>
</td>
#foreach (\App\Models\Order_product_size_color::where('order_id', '=', $row_order->id)->get() as $order_variant)
#foreach (\App\Models\Product_size_color::where('id', '=', $order_variant->product_size_color_id)->get() as $variant)
<div class="dropdown-menu">
<td class="border-0 p-0 dropdown-item">
<tr>
<td class="border-0"><img class="rounded" src="{{ asset('storage/'. $variant->image1->product_image) }}" alt="" style="width: 80px; height: 90px;"></td>
<td class="fw-bold border-0">{{ $variant->product->product_name }}</td>
<td class="border-0">{{ $order_variant->count }} products</td>
<td class="fw-bold border-0">Size: {{ $variant->size->size_name }}</td>
<td class="fw-bold border-0">Color: {{ $variant->color->color_name }}</td>
<td class="fw-bold border-0">${{ $variant->product->price }}</td>
</tr>
</td>
</div>
#endforeach
#endforeach
</div>
<tr>
<td class="fw-bold">Delivery Address:</td>
<td class="fw-bold">{{ $row_order->address }}</td>
</tr>
</tr>
<?php }//end foreach ?>
</tbody>
</table>

How can I fetch authenticated data from school homepage?

I want to crawl my authenticated data from university homepage and there are no API calls.
Therefore, I have to send POST data like id and password to server, but I cannot login without clicking login button.
Below is my code of university homepage.
<form action="./_login.php" method="post" autocomplete = "off" onSubmit="return comp()" name="login" >
<!--<form action="https://hisnet.handong.edu/login/_login.php" method="post" autocomplete = "off" onSubmit="return comp()" name="login" >-->
<!-- E-mail¿¡ ÀÖ´Â ¸µÅ©¸¦ Ŭ¸¯ÇÏ¿© À̵¿ÇÏ´Â °æ¿ì, ÀúÀåµÇ´Â °ª 3°¡Áö -->
<input type =hidden name ="part" value ="">
<input type =hidden name ="f_name" value ="">
<input type =hidden name ="agree" value =""> <!-- 2013.10.04 ÃÊ°ú±Ù¹« À̸ÞÀÏ¿¡¼­ °áÁ¦Ã¢À¸·Î ¹Ù·Î À̵¿ÇϱâÀ§ÇØ Ãß°¡ (±èÀÎŹ) -->
<table border="0" cellpadding="0" cellspacing="0" width="285">
<tr>
<td><img src="/2012_images/intro/logbox1.gif" /></td>
</tr>
<tr>
<td height="23" style="text-align:center; background-image:url(/2012_images/intro/logbox2.gif)">
<input type="radio" name="Language" value="Korean" checked>
<a href='#' onkeypress='checkKorean();'><font style='font-size:10pt;'>ÇѱÛ</font></a>
<input type="radio" name="Language" value="English">
<a href='#' onkeypress='checkEnglish();'><font style='font-size:10pt;'>English</font></a>
</td>
</tr>
<tr>
<td style="text-align:center; background-image:url(/2012_images/intro/logbox2.gif)">
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td><img src="/2012_images/intro/txt_id.gif" width="61" height="18" /></td>
<td><span style="">
<input type="text" style="color:#000000; height: 16px; width:138px;ime-mode:inactive" name="id" autocomplete="off" tabindex="1" placeholder="¾ÆÀ̵𸦠ÀÔ·ÂÇϽʽÿÀ." value=""/>
</span></td>
</tr>
<tr>
<td height="6" colspan="2"></td>
</tr>
<tr>
<td><img src="/2012_images/intro/txt_pwd.gif" width="61" height="18" /></td>
<td><input type="password" style="color:#000000; height: 16px; width:138px;ime-mode:inactive" name="password" autocomplete="off" tabindex="1" placeholder="Æнº¿öµå¸¦ ÀÔ·ÂÇϽʽÿÀ."></td>
</tr>
</table>
</td>
<td style="padding-left:8px;"><input type="image" src="/2012_images/intro/btn_login.gif" /></td>
</tr>
</table>
</td>
</tr>
<tr>
<td><img src="/2012_images/intro/logbox_line.gif" /></td>
</tr>
<tr>
<td style="text-align:center; background-image:url(/2012_images/intro/logbox2.gif); height:18px;">
<input type="checkbox" id="saveid" name="saveid" value="Y" /> ¾ÆÀ̵ðÀúÀå <a onclick="UserLoginPopUp()" style="cursor:pointer"><font color="#FF0000"><!--<b>* HISNet ·Î±×ÀÎÀÌ ¾ÈµÉ °æ¿ì</b>--></font></a>
</td>
</tr>
<tr>
<td><img src="/2012_images/intro/logbox3.gif" /></td>
</tr>
<tr>
<td> </td>
</tr>
<tr>
<td><img src="/2012_images/intro/line_txt1_1.gif" border=0/><img src="/2012_images/intro/line_txt1_2.gif" border=0/></td>
</tr>
<tr>
<td><img src="/2012_images/intro/line_txt2_1.gif" border=0/><img src="/2012_images/intro/line_txt2_2.gif" border=0/></td>
</tr>
<tr>
<td><img src="/2012_images/intro/line_txt3_1.gif" border=0/><img src="/2012_images/intro/line_txt3_2.gif" border=0/></td>
</tr>
</table>
</form>
I implemented like this.
main() async {
http.post('http://hisnet.handong.edu/login/login.php',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: {'id':'myID','password':'myPassword'})
.then((response){
print('Response status: ${response.statusCode}');
print('Response body: ${response.body}');
});
}
However, this implementation only fills the form and not click the login button. In this situation, I wanna send my data to server. How can I do that?
I believe here is how you grok the info.
Step 1, navigate to login page.
Step 2, open your browser debugging tools and select network
Step 3, fail or succeed the login to grab the post info
URL: https://hisnet.handong.edu/login/_login.php
POST data:
part
f_name
agree
Language=Korean
id=sadasd
password=asdasd
x=25
y=26
curl 'https://hisnet.handong.edu/login/_login.php' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:65.0) Gecko/20100101 Firefox/65.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Referer: https://hisnet.handong.edu/login/login.php' -H 'Content-Type: application/x-www-form-urlencoded' -H 'DNT: 1' -H 'Connection: keep-alive' -H 'Cookie: PHPSESSID=vn4f2mksuv4lfo1i7co2c0e184; NSC_xfcqpsubm_WJQ=ffffffffc8f47f3e45525d5f4f58455e445a4a423660; NSC_ijtofu_ttm=ffffffffc8f47f2145525d5f4f58455e445a4a423660' -H 'Upgrade-Insecure-Requests: 1' --data 'part=&f_name=&agree=&Language=Korean&id=sadasd&password=asdasd&x=25&y=26'
With all of that information, create your login
http.post(https://hisnet.handong.edu/login/_login.php, body: { "part" : null, "f_name" : null, "agree" : null, "Language": "Korean", "id": "sadasd", "password":"asdasd", "x": "25", "y":"26"})
I honestly do no understand what all these fields mean or have a successful attempt, so I cannot verify regardless whether I am supposed to send an int or string. The worst case scenario, you need to use a webbrowser

Elements above JQuery accordion losing padding

I have a jquery dialog that contains a jquery accordion among other things. When I click the accordion headings to expand the different sections, the elements above the accordion lose their padding for the duration of the animation. The result is that these elements shift to the left for the duration of the animation. Below are the HTML/JS snippets in question.
Any thoughts?
HTML:
<div id="bodyDiv">
<!-- Dialog -->
<div id="patientPopup" title="Patient:" class="ui-widget">
<table style="width: 100%">
<tr>
<td class="AppointmentImage">
<img src="images/John-Petrucci-tn.jpg" alt="Patient Photo">
</td>
<td>
<b>Name:</b> Smith, Sally <b>DOB:</b> 02/15/1984 <br />
<b>SSN:</b> 999-99-9999 <b>Address:</b> 123 Main St Nashville, TN 37204
</td>
</tr>
<tr>
<td colspan="2" style="width: 100%">
<!--Accordion-->
<div id="patientSummary">
<h3>Encounters</h3>
<div>
<table class="PatientSummary">
<tr>
<th>12/03/2011</th>
<td>
Office visit - this is text for the office visit. some notes perhaps.
</td>
</tr>
<tr>
<th>10/16/2011</th>
<td>
GYN visit - this is text to fill some space.
</td>
</tr>
</table>
</div>
<h3>Alerts</h3>
<div>
<ul>
<li>Diabetic</li>
<li>Due for FluShot</li>
</ul>
</div>
<h3>Labs/Radiology</h3>
<div>
<table style="vertical-align: text-top;">
<tr>
<th>Date</th>
<th>Lab</th>
<th>Result</th>
</tr>
<tr>
<td>12/03/2011</td>
<td>Blood Panel</td>
<td>N</td>
</tr>
<tr>
<td>12/03/2011</td>
<td>Pregnancy Test</td>
<td>Y</td>
</tr>
<tr>
<td>12/03/2011</td>
<td>Blood Panel</td>
<td>N</td>
</tr>
<tr>
<td>12/03/2011</td>
<td>Pregnancy Test</td>
<td>Y</td>
</tr>
<tr>
<td>12/03/2011</td>
<td>Blood Panel</td>
<td>N</td>
</tr>
<tr>
<td>12/03/2011</td>
<td>Pregnancy Test</td>
<td>Y</td>
</tr>
</table>
</div>
</div>
</td>
</tr>
</table>
</div>
<button id="showPatient">Show Patient</button>
</div>
JavaScript:
$("#patientPopup").dialog({
autoOpen: false,
modal: true,
height: 530,
width: 600,
draggable: false,
resizable: false,
open: function () {
$("#patientSummary").accordion({
fillSpace: true,
autoHeight: true
});
}
});
$("#showPatient").button().click(
function () {
$("#patientPopup").dialog("open");
}
);
Any help would be appreciated. Thanks!
The solution was quite simple. I ended up putting the image and text in a completely separate table than the accordion.
Never determined exactly why the top elements were losing their padding though...

Grails upload image

I am trying to upload a picture, and save it in database.
If I do the following I get this error:
Failed to convert property value of type
org.springframework.web.multipart.commons.CommonsMultipartFile to
required type java.lang.Byte[] for property picture1; nested exception
is java.lang.IllegalArgumentException: Cannot convert value of type
[org.springframework.web.multipart.commons.CommonsMultipartFile] to
required type [java.lang.Byte] for property picture1[0]:
PropertyEditor
[org.springframework.beans.propertyeditors.CustomNumberEditor]
returned inappropriate value
If i do it this way:
if(request instanceof MultipartHttpServletRequest){
MultipartHttpServletRequest mpr = (MultipartHttpServletRequest)request;
CommonsMultipartFile f = (CommonsMultipartFile) mpr.getFile("picture1");
}
I get this error:
Executing action [save] of controller [com.testapp.RequestController]
caused exception: Cannot cast object '
org.springframework.web.multipart.commons.CommonsMultipartFile#34ae1f02'
with class
'org.springframework.web.multipart.commons.CommonsMultipartFile' to
class 'java.lang.Byte'
What should I do to make this work?
Domain
package com.testapp
class Request{
String requestID
Date dateCreated
String subject
String startedBy
String description
String status
String priority
Productline productline
Topic topic
Subtopic subtopic
String company
Byte [] picture1
Byte [] picture2
Byte [] picture3
String acceptedBy
static constraints = {
requestID(blank:true,nullable:true)
dateCreated(blank:true,nullable:true)
subject()
description(maxSize:5000)
status (blank:true,nullable:true)
priority(inList:["Normal","Urgent","Not urgent"])
productline(blank:true,nullable:true)
topic(blank:true,nullable:true)
subtopic(blank:true,nullable:true)
company(blank:true,nullable:true)
startedBy(blank:true,nullable:true)
acceptedBy(blank:true,nullable:true)
picture1(blank:true,nullable:true)
picture2(blank:true,nullable:true)
picture3(blank:true,nullable:true)
}
}
GSP:
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="layout" content="main" />
<g:set var="entityName" value="${message(code: 'request.label', default: 'Request')}" />
<title><g:message code="New request" args="[entityName]" /></title>
</head>
<body>
<div class="nav">
<span class="menuButton"><a class="home" href="${createLink(uri: '/')}"><g:message `code="default.home.label"/></a></span>`
<span class="menuButton"><g:link class="list" action="userList"><g:message code="Lista zahteva" `args="[entityName]" /></g:link></span>`
</div>
<div class="body">
<h1><g:message code="New request" args="[entityName]" /></h1>
<g:if test="${flash.message}">
<div class="message">${flash.message}</div>
</g:if>
<g:hasErrors bean="${requestInstance}">
<div class="errors">
<g:renderErrors bean="${requestInstance}" as="list" />
</div>
</g:hasErrors>
<g:form action="save" method="post" enctype="multipart/form-data">
<div class="dialog">
<table>
<tbody>
<tr class="prop">
<td valign="top" class="name">
<label for="subject"><g:message code="request.subject.label" default="Subject" /></label>
</td>
<td valign="top" class="value ${hasErrors(bean: requestInstance, field: 'subject', 'errors')}">
<g:textField name="subject" value="${requestInstance?.subject}" />
</td>
</tr>
<tr class="prop">
<td valign="top" class="name">
<label for="description"><g:message code="request.description.label" default="Opis" /></label>
</td>
<td valign="top" class="value ${hasErrors(bean: requestInstance, field: 'description', 'errors')}">
<g:textArea name="description" cols="40" rows="5" value="${requestInstance?.description}" />
</td>
</tr>
<tr>
<td valign="top" class="name">
<label for="picture1"><g:message code="request.picture1.label" default="Printscreen" /></label>
</td>
<td valign="top" class="value">
<input type="file" id="picture1" name="picture1"/>
</td>
</tr>
<tr class="prop">
<td valign="top" class="name">
<label for="priority"><g:message code="request.priority.label" default="Priority" /></label>
</td>
<td valign="top" class="value ${hasErrors(bean: requestInstance, field: 'status', 'errors')}">
<g:select name="priority" from="${requestInstance.constraints.priority.inList}" value="${requestInstance?.priority}" valueMessagePrefix="request.priority" />
</td>
</tr>
<tr class="prop">
<td valign="top" class="name">
<label for="productline"><g:message code="request.productline.label" default="Productline" /></label>
</td>
<td valign="top" class="value ${hasErrors(bean: requestInstance, field: 'productline', 'errors')}">
<g:select name="productline.id" from="${com.testapp.Productline.list()}" optionKey="id" value="${requestInstance?.productline?.id}" />
</td>
</tr>
<tr class="prop">
<td valign="top" class="name">
<label for="topic"><g:message code="request.topic.label" default="Topic" /></label>
</td>
<td valign="top" class="value ${hasErrors(bean: requestInstance, field: 'topic', 'errors')}">
<g:select name="topic.id" from="${com.testapp.Topic.list()}" optionKey="id" value="${requestInstance?.topic?.id}" />
</td>
</tr>
<tr class="prop">
<td valign="top" class="name">
<label for="subtopic"><g:message code="request.subtopic.label" default="Subtopic" /></label>
</td>
<td valign="top" class="value ${hasErrors(bean: requestInstance, field: 'subtopic', 'errors')}">
<g:select name="subtopic.id" from="${com.testapp.Subtopic.list()}" optionKey="id" value="${requestInstance?.subtopic?.id}" />
</td>
</tr>
</tbody>
</table>
</div>
<div class="buttons">
<span class="button"><g:submitButton name="create" class="save" value="${message(code: 'default.button.create.label', default: 'Create')}" /></span>
</div>
</g:form>
</div>
</body>
Controller:
def save = {
def requestInstance = new Request(params)
def requestNumberInstance = new RequestNumber()
def upPic1 = request.getFile('picture1')
def lastReqNum = RequestNumber.find("from RequestNumber ORDER BY requestNumber desc")
if(lastReqNum){
requestNumberInstance.requestNumber = lastReqNum.requestNumber + 1
}
else{
requestNumberInstance.requestNumber = 110000
}
requestInstance.requestID = "CSC" + requestNumberInstance.requestNumber
def currentUserContact = Contact.findByUser(springSecurityService.getCurrentUser())
requestInstance.startedBy = currentUserContact.realname
requestInstance.company = currentUserContact.company
requestInstance.status = "Opened"
requestInstance.acceptedBy = "Not yet accepted"
requestInstance.picture1 = upPic1
if(requestNumberInstance.save()){
if (requestInstance.save()) {
flash.message = "${message(code: 'default.created.message', args: [message(code: 'request.label', default: 'Request'), requestInstance.id])}"
redirect(action: "show", id: requestInstance.id)
}
else {
render(view: "create", model: [requestInstance: requestInstance])
}
}
else{
render(view: "create", model: [requestInstance: requestInstance])
}
}
Please dont mind the spaghetti code. I'm just trying to get some basic concepts. I will clear it later.
Simplified example:
def save = {
def requestInstance = new Request(params)
def requestNumberInstance = new RequestNumber()
if(requestInstance.validate() && requestInstance.save(flush: true)){
println "Saved successfully with ${requestInstance.picture1.length} bytes"
}
else {
println "Save failed"
}
Update after question edit
The error is probably caused by this:
def upPic1 = request.getFile('picture1')
...
requestInstance.picture1 = upPic1
request.getFile() is returning a MultipartFile, and you're trying to assign it to a Byte[] field. Considering my small example (below), you shouldn't even need to try to make this assignment. The def requestInstance = new Request(params) will bind the byte[] automatically.
Uploaded files bind automatically to byte[] fields. Here's a working example:
Domain: grails-app/domain/my/Example.groovy
package my
class Example {
byte[] file
}
Controller: grails-app/controllers/my/ExampleController.groovy
package my
class ExampleController {
def create = { }
def save = {
def example = new Example(params)
if(example.validate() && example.save(flush: true)) {
println "Saved successfully with ${example.file.length} bytes"
} else {
println "Save failed"
}
redirect(action: 'create')
}
}
GSP: grails-app/views/example/create.gsp
<!DOCTYPE html>
<html>
<body>
<g:uploadForm action="save">
<input type="file" name="file"/>
<g:submitButton name="submit"/>
</g:uploadForm>
</body>
</html>
When I upload a small file using the GSP form, I see the following console output:
Saved successfully with 23 bytes
Suggestions
Try using Grails data binding to save your file contents.
Make sure your form is a <g:uploadForm> or has an enctype="multipart/form-data" if you're using a vanilla`.
Make sure you're binding the params using the domain constructor, domain.properties, or bindData().
I am guessing your typing is messed up.
What happens if you simply do:
def f = request.getFile('myFile')
as described in the manual. If you want strong typing it should be MultiPartfile, not CommonsMultiPartFile, as far as I remember (and you get it right from the request object).
This is the interface you're working on: http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/multipart/MultipartFile.html
The relevant method for you, should be getBytes().
Edit for edited question:
As I said, you want getBytes(), you are trying to shove a MultiPartFile into a byte array, thats not going to work.
requestInstance.picture = upPic.getBytes() and you should be allright.
It only worked when I changed my domain properties picture1,picture2,picture3 to:
byte [] picture1
byte [] picture2
byte [] picture3
and added those mappings:
static mapping = {
picture1 column:"picture1", sqlType: "blob"
picture2 column:"picture2", sqlType: "blob"
picture3 column:"picture3", sqlType: "blob"
}

Resources