<commit_before># -*- coding: utf-8 -*-
from logging import getLogger
from openprocurement.api.utils import (
    apply_patch,
    save_tender,
    check_tender_status,
    opresource,
    json_view,
    context_unpack,
)
from openprocurement.tender.openeu.validation import validate_patch_qualification_data

LOGGER = getLogger(__name__)

@opresource(name='TenderEU Qualification',
            collection_path='/tenders/{tender_id}/qualifications',
            path='/tenders/{tender_id}/qualifications/{qualification_id}',
            procurementMethodType='aboveThresholdEU',
            description="TenderEU Qualification")
class TenderQualificationResource(object):

    def __init__(self, request, context):
        self.request = request
        self.db = request.registry.db

    @json_view(permission='view_tender')
    def collection_get(self):
        """List qualifications
        """
        return {'data': [i.serialize("view") for i in self.request.validated['tender'].qualifications]}

    @json_view(permission='view_tender')
    def get(self):
        """Retrieving the qualification
        """
        return {'data': self.request.validated['qualification'].serialize("view")}

    @json_view(content_type="application/json", validators=(validate_patch_qualification_data,), permission='edit_tender')
    def patch(self):
        """Post a qualification resolution
        """
        def set_bid_status(tender, bid_id, status):
            for bid in tender.bids:
                if bid.id == bid_id:
                    bid.status = status
                    return

        tender = self.request.validated['tender']
        if tender.status not in ['active.pre-qualification']:
            self.request.errors.add('body', 'data', 'Can\'t update qualification in current ({}) tender status'.format(tender.status))
            self.request.errors.status = 403
            return

        apply_patch(self.request, save=False, src=self.request.context.serialize())
        if self.request.context.status == 'active':
            # approve related bid
            set_bid_status(tender, self.request.context.bidID, 'active')
        elif self.request.context.status == 'cancelled':
            # cancel related bid
            set_bid_status(tender, self.request.context.bidID, 'invalid')
        # switch to 'stand-still' when all bids are approved
        if all([bid.status != 'pending' for bid in tender.bids]):
            tender.status = 'active.pre-qualification.stand-still'

        if save_tender(self.request):
            LOGGER.info('Updated tender qualification {}'.format(self.request.context.id),
                        extra=context_unpack(self.request, {'MESSAGE_ID': 'tender_qualification_patch'}))
            return {'data': self.request.context.serialize("view")}
<commit_msg>invalidate tender when too few bidders left<commit_after># -*- coding: utf-8 -*-
from logging import getLogger
from openprocurement.api.utils import (
    apply_patch,
    save_tender,
    check_tender_status,
    opresource,
    json_view,
    context_unpack,
)
from openprocurement.tender.openeu.validation import validate_patch_qualification_data

LOGGER = getLogger(__name__)

@opresource(name='TenderEU Qualification',
            collection_path='/tenders/{tender_id}/qualifications',
            path='/tenders/{tender_id}/qualifications/{qualification_id}',
            procurementMethodType='aboveThresholdEU',
            description="TenderEU Qualification")
class TenderQualificationResource(object):

    def __init__(self, request, context):
        self.request = request
        self.db = request.registry.db

    @json_view(permission='view_tender')
    def collection_get(self):
        """List qualifications
        """
        return {'data': [i.serialize("view") for i in self.request.validated['tender'].qualifications]}

    @json_view(permission='view_tender')
    def get(self):
        """Retrieving the qualification
        """
        return {'data': self.request.validated['qualification'].serialize("view")}

    @json_view(content_type="application/json", validators=(validate_patch_qualification_data,), permission='edit_tender')
    def patch(self):
        """Post a qualification resolution
        """
        def set_bid_status(tender, bid_id, status):
            for bid in tender.bids:
                if bid.id == bid_id:
                    bid.status = status
                    return

        tender = self.request.validated['tender']
        if tender.status not in ['active.pre-qualification']:
            self.request.errors.add('body', 'data', 'Can\'t update qualification in current ({}) tender status'.format(tender.status))
            self.request.errors.status = 403
            return

        apply_patch(self.request, save=False, src=self.request.context.serialize())
        if self.request.context.status == 'active':
            # approve related bid
            set_bid_status(tender, self.request.context.bidID, 'active')
        elif self.request.context.status == 'cancelled':
            # cancel related bid
            set_bid_status(tender, self.request.context.bidID, 'invalid')
        # switch to 'stand-still' when all bids are approved
        if all([bid.status != 'pending' for bid in tender.bids]):
            if sum([1 for bid in tender.bids if bid.status == 'active']) < 2:
                tender.status = 'unsuccessful'
            else:
                tender.status = 'active.pre-qualification.stand-still'
        if save_tender(self.request):
            LOGGER.info('Updated tender qualification {}'.format(self.request.context.id),
                        extra=context_unpack(self.request, {'MESSAGE_ID': 'tender_qualification_patch'}))
            return {'data': self.request.context.serialize("view")}
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""Module to make asynchronous API calls.

.. moduleauthor:: Jiwen Xin <kevinxin@scripps.edu>

"""

import asyncio
from aiohttp import ClientSession, TCPConnector
from collections import Counter
import json
from .utils.common import add_s

class BioThingsCaller:
    """Call biothings APIs."""

    @staticmethod
    def print_request(method, url, params, request_body):
        if params:
            url += "?"
            params = [(str(m) + "=" + str(n)) for m, n in params.items()]
            url += "&".join(params)
        if method == "get":
            return url
        if method == "post":
            if request_body:
                url += " (POST -d "
                request_body = [
                    (str(m) + "=" + str(n)) for m, n in request_body.items()
                ]
                url += "&".join(request_body)
                url += ")"
            return url
        return ""

    async def call_one_arbitrary_api(self, _input, session, verbose=False):
        base_url = (
            _input["operation"]["server"].strip("/") + _input["operation"]["path"]
        )
        method = _input["operation"]["method"]
        request_body = _input["operation"].get("requestBody")
        header = {"content-type": "application/x-www-form-urlencoded"}
        if request_body:
            if request_body.get("header"):
                header = {"content-type": request_body.get("header")}
            request_body = eval(
                str(request_body["body"]).replace("{inputs[0]}", _input["value"])
            )
        parameters = _input["operation"].get("parameters")
        if parameters:
            if _input["operation"].get("path_params"):
                for path_param in _input["operation"]["path_params"]:
                    path_value_template = parameters.get(path_param)
                    base_url = base_url.replace(
                        "{" + path_param + "}", path_value_template
                    ).replace("{inputs[0]}", _input["value"])
                    parameters.pop(path_param)
            parameters = eval(str(parameters).replace("{inputs[0]}", _input["value"]))
        query_url = self.print_request(method, base_url, parameters, request_body)
        if method == "get":
            await asyncio.sleep(1)
            try:
                async with session.get(base_url, params=parameters) as res:
                    if verbose:
                        print("{}: {}".format(_input["internal_query_id"], query_url))
                    try:
                        if res.status in [400, 404]:
                            print(
                                "{} {} failed".format(
                                    _input["internal_query_id"], _input["api"]
                                )
                            )
                            return {
                                "internal_query_id": _input["internal_query_id"],
                                "result": {},
                            }
                        res = await res.json()
                        return {
                            "internal_query_id": _input["internal_query_id"],
                            "result": res,
                        }
                    except Exception as ex:
                        m = await res.text()
                        return {
                            "result": json.loads(m),
                            "internal_query_id": _input["internal_query_id"],
                        }
            except Exception:
                if verbose:
                    print(
                        "{} {} failed".format(
                            _input["internal_query_id"], _input["api"]
                        )
                    )
                return {"internal_query_id": _input["internal_query_id"], "result": {}}
        elif method == "post":
            await asyncio.sleep(1)
            try:
                async with session.post(
                    base_url, params=parameters, data=request_body, headers=header
                ) as res:
                    try:
                        if res.status in [400, 404]:
                            print(
                                "{} {} failed".format(
                                    _input["internal_query_id"], _input["api"]
                                )
                            )
                            return {
                                "internal_query_id": _input["internal_query_id"],
                                "result": {},
                            }
                        if verbose:
                            print(
                                "{}: {}".format(_input["internal_query_id"], query_url)
                            )
                        return {
                            "result": await res.json(),
                            "internal_query_id": _input["internal_query_id"],
                        }
                    except Exception as ex1:
                        print(ex1)
                        print("Unable to fetch results from {}".format(_input["api"]))
                        return {
                            "internal_query_id": _input["internal_query_id"],
                            "result": {},
                        }
            except Exception as ex:
                print(ex)
                if verbose:
                    print(
                        "{}: {} failed".format(
                            _input["internal_query_id"], _input["api"]
                        )
                    )
                return {"result": {}, "internal_query_id": _input["internal_query_id"]}

    async def call_one_api(self, _input, session, verbose=False):
        """Asynchronously make one API call.

        :param: _input (dict) : a python dict containing three keys, e.g. batch_mode, params, api
        :param: session (obj): a aiohttp session object
        """
        # check api type
        res = await self.call_one_arbitrary_api(_input, session, verbose=verbose)
        return res

    async def run(self, inputs, verbose=False):
        """Asynchronously make a list of API calls.

        :param: inputs (list): list of python dicts containing three keys
        """
        tasks = []
        # timeout = ClientTimeout(total=15)
        async with ClientSession(connector=TCPConnector(ssl=False)) as session:
            for i in inputs:
                task = self.call_one_api(i, session, verbose=verbose)
                tasks.append(task)
            responses = await asyncio.gather(*tasks)
            # print(responses)
            return responses

    def call_apis(self, inputs, verbose=False, loop=None):

        self.log = []
        if verbose:
            cnt = Counter()
            if inputs:
                for _input in inputs:
                    cnt[_input["api"]] += 1
            self.unique_apis = {_edge["api"] for _edge in inputs if _edge}
            if verbose:
                print("\nBTE found {} apis:\n".format(len(self.unique_apis)))
                for i, _api in enumerate(self.unique_apis):
                    print(
                        "API {}. {}({} API call{})".format(
                            i + 1, _api, cnt[_api], add_s(cnt[_api])
                        )
                    )
            self.log.append("\nBTE found {} apis:\n".format(len(self.unique_apis)))
            for i, _api in enumerate(self.unique_apis):
                self.log.append(
                    "API {}. {}({} API call{})".format(
                        i + 1, _api, cnt[_api], add_s(cnt[_api])
                    )
                )
            print("\n\n==== Step #2: Query path execution ====")
            self.log.append("\n\n==== Step #2: Query path execution ====")
            print(
                "NOTE: API requests are dispatched in parallel, so the list of APIs below is ordered by query time.\n"
            )
            self.log.append(
                "NOTE: API requests are dispatched in parallel, so the list of APIs below is ordered by query time.\n"
            )
        if not loop:
            loop = asyncio.new_event_loop()
        return (loop.run_until_complete(self.run(inputs, verbose=verbose)), self.log)
        # res = asyncio.run(self.run(inputs, verbose=verbose))
        # return (res, self.log)
<commit_msg>troubleshooting<commit_after># -*- coding: utf-8 -*-
"""Module to make asynchronous API calls.

