Odoo 14 - account.payment the invoice_ids is removed but what is it replaced with? - odoo

Till Odoo 12, while creating a payment using API calls for invoices, we had to populate the invoice_ids field on the account.payment module and it would automatically mark the corresponding invoices PAID once the payment is validated.
I understand there is no functionality loss, however, I don't know what is this functionality replaced with.
I tried using invoice_line_ids and the invoice still doesn't get marked as PAID. There is only 1 move_id and even if I try that the invoice still doesn't get marked as PAID.
any thoughts?
Edit: This is the json that I am trying to send to Odoo to register a payment against an invoice. but the response is :
"The register payment wizard should only be called on account.move or account.move.line records."
I created a separate content after passing args in the json but still the response remained the same.
{
"jsonrpc":"2.0",
"method":"call",
"params":{
"service": "object",
"method": "execute",
"args":[
"{{databaseName}}",
{{userId}},
"{{password}}",
"account.payment.register",
"create",
{
"can_edit_wizard":true,
"can_group_payments":false,
"payment_type":"inbound",
"partner_type":"customer",
"source_amount":5.48,
"source_amount_currency":5.48,
"source_currency_id":2,
"partner_id":505449,
"country_code":"US",
"journal_id":230,
"other_journal_id":false,
"show_other_journal":false,
"payment_method_id":7,
"partner_bank_id":false,
"group_payment":true,
"amount":5.48,
"currency_id":2,
"payment_date":"2022-02-04",
"communication":"Test Create Invoice 32",
"payment_difference_handling":"open",
"writeoff_account_id":false,
"writeoff_label":"Write-Off",
"active_model":"account.move",
"active_id":364660,
"active_ids":[
364660
]
}
]
}
}

Account payment wizard uses line_ids field which is supposed to be passed through the context using the active_ids key (Odoo will retrieve the account move lines using the active ids)
The active_model should be passed through the context, if the active model is different from account.move or account.move.line Odoo will raise the following error:
The register payment wizard should only be called on account.move or account.move.line records.
The following example will use the same logic used in Register Payment button to create and register invoice payment:
vals = {}
payment_register_id = models.execute_kw(db, uid, password, 'account.payment.register', 'create', [vals], {'context': {'active_model': 'account.move', 'active_ids': invoice_ids}})
models.execute_kw(db, uid, password, 'account.payment.register', 'action_create_payments', [[payment_register_id]])
The following values are the default values passed to the create method when we create a payment manually (Using the register payment button on a customer invoice form):
{'can_group_payments': False, 'payment_type': 'inbound', 'partner_type': 'customer', 'source_amount': 365125, 'source_amount_currency': 365125, 'source_currency_id': 2, 'company_id': 1, 'partner_id': 10, 'country_code': 'US', 'journal_id': 7, 'payment_method_id': 1, 'payment_token_id': False, 'partner_bank_id': False, 'group_payment': True, 'amount': 365125, 'currency_id': 2, 'payment_date': '2022-02-04', 'communication': 'INV/2021/12/0001', 'payment_difference_handling': 'open', 'writeoff_account_id': False, 'can_edit_wizard': True, 'writeoff_label': 'Write-Off'}
Edit
You can call the execute_kw method and pass context in kwargs
{'jsonrpc': '2.0',
'method': 'call',
'params': {
'service': 'object',
'method': 'execute_kw',
'args': ('{{databaseName}}',
{{userId}},
'{{password}}',
'account.payment.register',
'create',
[{'journal_id': 7, ...}],
{'context': {'active_model': 'account.move', 'active_ids': [23]}}
)
},
'id': 843350301
}
The following code is based on the JSON-RPC Library documentation example
import json
import random
import urllib.request
HOST =
PORT =
DB =
USER =
PASS =
def json_rpc(url, method, params):
data = {
"jsonrpc": "2.0",
"method": method,
"params": params,
"id": random.randint(0, 1000000000),
}
req = urllib.request.Request(url=url, data=json.dumps(data).encode(), headers={
"Content-Type":"application/json",
})
reply = json.loads(urllib.request.urlopen(req).read().decode('UTF-8'))
if reply.get("error"):
raise Exception(reply["error"])
return reply["result"]
def call(url, service, method, *args):
return json_rpc(url, "call", {"service": service, "method": method, "args": args})
# log in the given database
url = "http://%s:%s/jsonrpc" % (HOST, PORT)
uid = call(url, "common", "login", DB, USER, PASS)
args = [{'journal_id': 7}]
kwargs = {'context': {'active_model': 'account.move', 'active_ids': [23]}}
payment_register_id = call(url, "object", "execute_kw", DB, uid, PASS, 'account.payment.register', 'create', args, kwargs)
call(url, "object", "execute", DB, uid, PASS, 'account.payment.register', 'action_create_payments', [payment_register_id])

