Has anybody used openERP/ odoo for printing invoices via XML-RPC. I've been trying to create an xml rpc method for printing with no success.
function printInvoice($values,$model){
$print = new xmlrpc_client($this->server."report");
$print->return_type = 'phpvals';
foreach($values as $k=>$v){
$nval[$k] = new xmlrpcval( $v, xmlrpc_get_type($v) );
}
$msg = new xmlrpcmsg('report');
$msg->addParam(new xmlrpcval($this->database, "string"));
$msg->addParam(new xmlrpcval($this->uid, "int"));
$msg->addParam(new xmlrpcval($this->password, "string"));
$msg->addParam(new xmlrpcval($model, "string"));
$msg->addParam(new xmlrpcval("report", "string"));
$msg->addParam(new xmlrpcval(87, "int"));
$msg->addParam(new xmlrpcval($nval,"struct"));
$resp = $print->send($msg);
if ($resp->faultCode())
return $resp->faultString();
else
return $resp->value();
}
this is the code that I have so far, first of all i want to generate a report and then print it.
I figured it out a simple way to do it, you just pass the id of invoice or order in the links and this dynamically creates a pdf for the report, or instead of the pdf you can use 'html' which generates an html ready for print for the invoice like this:
http://serverurl:port/report/html/account.report_invoice/(id of invoice);
Here is the code if it helps someone.
function printInvoice($id,$type){
if($type == 'invoice')
{
return "http://serverurl:port/report/pdf/account.report_invoice/".$id;
}
else if($type == 'order')
{
return "http://serverurl:port/report/pdf/sale.report_saleorder/".$id;
}
else
{
return false;
}
}
There is another way that works even when session_id is missing. You should add a function on the server side which will return a pdf:
from openerp import models, api
from openerp.http import request
class AccountInvoice(models.Model):
_inherit = 'account.invoice'
#api.multi
def json_pdf(self):
request.website_multilang = False
pdf = self.env['report'].get_pdf(self, 'account.report_invoice')
if pdf:
return {'data': pdf.encode('base64'), 'name': self.number}
else:
return {'error': 'Attachment not found', 'name': self.number}
In python...
import time
import base64
printsock = xmlrpclib.ServerProxy('http://server:8069/xmlrpc/report')
model = 'account.invoice'
id_report = printsock.report(dbname, uid, pwd, model, ids, {'model': model, 'id': ids[0], 'report_type':'pdf'})
time.sleep(5)
state = False
attempt = 0
while not state:
report = printsock.report_get(dbname, uid, pwd, id_report)
state = report['state']
if not state:
time.sleep(1)
attempt += 1
if attempt>200:
print 'Printing aborted, too long delay !'
string_pdf = base64.decodestring(report['result'])
file_pdf = open('/tmp/file.pdf','w')
file_pdf.write(string_pdf)
file_pdf.close()
Related
this function must be run in the file where the bot is located
def start_pars():
from mainaio import data
username_input = driver.find_element(By.XPATH,
'/html/body/div/div/main/div/div/div/div[1]/form/div[1]/div[1]/div/input')
username_input.clear()
username_input.send_keys(data["username"])
pass_input = driver.find_element(By.XPATH,
'/html/body/div/div/main/div/div/div/div[1]/form/div[1]/div[2]/div/input')
pass_input.clear()
pass_input.send_keys(data["password"])
driver.find_element(By.XPATH, '/html/body/div/div/main/div/div/div/div[1]/form/div[2]/button').click()
time.sleep(1)
username1 = driver.find_element(By.XPATH, '/html/body/div[1]/nav[2]/div[2]/div/div[2]/div[2]/div')
print(username1.text)
less1 = []
lessundscore = driver.find_elements(By.XPATH, '/html/body/div[1]/div/main/div/div[2]/div/div[3]/div[1]')
for value in zip(lessundscore):
less1 += value
for val in less1:
print(val.text)
return username1, less1
items from the state must be transferred to the sending keys
class Registration(StatesGroup):
username = State()
password = State()
username = message.text
await state.update_data(username=username)
assword = message.text
await state.update_data(password=password)
data = await state.get_data()
I tried to run in the last registration function start_pars(data['username'], data['password'])
Now my spiders are sending data to my site in this way:
def parse_product(response, **cb_kwargs):
item = {}
item[url] = response.url
data = {
"source_id": 505,
"token": f"{API_TOKEN}",
"products": [item]
}
headers = {'Content-Type': 'application/json'}
url = 'http://some.site.com/api/'
requests.post(url=url, headers=headers, data=json.dumps(data))
is it possible to somehow implement this design through a pipeline or middleware, because it is inconvenient to prescribe for each spider?
p.s. the data (data) needs to be sent in the json format (json.dumps(data)), if I make the item = MyItemClass() class, an error occurs...
It can be done using a pipeline fairly easily. You can also use scrapy's Item class and item Field class as long as you cast them to a dict prior to calling json.dumps.
For Example:
class Pipeline:
def process_item(self, item, spider):
data = dict(item)
headers = {'Content-Type': 'application/json'}
url = 'http://some.site.com/api/'
requests.post(url=url, headers=headers, data=json.dumps(data))
return item
If you use this example it will call it on each and every item you yield from your spider. Just remember to activate it in your settings.py file.
I found another additional solution (on github), maybe someone will be interested...
pipeline.py
import json
import logging
import requests
from scrapy.utils.serialize import ScrapyJSONEncoder
from twisted.internet.defer import DeferredLock
from twisted.internet.threads import deferToThread
default_serialize = ScrapyJSONEncoder().encode
class HttpPostPipeline(object):
settings = None
items_buffer = []
DEFAULT_HTTP_POST_PIPELINE_BUFFERED = False
DEFAULT_HTTP_POST_PIPELINE_BUFFER_SIZE = 100
def __init__(self, url, headers=None, serialize_func=default_serialize):
"""Initialize pipeline.
Parameters
----------
url : StrictRedis
Redis client instance.
serialize_func : callable
Items serializer function.
"""
self.url = url
self.headers = headers if headers else {}
self.serialize_func = serialize_func
self._lock = DeferredLock()
#classmethod
def from_crawler(cls, crawler):
params = {
'url': crawler.settings.get('HTTP_POST_PIPELINE_URL'),
}
if crawler.settings.get('HTTP_POST_PIPELINE_HEADERS'):
params['headers'] = crawler.settings['HTTP_POST_PIPELINE_HEADERS']
ext = cls(**params)
ext.settings = crawler.settings
return ext
def process_item(self, item, spider):
if self.settings.get('HTTP_POST_PIPELINE_BUFFERED', self.DEFAULT_HTTP_POST_PIPELINE_BUFFERED):
self._lock.run(self._process_items, item)
return item
else:
return deferToThread(self._process_item, item, spider)
def _process_item(self, item, spider):
data = self.serialize_func(item)
requests.post(self.url, json=json.loads(data), headers=self.headers)
return item
def _process_items(self, item):
self.items_buffer.append(item)
if len(self.items_buffer) >= int(self.settings.get('HTTP_POST_PIPELINE_BUFFER_SIZE',
self.DEFAULT_HTTP_POST_PIPELINE_BUFFER_SIZE)):
deferToThread(self.send_items, self.items_buffer)
self.items_buffer = []
def send_items(self, items):
logging.debug("Sending batch of {} items".format(len(items)))
serialized_items = [self.serialize_func(item) for item in items]
requests.post(self.url, json=[json.loads(data) for data in serialized_items], headers=self.headers)
def close_spider(self, spider):
if len(self.items_buffer) > 0:
deferToThread(self.send_items, self.items_buffer)
Am trying to write update view,but got an error please help me to find the problem,thanks :)
At first I have many to many field in my model.It is my model
class Portfolio(models.Model):
name = models.CharField(max_length=50, unique=True, blank=False, null=True)
market = models.ForeignKey(Market, on_delete=models.DO_NOTHING, related_name='market')
investor = models.ForeignKey('accounts.User', on_delete=models.DO_NOTHING, related_name='investor')
assets = models.ManyToManyField(Assets, related_name='assets')
def __str__(self):
return self.name
After that I have a serializer for my view:
class PortfolioSerializer(serializers.ModelSerializer):
class Meta:
model = Portfolio
fields = ['name', 'market', 'investor', 'assets']
And it's my view:
class PortfolioUpdateView(APIView):
serializer_class = PortfolioSerializer
def put(self, request, *args,):
data = request.data
portfo = Portfolio.objects.get(id=id)
print(portfo)
serilize = self.serializer_class(instance=request.user, data=request.POST)
if serilize.is_valid():
name = serilize.data['name']
market = Market.objects.get(pk=int(request.POST.get('market', '')))
assets = Assets.objects.get(pk=int(request.POST.get('assets', '')))
Portfolio.objects.update(name=name, market=market,
assets=assets,
)
return portfo
else:
pass
and at the end it is my error:
TypeError at /market/update/1
put() got an unexpected keyword argument 'id'
I found the answer by my self,because I needed to use id for get obj so I used request.data that is body's data of object include obj's id and added query-set method for getting the class objs
class PortfolioUpdateView(viewsets.ModelViewSet):
serializer_class = PortfolioSerializer
def get_queryset(self):
portfolio = Portfolio.objects.all()
return portfolio
def put(self, request, *args, **kwargs):
data = Portfolio.objects.get(id=request.data['id'])
update_portfolio = Portfolio.objects.update(name=data['name']
, market=Market.objects.get(pk=int(request.POST.get('market', ''))))
update_portfolio.save()
for asset in data['assets']:
asset_obj = Assets.objects.update(asset_name=asset['asset_name'])
update_portfolio.assets.add(asset_obj)
serializer = PortfolioSerializer(update_portfolio)
return Response(serializer.data)
And this is the URL
router.register("update", PortfolioUpdateView, basename="update")
I want to post a request to a Python-based API that has an image in its body. I have tried to send data with 5 methods:
await http.post()
final api = Uri.parse("https://e8f628d7.ngrok.io/detections");
Map<String, dynamic> body = {'images': image};
final response = await http.post(
api,
body: body,
);
if (response.statusCode == 200) {
final responseJson = json.decode(response.body);
print(responseJson);
}
Client().post()
Map<String, dynamic> body = {'images': image};
var client = new http.Client();
client.post("https://e8f628d7.ngrok.io/detections",body: body).then((response) {
print("Post " + response.statusCode.toString());
});
dio
MultipartRequest
final api = Uri.parse("https://e8f628d7.ngrok.io/detections");
var stream = new http.ByteStream(DelegatingStream.typed(image.openRead()));
var length = await image.length();
var request = new http.MultipartRequest("POST", api);
var multipartFileSign = new http.MultipartFile(
'profile_pic', stream, length,
filename: path.basename(image.path));
request.files.add(multipartFileSign);
// send
var response = await request.send();
print(response.statusCode);
response.stream.transform(utf8.decoder).listen((value) {
print(value);
});
Link of [DELETED]First Answer to this question:
if (image == null) return;
String base64Image = base64Encode(image.readAsBytesSync());
http.post(api, body: {
'images': base64Image,
}).then((res) {
print(res.statusCode);
print(json.decode(res.body));
}).catchError((err) {
print(err);
});
}
I am able to send the image and am getting a 200 success response. But, I am not sure if the image is getting altered or any problem happens while sending the image as the response is empty whereas it should have some sort of response.
This is my app.py from with which my server works:
import time
from absl import app, logging
import cv2
import numpy as np
import tensorflow as tf
from yolov3_tf2.models import (
YoloV3, YoloV3Tiny
)
from yolov3_tf2.dataset import transform_images, load_tfrecord_dataset
from yolov3_tf2.utils import draw_outputs
from flask import Flask, request, Response, jsonify, send_from_directory, abort
import os
# customize your API through the following parameters
classes_path = './data/labels/coco.names'
weights_path = './weights/yolov3.tf'
tiny = False # set to True if using a Yolov3 Tiny model
size = 416 # size images are resized to for model
output_path = './detections/' # path to output folder where images with detections are saved
num_classes = 80 # number of classes in model
# load in weights and classes
physical_devices = tf.config.experimental.list_physical_devices('GPU')
if len(physical_devices) > 0:
tf.config.experimental.set_memory_growth(physical_devices[0], True)
if tiny:
yolo = YoloV3Tiny(classes=num_classes)
else:
yolo = YoloV3(classes=num_classes)
yolo.load_weights(weights_path).expect_partial()
print('weights loaded')
class_names = [c.strip() for c in open(classes_path).readlines()]
print('classes loaded')
# Initialize Flask application
app = Flask(__name__)
# API that returns JSON with classes found in images
#app.route('/detections', methods=['POST'])
def get_detections():
raw_images = []
images = request.files.getlist("images")
image_names = []
for image in images:
image_name = image.filename
image_names.append(image_name)
image.save(os.path.join(os.getcwd(), image_name))
img_raw = tf.image.decode_image(
open(image_name, 'rb').read(), channels=3)
raw_images.append(img_raw)
num = 0
# create list for final response
response = []
for j in range(len(raw_images)):
# create list of responses for current image
responses = []
raw_img = raw_images[j]
num+=1
img = tf.expand_dims(raw_img, 0)
img = transform_images(img, size)
t1 = time.time()
boxes, scores, classes, nums = yolo(img)
t2 = time.time()
print('time: {}'.format(t2 - t1))
print('detections:')
for i in range(nums[0]):
print('\t{}, {}, {}'.format(class_names[int(classes[0][i])],
np.array(scores[0][i]),
np.array(boxes[0][i])))
responses.append({
"class": class_names[int(classes[0][i])],
"confidence": float("{0:.2f}".format(np.array(scores[0][i])*100))
})
response.append({
"image": image_names[j],
"detections": responses
})
img = cv2.cvtColor(raw_img.numpy(), cv2.COLOR_RGB2BGR)
img = draw_outputs(img, (boxes, scores, classes, nums), class_names)
cv2.imwrite(output_path + 'detection' + str(num) + '.jpg', img)
print('output saved to: {}'.format(output_path + 'detection' + str(num) + '.jpg'))
#remove temporary images
for name in image_names:
os.remove(name)
try:
return jsonify({"response":response}), 200
except FileNotFoundError:
abort(404)
# API that returns image with detections on it
#app.route('/image', methods= ['POST'])
def get_image():
image = request.files["images"]
image_name = image.filename
image.save(os.path.join(os.getcwd(), image_name))
img_raw = tf.image.decode_image(
open(image_name, 'rb').read(), channels=3)
img = tf.expand_dims(img_raw, 0)
img = transform_images(img, size)
t1 = time.time()
boxes, scores, classes, nums = yolo(img)
t2 = time.time()
print('time: {}'.format(t2 - t1))
print('detections:')
for i in range(nums[0]):
print('\t{}, {}, {}'.format(class_names[int(classes[0][i])],
np.array(scores[0][i]),
np.array(boxes[0][i])))
img = cv2.cvtColor(img_raw.numpy(), cv2.COLOR_RGB2BGR)
img = draw_outputs(img, (boxes, scores, classes, nums), class_names)
cv2.imwrite(output_path + 'detection.jpg', img)
print('output saved to: {}'.format(output_path + 'detection.jpg'))
# prepare image for response
_, img_encoded = cv2.imencode('.png', img)
response = img_encoded.tostring()
#remove temporary image
os.remove(image_name)
try:
return Response(response=response, status=200, mimetype='image/png')
except FileNotFoundError:
abort(404)
if __name__ == '__main__':
app.run(debug=True, host = '0.0.0.0', port=5000)
I try to send the same image directly through Postman and get the desired response but when I do it with the flutter app, I don't get it. Is there any possibility of the image getting altered or modified? And, is there any other method in which I can send the image to the API other than the above 3?
You need to make sure that you are using a good version of http. There was a regression recently that broke multipart form. It's safest for now to hard code the exact version in pubspec.yaml (You might want to look in pubspec.lock to see what version you were using to confirm that it was one of the ones with the error.)
http: 0.12.0+4
Then try this:
main() async {
http.MultipartRequest request = http.MultipartRequest('POST', Uri.parse(url));
request.files.add(
await http.MultipartFile.fromPath(
'images',
File('kitten1.jpg').path,
contentType: MediaType('application', 'jpeg'),
),
);
http.StreamedResponse r = await request.send();
print(r.statusCode);
print(await r.stream.transform(utf8.decoder).join());
}
I have been trying to automate module installation from a http controller. Installation of module has been succeeded and since accounting module has some wizards to be processed, they are not executed and they are in open state in ir.actions.todo table. So I took an example from addons/account/account_pre_install.yml and modified it accordingly. The problem is, the write method on ir.actions.todo model is not working and create and execute_simple methods on account.installer model are not working.
Here is the whole code for that particular controller.
#http.route('/saas_worker/module', type="json", auth="none")
def check_module(self, fields):
params = dict(map(operator.itemgetter('name', 'value'), fields))
super_admin_password = config.get("admin_passwd")
response_data = {}
create_attrs = (
super_admin_password,
params["db_name"],
False,
params["db_lang"],
params["create_admin_password"]
)
db_created = request.session.proxy("db").create_database(*create_attrs)
if db_created:
db = openerp.sql_db.db_connect(params["db_name"])
with closing(db.cursor()) as cr:
registry = openerp.modules.registry.RegistryManager.new(cr.dbname, update_module=True)
ir_module = registry['ir.module.module']
ir_model_data = registry['ir.model.data']
wizards = registry['ir.actions.todo']
res_partner = registry['res.partner']
account_installer = registry['account.installer']
selected_modules = params["modules"].split(",")
module_ids = ir_module.search(cr,SUPERUSER_ID,[('name','in',selected_modules)])
#Install modules automatically
ir_module.button_immediate_install(cr,SUPERUSER_ID,module_ids,None)
wizard = wizards.browse(cr,SUPERUSER_ID,self.ref(cr, SUPERUSER_ID, ir_model_data,'account.account_configuration_installer_todo'))
if wizard.state=='open':
mod='l10n_us'
ids = ir_module.search(cr, SUPERUSER_ID, [ ('name','=',mod) ], context=None)
if ids:
wizards.write(cr, SUPERUSER_ID, self.ref(cr, SUPERUSER_ID, ir_model_data,'account.account_configuration_installer_todo'), {'state': 'done'})
wizard_id = account_installer.create(cr, SUPERUSER_ID, {'charts': mod})
account_installer.execute_simple(cr, SUPERUSER_ID, [wizard_id])
ir_module.state_update(cr, SUPERUSER_ID, ids,'to install', ['uninstalled'], context=None)
response_data["status"] = "ok"
response = json.dumps(response_data)
return response
def ref(self, cr, uid, registry_obj, external_id):
return registry_obj.xmlid_to_res_id(cr, uid, external_id, raise_if_not_found=True)