.. moduleauthor:: Jiwen Xin <kevinxin@scripps.edu>

"""

import asyncio
from aiohttp import ClientSession, TCPConnector
from collections import Counter
import json
from .utils.common import add_s

class BioThingsCaller:
    """Call biothings APIs."""

    @staticmethod
    def print_request(method, url, params, request_body):
        if params:
            url += "?"
            params = [(str(m) + "=" + str(n)) for m, n in params.items()]
            url += "&".join(params)
        if method == "get":
            return url
        if method == "post":
            if request_body:
                url += " (POST -d "
                request_body = [
                    (str(m) + "=" + str(n)) for m, n in request_body.items()
                ]
                url += "&".join(request_body)
                url += ")"
            return url
        return ""

    async def call_one_arbitrary_api(self, _input, session, verbose=False):
        counter = 0;
        base_url = (
            _input["operation"]["server"].strip("/") + _input["operation"]["path"]
        )
        method = _input["operation"]["method"]
        request_body = _input["operation"].get("requestBody")
        header = {"content-type": "application/x-www-form-urlencoded"}
        if request_body:
            if request_body.get("header"):
                header = {"content-type": request_body.get("header")}
            request_body = eval(
                str(request_body["body"]).replace("{inputs[0]}", _input["value"])
            )
        parameters = _input["operation"].get("parameters")
        if parameters:
            if _input["operation"].get("path_params"):
                for path_param in _input["operation"]["path_params"]:
                    path_value_template = parameters.get(path_param)
                    base_url = base_url.replace(
                        "{" + path_param + "}", path_value_template
                    ).replace("{inputs[0]}", _input["value"])
                    parameters.pop(path_param)
            parameters = eval(str(parameters).replace("{inputs[0]}", _input["value"]))
        query_url = self.print_request(method, base_url, parameters, request_body)
        if("mychem.info" in query_url):
            print("OMMMMGGGG")
            print(counter)
        if method == "get":
            try:
                async with session.get(base_url, params=parameters) as res:
                    if verbose:
                        print("{}: {}".format(_input["internal_query_id"], query_url))
                    try:
                        if res.status in [400, 404]:
                            print(
                                "{} {} failed".format(
                                    _input["internal_query_id"], _input["api"]
                                )
                            )
                            return {
                                "internal_query_id": _input["internal_query_id"],
                                "result": {},
                            }
                        res = await res.json()
                        return {
                            "internal_query_id": _input["internal_query_id"],
                            "result": res,
                        }
                    except Exception as ex:
                        m = await res.text()
                        return {
                            "result": json.loads(m),
                            "internal_query_id": _input["internal_query_id"],
                        }
            except Exception:
                if verbose:
                    print(
                        "{} {} failed".format(
                            _input["internal_query_id"], _input["api"]
                        )
                    )
                return {"internal_query_id": _input["internal_query_id"], "result": {}}
        elif method == "post":
            try:
                async with session.post(
                    base_url, params=parameters, data=request_body, headers=header
                ) as res:
                    try:
                        if res.status in [400, 404]:
                            print(
                                "{} {} failed".format(
                                    _input["internal_query_id"], _input["api"]
                                )
                            )
                            return {
                                "internal_query_id": _input["internal_query_id"],
                                "result": {},
                            }
                        if verbose:
                            print(
                                "{}: {}".format(_input["internal_query_id"], query_url)
                            )
                        return {
                            "result": await res.json(),
                            "internal_query_id": _input["internal_query_id"],
                        }
                    except Exception as ex1:
                        print(ex1)
                        print("Unable to fetch results from {}".format(_input["api"]))
                        return {
                            "internal_query_id": _input["internal_query_id"],
                            "result": {},
                        }
            except Exception as ex:
                print(ex)
                if verbose:
                    print(
                        "{}: {} failed".format(
                            _input["internal_query_id"], _input["api"]
                        )
                    )
                return {"result": {}, "internal_query_id": _input["internal_query_id"]}

    async def call_one_api(self, _input, session, verbose=False):
        """Asynchronously make one API call.

        :param: _input (dict) : a python dict containing three keys, e.g. batch_mode, params, api
        :param: session (obj): a aiohttp session object
        """
        # check api type
        res = await self.call_one_arbitrary_api(_input, session, verbose=verbose)
        return res

    async def run(self, inputs, verbose=False):
        """Asynchronously make a list of API calls.

        :param: inputs (list): list of python dicts containing three keys
        """
        tasks = []
        # timeout = ClientTimeout(total=15)
        async with ClientSession(connector=TCPConnector(ssl=False)) as session:
            for i in inputs:
                task = self.call_one_api(i, session, verbose=verbose)
                tasks.append(task)
            responses = await asyncio.gather(*tasks)
            # print(responses)
            return responses

    def call_apis(self, inputs, verbose=False, loop=None):

        self.log = []
        if verbose:
            cnt = Counter()
            if inputs:
                for _input in inputs:
                    cnt[_input["api"]] += 1
            self.unique_apis = {_edge["api"] for _edge in inputs if _edge}
            if verbose:
                print("\nBTE found {} apis:\n".format(len(self.unique_apis)))
                for i, _api in enumerate(self.unique_apis):
                    print(
                        "API {}. {}({} API call{})".format(
                            i + 1, _api, cnt[_api], add_s(cnt[_api])
                        )
                    )
            self.log.append("\nBTE found {} apis:\n".format(len(self.unique_apis)))
            for i, _api in enumerate(self.unique_apis):
                self.log.append(
                    "API {}. {}({} API call{})".format(
                        i + 1, _api, cnt[_api], add_s(cnt[_api])
                    )
                )
            print("\n\n==== Step #2: Query path execution ====")
            self.log.append("\n\n==== Step #2: Query path execution ====")
            print(
                "NOTE: API requests are dispatched in parallel, so the list of APIs below is ordered by query time.\n"
            )
            self.log.append(
                "NOTE: API requests are dispatched in parallel, so the list of APIs below is ordered by query time.\n"
            )
        if not loop:
            loop = asyncio.new_event_loop()
        return (loop.run_until_complete(self.run(inputs, verbose=verbose)), self.log)
        # res = asyncio.run(self.run(inputs, verbose=verbose))
        # return (res, self.log)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""Module to make asynchronous API calls.

.. moduleauthor:: Jiwen Xin <kevinxin@scripps.edu>

"""

import asyncio
from aiohttp import ClientSession, TCPConnector
from collections import Counter
import json
from .utils.common import add_s
import requests