Related

django rest pagination on api view decorator

im trying to do pagination on my django rest code, but i get the same code when i change the number of the page, this is what im doing to get that page: http://localhost:8000/movies?page=3
When i change the page number i get the same response, idk if i have to send the number of the page or something but i do the same of this stackoverflow thread
I put the entire view code:
#api_view(['GET', 'POST', 'DELETE', 'PUT'])
def movies(request):
if request.method == 'GET':
if request.query_params.get('id'):
try:
id = request.query_params.get('id')
movie = Movie.objects.get(id=id)
serializer = MovieSerializer(movie, many=False)
return Response(serializer.data)
except Movie.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
movies = Movie.objects.all().order_by('release_date')
serializer = MovieSerializer(movies , many=True, context={'request':request})
if request.query_params.get('page'):
paginator = LimitOffsetPagination()
result_page = paginator.paginate_queryset(movies, request)
serializer = MovieSerializer(result_page, many=True, context={'request':request})
return Response(serializer.data)
if request.query_params.get('Genre'):
genreparam = request.query_params.get('Genre')
genre = Genre.objects.get(name=genreparam)
queryset = Movie.objects.filter(genre_relation=genre.id).values().order_by('release_date')
return Response(queryset)
return Response(serializer.data)
this is my settings.py
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 2,
}
this is what i get whatever number i send via request params
[
{
"id": 1,
"title": "Guardians of the galaxy",
"tagline": "this is a tagline",
"overview": "this is an overview, starlord in the begins...",
"release_date": "1971-07-13T03:00:00Z",
"poster_url": "http\"//posterurl",
"backdrop_url": "http\"//backdropurl",
"imdb_id": "idk what is a imdb",
"genre_relation": []
},
{
"id": 2,
"title": "Avengers endgame",
"tagline": "this is a tagline",
"overview": "tony stark dies, theres no more happy days, only days",
"release_date": "2019-07-13T03:00:00Z",
"poster_url": "http//posterurl",
"backdrop_url": "http//backdropurl",
"imdb_id": "idk what is a imdb",
"genre_relation": [
1
]
}
]
You are not using the pagination properly. You need to instantiate the paginator with the request, and then call paginate_queryset. You are merely instantiating a paginator, and then completely ignoring it.
paginator = LimitOffsetPagination()
result_page = paginator.paginate_queryset(movies, request)
You thus should rewrite this to:
paginator = LimitOffsetPagination()
result_page = paginator.paginate_queryset(movies, request, view=self)
Note that we here pass view=self, since the LimitOffsetPagination uses self.request, self.response, etc.
Furthermore you should not construct a new serializer, but reuse the existing one, and pass result_page as the queryset:
serializer = MovieSerializer(result_page, many=True, context={'request': request})
Finally you should return the paginated results with:
return paginator.get_paginated_response(serializer.data)
This will add pagination metadata to the response.
So a full example:
#api_view(['GET', 'POST', 'DELETE', 'PUT'])
def movies(request):
# ...
if request.query_params.get('page'):
paginator = LimitOffsetPagination()
result_page = paginator.paginate_queryset(movies, request, view=self)
serializer = MovieSerializer(result_page, many=True, context={'request':request})
return paginator.get_paginated_response(serializer.data)
# ...
Note that using the #api_view decorator is often discouraged. You might want to consider using the #api_view decorator.

JWS Error during API testing python flask

I am trying to test a function, which basically calls the API by passing a some values, which is then loaded to the schema to be validated and then accepted or rejected based on validation.
The below is my test function.
params = {
'first': [10,20],
'second': 400,
'third ': 'Testing'
}
headers = {
'Authorization': 'Bearer{}'.format(token),
'Data-type' : "json"
}
response = self.client.post(url_for('MyView:post', id=current_id.id),
json=params,
headers=headers)
This renders me the error below:
{
"msg": "Invalid header string: must be a json object"
}
I was able to check the issue and found out its due to the mapping of invalid types. But as headers is still a dictionary, I am not able to comprehend why this error is being rendered.
I have also added the structure of my schema and API below:
class MySchema(marshmallow.Schema):
id = fields.Integer(required=True)
second = fields.Integer(fields.Integer(), required=True)
first = fields.List(fields.String(), required=False)
third = fields.Str(validate=validate.Length(min=0, max=255), required=False)
class Meta:
fields = ('id',
'second',
'first',
'third')
#validates_schema(pass_original=True)
def validate_numbers(self, _, data):
//function code
The below is the structure of my API
class MyView(V1FlaskView):
#jwt_requried
def post(id):
//code
Maybe a space character is missing after Bearer:
'Authorization': 'Bearer {}'.format(token),

