<commit_before># -*- coding: utf-8 -*-
"""
This module provides the necessary definitions to generate a Python Interpreter object.
"""

import os
import csv
import fnmatch
import uuid
import subprocess
try:
    import winreg
except ImportError:
    import _winreg as winreg
from pymake.register import PyRegisterable

class PymakeInterpreter(PyRegisterable):
    """
    PymakeInterpreter encapsulates the logic and data used to describe a Python interpreter or virtual environments

    :ivar GUID:                    The GUID of the Python Interpreter; if not provided one is generated automatically.
    :ivar BaseInterpreter:         The GUID of the base Python Interpreter (different if PymakeInterpreter is Virtual Environment); if not provided the value is self.GUID
    :ivar Architecture:            The architecture (either x86 or Amd64). if not provide the value is "".
    :ivar Version:                 The major.minor version string; if not provide the value is "".
    :ivar Description:             The human readable description string; if not provide the value is ""
    :ivar Path:                    The absolute path of the 'python.exe'; if not provide the value is ""
    :ivar InterpreterPath:         The relative path to self.Path of the 'python.exe'; if not provide the value is ""
    :ivar WindowsInterpreterPath:  The relative path to self.Path of the 'pythonw.exe'; if not provide the value is ""
    :ivar LibraryPath:             The relative path to self.Path of the 'Lib' folder that is part of the python.exe distribution; if not provide the value is "".
    :ivar PathEnvironmentVariable: The name of the Environment variable to be uses as PYTHONPATH; if not provide the value is "".
    """
    __registerable_name__ = "Python Interpreter"

    #: PTVS Interpreter Register Location
    regkey_name = r'Software\Microsoft\VisualStudio\11.0\PythonTools\Interpreters'

    #: A CSV file contains the values of an environment
    EnvDefintionFile = 'PTVSEnvironment.csv'

    def __init__(self, **kwargs):
        """
        Constructor.

        :param **kwargs:         List of arbitrary keyworded arguments to be processed as instance variable data
        """
        super(PymakeInterpreter, self).__init__()
        self._import(kwargs)

    @staticmethod
    def from_directory(directory):
        """
        Creates one or more PymakeInterpreter(s) from all PTVSEnvironment.csv files recursively found in the directory.

        :param directory: The absolute path to the root directory.
        :return           A valid PymakeInterpreter instance if succesful; None otherwise.
        """
        interpreters = []
        for root, dirnames, filenames in os.walk(directory):
            for filename in fnmatch.filter(filenames, PymakeInterpreter.EnvDefintionFile):
                interpreters.extend( PymakeInterpreter.from_file(os.path.join(root, filename)))
        return interpreters

    @staticmethod
    def from_virtual_environment(directory):
        """
        Creates a PymakeInterpreter from an Python Virtual Environment in the directory.

        :param directory: The absolute path to the python installation directory.
        :return           A valid PymakeInterpreter instance if succesful; None otherwise.
        """
        root = os.path.abspath(directory)
        python = os.path.abspath(os.path.join(root, 'Scripts', 'python.exe'))
        if not os.path.exists(python):
            return None

        root = os.path.abspath(directory)
        origprefix = os.path.abspath(os.path.join(root, 'Lib', 'orig-prefix.txt'))
        if not os.path.exists(origprefix):
            return None

        with open(origprefix) as f:
            basedir = os.path.abspath(f.readlines()[0])
            baseinterpretter = PymakeInterpreter.from_python_installation(basedir)

        args = {
            'Path': root,
            'BaseInterpreter': baseinterpretter.GUID,
            'InterpreterPath': os.path.join('Scripts', 'python.exe'),
            'Description': '{} ({})'.format(os.path.basename(root), baseinterpretter.Description),
        }

        if os.path.exists(os.path.join(root, 'Scripts', 'pythonw.exe')):
            args['WindowsInterpreterPath'] = os.path.join('Scripts', 'pythonw.exe')

        if os.path.exists(os.path.join(root, 'Lib')):
            args['LibraryPath'] = 'Lib\\'

        try:
            out, err = subprocess.Popen([python, '-c', 'import sys;print ".".join(str(s) for s in sys.version_info[:2])'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
            args['Version'] = out.rstrip()
        except Exception as e:
            pass

        try:
            out, err = subprocess.Popen([python, '-c', 'import platform; print "AMD64" if "64bit" in platform.architecture() else "x86"'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
            args['Architecture'] = out.rstrip()
        except Exception:
            pass

        interpreter = PymakeInterpreter(**args)
        return interpreter

    @staticmethod
    def from_python_installation(directory):
        """
        Creates a PymakeInterpreter from an Python Installation in the directory.

        :param directory: The absolute path to the python installation directory.
        :return           A valid PymakeInterpreter instance if succesful; None otherwise.
        """
        root = os.path.abspath(directory)
        python = os.path.abspath(os.path.join(root, 'python.exe'))
        if not os.path.exists(python):
            return None

        args = {
            'Path': root,
            'InterpreterPath': 'python.exe',
            'Description': os.path.basename(root)
        }

        if os.path.exists(os.path.join(root, 'pythonw.exe')):
            args['WindowsInterpreterPath'] = 'pythonw.exe'

        if os.path.exists(os.path.join(root, 'Lib')):
            args['LibraryPath'] = 'Lib\\'

        try:
            out, err = subprocess.Popen([python, '-c', 'import sys;print ".".join(str(s) for s in sys.version_info[:2])'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
            args['Version'] = out.rstrip()
        except Exception as e:
            pass

        try:
            out, err = subprocess.Popen([python, '-c', 'import platform; print "Amd64" if "64bit" in platform.architecture() else "x86"'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
            args['Architecture'] = out.rstrip()
        except Exception:
            pass

        interpreter = PymakeInterpreter(**args)
        interpreter.resolve()
        return interpreter

    @staticmethod
    def from_file(filename):
        """
        Creates one or more PymakeInterpreter(s) from a single PTVSEnvironment.csv file.

        :param filename:  The absolute path to the PTVSEnvironment.csv file.
        :return           List of PymakeInterpreter instances; an empty list otherwise.
        """
        interpreters = []
        try:
            with open(filename, 'rb') as csvfile:
                reader = csv.DictReader(csvfile, delimiter=',', quotechar='"')
                for line in reader:
                    line['Path'] = os.path.dirname(filename)
                    interpreters.append(PymakeInterpreter(**line))
        except IOError:
            pass

        return interpreters

    @staticmethod
    def from_registry_key(keyname):
        """
        Creates a PymakeInterpreter from a single registry key.

        :param keyname:  The keyname under HKEY_CURRENT_USER referring to the environment.
        :return:         A valid PymakeInterpreter instance if succesful; None otherwise.
        """
        args = {}
        try:
            regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, keyname)
            for k in ['Architecture', 'Description', 'InterpreterPath', 'LibraryPath', 'PathEnvironmentVariable', 'Version', 'WindowsInterpreterPath', 'PathEnvironmentVariable']:
                args[k] = winreg.QueryValueEx(regkey, k)[0]
            winreg.CloseKey(regkey)
        except WindowsError as ex:
            pass

        if 'InterpreterPath' in args:
            args['Path'] = os.path.dirname(args['InterpreterPath'])
            args['Id'] = os.path.basename(keyname)[1:-1]
            return PymakeInterpreter(**args)
        return None

    def _import(self, datadict):
        """
        Internal method to import instance variables data from a dictionary.

        :param datadict: The dictionary containing variables values.
        """
        self.GUID                       = datadict.get('Id', uuid.uuid1())
        self.BaseInterpreter            = datadict.get('BaseInterpreter', self.GUID)
        self.Architecture               = datadict.get('Architecture', "")
        self.Version                    = datadict.get('Version', "")
        self.Path                       = datadict.get('Path', "")
        self.Description                = datadict.get('Description', "")
        self.InterpreterPath            = datadict.get('InterpreterPath', "")
        self.InterpreterAbsPath         = datadict.get('InterpreterAbsPath', self.InterpreterPath if os.path.isabs(self.InterpreterPath) else os.path.abspath(os.path.join(self.Path, self.InterpreterPath)))
        self.WindowsInterpreterPath     = datadict.get('WindowsInterpreterPath', "")
        self.WindowsInterpreterAbsPath  = datadict.get('WindowsInterpreterAbsPath', self.WindowsInterpreterPath if os.path.isabs(self.WindowsInterpreterPath) else os.path.abspath(os.path.join(self.Path, self.WindowsInterpreterPath)))
        self.LibraryPath                = datadict.get('LibraryPath', "")
        self.LibraryAbsPath             = datadict.get('LibraryAbsPath', self.LibraryPath if os.path.isabs(self.LibraryPath) else os.path.abspath(os.path.join(self.Path, self.LibraryPath)))
        self.PathEnvironmentVariable    = datadict.get('PathEnvironmentVariable', "")

    def resolve(self):
        """
        'Resolves' the environment with existing environments in the windows registry.
        """
        regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, self.regkey_name)
        try:
            reginfo = winreg.QueryInfoKey(regkey)
            for i in range(reginfo[0]):
                regkey_name = '{0}\\{1}'.format(self.regkey_name, winreg.EnumKey(regkey, i))
                interpreter = PymakeInterpreter.from_registry_key(regkey_name)
                if interpreter and interpreter.InterpreterAbsPath == self.InterpreterAbsPath:
                    self.GUID = uuid.UUID(interpreter.GUID)
                    self.BaseInterpreter = self.GUID
                    break
        except WindowsError as ex:
            pass

    def register(self):
        """
        'Registers' the environment into the windows registry.

        :..note: https://pytools.codeplex.com/workitem/2765
        """
        regkey_name = '{0}\\{{{1}}}'.format(self.regkey_name, str(self.GUID).lower())
        try:
            regkey = winreg.CreateKey(winreg.HKEY_CURRENT_USER, regkey_name)
            winreg.SetValueEx(regkey, 'Architecture', 0, winreg.REG_SZ, self.Architecture)
            winreg.SetValueEx(regkey, 'Description', 0, winreg.REG_SZ, self.Description)
            winreg.SetValueEx(regkey, 'InterpreterPath', 0, winreg.REG_SZ, self.InterpreterAbsPath)
            winreg.SetValueEx(regkey, 'LibraryPath', 0, winreg.REG_SZ, self.LibraryAbsPath)
            winreg.SetValueEx(regkey, 'PathEnvironmentVariable', 0, winreg.REG_SZ, self.PathEnvironmentVariable)
            winreg.SetValueEx(regkey, 'Version', 0, winreg.REG_SZ, self.Version)
            winreg.SetValueEx(regkey, 'WindowsInterpreterPath', 0, winreg.REG_SZ, self.WindowsInterpreterAbsPath)
            winreg.SetValueEx(regkey, 'PathEnvironmentVariable', 0, winreg.REG_SZ, self.PathEnvironmentVariable)
            winreg.CloseKey(regkey)
        except WindowsError as ex:
            return False
        return True
<commit_msg>Minor fix in Architecture text.<commit_after># -*- coding: utf-8 -*-
"""
This module provides the necessary definitions to generate a Python Interpreter object.
"""

import os
import csv
import fnmatch
import uuid
import subprocess
try:
    import winreg
except ImportError:
    import _winreg as winreg
from pymake.register import PyRegisterable

class PymakeInterpreter(PyRegisterable):
    """
    PymakeInterpreter encapsulates the logic and data used to describe a Python interpreter or virtual environments

    :ivar GUID:                    The GUID of the Python Interpreter; if not provided one is generated automatically.
    :ivar BaseInterpreter:         The GUID of the base Python Interpreter (different if PymakeInterpreter is Virtual Environment); if not provided the value is self.GUID
    :ivar Architecture:            The architecture (either x86 or Amd64). if not provide the value is "".
    :ivar Version:                 The major.minor version string; if not provide the value is "".
    :ivar Description:             The human readable description string; if not provide the value is ""
    :ivar Path:                    The absolute path of the 'python.exe'; if not provide the value is ""
    :ivar InterpreterPath:         The relative path to self.Path of the 'python.exe'; if not provide the value is ""
    :ivar WindowsInterpreterPath:  The relative path to self.Path of the 'pythonw.exe'; if not provide the value is ""
    :ivar LibraryPath:             The relative path to self.Path of the 'Lib' folder that is part of the python.exe distribution; if not provide the value is "".
    :ivar PathEnvironmentVariable: The name of the Environment variable to be uses as PYTHONPATH; if not provide the value is "".
    """
    __registerable_name__ = "Python Interpreter"

    #: PTVS Interpreter Register Location
    regkey_name = r'Software\Microsoft\VisualStudio\11.0\PythonTools\Interpreters'

    #: A CSV file contains the values of an environment
    EnvDefintionFile = 'PTVSEnvironment.csv'

    def __init__(self, **kwargs):
        """
        Constructor.

        :param **kwargs:         List of arbitrary keyworded arguments to be processed as instance variable data
        """
        super(PymakeInterpreter, self).__init__()
        self._import(kwargs)

    @staticmethod
    def from_directory(directory):
        """
        Creates one or more PymakeInterpreter(s) from all PTVSEnvironment.csv files recursively found in the directory.

        :param directory: The absolute path to the root directory.
        :return           A valid PymakeInterpreter instance if succesful; None otherwise.
        """
        interpreters = []
        for root, dirnames, filenames in os.walk(directory):
            for filename in fnmatch.filter(filenames, PymakeInterpreter.EnvDefintionFile):
                interpreters.extend( PymakeInterpreter.from_file(os.path.join(root, filename)))
        return interpreters

    @staticmethod
    def from_virtual_environment(directory):
        """
        Creates a PymakeInterpreter from an Python Virtual Environment in the directory.

        :param directory: The absolute path to the python installation directory.
        :return           A valid PymakeInterpreter instance if succesful; None otherwise.
        """
        root = os.path.abspath(directory)
        python = os.path.abspath(os.path.join(root, 'Scripts', 'python.exe'))
        if not os.path.exists(python):
            return None

        root = os.path.abspath(directory)
        origprefix = os.path.abspath(os.path.join(root, 'Lib', 'orig-prefix.txt'))
        if not os.path.exists(origprefix):
            return None

        with open(origprefix) as f:
            basedir = os.path.abspath(f.readlines()[0])
            baseinterpretter = PymakeInterpreter.from_python_installation(basedir)

        args = {
            'Path': root,
            'BaseInterpreter': baseinterpretter.GUID,
            'InterpreterPath': os.path.join('Scripts', 'python.exe'),
            'Description': '{} ({})'.format(os.path.basename(root), baseinterpretter.Description),
        }

        if os.path.exists(os.path.join(root, 'Scripts', 'pythonw.exe')):
            args['WindowsInterpreterPath'] = os.path.join('Scripts', 'pythonw.exe')

        if os.path.exists(os.path.join(root, 'Lib')):
            args['LibraryPath'] = 'Lib\\'

        try:
            out, err = subprocess.Popen([python, '-c', 'import sys;print ".".join(str(s) for s in sys.version_info[:2])'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
            args['Version'] = out.rstrip()
        except Exception as e:
            pass

        try:
            out, err = subprocess.Popen([python, '-c', 'import platform; print "Amd64" if "64bit" in platform.architecture() else "x86"'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
            args['Architecture'] = out.rstrip()
        except Exception:
            pass

        interpreter = PymakeInterpreter(**args)
        return interpreter

    @staticmethod
    def from_python_installation(directory):
        """
        Creates a PymakeInterpreter from an Python Installation in the directory.

        :param directory: The absolute path to the python installation directory.
        :return           A valid PymakeInterpreter instance if succesful; None otherwise.
        """
        root = os.path.abspath(directory)
        python = os.path.abspath(os.path.join(root, 'python.exe'))
        if not os.path.exists(python):
            return None

        args = {
            'Path': root,
            'InterpreterPath': 'python.exe',
            'Description': os.path.basename(root)
        }

        if os.path.exists(os.path.join(root, 'pythonw.exe')):
            args['WindowsInterpreterPath'] = 'pythonw.exe'

        if os.path.exists(os.path.join(root, 'Lib')):
            args['LibraryPath'] = 'Lib\\'

        try:
            out, err = subprocess.Popen([python, '-c', 'import sys;print ".".join(str(s) for s in sys.version_info[:2])'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
            args['Version'] = out.rstrip()
        except Exception as e:
            pass

        try:
            out, err = subprocess.Popen([python, '-c', 'import platform; print "Amd64" if "64bit" in platform.architecture() else "x86"'], stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
            args['Architecture'] = out.rstrip()
        except Exception:
            pass

        interpreter = PymakeInterpreter(**args)
        interpreter.resolve()
        return interpreter

    @staticmethod
    def from_file(filename):
        """
        Creates one or more PymakeInterpreter(s) from a single PTVSEnvironment.csv file.

        :param filename:  The absolute path to the PTVSEnvironment.csv file.
        :return           List of PymakeInterpreter instances; an empty list otherwise.
        """
        interpreters = []
        try:
            with open(filename, 'rb') as csvfile:
                reader = csv.DictReader(csvfile, delimiter=',', quotechar='"')
                for line in reader:
                    line['Path'] = os.path.dirname(filename)
                    interpreters.append(PymakeInterpreter(**line))
        except IOError:
            pass

        return interpreters

    @staticmethod
    def from_registry_key(keyname):
        """
        Creates a PymakeInterpreter from a single registry key.

        :param keyname:  The keyname under HKEY_CURRENT_USER referring to the environment.
        :return:         A valid PymakeInterpreter instance if succesful; None otherwise.
        """
        args = {}
        try:
            regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, keyname)
            for k in ['Architecture', 'Description', 'InterpreterPath', 'LibraryPath', 'PathEnvironmentVariable', 'Version', 'WindowsInterpreterPath', 'PathEnvironmentVariable']:
                args[k] = winreg.QueryValueEx(regkey, k)[0]
            winreg.CloseKey(regkey)
        except WindowsError as ex:
            pass

        if 'InterpreterPath' in args:
            args['Path'] = os.path.dirname(args['InterpreterPath'])
            args['Id'] = os.path.basename(keyname)[1:-1]
            return PymakeInterpreter(**args)
        return None

    def _import(self, datadict):
        """
        Internal method to import instance variables data from a dictionary.

        :param datadict: The dictionary containing variables values.
        """
        self.GUID                       = datadict.get('Id', uuid.uuid1())
        self.BaseInterpreter            = datadict.get('BaseInterpreter', self.GUID)
        self.Architecture               = datadict.get('Architecture', "")
        self.Version                    = datadict.get('Version', "")
        self.Path                       = datadict.get('Path', "")
        self.Description                = datadict.get('Description', "")
        self.InterpreterPath            = datadict.get('InterpreterPath', "")
        self.InterpreterAbsPath         = datadict.get('InterpreterAbsPath', self.InterpreterPath if os.path.isabs(self.InterpreterPath) else os.path.abspath(os.path.join(self.Path, self.InterpreterPath)))
        self.WindowsInterpreterPath     = datadict.get('WindowsInterpreterPath', "")
        self.WindowsInterpreterAbsPath  = datadict.get('WindowsInterpreterAbsPath', self.WindowsInterpreterPath if os.path.isabs(self.WindowsInterpreterPath) else os.path.abspath(os.path.join(self.Path, self.WindowsInterpreterPath)))
        self.LibraryPath                = datadict.get('LibraryPath', "")
        self.LibraryAbsPath             = datadict.get('LibraryAbsPath', self.LibraryPath if os.path.isabs(self.LibraryPath) else os.path.abspath(os.path.join(self.Path, self.LibraryPath)))
        self.PathEnvironmentVariable    = datadict.get('PathEnvironmentVariable', "")

    def resolve(self):
        """
        'Resolves' the environment with existing environments in the windows registry.
        """
        regkey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, self.regkey_name)
        try:
            reginfo = winreg.QueryInfoKey(regkey)
            for i in range(reginfo[0]):
                regkey_name = '{0}\\{1}'.format(self.regkey_name, winreg.EnumKey(regkey, i))
                interpreter = PymakeInterpreter.from_registry_key(regkey_name)
                if interpreter and interpreter.InterpreterAbsPath == self.InterpreterAbsPath:
                    self.GUID = uuid.UUID(interpreter.GUID)
                    self.BaseInterpreter = self.GUID
                    break
        except WindowsError as ex:
            pass

    def register(self):
        """
        'Registers' the environment into the windows registry.

        :..note: https://pytools.codeplex.com/workitem/2765
        """
        regkey_name = '{0}\\{{{1}}}'.format(self.regkey_name, str(self.GUID).lower())
        try:
            regkey = winreg.CreateKey(winreg.HKEY_CURRENT_USER, regkey_name)
            winreg.SetValueEx(regkey, 'Architecture', 0, winreg.REG_SZ, self.Architecture)
            winreg.SetValueEx(regkey, 'Description', 0, winreg.REG_SZ, self.Description)
            winreg.SetValueEx(regkey, 'InterpreterPath', 0, winreg.REG_SZ, self.InterpreterAbsPath)
            winreg.SetValueEx(regkey, 'LibraryPath', 0, winreg.REG_SZ, self.LibraryAbsPath)
            winreg.SetValueEx(regkey, 'PathEnvironmentVariable', 0, winreg.REG_SZ, self.PathEnvironmentVariable)
            winreg.SetValueEx(regkey, 'Version', 0, winreg.REG_SZ, self.Version)
            winreg.SetValueEx(regkey, 'WindowsInterpreterPath', 0, winreg.REG_SZ, self.WindowsInterpreterAbsPath)
            winreg.SetValueEx(regkey, 'PathEnvironmentVariable', 0, winreg.REG_SZ, self.PathEnvironmentVariable)
            winreg.CloseKey(regkey)
        except WindowsError as ex:
            return False
        return True
<|endoftext|>


<commit_before>from django.db.models import Field
from django.forms import widgets
from s3direct.widgets import S3DirectEditor
from django.conf import settings

class S3DirectField(Field):
    def __init__(self, *args, **kwargs):
        upload_to = kwargs.pop('upload_to', '')
        self.widget = S3DirectEditor(upload_to=upload_to)
        super(S3DirectField, self).__init__(*args, **kwargs)

    def get_internal_type(self):
        return "TextField"

    def formfield(self, **kwargs):
        defaults = {'widget': self.widget}
        defaults.update(kwargs)
        return super(S3DirectField, self).formfield(**defaults)

if 'south' in settings.INSTALLED_APPS:
    from south.modelsinspector import add_introspection_rules
    add_introspection_rules([], ["^s3direct\.fields\.S3DirectField"])<commit_msg>Return a URL field.<commit_after>from django.db.models import Field
from django.conf import settings
from s3direct.widgets import S3DirectWidget

S3DIRECT_DIR = getattr(settings, 'S3DIRECT_DIR', 's3direct')

class S3DirectField(Field):
    def __init__(self, upload_to=S3DIRECT_DIR):
        self.widget = S3DirectWidget(upload_to=upload_to)
        super(S3DirectField, self).__init__()

    def get_internal_type(self):
        return 'URLField'

    def formfield(self, **kwargs):
        defaults = {'widget': self.widget}
        defaults.update(kwargs)
        return super(S3DirectField, self).formfield(**defaults)

if 'south' in settings.INSTALLED_APPS:
    from south.modelsinspector import add_introspection_rules
    add_introspection_rules([], ["^s3direct\.fields\.S3DirectField"])<|endoftext|>


<commit_before>__prog__ = 's3pypi'
__version__ = u'0.8.0'
<commit_msg>Version bump<commit_after>__prog__ = 's3pypi'
__version__ = u'0.9.0'
<|endoftext|>


<commit_before>from accelerator_abstract.models import (
    FORM_ELEM_FEEDBACK_TO_MC,
    FORM_ELEM_FEEDBACK_TO_STARTUP,
    FORM_ELEM_OVERALL_RECOMMENDATION,
)

from accelerator.models import (
    ASSIGNED_PANEL_ASSIGNMENT_STATUS,
    COMPLETE_PANEL_ASSIGNMENT_STATUS,
    FEEDBACK_DISPLAY_DISABLED as DISABLED,
    FEEDBACK_DISPLAY_ENABLED as ENABLED,
    IN_PERSON_JUDGING_ROUND_TYPE,
    ONLINE_JUDGING_ROUND_TYPE,

    PREVIEW_PANEL_STATUS,
    SUBMITTED_APP_STATUS,
    UserRole,
)
from accelerator.tests.factories import (
    ApplicationAnswerFactory,
    ApplicationFactory,
    ApplicationPanelAssignmentFactory,
    ExpertFactory,
    JudgeApplicationFeedbackFactory,
    JudgeFeedbackComponentFactory,
    JudgePanelAssignmentFactory,
    JudgeRoundCommitmentFactory,
    JudgingFormElementFactory,
    JudgingRoundFactory,
    PanelFactory,
    ProgramCycleFactory,
    ProgramRoleFactory,
    ProgramRoleGrantFactory,
    ScenarioFactory,
    StartupCycleInterestFactory,
    StartupProgramInterestFactory,
)

ELEMENT_NAMES = [
    FORM_ELEM_OVERALL_RECOMMENDATION,
    FORM_ELEM_FEEDBACK_TO_STARTUP,
    FORM_ELEM_FEEDBACK_TO_MC,
]
_round_type = {True: ONLINE_JUDGING_ROUND_TYPE,
               False: IN_PERSON_JUDGING_ROUND_TYPE}

class JudgeFeedbackContext:
    def __init__(self,
                 application=None,
                 num_components=1,
                 complete=True,
                 panel_status=PREVIEW_PANEL_STATUS,
                 display_feedback=False,
                 merge_feedback_with=None,
                 cycle_based_round=False,
                 online_round=True,
                 is_active=True,
                 judge_capacity=10):
        self.judging_capacity = 0
        if application:
            self.application = application
            self.cycle = application.cycle
        else:
            self.cycle = ProgramCycleFactory()
            self.application = ApplicationFactory(
                application_status=SUBMITTED_APP_STATUS,
                application_type=self.cycle.default_application_type,
                cycle=self.cycle)
        self.application_type = self.application.application_type
        self.applications = [self.application]
        self.startup = self.application.startup
        self.industry = self.startup.primary_industry
        feedback_display = ENABLED if display_feedback else DISABLED
        jr_kwargs = {
            'program__cycle': self.cycle,
            'round_type': _round_type[online_round],
            'feedback_display': feedback_display,
            'cycle_based_round': cycle_based_round,
            'application_type': self.application_type,
            'is_active': is_active,
        }
        if merge_feedback_with:
            jr_kwargs['feedback_merge_with'] = merge_feedback_with
        self.judging_round = JudgingRoundFactory(**jr_kwargs)
        self.program = self.judging_round.program
        self.panel = PanelFactory(status=panel_status,
                                  panel_time__judging_round=self.judging_round)
        self.scenario = ScenarioFactory(judging_round=self.judging_round)
        self.judge_role = ProgramRoleFactory(program=self.program,
                                             user_role__name=UserRole.JUDGE)
        self.judges = []
        self.judge = self.add_judge(complete=complete,
                                    capacity=judge_capacity)
        self.feedback = JudgeApplicationFeedbackFactory(
            judge=self.judge,
            application=self.application,
            panel=self.panel,
            form_type=self.judging_round.judging_form)
        self.judging_form = self.feedback.form_type
        self.application_assignment = ApplicationPanelAssignmentFactory(
            application=self.application,
            panel=self.panel,
            scenario=self.scenario)
        cycle_interest = StartupCycleInterestFactory(cycle=self.program.cycle,
                                                     startup=self.startup)
        StartupProgramInterestFactory(program=self.program,
                                      startup=self.startup,
                                      startup_cycle_interest=cycle_interest,
                                      applying=True)
        self.components = []
        self.elements = []
        self.application_questions = []
        self.application_answers = []
        for element_name in ELEMENT_NAMES:
            self.add_component(element_name=element_name)

        if complete:
            self.feedback.save()
            for _ in range(num_components):
                self.add_component()
        else:
            for _ in range(num_components):
                self.add_element()

    def add_application_answer(self, question=None, answer_text=None):
        question = question or self.application_questions[0]
        kwargs = {"application_question": question,
                  "application": self.application}
        if answer_text:
            kwargs["answer_text"] = answer_text
        app_answer = ApplicationAnswerFactory(**kwargs)
        self.application_answers.append(app_answer)
        return app_answer

    def add_component(self, element_name=None,
                      feedback_element=None,
                      add_answer=True,
                      answer_text=None):

        factory_params = {
            "judge_feedback": self.feedback, }

        if feedback_element is None:
            app_type_key = "__".join(["feedback_element",
                                      "application_question",
                                      "application_type"])
            factory_params.update(
                {
                    "feedback_element__form_type": self.judging_form,
                    "feedback_element__element_type": "feedback",
                    "feedback_element__mandatory": True,
                    "feedback_element__sharing": "share-with-startup",
                    app_type_key: self.application_type}
            )
            if element_name:
                factory_params['feedback_element__element_name'] = element_name
        else:
            factory_params.update({"feedback_element": feedback_element})

        if answer_text:
            factory_params["answer_text"] = answer_text

        component = JudgeFeedbackComponentFactory(
            **factory_params)
        self.components.append(component)
        question = component.feedback_element.application_question
        self.application_questions.append(question)
        if add_answer:
            app_answer = ApplicationAnswerFactory(
                application_question=question,
                application=self.application)
            self.application_answers.append(app_answer)
        if feedback_element is None:
            self.elements.append(component.feedback_element)
        self.feedback.save()
        return component

    def add_element(self,
                    feedback_type="",
                    element_type="feedback",
                    choice_layout="",
                    mandatory=True,
                    text_minimum=0,
                    text_minimum_units="",
                    answer_text=None):
        element = JudgingFormElementFactory(
            form_type=self.judging_form,
            mandatory=mandatory,
            element_type=element_type,
            feedback_type=feedback_type,
            choice_layout=choice_layout,
            sharing="share-with-startup",
            application_question__application_type=self.application_type,
            text_minimum=text_minimum,
            text_minimum_units=text_minimum_units
        )
        application_question = element.application_question
        self.application_questions.append(application_question)
        answer_kwargs = {"application_question": application_question,
                         "application": self.application}
        if answer_text:
            answer_kwargs["answer_text"] = answer_text
        application_answer = ApplicationAnswerFactory(**answer_kwargs)
        self.application_answers.append(application_answer)
        self.elements.append(element)
        self.feedback.save()
        return element

    def add_extra_scenario(self):
        return ScenarioFactory(judging_round=self.judging_round)

    def add_panel(self):
        return PanelFactory(
            panel_time__judging_round=self.judging_round,
            panel_type__judging_round=self.judging_round,
            location__judging_round=self.judging_round)

    def add_assignment(self,
                       judge=None,
                       panel=None,
                       scenario=None):
        scenario = scenario or self.scenario
        judge = judge or self.judge
        panel = panel or self.panel
        return JudgePanelAssignmentFactory(
            judge=judge,
            panel=panel,
            scenario=scenario)

    def add_feedback(self,
                     application=None,
                     judge=None,
                     panel=None):
        judge = judge or self.judge
        application = application or self.application
        panel = panel or self.panel
        if not panel.applicationpanelassignment_set.filter(
                application=application).exists():
            ApplicationPanelAssignmentFactory(
                application=application,
                panel=panel,
                scenario=self.scenario)
        return JudgeApplicationFeedbackFactory(
            judge=judge,
            application=application,
            panel=panel,
            form_type=self.judging_round.judging_form)

    def add_application(self,
                        application=None,
                        field=None,
                        option=None,
                        program=None):
        program = program or self.program
        if application is None:
            fields = {
                "application_status": SUBMITTED_APP_STATUS,
                "application_type": self.application_type,
            }
            if field:
                fields[field] = option
            application = ApplicationFactory(**fields)
        self.applications.append(application)
        startup = application.startup
        cycle_interest = StartupCycleInterestFactory(cycle=program.cycle,
                                                     startup=startup)
        StartupProgramInterestFactory(program=program,
                                      startup=startup,
                                      startup_cycle_interest=cycle_interest,
                                      applying=True)

    def add_applications(self, count, field=None, options=[], programs=[]):
        result = []
        option_count = len(options)
        option = None
        program_count = len(programs)
        program = None
        for i in range(count):
            if option_count > 0:
                option = options[i % option_count]
            if program_count > 0:
                program = programs[i % program_count]
            result.append(self.add_application(field=field,
                                               option=option,
                                               program=program))
        return result

    def add_judge(self,
                  assigned=True,
                  complete=True,
                  judge=None,
                  panel=None,
                  capacity=10):
        if judge is None:
            judge = ExpertFactory(
                profile__primary_industry=self.industry,
                profile__home_program_family=self.program.program_family)
        ProgramRoleGrantFactory(person=judge, program_role=self.judge_role)
        self.judging_round.confirmed_judge_label.users.add(judge)
        JudgeRoundCommitmentFactory(judging_round=self.judging_round,
                                    judge=judge,
                                    capacity=10,
                                    commitment_state=True)
        self.judging_capacity += capacity
        if assigned:
            if complete:
                status = COMPLETE_PANEL_ASSIGNMENT_STATUS
            else:
                status = ASSIGNED_PANEL_ASSIGNMENT_STATUS
            JudgePanelAssignmentFactory(
                judge=judge,
                assignment_status=status,
                panel=panel or self.panel,
                scenario=self.scenario)
        self.judges.append(judge)
        return judge

    @classmethod
    def create_batch(cls, qty, *args, **kwargs):
        if 'merge_feedback' in kwargs:
            merge_feedback = kwargs.pop('merge_feedback')
        else:
            merge_feedback = False
        contexts = [cls(*args, **kwargs)]
        if merge_feedback:
            kwargs['merge_feedback_with'] = contexts[0].judging_round
        for _ in range(1, qty):
            contexts.append(cls(*args, **kwargs))
        return contexts
<commit_msg>[AC-5853] JudgeFeedbackContext sets initial interest level to 1<commit_after>from accelerator_abstract.models import (
    FORM_ELEM_FEEDBACK_TO_MC,
    FORM_ELEM_FEEDBACK_TO_STARTUP,
    FORM_ELEM_OVERALL_RECOMMENDATION,
)

from accelerator.models import (
    ASSIGNED_PANEL_ASSIGNMENT_STATUS,
    COMPLETE_PANEL_ASSIGNMENT_STATUS,
    FEEDBACK_DISPLAY_DISABLED as DISABLED,
    FEEDBACK_DISPLAY_ENABLED as ENABLED,
    IN_PERSON_JUDGING_ROUND_TYPE,
    ONLINE_JUDGING_ROUND_TYPE,

    PREVIEW_PANEL_STATUS,
    SUBMITTED_APP_STATUS,
    UserRole,
)
from accelerator.tests.factories import (
    ApplicationAnswerFactory,
    ApplicationFactory,
    ApplicationPanelAssignmentFactory,
    ExpertFactory,
    JudgeApplicationFeedbackFactory,
    JudgeFeedbackComponentFactory,
    JudgePanelAssignmentFactory,
    JudgeRoundCommitmentFactory,
    JudgingFormElementFactory,
    JudgingRoundFactory,
    PanelFactory,
    ProgramCycleFactory,
    ProgramRoleFactory,
    ProgramRoleGrantFactory,
    ScenarioFactory,
    StartupCycleInterestFactory,
    StartupProgramInterestFactory,
)

ELEMENT_NAMES = [
    FORM_ELEM_OVERALL_RECOMMENDATION,
    FORM_ELEM_FEEDBACK_TO_STARTUP,
    FORM_ELEM_FEEDBACK_TO_MC,
]
_round_type = {True: ONLINE_JUDGING_ROUND_TYPE,
               False: IN_PERSON_JUDGING_ROUND_TYPE}

class JudgeFeedbackContext:
    def __init__(self,
                 application=None,
                 num_components=1,
                 complete=True,
                 panel_status=PREVIEW_PANEL_STATUS,
                 display_feedback=False,
                 merge_feedback_with=None,
                 cycle_based_round=False,
                 online_round=True,
                 is_active=True,
                 judge_capacity=10):
        self.judging_capacity = 0
        if application:
            self.application = application
            self.cycle = application.cycle
        else:
            self.cycle = ProgramCycleFactory()
            self.application = ApplicationFactory(
                application_status=SUBMITTED_APP_STATUS,
                application_type=self.cycle.default_application_type,
                cycle=self.cycle)
        self.application_type = self.application.application_type
        self.applications = [self.application]
        self.startup = self.application.startup
        self.industry = self.startup.primary_industry
        feedback_display = ENABLED if display_feedback else DISABLED
        jr_kwargs = {
            'program__cycle': self.cycle,
            'round_type': _round_type[online_round],
            'feedback_display': feedback_display,
            'cycle_based_round': cycle_based_round,
            'application_type': self.application_type,
            'is_active': is_active,
        }
        if merge_feedback_with:
            jr_kwargs['feedback_merge_with'] = merge_feedback_with
        self.judging_round = JudgingRoundFactory(**jr_kwargs)
        self.program = self.judging_round.program
        self.panel = PanelFactory(status=panel_status,
                                  panel_time__judging_round=self.judging_round)
        self.scenario = ScenarioFactory(judging_round=self.judging_round)
        self.judge_role = ProgramRoleFactory(program=self.program,
                                             user_role__name=UserRole.JUDGE)
        self.judges = []
        self.judge = self.add_judge(complete=complete,
                                    capacity=judge_capacity)
        self.feedback = JudgeApplicationFeedbackFactory(
            judge=self.judge,
            application=self.application,
            panel=self.panel,
            form_type=self.judging_round.judging_form)
        self.judging_form = self.feedback.form_type
        self.application_assignment = ApplicationPanelAssignmentFactory(
            application=self.application,
            panel=self.panel,
            scenario=self.scenario)
        cycle_interest = StartupCycleInterestFactory(cycle=self.program.cycle,
                                                     startup=self.startup)
        StartupProgramInterestFactory(program=self.program,
                                      startup=self.startup,
                                      startup_cycle_interest=cycle_interest,
                                      applying=True)
        self.components = []
        self.elements = []
        self.application_questions = []
        self.application_answers = []
        for element_name in ELEMENT_NAMES:
            self.add_component(element_name=element_name)

        if complete:
            self.feedback.save()
            for _ in range(num_components):
                self.add_component()
        else:
            for _ in range(num_components):
                self.add_element()

    def add_application_answer(self, question=None, answer_text=None):
        question = question or self.application_questions[0]
        kwargs = {"application_question": question,
                  "application": self.application}
        if answer_text:
            kwargs["answer_text"] = answer_text
        app_answer = ApplicationAnswerFactory(**kwargs)
        self.application_answers.append(app_answer)
        return app_answer

    def add_component(self, element_name=None,
                      feedback_element=None,
                      add_answer=True,
                      answer_text=None):

        factory_params = {
            "judge_feedback": self.feedback, }

        if feedback_element is None:
            app_type_key = "__".join(["feedback_element",
                                      "application_question",
                                      "application_type"])
            factory_params.update(
                {
                    "feedback_element__form_type": self.judging_form,
                    "feedback_element__element_type": "feedback",
                    "feedback_element__mandatory": True,
                    "feedback_element__sharing": "share-with-startup",
                    app_type_key: self.application_type}
            )
            if element_name:
                factory_params['feedback_element__element_name'] = element_name
        else:
            factory_params.update({"feedback_element": feedback_element})

        if answer_text:
            factory_params["answer_text"] = answer_text

        component = JudgeFeedbackComponentFactory(
            **factory_params)
        self.components.append(component)
        question = component.feedback_element.application_question
        self.application_questions.append(question)
        if add_answer:
            app_answer = ApplicationAnswerFactory(
                application_question=question,
                application=self.application)
            self.application_answers.append(app_answer)
        if feedback_element is None:
            self.elements.append(component.feedback_element)
        self.feedback.save()
        return component

    def add_element(self,
                    feedback_type="",
                    element_type="feedback",
                    choice_layout="",
                    mandatory=True,
                    text_minimum=0,
                    text_minimum_units="",
                    answer_text=None):
        element = JudgingFormElementFactory(
            form_type=self.judging_form,
            mandatory=mandatory,
            element_type=element_type,
            feedback_type=feedback_type,
            choice_layout=choice_layout,
            sharing="share-with-startup",
            application_question__application_type=self.application_type,
            text_minimum=text_minimum,
            text_minimum_units=text_minimum_units
        )
        application_question = element.application_question
        self.application_questions.append(application_question)
        answer_kwargs = {"application_question": application_question,
                         "application": self.application}
        if answer_text:
            answer_kwargs["answer_text"] = answer_text
        application_answer = ApplicationAnswerFactory(**answer_kwargs)
        self.application_answers.append(application_answer)
        self.elements.append(element)
        self.feedback.save()
        return element

    def add_extra_scenario(self):
        return ScenarioFactory(judging_round=self.judging_round)

    def add_panel(self):
        return PanelFactory(
            panel_time__judging_round=self.judging_round,
            panel_type__judging_round=self.judging_round,
            location__judging_round=self.judging_round)

    def add_assignment(self,
                       judge=None,
                       panel=None,
                       scenario=None):
        scenario = scenario or self.scenario
        judge = judge or self.judge
        panel = panel or self.panel
        return JudgePanelAssignmentFactory(
            judge=judge,
            panel=panel,
            scenario=scenario)

    def add_feedback(self,
                     application=None,
                     judge=None,
                     panel=None):
        judge = judge or self.judge
        application = application or self.application
        panel = panel or self.panel
        if not panel.applicationpanelassignment_set.filter(
                application=application).exists():
            ApplicationPanelAssignmentFactory(
                application=application,
                panel=panel,
                scenario=self.scenario)
        return JudgeApplicationFeedbackFactory(
            judge=judge,
            application=application,
            panel=panel,
            form_type=self.judging_round.judging_form)

    def add_application(self,
                        application=None,
                        field=None,
                        option=None,
                        program=None):
        program = program or self.program
        if application is None:
            fields = {
                "application_status": SUBMITTED_APP_STATUS,
                "application_type": self.application_type,
            }
            if field:
                fields[field] = option
            application = ApplicationFactory(**fields)
        self.applications.append(application)
        startup = application.startup
        cycle_interest = StartupCycleInterestFactory(cycle=program.cycle,
                                                     startup=startup)
        StartupProgramInterestFactory(program=program,
                                      startup=startup,
                                      startup_cycle_interest=cycle_interest,
                                      applying=True,
                                      interest_level=1)

    def add_applications(self, count, field=None, options=[], programs=[]):
        result = []
        option_count = len(options)
        option = None
        program_count = len(programs)
        program = None
        for i in range(count):
            if option_count > 0:
                option = options[i % option_count]
            if program_count > 0:
                program = programs[i % program_count]
            result.append(self.add_application(field=field,
                                               option=option,
                                               program=program))
        return result

    def add_judge(self,
                  assigned=True,
                  complete=True,
                  judge=None,
                  panel=None,
                  capacity=10):
        if judge is None:
            judge = ExpertFactory(
                profile__primary_industry=self.industry,
                profile__home_program_family=self.program.program_family)
        ProgramRoleGrantFactory(person=judge, program_role=self.judge_role)
        self.judging_round.confirmed_judge_label.users.add(judge)
        JudgeRoundCommitmentFactory(judging_round=self.judging_round,
                                    judge=judge,
                                    capacity=10,
                                    commitment_state=True)
        self.judging_capacity += capacity
        if assigned:
            if complete:
                status = COMPLETE_PANEL_ASSIGNMENT_STATUS
            else:
                status = ASSIGNED_PANEL_ASSIGNMENT_STATUS
            JudgePanelAssignmentFactory(
                judge=judge,
                assignment_status=status,
                panel=panel or self.panel,
                scenario=self.scenario)
        self.judges.append(judge)
        return judge

    @classmethod
    def create_batch(cls, qty, *args, **kwargs):
        if 'merge_feedback' in kwargs:
            merge_feedback = kwargs.pop('merge_feedback')
        else:
            merge_feedback = False
        contexts = [cls(*args, **kwargs)]
        if merge_feedback:
            kwargs['merge_feedback_with'] = contexts[0].judging_round
        for _ in range(1, qty):
            contexts.append(cls(*args, **kwargs))
        return contexts
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
#    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 time

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

class account_automatic_reconcile(osv.osv_memory):
    _name = 'account.automatic.reconcile'
    _description = 'Automatic Reconcile'

    _columns = {
        'account_ids': fields.many2many('account.account', 'reconcile_account_rel', 'reconcile_id', 'account_id', 'Accounts to Reconcile', domain = [('reconcile','=',1)],),
        'writeoff_acc_id': fields.many2one('account.account', 'Account'),
        'journal_id': fields.many2one('account.journal', 'Journal'),
        'period_id': fields.many2one('account.period', 'Period'),
        'max_amount': fields.float('Maximum write-off amount'),
        'power': fields.selection([(p, str(p)) for p in range(2, 5)], 'Power', required=True, help='Number of partial amounts that can be combined to find a balance point can be chosen as the power of the automatic reconciliation'),
        'reconciled': fields.integer('Reconciled transactions', readonly=True),
        'unreconciled': fields.integer('Not reconciled transactions', readonly=True),
        'allow_write_off': fields.boolean('Allow write off')
    }

    def _get_reconciled(self, cr, uid, context=None):
        if context is None:
            context = {}
        return context.get('reconciled', 0)

    def _get_unreconciled(self, cr, uid, context=None):
        if context is None:
            context = {}
        return context.get('unreconciled', 0)

    _defaults = {
        'reconciled': _get_reconciled,
        'unreconciled': _get_unreconciled,
        'power': 2
    }

    #TODO: cleanup and comment this code... For now, it is awfulllll
    # (way too complex, and really slow)...
    def do_reconcile(self, cr, uid, credits, debits, max_amount, power, writeoff_acc_id, period_id, journal_id, context=None):
        """
        for one value of a credit, check all debits, and combination of them
        depending on the power. It starts with a power of one and goes up
        to the max power allowed.
        """
        move_line_obj = self.pool.get('account.move.line')
        if context is None:
            context = {}
        def check2(value, move_list, power):
            def check(value, move_list, power):
                for i in range(len(move_list)):
                    move = move_list[i]
                    if power == 1:
                        if abs(value - move[1]) <= max_amount + 0.00001:
                            return [move[0]]
                    else:
                        del move_list[i]
                        res = check(value - move[1], move_list, power-1)
                        move_list[i:i] = [move]
                        if res:
                            res.append(move[0])
                            return res
                return False

            for p in range(1, power+1):
                res = check(value, move_list, p)
                if res:
                    return res
            return False

        def check4(list1, list2, power):
            """
            for a list of credit and debit and a given power, check if there
            are matching tuples of credit and debits, check all debits, and combination of them
            depending on the power. It starts with a power of one and goes up
            to the max power allowed.
            """
            def check3(value, list1, list2, list1power, power):
                for i in range(len(list1)):
                    move = list1[i]
                    if list1power == 1:
                        res = check2(value + move[1], list2, power - 1)
                        if res:
                            return ([move[0]], res)
                    else:
                        del list1[i]
                        res = check3(value + move[1], list1, list2, list1power-1, power-1)
                        list1[i:i] = [move]
                        if res:
                            x, y = res
                            x.append(move[0])
                            return (x, y)
                return False

            for p in range(1, power):
                res = check3(0, list1, list2, p, power)
                if res:
                    return res
            return False

        def check5(list1, list2, max_power):
            for p in range(2, max_power+1):
                res = check4(list1, list2, p)
                if res:
                    return res
            return False

        ok = True
        reconciled = 0
        while credits and debits and ok:
            res = check5(credits, debits, power)
            if res:
                move_line_obj.reconcile(cr, uid, res[0] + res[1], 'auto', writeoff_acc_id, period_id, journal_id, context)
                reconciled += len(res[0]) + len(res[1])
                credits = [(id, credit) for (id, credit) in credits if id not in res[0]]
                debits = [(id, debit) for (id, debit) in debits if id not in res[1]]
            else:
                ok = False
        return (reconciled, len(credits)+len(debits))

    def reconcile(self, cr, uid, ids, context=None):
        move_line_obj = self.pool.get('account.move.line')
        obj_model = self.pool.get('ir.model.data')
        if context is None:
            context = {}
        form = self.browse(cr, uid, ids, context=context)[0]
        max_amount = form.max_amount or 0.0
        power = form.power
        allow_write_off = form.allow_write_off
        reconciled = unreconciled = 0
        if not form.account_ids:
            raise osv.except_osv(_('User Error!'), _('You must select accounts to reconcile.'))
        for account_id in form.account_ids:
            params = (account_id.id,)
            if not allow_write_off:
                query = """SELECT partner_id FROM account_move_line WHERE account_id=%s AND reconcile_id IS NULL
                AND state <> 'draft' GROUP BY partner_id
                HAVING ABS(SUM(debit-credit)) = 0.0 AND count(*)>0"""
            else:
                query = """SELECT partner_id FROM account_move_line WHERE account_id=%s AND reconcile_id IS NULL
                AND state <> 'draft' GROUP BY partner_id
                HAVING ABS(SUM(debit-credit)) < %s AND count(*)>0"""
                params += (max_amount,)
            # reconcile automatically all transactions from partners whose balance is 0
            cr.execute(query, params)
            partner_ids = [id for (id,) in cr.fetchall()]
            for partner_id in partner_ids:
                cr.execute(
                    "SELECT id " \
                    "FROM account_move_line " \
                    "WHERE account_id=%s " \
                    "AND partner_id=%s " \
                    "AND state <> 'draft' " \
                    "AND reconcile_id IS NULL",
                    (account_id.id, partner_id))
                line_ids = [id for (id,) in cr.fetchall()]
                if line_ids:
                    reconciled += len(line_ids)
                    if allow_write_off:
                        move_line_obj.reconcile(cr, uid, line_ids, 'auto', form.writeoff_acc_id.id, form.period_id.id, form.journal_id.id, context)
                    else:
                        move_line_obj.reconcile_partial(cr, uid, line_ids, 'manual', context=context)

            # get the list of partners who have more than one unreconciled transaction
            cr.execute(
                "SELECT partner_id " \
                "FROM account_move_line " \
                "WHERE account_id=%s " \
                "AND reconcile_id IS NULL " \
                "AND state <> 'draft' " \
                "AND partner_id IS NOT NULL " \
                "GROUP BY partner_id " \
                "HAVING count(*)>1",
                (account_id.id,))
            partner_ids = [id for (id,) in cr.fetchall()]
            #filter?
            for partner_id in partner_ids:
                # get the list of unreconciled 'debit transactions' for this partner
                cr.execute(
                    "SELECT id, debit " \
                    "FROM account_move_line " \
                    "WHERE account_id=%s " \
                    "AND partner_id=%s " \
                    "AND reconcile_id IS NULL " \
                    "AND state <> 'draft' " \
                    "AND debit > 0 " \
                    "ORDER BY date_maturity",
                    (account_id.id, partner_id))
                debits = cr.fetchall()

                # get the list of unreconciled 'credit transactions' for this partner
                cr.execute(
                    "SELECT id, credit " \
                    "FROM account_move_line " \
                    "WHERE account_id=%s " \
                    "AND partner_id=%s " \
                    "AND reconcile_id IS NULL " \
                    "AND state <> 'draft' " \
                    "AND credit > 0 " \
                    "ORDER BY date_maturity",
                    (account_id.id, partner_id))
                credits = cr.fetchall()

                (rec, unrec) = self.do_reconcile(cr, uid, credits, debits, max_amount, power, form.writeoff_acc_id.id, form.period_id.id, form.journal_id.id, context)
                reconciled += rec
                unreconciled += unrec

            # add the number of transactions for partners who have only one
            # unreconciled transactions to the unreconciled count
            partner_filter = partner_ids and 'AND partner_id not in (%s)' % ','.join(map(str, filter(None, partner_ids))) or ''
            cr.execute(
                "SELECT count(*) " \
                "FROM account_move_line " \
                "WHERE account_id=%s " \
                "AND reconcile_id IS NULL " \
                "AND state <> 'draft' " + partner_filter,
                (account_id.id,))
            additional_unrec = cr.fetchone()[0]
            unreconciled = unreconciled + additional_unrec
        context = dict(context, reconciled=reconciled, unreconciled=unreconciled)
        model_data_ids = obj_model.search(cr,uid,[('model','=','ir.ui.view'),('name','=','account_automatic_reconcile_view1')])
        resource_id = obj_model.read(cr, uid, model_data_ids, fields=['res_id'])[0]['res_id']
        return {
            'view_type': 'form',
            'view_mode': 'form',
            'res_model': 'account.automatic.reconcile',
            'views': [(resource_id,'form')],
            'type': 'ir.actions.act_window',
            'target': 'new',
            'context': context,
        }

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
<commit_msg>[FIX] Auto recondile shoud not move partial reconsilations<commit_after># -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
#    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 time

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

class account_automatic_reconcile(osv.osv_memory):
    _name = 'account.automatic.reconcile'
    _description = 'Automatic Reconcile'

    _columns = {
        'account_ids': fields.many2many('account.account', 'reconcile_account_rel', 'reconcile_id', 'account_id', 'Accounts to Reconcile', domain = [('reconcile','=',1)],),
        'writeoff_acc_id': fields.many2one('account.account', 'Account'),
        'journal_id': fields.many2one('account.journal', 'Journal'),
        'period_id': fields.many2one('account.period', 'Period'),
        'max_amount': fields.float('Maximum write-off amount'),
        'power': fields.selection([(p, str(p)) for p in range(2, 5)], 'Power', required=True, help='Number of partial amounts that can be combined to find a balance point can be chosen as the power of the automatic reconciliation'),
        'reconciled': fields.integer('Reconciled transactions', readonly=True),
        'unreconciled': fields.integer('Not reconciled transactions', readonly=True),
        'allow_write_off': fields.boolean('Allow write off')
    }

    def _get_reconciled(self, cr, uid, context=None):
        if context is None:
            context = {}
        return context.get('reconciled', 0)

    def _get_unreconciled(self, cr, uid, context=None):
        if context is None:
            context = {}
        return context.get('unreconciled', 0)

    _defaults = {
        'reconciled': _get_reconciled,
        'unreconciled': _get_unreconciled,
        'power': 2
    }

    #TODO: cleanup and comment this code... For now, it is awfulllll
    # (way too complex, and really slow)...
    def do_reconcile(self, cr, uid, credits, debits, max_amount, power, writeoff_acc_id, period_id, journal_id, context=None):
        """
        for one value of a credit, check all debits, and combination of them
        depending on the power. It starts with a power of one and goes up
        to the max power allowed.
        """
        move_line_obj = self.pool.get('account.move.line')
        if context is None:
            context = {}
        def check2(value, move_list, power):
            def check(value, move_list, power):
                for i in range(len(move_list)):
                    move = move_list[i]
                    if power == 1:
                        if abs(value - move[1]) <= max_amount + 0.00001:
                            return [move[0]]
                    else:
                        del move_list[i]
                        res = check(value - move[1], move_list, power-1)
                        move_list[i:i] = [move]
                        if res:
                            res.append(move[0])
                            return res
                return False

            for p in range(1, power+1):
                res = check(value, move_list, p)
                if res:
                    return res
            return False

        def check4(list1, list2, power):
            """
            for a list of credit and debit and a given power, check if there
            are matching tuples of credit and debits, check all debits, and combination of them
            depending on the power. It starts with a power of one and goes up
            to the max power allowed.
            """
            def check3(value, list1, list2, list1power, power):
                for i in range(len(list1)):
                    move = list1[i]
                    if list1power == 1:
                        res = check2(value + move[1], list2, power - 1)
                        if res:
                            return ([move[0]], res)
                    else:
                        del list1[i]
                        res = check3(value + move[1], list1, list2, list1power-1, power-1)
                        list1[i:i] = [move]
                        if res:
                            x, y = res
                            x.append(move[0])
                            return (x, y)
                return False

            for p in range(1, power):
                res = check3(0, list1, list2, p, power)
                if res:
                    return res
            return False

        def check5(list1, list2, max_power):
            for p in range(2, max_power+1):
                res = check4(list1, list2, p)
                if res:
                    return res
            return False

        ok = True
        reconciled = 0
        while credits and debits and ok:
            res = check5(credits, debits, power)
            if res:
                move_line_obj.reconcile(cr, uid, res[0] + res[1], 'auto', writeoff_acc_id, period_id, journal_id, context)
                reconciled += len(res[0]) + len(res[1])
                credits = [(id, credit) for (id, credit) in credits if id not in res[0]]
                debits = [(id, debit) for (id, debit) in debits if id not in res[1]]
            else:
                ok = False
        return (reconciled, len(credits)+len(debits))

    def reconcile(self, cr, uid, ids, context=None):
        move_line_obj = self.pool.get('account.move.line')
        obj_model = self.pool.get('ir.model.data')
        if context is None:
            context = {}
        form = self.browse(cr, uid, ids, context=context)[0]
        max_amount = form.max_amount or 0.0
        power = form.power
        allow_write_off = form.allow_write_off
        reconciled = unreconciled = 0
        if not form.account_ids:
            raise osv.except_osv(_('User Error!'), _('You must select accounts to reconcile.'))
        for account_id in form.account_ids:
            params = (account_id.id,)
            if not allow_write_off:
                query = """SELECT partner_id FROM account_move_line WHERE account_id=%s AND reconcile_id IS NULL
                AND reconcile_partial_id IS NULL
                AND state <> 'draft' GROUP BY partner_id
                HAVING ABS(SUM(debit-credit)) = 0.0 AND count(*)>0"""
            else:
                query = """SELECT partner_id FROM account_move_line WHERE account_id=%s AND reconcile_id IS NULL
                 AND reconcile_partial_id IS NULL
                 AND state <> 'draft' GROUP BY partner_id
                HAVING ABS(SUM(debit-credit)) < %s AND count(*)>0"""
                params += (max_amount,)
            # reconcile automatically all transactions from partners whose balance is 0
            cr.execute(query, params)
            partner_ids = [id for (id,) in cr.fetchall()]
            print "----- partner ids--------", partner_ids, query
            for partner_id in partner_ids:
                cr.execute(
                    "SELECT id " \
                    "FROM account_move_line " \
                    "WHERE account_id=%s " \
                    "AND partner_id=%s " \
                    "AND state <> 'draft' " \
                    "AND reconcile_partial_id IS NULL " \
                    "AND reconcile_id IS NULL",
                    (account_id.id, partner_id))
                line_ids = [id for (id,) in cr.fetchall()]
                if line_ids:
                    reconciled += len(line_ids)
                    if allow_write_off:
                        move_line_obj.reconcile(cr, uid, line_ids, 'auto', form.writeoff_acc_id.id, form.period_id.id, form.journal_id.id, context)
                    else:
                        move_line_obj.reconcile_partial(cr, uid, line_ids, 'manual', context=context)

            # get the list of partners who have more than one unreconciled transaction
            cr.execute(
                "SELECT partner_id " \
                "FROM account_move_line " \
                "WHERE account_id=%s " \
                "AND reconcile_id IS NULL " \
                "AND reconcile_partial_id IS NULL " \
                "AND state <> 'draft' " \
                "AND partner_id IS NOT NULL " \
                "GROUP BY partner_id " \
                "HAVING count(*)>1",
                (account_id.id,))
            partner_ids = [id for (id,) in cr.fetchall()]
            #filter?
            for partner_id in partner_ids:
                # get the list of unreconciled 'debit transactions' for this partner
                cr.execute(
                    "SELECT id, debit " \
                    "FROM account_move_line " \
                    "WHERE account_id=%s " \
                    "AND partner_id=%s " \
                    "AND reconcile_id IS NULL " \
                    "AND reconcile_partial_id IS NULL " \
                    "AND state <> 'draft' " \
                    "AND debit > 0 " \
                    "ORDER BY date_maturity",
                    (account_id.id, partner_id))
                debits = cr.fetchall()

                # get the list of unreconciled 'credit transactions' for this partner
                cr.execute(
                    "SELECT id, credit " \
                    "FROM account_move_line " \
                    "WHERE account_id=%s " \
                    "AND partner_id=%s " \
                    "AND reconcile_id IS NULL " \
                    "AND reconcile_partial_id IS NULL " \
                    "AND state <> 'draft' " \
                    "AND credit > 0 " \
                    "ORDER BY date_maturity",
                    (account_id.id, partner_id))
                credits = cr.fetchall()

                (rec, unrec) = self.do_reconcile(cr, uid, credits, debits, max_amount, power, form.writeoff_acc_id.id, form.period_id.id, form.journal_id.id, context)
                reconciled += rec
                unreconciled += unrec

            # add the number of transactions for partners who have only one
            # unreconciled transactions to the unreconciled count
            partner_filter = partner_ids and 'AND partner_id not in (%s)' % ','.join(map(str, filter(None, partner_ids))) or ''
            cr.execute(
                "SELECT count(*) " \
                "FROM account_move_line " \
                "WHERE account_id=%s " \
                "AND reconcile_id IS NULL " \
                "AND state <> 'draft' " + partner_filter,
                (account_id.id,))
            additional_unrec = cr.fetchone()[0]
            unreconciled = unreconciled + additional_unrec
        context = dict(context, reconciled=reconciled, unreconciled=unreconciled)
        model_data_ids = obj_model.search(cr,uid,[('model','=','ir.ui.view'),('name','=','account_automatic_reconcile_view1')])
        resource_id = obj_model.read(cr, uid, model_data_ids, fields=['res_id'])[0]['res_id']
        return {
            'view_type': 'form',
            'view_mode': 'form',
            'res_model': 'account.automatic.reconcile',
            'views': [(resource_id,'form')],
            'type': 'ir.actions.act_window',
            'target': 'new',
            'context': context,
        }

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
<|endoftext|>


<commit_before>'''
The caller module is used as a front-end to manage direct calls to the salt
minion modules.
'''

# Import python modules
import sys
import logging
import datetime
import traceback

# Import salt libs
import salt.loader
import salt.minion
import salt.output
from salt._compat import string_types
from salt.log import LOG_LEVELS

# Custom exceptions
from salt.exceptions import (
    SaltClientError,
    CommandNotFoundError,
    CommandExecutionError,
)

class Caller(object):
    '''
    Object to wrap the calling of local salt modules for the salt-call command
    '''
    def __init__(self, opts):
        '''
        Pass in the command line options
        '''
        self.opts = opts
        # Handle this here so other deeper code which might
        # be imported as part of the salt api doesn't do  a
        # nasty sys.exit() and tick off our developer users
        try:
            self.minion = salt.minion.SMinion(opts)
        except SaltClientError as exc:
            raise SystemExit(str(exc))

    def call(self):
        '''
        Call the module
        '''
        ret = {}
        fun = self.opts['fun']

        if fun not in self.minion.functions:
            sys.stderr.write('Function {0} is not available\n'.format(fun))
            sys.exit(1)
        try:
            args, kw = salt.minion.detect_kwargs(
                self.minion.functions[fun], self.opts['arg'])
            ret['return'] = self.minion.functions[fun](*args, **kw)
        except (TypeError, CommandExecutionError) as exc:
            msg = 'Error running \'{0}\': {1}\n'
            active_level = LOG_LEVELS.get(
                self.opts['log_level'].lower, logging.ERROR)
            if active_level <= logging.DEBUG:
                sys.stderr.write(traceback.format_exc())
            sys.stderr.write(msg.format(fun, str(exc)))
            sys.exit(1)
        except CommandNotFoundError as exc:
            msg = 'Command required for \'{0}\' not found: {1}\n'
            sys.stderr.write(msg.format(fun, str(exc)))
            sys.exit(1)
        if hasattr(self.minion.functions[fun], '__outputter__'):
            oput = self.minion.functions[fun].__outputter__
            if isinstance(oput, string_types):
                ret['out'] = oput
        if self.opts.get('return', ''):
            ret['id'] = self.opts['id']
            ret['jid'] = '{0:%Y%m%d%H%M%S%f}'.format(datetime.datetime.now())
            ret['fun'] = fun
            for returner in self.opts['return'].split(','):
                try:
                    self.minion.returners['{0}.returner'.format(returner)](ret)
                except Exception as exc:
                    pass

        return ret

    def print_docs(self):
        '''
        Pick up the documentation for all of the modules and print it out.
        '''
        docs = {}
        for name, func in self.minion.functions.items():
            if name not in docs:
                if func.__doc__:
                    docs[name] = func.__doc__
        for name in sorted(docs):
            if name.startswith(self.opts.get('fun', '')):
                print('{0}:\n{1}\n'.format(name, docs[name]))

    def print_grains(self):
        '''
        Print out the grains
        '''
        grains = salt.loader.grains(self.opts)
        salt.output.display_output(grains, 'yaml', self.opts)

    def run(self):
        '''
        Execute the salt call logic
        '''
        ret = self.call()
        salt.output.display_output(
                {'local': ret['return']},
                ret.get('out', 'pprint'),
                self.opts)
<commit_msg>Make salt-call register to the job cache<commit_after>'''
The caller module is used as a front-end to manage direct calls to the salt
minion modules.
'''

# Import python modules
import sys
import logging
import datetime
import traceback

# Import salt libs
import salt.loader
import salt.minion
import salt.output
from salt._compat import string_types
from salt.log import LOG_LEVELS

# Custom exceptions
from salt.exceptions import (
    SaltClientError,
    CommandNotFoundError,
    CommandExecutionError,
)

class Caller(object):
    '''
    Object to wrap the calling of local salt modules for the salt-call command
    '''
    def __init__(self, opts):
        '''
        Pass in the command line options
        '''
        self.opts = opts
        # Handle this here so other deeper code which might
        # be imported as part of the salt api doesn't do  a
        # nasty sys.exit() and tick off our developer users
        try:
            self.minion = salt.minion.SMinion(opts)
        except SaltClientError as exc:
            raise SystemExit(str(exc))

    def call(self):
        '''
        Call the module
        '''
        ret = {}
        fun = self.opts['fun']
        ret['jid'] = '{0:%Y%m%d%H%M%S%f}'.format(datetime.datetime.now())
        proc_fn = os.path.join(
                salt.minion.get_proc_dir(self.opts['cachedir']),
                data['jid'])
        if fun not in self.minion.functions:
            sys.stderr.write('Function {0} is not available\n'.format(fun))
            sys.exit(1)
        try:
            args, kw = salt.minion.detect_kwargs(
                self.minion.functions[fun], self.opts['arg'])
            sdata = {
                    'fun': fun,
                    'pid': os.getpid(),
                    'jid': ret['jid'],
                    'tgt': 'salt-call'}
            with open(proc_fn, 'w+') as fp_:
                fp_.write(self.serial.dumps(sdata))
            ret['return'] = self.minion.functions[fun](*args, **kw)
        except (TypeError, CommandExecutionError) as exc:
            msg = 'Error running \'{0}\': {1}\n'
            active_level = LOG_LEVELS.get(
                self.opts['log_level'].lower, logging.ERROR)
            if active_level <= logging.DEBUG:
                sys.stderr.write(traceback.format_exc())
            sys.stderr.write(msg.format(fun, str(exc)))
            sys.exit(1)
        except CommandNotFoundError as exc:
            msg = 'Command required for \'{0}\' not found: {1}\n'
            sys.stderr.write(msg.format(fun, str(exc)))
            sys.exit(1)
        try:
            os.remove(proc_fn)
        except (IOError, OSError):
            pass
        if hasattr(self.minion.functions[fun], '__outputter__'):
            oput = self.minion.functions[fun].__outputter__
            if isinstance(oput, string_types):
                ret['out'] = oput
        if self.opts.get('return', ''):
            ret['id'] = self.opts['id']
            ret['fun'] = fun
            for returner in self.opts['return'].split(','):
                try:
                    self.minion.returners['{0}.returner'.format(returner)](ret)
                except Exception as exc:
                    pass
        return ret

    def print_docs(self):
        '''
        Pick up the documentation for all of the modules and print it out.
        '''
        docs = {}
        for name, func in self.minion.functions.items():
            if name not in docs:
                if func.__doc__:
                    docs[name] = func.__doc__
        for name in sorted(docs):
            if name.startswith(self.opts.get('fun', '')):
                print('{0}:\n{1}\n'.format(name, docs[name]))

    def print_grains(self):
        '''
        Print out the grains
        '''
        grains = salt.loader.grains(self.opts)
        salt.output.display_output(grains, 'yaml', self.opts)

    def run(self):
        '''
        Execute the salt call logic
        '''
        ret = self.call()
        salt.output.display_output(
                {'local': ret['return']},
                ret.get('out', 'pprint'),
                self.opts)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
#    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 osv import fields, osv
import tools

class sale_journal_picking_report(osv.osv):
    """
    Picking list by journal and by invoice
    """
    _name = "sale.journal.picking.report"
    _description = "Picking lists"
    _auto = False
    _columns = {
        'name': fields.char('Year', size=64, required=False, readonly=True),
        'month': fields.selection([('01', 'January'), ('02', 'February'), ('03', 'March'), ('04', 'April'), ('05', 'May'), ('06', 'June'),
                          ('07', 'July'), ('08', 'August'), ('09', 'September'), ('10', 'October'), ('11', 'November'), ('12', 'December')], 'Month', readonly=True),

        'invoice_state':fields.selection([
            ("invoiced", "invoiced"),
            ("2binvoiced", "to be invoiced"),
            ("none", "None")
        ], "Invoice state", readonly=True),
        'state': fields.selection([
            ('draft', 'draft'),
            ('auto', 'waiting'),
            ('confirmed', 'confirmed'),
            ('assigned', 'assigned'),
            ('done', 'done'),
            ('cancel', 'cancel'),
        ], 'State', readonly=True),
        'invoice_type_id': fields.many2one('sale_journal.invoice.type', 'Invoicing method', readonly=True),
        'journal_id': fields.many2one('sale_journal.picking.journal', 'Journal', readonly=True),
        'quantity': fields.float('Quantities', readonly=True),
        'price_total': fields.float('Total Price', readonly=True),
        'price_average': fields.float('Average Price', readonly=True),
        'count': fields.integer('# of Lines', readonly=True),
    }
    _order = 'journal_id, name desc, price_total desc'

    def init(self, cr):
        tools.drop_view_if_exists(cr, 'sale_journal_picking_report')

        cr.execute("""
            create or replace view sale_journal_picking_report as (
                select
                    min(l.id) as id,
                    to_char(s.date, 'YYYY') as name,
                    to_char(s.date, 'MM') as month,
                    s.state,
                    s.invoice_state,
                    s.invoice_type_id,
                    s.journal_id,
                    sum(l.product_qty) as quantity,
                    count(*) as count,
                    sum(l.product_qty*ol.price_unit*(1.0-ol.discount/100.0)) as price_total,
                    (sum(l.product_qty*ol.price_unit*(1.0-ol.discount/100.0))/sum(l.product_qty))::decimal(16,2) as price_average
                from stock_picking s
                    right join stock_move l on (s.id=l.picking_id)
                    left join sale_order_line ol on (l.sale_line_id=ol.id)
                group by s.journal_id, s.invoice_type_id, to_char(s.date, 'YYYY'),to_char(s.date, 'MM'),s.state, s.invoice_state
                order by s.invoice_type_id, s.invoice_state, s.state
                )
        """)

sale_journal_picking_report()

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:<commit_msg>[IMP] sale_journal: 'picking journal' report now uses decimal.precision<commit_after># -*- coding: utf-8 -*-
##############################################################################
#
#    OpenERP, Open Source Management Solution
#    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
#    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 osv import fields, osv
import tools
from decimal_precision import decimal_precision as dp

class sale_journal_picking_report(osv.osv):
    """
    Picking list by journal and by invoice
    """
    _name = "sale.journal.picking.report"
    _description = "Picking lists"
    _auto = False
    _columns = {
        'name': fields.char('Year', size=64, required=False, readonly=True),
        'month': fields.selection([('01', 'January'), ('02', 'February'), ('03', 'March'), ('04', 'April'), ('05', 'May'), ('06', 'June'),
                          ('07', 'July'), ('08', 'August'), ('09', 'September'), ('10', 'October'), ('11', 'November'), ('12', 'December')], 'Month', readonly=True),

        'invoice_state':fields.selection([
            ("invoiced", "invoiced"),
            ("2binvoiced", "to be invoiced"),
            ("none", "None")
        ], "Invoice state", readonly=True),
        'state': fields.selection([
            ('draft', 'draft'),
            ('auto', 'waiting'),
            ('confirmed', 'confirmed'),
            ('assigned', 'assigned'),
            ('done', 'done'),
            ('cancel', 'cancel'),
        ], 'State', readonly=True),
        'invoice_type_id': fields.many2one('sale_journal.invoice.type', 'Invoicing method', readonly=True),
        'journal_id': fields.many2one('sale_journal.picking.journal', 'Journal', readonly=True),
        'quantity': fields.float('Quantities', readonly=True),
        'price_total': fields.float('Total Price', readonly=True, digits_compute=dp.get_precision('Sale Price')),
        'price_average': fields.float('Average Price', readonly=True, digits_compute=dp.get_precision('Sale Price')),
        'count': fields.integer('# of Lines', readonly=True),
    }
    _order = 'journal_id, name desc, price_total desc'

    def init(self, cr):
        tools.drop_view_if_exists(cr, 'sale_journal_picking_report')

        cr.execute("""
            create or replace view sale_journal_picking_report as (
                select
                    min(l.id) as id,
                    to_char(s.date, 'YYYY') as name,
                    to_char(s.date, 'MM') as month,
                    s.state,
                    s.invoice_state,
                    s.invoice_type_id,
                    s.journal_id,
                    sum(l.product_qty) as quantity,
                    count(*) as count,
                    sum(l.product_qty*ol.price_unit*(1.0-ol.discount/100.0)) as price_total,
                    (sum(l.product_qty*ol.price_unit*(1.0-ol.discount/100.0))/sum(l.product_qty))::decimal(16,2) as price_average
                from stock_picking s
                    right join stock_move l on (s.id=l.picking_id)
                    left join sale_order_line ol on (l.sale_line_id=ol.id)
                group by s.journal_id, s.invoice_type_id, to_char(s.date, 'YYYY'),to_char(s.date, 'MM'),s.state, s.invoice_state
                order by s.invoice_type_id, s.invoice_state, s.state
                )
        """)

sale_journal_picking_report()

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
<|endoftext|>


<commit_before>from __future__ import print_function

import logging
import os
import sys

from six import MAXSIZE

_LEVEL_STRING = {"DEBUG": 10, "INFO": 20, "WARNING": 30, "ERROR": 40}
_CMT_LOG_FORMAT = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"

def log_level_string_to_int(level):
    if level.upper() in ["TRUE", "YES", "ON", "ENABLED"]:
        verbosity = MAXSIZE
    elif level.upper() in ["FALSE", "NO", "OFF", "DISABLED"]:
        verbosity = 0
    else:
        try:
            verbosity = _LEVEL_STRING[level]
        except KeyError:
            raise ValueError(level)

    return verbosity

def get_log_level_from_environ(level):
    try:
        level = int(os.environ["CMT_VERBOSE"])
    except KeyError:
        pass
    except ValueError:
        level = log_level_string_to_int(level)

    return level

def setup_pymt_logging_channel():
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    formatter = logging.Formatter(_CMT_LOG_FORMAT)
    ch.setFormatter(formatter)
    return ch

class CmtLogger(logging.Logger):
    def __init__(self, name, level):
        level = get_log_level_from_environ(level)

        logging.Logger.__init__(self, name, level=level)
        ch = setup_pymt_logging_channel()
        self.addHandler(ch)

class Verbose(object):
    def __init__(self, verbosity=0, log=sys.stderr):
        self._verbosity = verbosity
        self._log = log

    def __call__(self, verbosity, msg):
        if verbosity <= self._verbosity:
            print(self._construct_msg(verbosity, msg), file=self._log)

    def _construct_msg(self, verbosity, msg):
        if verbosity == 0:
            return msg
        else:
            return "*" * verbosity + " " + msg

class CmtVerbose(Verbose):
    """
    >>> if 'CMT_VERBOSE' in os.environ: del os.environ['CMT_VERBOSE']
    >>> verbose = CmtVerbose (1, log=sys.stdout)
    >>> verbose (1, "Level one")
    #CMT Level one
    >>> verbose (2, "Level two")
    >>> verbose (0, "Level %d" % 0)
    #CMT Level 0

    >>> os.environ['CMT_VERBOSE'] = '3'
    >>> verbose = CmtVerbose (log=sys.stdout)
    >>> verbose (1, "Level one")
    #CMT Level one
    >>> verbose (2, "Level two")
    #CMT Level two
    >>> verbose (4, "Level %d" % 0)

    >>> os.environ['CMT_VERBOSE'] = 'False'
    >>> verbose = CmtVerbose (log=sys.stdout)
    >>> verbose (0, 'No message')
    #CMT No message
    >>> verbose (1, 'No message')

    >>> os.environ['CMT_VERBOSE'] = 'True'
    >>> verbose = CmtVerbose (log=sys.stdout)
    >>> verbose (1, 'No message')
    #CMT No message
    >>> verbose (0, 'No message')
    #CMT No message
    """

    def __init__(self, verbosity=1, log=sys.stderr):
        if "CMT_VERBOSE" in os.environ:
            level = os.environ["CMT_VERBOSE"]
            if level.upper() in ["TRUE", "YES", "ON", "ENABLED"]:
                verbosity = MAXSIZE
            elif level.upper() in ["FALSE", "NO", "OFF", "DISABLED"]:
                verbosity = 0
            else:
                try:
                    verbosity = int(level)
                except ValueError:
                    verbosity = 0

        Verbose.__init__(self, verbosity, log)

    def _construct_msg(self, verbosity, msg):
        return "#CMT " + msg.strip()
<commit_msg>Make _construct_msg a static method.<commit_after>from __future__ import print_function

import logging
import os
import sys

from six import MAXSIZE

_LEVEL_STRING = {"DEBUG": 10, "INFO": 20, "WARNING": 30, "ERROR": 40}
_CMT_LOG_FORMAT = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"

def log_level_string_to_int(level):
    if level.upper() in ["TRUE", "YES", "ON", "ENABLED"]:
        verbosity = MAXSIZE
    elif level.upper() in ["FALSE", "NO", "OFF", "DISABLED"]:
        verbosity = 0
    else:
        try:
            verbosity = _LEVEL_STRING[level]
        except KeyError:
            raise ValueError(level)

    return verbosity

def get_log_level_from_environ(level):
    try:
        level = int(os.environ["CMT_VERBOSE"])
    except KeyError:
        pass
    except ValueError:
        level = log_level_string_to_int(level)

    return level

def setup_pymt_logging_channel():
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    formatter = logging.Formatter(_CMT_LOG_FORMAT)
    ch.setFormatter(formatter)
    return ch

class CmtLogger(logging.Logger):
    def __init__(self, name, level):
        level = get_log_level_from_environ(level)

        logging.Logger.__init__(self, name, level=level)
        ch = setup_pymt_logging_channel()
        self.addHandler(ch)

class Verbose(object):
    def __init__(self, verbosity=0, log=sys.stderr):
        self._verbosity = verbosity
        self._log = log

    def __call__(self, verbosity, msg):
        if verbosity <= self._verbosity:
            print(self._construct_msg(verbosity, msg), file=self._log)

    @staticmethod
    def _construct_msg(verbosity, msg):
        if verbosity == 0:
            return msg
        else:
            return "*" * verbosity + " " + msg

class CmtVerbose(Verbose):
    """
    >>> if 'CMT_VERBOSE' in os.environ: del os.environ['CMT_VERBOSE']
    >>> verbose = CmtVerbose (1, log=sys.stdout)
    >>> verbose (1, "Level one")
    #CMT Level one
    >>> verbose (2, "Level two")
    >>> verbose (0, "Level %d" % 0)
    #CMT Level 0

    >>> os.environ['CMT_VERBOSE'] = '3'
    >>> verbose = CmtVerbose (log=sys.stdout)
    >>> verbose (1, "Level one")
    #CMT Level one
    >>> verbose (2, "Level two")
    #CMT Level two
    >>> verbose (4, "Level %d" % 0)

    >>> os.environ['CMT_VERBOSE'] = 'False'
    >>> verbose = CmtVerbose (log=sys.stdout)
    >>> verbose (0, 'No message')
    #CMT No message
    >>> verbose (1, 'No message')

    >>> os.environ['CMT_VERBOSE'] = 'True'
    >>> verbose = CmtVerbose (log=sys.stdout)
    >>> verbose (1, 'No message')
    #CMT No message
    >>> verbose (0, 'No message')
    #CMT No message
    """

    def __init__(self, verbosity=1, log=sys.stderr):
        if "CMT_VERBOSE" in os.environ:
            level = os.environ["CMT_VERBOSE"]
            if level.upper() in ["TRUE", "YES", "ON", "ENABLED"]:
                verbosity = MAXSIZE
            elif level.upper() in ["FALSE", "NO", "OFF", "DISABLED"]:
                verbosity = 0
            else:
                try:
                    verbosity = int(level)
                except ValueError:
                    verbosity = 0

        Verbose.__init__(self, verbosity, log)

    @staticmethod
    def _construct_msg(verbosity, msg):
        return "#CMT " + msg.strip()
<|endoftext|>