class BioThingsCaller:
    """Call biothings APIs."""

    @staticmethod
    def print_request(method, url, params, request_body):
        if params:
            url += "?"
            params = [(str(m) + "=" + str(n)) for m, n in params.items()]
            url += "&".join(params)
        if method == "get":
            return url
        if method == "post":
            if request_body:
                url += " (POST -d "
                request_body = [
                    (str(m) + "=" + str(n)) for m, n in request_body.items()
                ]
                url += "&".join(request_body)
                url += ")"
            return url
        return ""

    async def call_one_arbitrary_api(self, _input, session, verbose=False):
        base_url = (
            _input["operation"]["server"].strip("/") + _input["operation"]["path"]
        )
        method = _input["operation"]["method"]
        request_body = _input["operation"].get("requestBody")
        header = {"content-type": "application/x-www-form-urlencoded"}
        if request_body:
            if request_body.get("header"):
                header = {"content-type": request_body.get("header")}
            request_body = eval(
                str(request_body["body"]).replace("{inputs[0]}", _input["value"])
            )
        parameters = _input["operation"].get("parameters")
        if parameters:
            if _input["operation"].get("path_params"):
                for path_param in _input["operation"]["path_params"]:
                    path_value_template = parameters.get(path_param)
                    base_url = base_url.replace(
                        "{" + path_param + "}", path_value_template
                    ).replace("{inputs[0]}", _input["value"])
                    parameters.pop(path_param)
            parameters = eval(str(parameters).replace("{inputs[0]}", _input["value"]))
        query_url = self.print_request(method, base_url, parameters, request_body)
        if method == "get":
            try:
                async with session.get(base_url, params=parameters) as res:
                    if verbose:
                        print("{}: {}".format(_input["internal_query_id"], query_url))
                    try:
                        if res.status in [400, 404]:
                            print(
                                "{} {} failed".format(
                                    _input["internal_query_id"], _input["api"]
                                )
                            )
                            return {
                                "internal_query_id": _input["internal_query_id"],
                                "result": {},
                            }
                        res = await res.json()
                        return {
                            "internal_query_id": _input["internal_query_id"],
                            "result": res,
                        }
                    except Exception as ex:
                        m = await res.text()
                        return {
                            "result": json.loads(m),
                            "internal_query_id": _input["internal_query_id"],
                        }
            except Exception:
                if verbose:
                    print(
                        "{} {} failed".format(
                            _input["internal_query_id"], _input["api"]
                        )
                    )
                return {"internal_query_id": _input["internal_query_id"], "result": {}}
        elif method == "post":
            if("mychem.info" not in base_url):
                try:
                    async with session.post(
                        base_url, params=parameters, data=request_body, headers=header
                    ) as res:
                        try:
                            if res.status in [400, 404]:
                                print(
                                    "{} {} failed".format(
                                        _input["internal_query_id"], _input["api"]
                                    )
                                )
                                return {
                                    "internal_query_id": _input["internal_query_id"],
                                    "result": {},
                                }
                            if verbose:
                                print(
                                    "{}: {}".format(_input["internal_query_id"], query_url)
                                )
                            return {
                                "result": await res.json(),
                                "internal_query_id": _input["internal_query_id"],
                            }
                        except Exception as ex1:
                            print(ex1)
                            print("Unable to fetch results from {}".format(_input["api"]))
                            return {
                                "internal_query_id": _input["internal_query_id"],
                                "result": {},
                            }
                except Exception as ex:
                    print(ex)
                    if verbose:
                        print(
                            "{}: {} failed".format(
                                _input["internal_query_id"], _input["api"]
                            )
                        )
                    return {"result": {}, "internal_query_id": _input["internal_query_id"]}
            else:
                await asyncio.sleep(5)
                res = requests.post(base_url, params=parameters, data=request_body, headers=header)
                print("RES JSON")
                print(res.json())
                try:
                    return {
                        "result": res.json(),
                        "internal_query_id": _input["internal_query_id"]
                    }
                except Exception as ex1:
                    print(ex1)
                    print("Unable to fetch results from {}".format(_input["api"]))
                    return {
                        "internal_query_id": _input["internal_query_id"],
                        "result": {},
                    }

                # try:
                #     if res.status in [400, 404]:
                #         print(
                #             "{} {} failed".format(
                #                 _input["internal_query_id"], _input["api"]
                #             )
                #         )
                #         return {
                #             "internal_query_id": _input["internal_query_id"],
                #             "result": {},
                #         }
                #     if verbose:
                #         print(
                #             "{}: {}".format(_input["internal_query_id"], query_url)
                #         )

                # except Exception as ex1:
                #     print(ex1)
                #     print("Unable to fetch results from {}".format(_input["api"]))
                #     return {
                #         "internal_query_id": _input["internal_query_id"],
                #         "result": {},
                #     }
                # print("WADDUP")
                # print(res)

    async def call_one_api(self, _input, session, verbose=False):
        """Asynchronously make one API call.

        :param: _input (dict) : a python dict containing three keys, e.g. batch_mode, params, api
        :param: session (obj): a aiohttp session object
        """
        # check api type
        res = await self.call_one_arbitrary_api(_input, session, verbose=verbose)
        return res

    async def run(self, inputs, verbose=False):
        """Asynchronously make a list of API calls.

        :param: inputs (list): list of python dicts containing three keys
        """
        tasks = []
        # timeout = ClientTimeout(total=15)
        async with ClientSession(connector=TCPConnector(ssl=False)) as session:
            for i in inputs:
                task = self.call_one_api(i, session, verbose=verbose)
                tasks.append(task)
            responses = await asyncio.gather(*tasks)
            # print(responses)
            return responses

    def call_apis(self, inputs, verbose=False, loop=None):

        self.log = []
        if verbose:
            cnt = Counter()
            if inputs:
                for _input in inputs:
                    cnt[_input["api"]] += 1
            self.unique_apis = {_edge["api"] for _edge in inputs if _edge}
            if verbose:
                print("\nBTE found {} apis:\n".format(len(self.unique_apis)))
                for i, _api in enumerate(self.unique_apis):
                    print(
                        "API {}. {}({} API call{})".format(
                            i + 1, _api, cnt[_api], add_s(cnt[_api])
                        )
                    )
            self.log.append("\nBTE found {} apis:\n".format(len(self.unique_apis)))
            for i, _api in enumerate(self.unique_apis):
                self.log.append(
                    "API {}. {}({} API call{})".format(
                        i + 1, _api, cnt[_api], add_s(cnt[_api])
                    )
                )
            print("\n\n==== Step #2: Query path execution ====")
            self.log.append("\n\n==== Step #2: Query path execution ====")
            print(
                "NOTE: API requests are dispatched in parallel, so the list of APIs below is ordered by query time.\n"
            )
            self.log.append(
                "NOTE: API requests are dispatched in parallel, so the list of APIs below is ordered by query time.\n"
            )
        if not loop:
            loop = asyncio.new_event_loop()
        return (loop.run_until_complete(self.run(inputs, verbose=verbose)), self.log)
        # res = asyncio.run(self.run(inputs, verbose=verbose))
        # return (res, self.log)
<commit_msg>idk anymore<commit_after># -*- coding: utf-8 -*-
"""Module to make asynchronous API calls.

.. moduleauthor:: Jiwen Xin <kevinxin@scripps.edu>

"""

import asyncio
from aiohttp import ClientSession, TCPConnector
from collections import Counter
import json
from .utils.common import add_s
import requests