How to add modifiers to cart line item in BigCommerce Api

I already tried the solution given in this Cart API V3: Can't create a Cart for product that has options link but it's not working for me.
modifier is extra fitting added to the product like "name tag" for suitcase.
I tried to add the modifier in "option_selections" like below but it returns 422 error.
Request:
{
"quantity":"1",
"product_id":"5846",
"variant_id":150922,
"list_price":" 170.00",
"option_selections":[{"option_id":23800, "option_value":"10088"}]
}
Response:
StatusCode: 422, ReasonPhrase: 'Unprocessable Entity'
Thanks for your reply in advance.
If you're creating a new cart, try this request body (POST to /carts endpoint):
{
"line_items": [
{
"quantity": 1,
"product_id": 76,
"list_price": 170.00,
"option_selections": [
{
"option_id": 21506,
"option_value": 10090
}
]
}
]
}
You shouldn't have quotes around any of these field values--list_price, product_id, etc all accept a number, not a string.
If you want to add a new line item to an existing cart, you can use the same request body as above. The request will be a POST to carts/{cartID}/items
EDIT:
If you are updating a line item that already exists in the cart, you'll want to make a PUT to /carts/{cartID}/items/{itemID}.
Request body:
{
"line_item": {
"quantity": 1,
"product_id": 76,
"list_price": 170.00,
"option_selections": [
{
"option_id": 21506,
"option_value": 10090
}
]
}
}
Note: it does need to be "line_item" rather than "line_items" when updating a single cart item. I'll work with our documentation team to get this updated in the API reference.
I was able to solve the issue, though I agree with Karen White's answer, I wanted to add a product which has options like colors and modifiers too. Which I was not able to achieve with that. I used the following data to add product with option and modifier.
Instead of passing variant_id, pass variant as option (option_id gets option's id and option_value gets option value's id) and pass modifier as option (modifier option_id gets option's id and option_value gets option value's id)
{
"line_items": [{
"quantity": 1,
"product_id": 5846,
"option_selections": [{
"option_id": 23799,
"option_value": 10173
}, {
"option_id": 23800,
"option_value": 10088
}]
}]
}

How can I combine a warning message and update field value inside of onchange method? In odoo 9

In older versions of odoo (openerp 7), I used to do things like this:
#api.multi
#api.onchange('my_field')
def my_field_change(self, cr, uid, partner_ids, context=None):
if condition is True:
return {
'warning': {'title': _('Error'), 'message': _('Error message'),},
'value': { 'my_field': new_value },
}
If I want to do this in odoo 9, I have this code:
#api.multi
#api.onchange('my_field')
def my_field_change(self):
if condition is True:
return {
'warning': {'title': _('Error'), 'message': _('Error message'),},
'value': { 'my_field': new_value },
}
The warning window is displayed but the value field is ignored.
How can I change the value of the field?
In odoo Onchange method, you can't return value same as older version of odoo.
Onchange method will only return Warning and Domain.
#api.multi
#api.onchange('my_field')
def my_field_change(self):
self.field=value
return {
'warning': {'title': _('Error'), 'message': _('Error message'),},
}
In Odoo new api no need to return value in dict just assign value in relevant field.
Ex: sale.field=value
This may help you.

when I write Orm Query to get all project.project data to pass it to webKit report

when I write Orm Query to get all project.project data to pass it to webKit report I get this error :
TypeError: browse_record(project.project, 1) is not JSON serializable
and this my code:
def print_report(self, cr, uid, ids, context=None):
# assert len(ids) == 1
project_obj=self.pool.get("project.project")
project_ids=project_obj.search(cr,uid,[('analytic_account_id','!=',-1)])
data = project_obj.browse(cr, uid, project_ids)
return {'type': 'ir.actions.report.xml',
'report_name': 'taskmng.report',
'datas': data}
Problem is that you must pass three things: list of ids, object name, dictionary which contains data.
In your case try this:
datas = {
'ids': project_ids,
'model': 'project.project',
'form': {}
}
return {
'type': 'ir.actions.report.xml',
'report_name': 'taskmng.report',
'datas': datas
}