class BioThingsCaller:
    """Call biothings APIs."""

    @staticmethod
    def print_request(method, url, params, request_body):
        if params:
            url += "?"
            params = [(str(m) + "=" + str(n)) for m, n in params.items()]
            url += "&".join(params)
        if method == "get":
            return url
        if method == "post":
            if request_body:
                url += " (POST -d "
                request_body = [
                    (str(m) + "=" + str(n)) for m, n in request_body.items()
                ]
                url += "&".join(request_body)
                url += ")"
            return url
        return ""

    async def call_one_arbitrary_api(self, _input, session, verbose=False):
        base_url = (
            _input["operation"]["server"].strip("/") + _input["operation"]["path"]
        )
        method = _input["operation"]["method"]
        request_body = _input["operation"].get("requestBody")
        header = {"content-type": "application/x-www-form-urlencoded"}
        if request_body:
            if request_body.get("header"):
                header = {"content-type": request_body.get("header")}
            request_body = eval(
                str(request_body["body"]).replace("{inputs[0]}", _input["value"])
            )
        parameters = _input["operation"].get("parameters")
        if parameters:
            if _input["operation"].get("path_params"):
                for path_param in _input["operation"]["path_params"]:
                    path_value_template = parameters.get(path_param)
                    base_url = base_url.replace(
                        "{" + path_param + "}", path_value_template
                    ).replace("{inputs[0]}", _input["value"])
                    parameters.pop(path_param)
            parameters = eval(str(parameters).replace("{inputs[0]}", _input["value"]))
        query_url = self.print_request(method, base_url, parameters, request_body)
        if method == "get":
            try:
                async with session.get(base_url, params=parameters) as res:
                    if verbose:
                        print("{}: {}".format(_input["internal_query_id"], query_url))
                    try:
                        if res.status in [400, 404]:
                            print(
                                "{} {} failed".format(
                                    _input["internal_query_id"], _input["api"]
                                )
                            )
                            return {
                                "internal_query_id": _input["internal_query_id"],
                                "result": {},
                            }
                        res = await res.json()
                        return {
                            "internal_query_id": _input["internal_query_id"],
                            "result": res,
                        }
                    except Exception as ex:
                        m = await res.text()
                        return {
                            "result": json.loads(m),
                            "internal_query_id": _input["internal_query_id"],
                        }
            except Exception:
                if verbose:
                    print(
                        "{} {} failed".format(
                            _input["internal_query_id"], _input["api"]
                        )
                    )
                return {"internal_query_id": _input["internal_query_id"], "result": {}}
        elif method == "post":
            if("mychem.info" not in base_url):
                print("NOT MYCHEM RESULT")
                try:
                    async with session.post(
                        base_url, params=parameters, data=request_body, headers=header
                    ) as res:
                        try:
                            if res.status in [400, 404]:
                                print(
                                    "{} {} failed".format(
                                        _input["internal_query_id"], _input["api"]
                                    )
                                )
                                return {
                                    "internal_query_id": _input["internal_query_id"],
                                    "result": {},
                                }
                            if verbose:
                                print(
                                    "{}: {}".format(_input["internal_query_id"], query_url)
                                )
                            return {
                                "result": await res.json(),
                                "internal_query_id": _input["internal_query_id"],
                            }
                        except Exception as ex1:
                            print(ex1)
                            print("Unable to fetch results from {}".format(_input["api"]))
                            return {
                                "internal_query_id": _input["internal_query_id"],
                                "result": {},
                            }
                except Exception as ex:
                    print(ex)
                    if verbose:
                        print(
                            "{}: {} failed".format(
                                _input["internal_query_id"], _input["api"]
                            )
                        )
                    return {"result": {}, "internal_query_id": _input["internal_query_id"]}
            else:
                print("MYCHEM RESULT")
                res = requests.post(base_url, params=parameters, data=request_body, headers=header)
                # print("RES JSON")
                # print(res.json())
                try:
                    return {
                        "result": res.json(),
                        "internal_query_id": _input["internal_query_id"]
                    }
                except Exception as ex1:
                    print(ex1)
                    print("Unable to fetch results from {}".format(_input["api"]))
                    return {
                        "internal_query_id": _input["internal_query_id"],
                        "result": {},
                    }

                # try:
                #     if res.status in [400, 404]:
                #         print(
                #             "{} {} failed".format(
                #                 _input["internal_query_id"], _input["api"]
                #             )
                #         )
                #         return {
                #             "internal_query_id": _input["internal_query_id"],
                #             "result": {},
                #         }
                #     if verbose:
                #         print(
                #             "{}: {}".format(_input["internal_query_id"], query_url)
                #         )

                # except Exception as ex1:
                #     print(ex1)
                #     print("Unable to fetch results from {}".format(_input["api"]))
                #     return {
                #         "internal_query_id": _input["internal_query_id"],
                #         "result": {},
                #     }
                # print("WADDUP")
                # print(res)

    async def call_one_api(self, _input, session, verbose=False):
        """Asynchronously make one API call.

        :param: _input (dict) : a python dict containing three keys, e.g. batch_mode, params, api
        :param: session (obj): a aiohttp session object
        """
        # check api type
        res = await self.call_one_arbitrary_api(_input, session, verbose=verbose)
        return res

    async def run(self, inputs, verbose=False):
        """Asynchronously make a list of API calls.

        :param: inputs (list): list of python dicts containing three keys
        """
        tasks = []
        # timeout = ClientTimeout(total=15)
        async with ClientSession(connector=TCPConnector(ssl=False)) as session:
            for i in inputs:
                task = self.call_one_api(i, session, verbose=verbose)
                tasks.append(task)
            responses = await asyncio.gather(*tasks)
            # print(responses)
            return responses

    def call_apis(self, inputs, verbose=False, loop=None):

        self.log = []
        if verbose:
            cnt = Counter()
            if inputs:
                for _input in inputs:
                    cnt[_input["api"]] += 1
            self.unique_apis = {_edge["api"] for _edge in inputs if _edge}
            if verbose:
                print("\nBTE found {} apis:\n".format(len(self.unique_apis)))
                for i, _api in enumerate(self.unique_apis):
                    print(
                        "API {}. {}({} API call{})".format(
                            i + 1, _api, cnt[_api], add_s(cnt[_api])
                        )
                    )
            self.log.append("\nBTE found {} apis:\n".format(len(self.unique_apis)))
            for i, _api in enumerate(self.unique_apis):
                self.log.append(
                    "API {}. {}({} API call{})".format(
                        i + 1, _api, cnt[_api], add_s(cnt[_api])
                    )
                )
            print("\n\n==== Step #2: Query path execution ====")
            self.log.append("\n\n==== Step #2: Query path execution ====")
            print(
                "NOTE: API requests are dispatched in parallel, so the list of APIs below is ordered by query time.\n"
            )
            self.log.append(
                "NOTE: API requests are dispatched in parallel, so the list of APIs below is ordered by query time.\n"
            )
        if not loop:
            loop = asyncio.new_event_loop()
        return (loop.run_until_complete(self.run(inputs, verbose=verbose)), self.log)
        # res = asyncio.run(self.run(inputs, verbose=verbose))
        # return (res, self.log)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Addons modules by CLEARCORP S.A.
#    Copyright (C) 2009-TODAY CLEARCORP S.A. (<http://clearcorp.co.cr>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

import pooler
from openerp.report import report_sxw
from openerp.tools.translate import _
from openerp.addons.account_report_lib.account_report_base import accountReportbase
from numpy.ma.core import ids

class Parser(accountReportbase):

    def __init__(self, cr, uid, name, context):
        super(Parser, self).__init__(cr, uid, name, context=context)
        self.pool = pooler.get_pool(self.cr.dbname)
        self.cursor = self.cr

        self.localcontext.update({
           'cr' : cr,
           'uid': uid,
           'storage':{},
           'display_taxes':self.display_taxes,
           'set_currency_name':self.set_currency_name,
           'get_order_taxes':self.get_order_taxes,
           'get_tax_name': self.get_tax_name,
           'get_data_block_tax': self.get_data_block_tax,
           'compute_total_block':self.compute_total_block,
           'check_inv_tax': self.check_inv_tax,
        })

    #---------SET AND GET DATA ----------#
    # Get taxes from wizard
    def get_taxes(self, data):
        return self._get_info(data,'account_tax_ids', 'account.tax')

    #Get taxes order by name
    def get_order_taxes(self, data):
        taxes_ids = []

        if not self.get_taxes(data):
            taxes_ids = self.pool.get('account.tax').search(self.cr, self.uid, [], order="name ASC")
            return self.pool.get('account.tax').browse(self.cr, self.uid, taxes_ids)
        else:
           return self.get_taxes(data) #browse record list

    #Extract ids from taxes
    def get_taxes_ids(self, data):
        ids = []
        if self.get_taxes(data):
            for tax in self.get_taxes(data):
                ids.append(tax.id)
        return ids

    def get_tax_name(self, tax_id):
        name = ''
        tax = self.pool.get('account.tax').browse(self.cr, self.uid, tax_id)

        if tax.type == 'percent' or tax.type == 'fixed':
            tax_amount = 100 * tax.amount
            name = tax.name + ' - ' + str(tax_amount) + '%'
        else:
            name = tax.name

        return name

    def set_currency_name(self, currency_id):
        currency = self.pool.get('res.currency').browse(self.cr, self.uid, currency_id)
        return currency.name

    def check_inv_tax(self):
        if self.get_data_template('res'):
            return True
        else:
            return False

    #================ DISPLAY DATA ===========================#
    def display_taxes(self, data):
       name = ''

       if not self.get_taxes(data): #It means that non-one was selected
           return _('All taxes')
       else:
           taxes = self.get_taxes(data)
           for tax in taxes:
               name += tax.name + ', '
           return name

    #========= BUILD DATA
    def get_invoices(self, tax_id, data):
        account_invoice_obj = self.pool.get('account.invoice')
        result={}
        domain = []

        date_from = self.get_date_from(data)
        date_to = self.get_date_to(data)
        domain.append(('date_invoice', '>=', date_from))
        domain.append(('date_invoice', '<=', date_to))

        tuple = ('invoice_line.invoice_line_tax_id', 'in', tax_id)
        domain.append(tuple)

        tuple = ('state', '!=', 'draft')
        domain.append(tuple)

        invoices_ids = account_invoice_obj.search(self.cr, self.uid, domain, context=None)
        invoices_obj = account_invoice_obj.browse(self.cr, self.uid, invoices_ids, context=None)

        return invoices_obj

    """
        1. Create a structure like this:
            tax_block[tax_id] = {} (invoices)

            Then invoices is a dictionary, where key is id invoice and each key
            has a list with lines that its tax match with tax_id that is passed
            as a parameter

            So, iterate dictionary like this

            for tax_id, invoice in tax_block.iteritems():
                tax_id ...
                for invoices in invoices:
                    for line in invoices['lines']:
                        (line as a dictionary)
    """

    def get_invoices_lines_to_process(self, tax_id, data):
        line_info = {}
        currency = {}
        invoice_dict = {}
        tax_block = {}
        qty_lines = 0
        list = []

        add_invoice = False

        for invoice in self.get_invoices(tax_id, data):
            line_info = {}
            invoice_dict = {}
            qty_lines = 0 #this variable is per invoice

            for line in invoice.invoice_line:
                added_line = False
                for tax in line.invoice_line_tax_id:
                    if tax.id == tax_id:
                        if invoice.currency_id:
                            currency_id = invoice.currency_id.id

                        qty_lines += 1
                        invoice_dict[invoice.id] = {'lines':[],}
                        add_invoice = True

                        if len(invoice_dict[invoice.id]['lines']) > 0:
                            for dict in invoice_dict['lines']:
                                if line.id == dict['id']:
                                    added_line = True

                            if not added_line:
                                #compute taxes
                                price = line.price_unit * (1-(line.discount or 0.0)/100.0)
                                amount_tax = self.pool.get('account.tax').compute_all(self.cr, self.uid, [tax], price, line.quantity, product=line.product_id, partner=line.invoice_id.partner_id)

                                line_info['id'] = line.id
                                line_info['price_sub_not_dis'] = line.price_subtotal_not_discounted
                                line_info['price_subtotal'] = line.price_subtotal,
                                line_info['taxes'] = amount_tax['total_included'] - line.price_subtotal

                        else:
                            #compute taxes
                            price = line.price_unit * (1-(line.discount or 0.0)/100.0)
                            #amount_tax is a dictionary
                            amount_tax = self.pool.get('account.tax').compute_all(self.cr, self.uid, [tax], price,  line.quantity, product=line.product_id, partner=line.invoice_id.partner_id)

                            line_info['id'] = line.id
                            line_info['price_sub_not_dis'] = line.price_subtotal_not_discounted
                            line_info['price_subtotal'] = line.price_subtotal,
                            line_info['taxes'] = amount_tax['total_included'] - line.price_subtotal

                        invoice_dict[invoice.id]['lines'].append(line_info)

            if add_invoice:
                #Add currency
                if currency_id not in currency.keys():
                    currency[currency_id] = {'invoices': []}

                invoice_dict[invoice.id].update({
                               'number': invoice.number,
                               'client': invoice.partner_id.name or '',
                               'qty_lines': qty_lines,
                               'qty_lines_total': len(invoice.invoice_line),
                               'type': invoice.type,
                               })
                list.append(invoice_dict)
                currency[currency_id]['invoices'] = list
                add_invoice = False

        tax_block[tax_id] = {}
        tax_block[tax_id].update({'currency': currency})

        return tax_block

    #========== COMPUTE DATA
    def get_price_subtotal_not_discounted_per_invoice(self, invoice):
        price_subtotal_not_discount =  0.0

        for line in invoice['lines']:
            price_subtotal_not_discount += line['price_sub_not_dis']

        return price_subtotal_not_discount

    def get_price_subtotal_per_invoice(self, invoice):
        price_subtotal =  0.0

        for line in invoice['lines']:
            price_subtotal += line['price_subtotal'][0]

        return price_subtotal

    def get_discount_per_invoice(self, invoice):
        discount = 0.0
        price_subtotal =  0.0
        price_subtotal_not_discount =  0.0

        price_subtotal_not_discount = self.get_price_subtotal_not_discounted_per_invoice(invoice)
        price_subtotal = self.get_price_subtotal_per_invoice(invoice)

        discount = price_subtotal_not_discount -  price_subtotal

        return discount

    def get_taxes_per_invoice(self, invoice):
        taxes =  0.0

        for line in invoice['lines']:
            taxes += line['taxes']

        return taxes

    #============== FINAL FUNCTION
    def set_data_template(self, tax_id, data):
        #Invoices and lines are processing in this function
        tax_block = self.get_invoices_lines_to_process(tax_id, data)

        dict_update = {
                       'tax_block': tax_block,
                       'res': {},
                       }
        self.localcontext['storage'].update(dict_update)

        #This method process amounts and other aspects to return final invoices
        #in a dict and print it in a easy way in odt and ods template
        res = self.get_data_block_tax(tax_id)
        dict_update.update({'res':res})
        self.localcontext['storage'].update(dict_update)

        return False

    def get_data_block_tax(self, tax_id):
        final_block = {}
        final_list = []
        res = {}

        for currency_id, dict in self.get_data_template('tax_block')[tax_id]['currency'].iteritems():
            if currency_id not in res.keys():
                res[currency_id] = []

            for key, invoices in dict.iteritems():
                for element in invoices:
                    for id, invoice in element.iteritems():
                        final_block = {}
                        if invoice['type'] == 'out_refund' or invoice['type'] == 'in_refund':
                            final_block['invoice_number'] = invoice['number']
                            final_block['client'] = invoice['client']
                            final_block['qty_lines'] = str(invoice['qty_lines']) + "/" + str(invoice['qty_lines_total'])
                            final_block['subtotal_without_dis'] = -1 * self.get_price_subtotal_not_discounted_per_invoice(invoice)
                            discount = self.get_discount_per_invoice(invoice)
                            if discount > 0:
                                final_block['discount'] = -1 * discount
                            else:
                                final_block['discount'] = discount
                            final_block['subtotal_dis'] = -1 * self.get_price_subtotal_per_invoice(invoice)
                            final_block['taxes'] = -1 * self.get_taxes_per_invoice(invoice)
                            final_block['total'] = final_block['subtotal_dis'] + final_block['taxes']
                        else:
                            final_block['invoice_number'] = invoice['number']
                            final_block['client'] = invoice['client']
                            final_block['qty_lines'] = str(invoice['qty_lines']) + "/" + str(invoice['qty_lines_total'])
                            final_block['subtotal_without_dis'] = self.get_price_subtotal_not_discounted_per_invoice(invoice)
                            final_block['discount'] = self.get_discount_per_invoice(invoice)
                            final_block['subtotal_dis'] = self.get_price_subtotal_per_invoice(invoice)
                            final_block['taxes'] = self.get_taxes_per_invoice(invoice)
                            final_block['total'] = final_block['subtotal_dis'] + final_block['taxes']

                        final_list.append(final_block)

            res[currency_id] = final_list

        return res

    def compute_total_block(self, invoices):
        totals = {
                  'subtotal_without_dis': 0.0,
                  'discount':0.0,
                  'subtotal_dis':0.0,
                  'taxes': 0.0,
                  'total': 0.0,
                  }

        for element in invoices:
            totals['subtotal_without_dis'] += element['subtotal_without_dis']
            totals['discount'] += element['discount']
            totals['subtotal_dis'] += element['subtotal_dis']
            totals['taxes'] += element['taxes']
            totals['total'] += element['total']

        dict_update = {'totals': totals}
        self.localcontext['storage'].update(dict_update)

        return False

            <commit_msg>[FIX] Fix error when report computes values in each line for each invoice<commit_after># -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Addons modules by CLEARCORP S.A.
#    Copyright (C) 2009-TODAY CLEARCORP S.A. (<http://clearcorp.co.cr>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

import pooler
from openerp.report import report_sxw
from openerp.tools.translate import _
from openerp.addons.account_report_lib.account_report_base import accountReportbase
from numpy.ma.core import ids

class Parser(accountReportbase):

    def __init__(self, cr, uid, name, context):
        super(Parser, self).__init__(cr, uid, name, context=context)
        self.pool = pooler.get_pool(self.cr.dbname)
        self.cursor = self.cr

        self.localcontext.update({
           'cr' : cr,
           'uid': uid,
           'storage':{},
           'display_taxes':self.display_taxes,
           'set_currency_name':self.set_currency_name,
           'get_order_taxes':self.get_order_taxes,
           'get_tax_name': self.get_tax_name,
           'get_data_block_tax': self.get_data_block_tax,
           'compute_total_block':self.compute_total_block,
           'check_inv_tax': self.check_inv_tax,
        })

    #---------SET AND GET DATA ----------#
    # Get taxes from wizard
    def get_taxes(self, data):
        return self._get_info(data,'account_tax_ids', 'account.tax')

    #Get taxes order by name
    def get_order_taxes(self, data):
        taxes_ids = []

        if not self.get_taxes(data):
            taxes_ids = self.pool.get('account.tax').search(self.cr, self.uid, [], order="name ASC")
            return self.pool.get('account.tax').browse(self.cr, self.uid, taxes_ids)
        else:
           return self.get_taxes(data) #browse record list

    #Extract ids from taxes
    def get_taxes_ids(self, data):
        ids = []
        if self.get_taxes(data):
            for tax in self.get_taxes(data):
                ids.append(tax.id)
        return ids

    def get_tax_name(self, tax_id):
        name = ''
        tax = self.pool.get('account.tax').browse(self.cr, self.uid, tax_id)

        if tax.type == 'percent' or tax.type == 'fixed':
            tax_amount = 100 * tax.amount
            name = tax.name + ' - ' + str(tax_amount) + '%'
        else:
            name = tax.name

        return name

    def set_currency_name(self, currency_id):
        currency = self.pool.get('res.currency').browse(self.cr, self.uid, currency_id)
        return currency.name

    def check_inv_tax(self):
        if self.get_data_template('res'):
            return True
        else:
            return False

    #================ DISPLAY DATA ===========================#
    def display_taxes(self, data):
       name = ''

       if not self.get_taxes(data): #It means that non-one was selected
           return _('All taxes')
       else:
           taxes = self.get_taxes(data)
           for tax in taxes:
               name += tax.name + ', '
           return name

    #========= BUILD DATA
    def get_invoices(self, tax_id, data):
        account_invoice_obj = self.pool.get('account.invoice')
        result={}
        domain = []

        date_from = self.get_date_from(data)
        date_to = self.get_date_to(data)
        domain.append(('date_invoice', '>=', date_from))
        domain.append(('date_invoice', '<=', date_to))

        tuple = ('invoice_line.invoice_line_tax_id', 'in', tax_id)
        domain.append(tuple)

        tuple = ('state', '!=', 'draft')
        domain.append(tuple)

        invoices_ids = account_invoice_obj.search(self.cr, self.uid, domain, context=None)
        invoices_obj = account_invoice_obj.browse(self.cr, self.uid, invoices_ids, context=None)

        return invoices_obj

    """
        1. Create a structure like this:
            tax_block[tax_id] = {} (invoices)

            Then invoices is a dictionary, where key is id invoice and each key
            has a list with lines that its tax match with tax_id that is passed
            as a parameter

            So, iterate dictionary like this

            for tax_id, invoice in tax_block.iteritems():
                tax_id ...
                for invoices in invoices:
                    for line in invoices['lines']:
                        (line as a dictionary)
    """

    def get_invoices_lines_to_process(self, tax_id, data):
        line_info = {}
        currency = {}
        invoice_dict = {}
        tax_block = {}
        qty_lines = 0
        list = []
        list_lines = []

        add_invoice = False

        for invoice in self.get_invoices(tax_id, data):
            invoice_dict = {}
            qty_lines = 0 #this variable is per invoice
            list_lines = []

            for line in invoice.invoice_line:
                added_line = False
                line_info = {}
                for tax in line.invoice_line_tax_id:
                    if tax.id == tax_id:
                        if invoice.currency_id:
                            currency_id = invoice.currency_id.id

                        qty_lines += 1
                        invoice_dict[invoice.id] = {'lines':[],}
                        add_invoice = True

                        if len(invoice_dict[invoice.id]['lines']) > 0:
                            for dict in invoice_dict['lines']:
                                if line.id == dict['id']:
                                    added_line = True

                            if not added_line:
                                #compute taxes
                                price = line.price_unit * (1-(line.discount or 0.0)/100.0)
                                amount_tax = self.pool.get('account.tax').compute_all(self.cr, self.uid, [tax], price, line.quantity, product=line.product_id, partner=line.invoice_id.partner_id)

                                line_info['id'] = line.id
                                line_info['price_sub_not_dis'] = line.price_subtotal_not_discounted
                                line_info['price_subtotal'] = line.price_subtotal,
                                line_info['taxes'] = amount_tax['total_included'] - line.price_subtotal

                                list_lines.append(line_info)

                        else:
                            #compute taxes
                            price = line.price_unit * (1-(line.discount or 0.0)/100.0)
                            #amount_tax is a dictionary
                            amount_tax = self.pool.get('account.tax').compute_all(self.cr, self.uid, [tax], price,  line.quantity, product=line.product_id, partner=line.invoice_id.partner_id)

                            line_info['id'] = line.id
                            line_info['price_sub_not_dis'] = line.price_subtotal_not_discounted
                            line_info['price_subtotal'] = line.price_subtotal,
                            line_info['taxes'] = amount_tax['total_included'] - line.price_subtotal

                            list_lines.append(line_info)

            #Update list_lines
            invoice_dict[invoice.id]['lines'] = list_lines

            if add_invoice:
                #Add currency
                if currency_id not in currency.keys():
                    currency[currency_id] = {'invoices': []}

                invoice_dict[invoice.id].update({
                               'number': invoice.number,
                               'client': invoice.partner_id.name or '',
                               'qty_lines': qty_lines,
                               'qty_lines_total': len(invoice.invoice_line),
                               'type': invoice.type,
                               })
                list.append(invoice_dict)
                currency[currency_id]['invoices'] = list
                add_invoice = False

        tax_block[tax_id] = {}
        tax_block[tax_id].update({'currency': currency})

        return tax_block

    #========== COMPUTE DATA
    def get_price_subtotal_not_discounted_per_invoice(self, invoice):
        price_subtotal_not_discount =  0.0

        for line in invoice['lines']:
            price_subtotal_not_discount += line['price_sub_not_dis']

        return price_subtotal_not_discount

    def get_price_subtotal_per_invoice(self, invoice):
        price_subtotal =  0.0

        for line in invoice['lines']:
            price_subtotal += line['price_subtotal'][0]

        return price_subtotal

    def get_discount_per_invoice(self, invoice):
        discount = 0.0
        price_subtotal =  0.0
        price_subtotal_not_discount =  0.0

        price_subtotal_not_discount = self.get_price_subtotal_not_discounted_per_invoice(invoice)
        price_subtotal = self.get_price_subtotal_per_invoice(invoice)

        discount = price_subtotal_not_discount -  price_subtotal

        return discount

    def get_taxes_per_invoice(self, invoice):
        taxes =  0.0

        for line in invoice['lines']:
            taxes += line['taxes']

        return taxes

    #============== FINAL FUNCTION
    def set_data_template(self, tax_id, data):
        #Invoices and lines are processing in this function
        tax_block = self.get_invoices_lines_to_process(tax_id, data)

        dict_update = {
                       'tax_block': tax_block,
                       'res': {},
                       }
        self.localcontext['storage'].update(dict_update)

        #This method process amounts and other aspects to return final invoices
        #in a dict and print it in a easy way in odt and ods template
        res = self.get_data_block_tax(tax_id)
        dict_update.update({'res':res})
        self.localcontext['storage'].update(dict_update)

        return False

    def get_data_block_tax(self, tax_id):
        final_block = {}
        final_list = []
        res = {}

        for currency_id, dict in self.get_data_template('tax_block')[tax_id]['currency'].iteritems():
            if currency_id not in res.keys():
                res[currency_id] = []

            for key, invoices in dict.iteritems():
                for element in invoices:
                    for id, invoice in element.iteritems():
                        final_block = {}
                        if invoice['type'] == 'out_refund' or invoice['type'] == 'in_refund':
                            final_block['invoice_number'] = invoice['number']
                            final_block['client'] = invoice['client']
                            final_block['qty_lines'] = str(invoice['qty_lines']) + "/" + str(invoice['qty_lines_total'])
                            final_block['subtotal_without_dis'] = -1 * self.get_price_subtotal_not_discounted_per_invoice(invoice)
                            discount = self.get_discount_per_invoice(invoice)
                            if discount > 0:
                                final_block['discount'] = -1 * discount
                            else:
                                final_block['discount'] = discount
                            final_block['subtotal_dis'] = -1 * self.get_price_subtotal_per_invoice(invoice)
                            final_block['taxes'] = -1 * self.get_taxes_per_invoice(invoice)
                            final_block['total'] = final_block['subtotal_dis'] + final_block['taxes']
                        else:
                            final_block['invoice_number'] = invoice['number']
                            final_block['client'] = invoice['client']
                            final_block['qty_lines'] = str(invoice['qty_lines']) + "/" + str(invoice['qty_lines_total'])
                            final_block['subtotal_without_dis'] = self.get_price_subtotal_not_discounted_per_invoice(invoice)
                            final_block['discount'] = self.get_discount_per_invoice(invoice)
                            final_block['subtotal_dis'] = self.get_price_subtotal_per_invoice(invoice)
                            final_block['taxes'] = self.get_taxes_per_invoice(invoice)
                            final_block['total'] = final_block['subtotal_dis'] + final_block['taxes']

                        final_list.append(final_block)

            res[currency_id] = final_list

        return res

    def compute_total_block(self, invoices):
        totals = {
                  'subtotal_without_dis': 0.0,
                  'discount':0.0,
                  'subtotal_dis':0.0,
                  'taxes': 0.0,
                  'total': 0.0,
                  }

        for element in invoices:
            totals['subtotal_without_dis'] += element['subtotal_without_dis']
            totals['discount'] += element['discount']
            totals['subtotal_dis'] += element['subtotal_dis']
            totals['taxes'] += element['taxes']
            totals['total'] += element['total']

        dict_update = {'totals': totals}
        self.localcontext['storage'].update(dict_update)

        return False

            <|endoftext|>


<commit_before># -*- encoding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
#    $Id$
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

from openerp.osv import fields, osv
from openerp.tools.translate import _

class product_pricelist(osv.osv):
    _inherit = 'product.pricelist'

    _columns ={
        'visible_discount': fields.boolean('Visible Discount'),
    }
    _defaults = {
         'visible_discount': True,
    }

product_pricelist()

class sale_order_line(osv.osv):
    _inherit = "sale.order.line"

    def product_id_change(self, cr, uid, ids, pricelist, product, qty=0,
            uom=False, qty_uos=0, uos=False, name='', partner_id=False,
            lang=False, update_tax=True, date_order=False, packaging=False,
            fiscal_position=False, flag=False, context=None):

        def get_real_price(res_dict, product_id, qty, uom, pricelist):
            item_obj = self.pool.get('product.pricelist.item')
            price_type_obj = self.pool.get('product.price.type')
            product_obj = self.pool.get('product.product')
            field_name = 'list_price'

            if res_dict.get('item_id',False) and res_dict['item_id'].get(pricelist,False):
                item = res_dict['item_id'].get(pricelist,False)
                item_base = item_obj.read(cr, uid, [item], ['base'])[0]['base']
                if item_base > 0:
                    field_name = price_type_obj.browse(cr, uid, item_base).field

            product = product_obj.browse(cr, uid, product_id, context)
            product_read = product_obj.read(cr, uid, product_id, [field_name], context=context)

            factor = 1.0
            if uom and uom != product.uom_id.id:
                product_uom_obj = self.pool.get('product.uom')
                uom_data = product_uom_obj.browse(cr, uid,  product.uom_id.id)
                factor = uom_data.factor
            return product_read[field_name] * factor

        res=super(sale_order_line, self).product_id_change(cr, uid, ids, pricelist, product, qty,
            uom, qty_uos, uos, name, partner_id,
            lang, update_tax, date_order, packaging=packaging, fiscal_position=fiscal_position, flag=flag, context=context)

        context = {'lang': lang, 'partner_id': partner_id}
        result=res['value']
        pricelist_obj=self.pool.get('product.pricelist')
        product_obj = self.pool.get('product.product')
        if product and pricelist:
            if result.get('price_unit',False):
                price=result['price_unit']
            else:
                return res

            product = product_obj.browse(cr, uid, product, context)
            list_price = pricelist_obj.price_get(cr, uid, [pricelist],
                    product.id, qty or 1.0, partner_id, {'uom': uom,'date': date_order })

            so_pricelist = pricelist_obj.browse(cr, uid, pricelist, context=context)

            new_list_price = get_real_price(list_price, product.id, qty, uom, pricelist)
            if so_pricelist.visible_discount and list_price[pricelist] != 0 and new_list_price != 0:
                if product.company_id and so_pricelist.currency_id.id != product.company_id.currency_id.id:
                    # new_list_price is in company's currency while price in pricelist currency
                    ctx = context.copy()
                    ctx['date'] = date_order
                    new_list_price = self.pool['res.currency'].compute(cr, uid,
                        product.company_id.currency_id.id, so_pricelist.currency_id.id,
                        new_list_price, context=ctx)
                discount = (new_list_price - price) / new_list_price * 100
                if discount > 0:
                    result['price_unit'] = new_list_price
                    result['discount'] = discount
                else:
                    result['discount'] = 0.0
            else:
                result['discount'] = 0.0
        else:
            result['discount'] = 0.0
        return res
<commit_msg>[FIX] product_visible_discount: discount with different unit of measures<commit_after># -*- encoding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved
#    $Id$
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

from openerp.osv import fields, osv
from openerp.tools.translate import _

class product_pricelist(osv.osv):
    _inherit = 'product.pricelist'

    _columns ={
        'visible_discount': fields.boolean('Visible Discount'),
    }
    _defaults = {
         'visible_discount': True,
    }

product_pricelist()

class sale_order_line(osv.osv):
    _inherit = "sale.order.line"

    def product_id_change(self, cr, uid, ids, pricelist, product, qty=0,
            uom=False, qty_uos=0, uos=False, name='', partner_id=False,
            lang=False, update_tax=True, date_order=False, packaging=False,
            fiscal_position=False, flag=False, context=None):

        def get_real_price(res_dict, product_id, qty, uom, pricelist):
            """Retrieve the price before applying the pricelist"""
            item_obj = self.pool.get('product.pricelist.item')
            price_type_obj = self.pool.get('product.price.type')
            product_obj = self.pool.get('product.product')
            field_name = 'list_price'

            if res_dict.get('item_id',False) and res_dict['item_id'].get(pricelist,False):
                item = res_dict['item_id'].get(pricelist,False)
                item_base = item_obj.read(cr, uid, [item], ['base'])[0]['base']
                if item_base > 0:
                    field_name = price_type_obj.browse(cr, uid, item_base).field

            product = product_obj.browse(cr, uid, product_id, context)
            product_read = product_obj.read(cr, uid, product_id, [field_name], context=context)

            factor = 1.0
            if uom and uom != product.uom_id.id:
                # the unit price is in a different uom
                factor = self.pool['product.uom']._compute_qty(cr, uid, uom, 1.0, product.uom_id.id)
            return product_read[field_name] * factor

        res=super(sale_order_line, self).product_id_change(cr, uid, ids, pricelist, product, qty,
            uom, qty_uos, uos, name, partner_id,
            lang, update_tax, date_order, packaging=packaging, fiscal_position=fiscal_position, flag=flag, context=context)

        context = {'lang': lang, 'partner_id': partner_id}
        result=res['value']
        pricelist_obj=self.pool.get('product.pricelist')
        product_obj = self.pool.get('product.product')
        if product and pricelist:
            if result.get('price_unit',False):
                price=result['price_unit']
            else:
                return res

            product = product_obj.browse(cr, uid, product, context)
            list_price = pricelist_obj.price_get(cr, uid, [pricelist],
                    product.id, qty or 1.0, partner_id, {'uom': uom,'date': date_order })

            so_pricelist = pricelist_obj.browse(cr, uid, pricelist, context=context)

            new_list_price = get_real_price(list_price, product.id, qty, uom, pricelist)
            if so_pricelist.visible_discount and list_price[pricelist] != 0 and new_list_price != 0:
                if product.company_id and so_pricelist.currency_id.id != product.company_id.currency_id.id:
                    # new_list_price is in company's currency while price in pricelist currency
                    ctx = context.copy()
                    ctx['date'] = date_order
                    new_list_price = self.pool['res.currency'].compute(cr, uid,
                        product.company_id.currency_id.id, so_pricelist.currency_id.id,
                        new_list_price, context=ctx)
                discount = (new_list_price - price) / new_list_price * 100
                if discount > 0:
                    result['price_unit'] = new_list_price
                    result['discount'] = discount
                else:
                    result['discount'] = 0.0
            else:
                result['discount'] = 0.0
        else:
            result['discount'] = 0.0
        return res
<|endoftext|>


<commit_before><commit_msg>Fix for blocking calles when inside gevent<commit_after><|endoftext|>


<commit_before># -*- coding: UTF-8 -*-
"""
:mod:`phi_pade` -- Exponentials with rational approximations
============================================================

Computation of φ functions using Padé approximations and Scaling and Squaring.

.. module :: phi_pade
	:synopsis: Computation of φ functions.
.. moduleauthor :: Olivier Verdier <olivier.verdier@gmail.com>

Some formulae are taken from the `Expint documentation`_, of Håvard Berland, Bård Skaflestad and Will Wright.

.. _Expint project: http://www.math.ntnu.no/num/expint/
.. _Expint documentation: http://www.math.ntnu.no/preprint/numerics/2005/N4-2005.pdf

"""
from __future__ import division

import numpy as np
import math
import numpy.linalg as lin

from .rational import RationalFraction, Polynomial

def ninf(M):
	if np.isscalar(M):
		return abs(M)
	return lin.norm(M,np.inf)

class Exponential(object):
	r"""
Main class to compute the :math:`φ_l` functions.
The simplest way to define those functions is by the formula:

.. math::
	φ_{\ell}(x) = ∑_{k=0}^{∞} \frac{x^k}{(\ell+k)!}

Usage is as follows::

	phi = Exponential(k,d)
	result = phi(M)

where :data:`M` is a square array.
The variable ``result`` is a list of all the values of :math:`φ_{k}(M)` for :math:`0≤k≤l`.
	"""

	def __init__(self, k, d=6):
		self.d = d
		self.factorials = self.compute_factorials(k+d+1)
		self.pade = list(self.compute_Pade(k,d))

	@classmethod
	def compute_factorials(self, n):
		"""
		Factorials up to order n: 0!, 1!, ..., n!
		"""
		C = np.empty(n+1)
		C[0] = 1.
		C[1:] = 1./np.cumprod(np.arange(n)+1)
		return C

	def compute_Pade(self, k, d):
		r"""
Compute the Padé approximations of order :math:`d` of :math:`φ_l`, for :math:`0 ≤ l ≤ k`.

The goal is to produce an approximation of the form:

.. math::
	φ_{\ell} = \frac{N}{D}

where :math:`N` and :math:`D` are polynomials.
The formula for :math:`D` is first computed recursively using the following recursion relations:

.. math::
	D_0^0 = 1\\
	D_{j+1}^0 = \frac{-(d-j)}{(2d -j)(j+1)} D_{j}^0\\
	D_{j}^{\ell+1} = (2d-\ell)(2d+\ell+1-j) D_{j}^{\ell}

Then, considering the inverse factorial series:

.. math::
	C_j := \frac{1}{j!}

The numerator :math:`N` is now computed by:

.. math::
	N = D*C

		"""
		J = np.arange(d+1)
		j = J[:-1]
		a = -(d-j)/(2*d-j)/(j+1)
		D = np.ones([k+1,d+1])
		D[0,1:] = np.cumprod(a)
		l = np.arange(k).reshape(-1,1)
		al = (2*d-l)*(2*d+l+1-J)
		D[1:,:] = np.cumprod(al,0) * D[0,:]
		for m,Dr in enumerate(D):
			yield RationalFraction(np.convolve(Dr, self.factorials[m:m+d+1])[:d+1], Dr)

	@classmethod
	def scaling(self, z, threshold=0):
		norm = ninf(z)
		e = max(threshold, np.log2(norm))
		return int(math.ceil(e))

	@classmethod
	def optimal_exponent(self, d):
		s = int(math.floor(math.sqrt(d)))
		return s

	def eval_pade(self, z, s=None):
		"""
		Evaluate :math:`φ_l(z)` using the Padé approximation.
		"""
		if s is None:
			s = self.optimal_exponent(self.d)
		Rs = self.pade
		Z = Polynomial.exponents(z,s)
		phi = [R(Z) for R in Rs]
		return phi

	def __call__(self, z):
		"""
The final call to compute the values of :math:`φ_k(z)`.
It proceeds in three steps:

1. figure out a scaling exponent :math:`s` such that :math:`z/2^s` is reasonably little
2. compute :math:`φ_k(z/2^s)` using the Padé approximation
3. scale back by repeatedly squaring
		"""
		scaling = self.scaling(z)
		phis = self.eval_pade(z/2**scaling)
		for s in range(scaling):
			phis = self.square(phis)
		return phis

	def square_last(self, phis):
		"""
Formula for squaring phi_l from existing phi_k for k≤l, taken from the `Expint documentation`_.

The argument is an array containing [phi_0,...,phi_l].

.. _Expint documentation: http://www.math.ntnu.no/preprint/numerics/2005/N4-2005.pdf
		"""
		l = len(phis) - 1
		ifac = self.factorials
		odd = l % 2
		half = l//2
		next = half
		if odd:
			next += 1
		res = np.dot(phis[half], phis[next])
		res += sum(2*ifac[j]*phis[l-j] for j in xrange(half))
		if odd:
			res += ifac[half]*phis[half+1]
		res /= 2**l
		return res

	def square(self, phis):
		phis = [self.square_last(phis[:l+1]) for l in range(len(phis))]
		return phis

<commit_msg>d -> order<commit_after># -*- coding: UTF-8 -*-
"""
:mod:`phi_pade` -- Exponentials with rational approximations
============================================================

Computation of φ functions using Padé approximations and Scaling and Squaring.

.. module :: phi_pade
	:synopsis: Computation of φ functions.
.. moduleauthor :: Olivier Verdier <olivier.verdier@gmail.com>

Some formulae are taken from the `Expint documentation`_, of Håvard Berland, Bård Skaflestad and Will Wright.

.. _Expint project: http://www.math.ntnu.no/num/expint/
.. _Expint documentation: http://www.math.ntnu.no/preprint/numerics/2005/N4-2005.pdf

"""
from __future__ import division

import numpy as np
import math
import numpy.linalg as lin

from .rational import RationalFraction, Polynomial

def ninf(M):
	if np.isscalar(M):
		return abs(M)
	return lin.norm(M,np.inf)

class Exponential(object):
	r"""
Main class to compute the :math:`φ_l` functions.
The simplest way to define those functions is by the formula:

.. math::
	φ_{\ell}(x) = ∑_{k=0}^{∞} \frac{x^k}{(\ell+k)!}

Usage is as follows::

	phi = Exponential(k,d)
	result = phi(M)

where :data:`M` is a square array.
The variable ``result`` is a list of all the values of :math:`φ_{k}(M)` for :math:`0≤k≤l`.
	"""

	def __init__(self, k, order=6):
		self.order = order
		self.factorials = self.compute_factorials(k+order+1)
		self.pade = list(self.compute_Pade(k,order))

	@classmethod
	def compute_factorials(self, n):
		"""
		Factorials up to order n: 0!, 1!, ..., n!
		"""
		C = np.empty(n+1)
		C[0] = 1.
		C[1:] = 1./np.cumprod(np.arange(n)+1)
		return C

	def compute_Pade(self, k, order):
		r"""
Compute the Padé approximations of order :math:`d` of :math:`φ_l`, for :math:`0 ≤ l ≤ k`.

The goal is to produce an approximation of the form:

.. math::
	φ_{\ell} = \frac{N}{D}

where :math:`N` and :math:`D` are polynomials.
The formula for :math:`D` is first computed recursively using the following recursion relations:

.. math::
	D_0^0 = 1\\
	D_{j+1}^0 = \frac{-(d-j)}{(2d -j)(j+1)} D_{j}^0\\
	D_{j}^{\ell+1} = (2d-\ell)(2d+\ell+1-j) D_{j}^{\ell}

Then, considering the inverse factorial series:

.. math::
	C_j := \frac{1}{j!}

The numerator :math:`N` is now computed by:

.. math::
	N = D*C

		"""
		d = order
		J = np.arange(d+1)
		j = J[:-1]
		a = -(d-j)/(2*d-j)/(j+1)
		D = np.ones([k+1,d+1])
		D[0,1:] = np.cumprod(a)
		l = np.arange(k).reshape(-1,1)
		al = (2*d-l)*(2*d+l+1-J)
		D[1:,:] = np.cumprod(al,0) * D[0,:]
		for m,Dr in enumerate(D):
			rat = RationalFraction(np.convolve(Dr, self.factorials[m:m+d+1])[:d+1], Dr)
			yield rat

	@classmethod
	def scaling(self, z, threshold=0):
		norm = ninf(z)
		e = max(threshold, np.log2(norm))
		return int(math.ceil(e))

	@classmethod
	def optimal_exponent(self, order):
		s = int(math.floor(math.sqrt(order)))
		return s

	def eval_pade(self, z, s=None):
		"""
		Evaluate :math:`φ_l(z)` using the Padé approximation.
		"""
		if s is None:
			s = self.optimal_exponent(self.order)
		Rs = self.pade
		Z = Polynomial.exponents(z,s)
		phi = [R(Z) for R in Rs]
		return phi

	def __call__(self, z):
		"""
The final call to compute the values of :math:`φ_k(z)`.
It proceeds in three steps:

1. figure out a scaling exponent :math:`s` such that :math:`z/2^s` is reasonably little
2. compute :math:`φ_k(z/2^s)` using the Padé approximation
3. scale back by repeatedly squaring
		"""
		scaling = self.scaling(z)
		phis = self.eval_pade(z/2**scaling)
		for s in range(scaling):
			phis = self.square(phis)
		return phis

	def square_last(self, phis):
		"""
Formula for squaring phi_l from existing phi_k for k≤l, taken from the `Expint documentation`_.

The argument is an array containing [phi_0,...,phi_l].

.. _Expint documentation: http://www.math.ntnu.no/preprint/numerics/2005/N4-2005.pdf
		"""
		l = len(phis) - 1
		ifac = self.factorials
		odd = l % 2
		half = l//2
		next = half
		if odd:
			next += 1
		res = np.dot(phis[half], phis[next])
		res += sum(2*ifac[j]*phis[l-j] for j in xrange(half))
		if odd:
			res += ifac[half]*phis[half+1]
		res /= 2**l
		return res

	def square(self, phis):
		phis = [self.square_last(phis[:l+1]) for l in range(len(phis))]
		return phis

<|endoftext|>