Exemple #1
0
 def __setup__(cls):
     super(Appointment, cls).__setup__()
     cls._error_messages.update(
         no_institution="No institution specified in appointment [%s]")
     cls.state.selection = APPOINTMENT_STATES
     cls._buttons.update({
         'start_encounter': {
             'readonly':
             Not(And(Equal(Eval('state'), 'arrived'), Bool(Eval('name')))),
             'invisible':
             In(Eval('state'), ['processing', 'done']),
         },
         'goto_encounter': {
             'invisible': Not(In(Eval('state'), ['processing', 'done']))
         },
         'client_arrived': {
             'readonly':
             Not(And(Equal(Eval('state'), 'confirmed'), Bool(Eval('name'))))
         }
     })
     ro_states = {'readonly': Not(In(Eval('state'), ['confirmed', 'free']))}
     cls.patient.states.update(ro_states)
     cls.institution.states = ro_states
     cls.state.states = ro_states
     cls.appointment_date.states = ro_states
     cls.comments.states.update(
         {'invisible': ~Eval('can_do_details', False)})
Exemple #2
0
class BankAccount(metaclass=PoolMeta):
    __name__ = 'bank.account'

    journal = fields.Many2One('account.journal',
                              'Account Journal',
                              states={
                                  'required':
                                  If(
                                      In(Eval('party_company'),
                                         Eval('owners', [])), True, False),
                              },
                              depends=['owners', 'party_company'])
    credit_account = fields.Many2One(
        'account.account',
        'Credit Account',
        states={
            'required':
            If(In(Eval('party_company'), Eval('owners', [])), True, False),
        },
        domain=[
            ('kind', '!=', 'view'),
            ('company', '=', Eval('context', {}).get('company', -1)),
        ],
        depends=['owners', 'party_company'])
    debit_account = fields.Many2One(
        'account.account',
        'Debit Account',
        states={
            'required':
            If(In(Eval('party_company'), Eval('owners', [])), True, False),
        },
        domain=[
            ('kind', '!=', 'view'),
            ('company', '=', Eval('context', {}).get('company', -1)),
        ],
        depends=['owners', 'party_company'])
    party_company = fields.Function(
        fields.Many2One('party.party', 'party_company'),
        'on_change_with_party_company')

    @staticmethod
    def default_party_company():
        Company = Pool().get('company.company')
        if Transaction().context.get('company'):
            company = Company(Transaction().context['company'])
            return company.party.id

    def on_change_with_party_company(self, name=None):
        Company = Pool().get('company.company')
        if Transaction().context.get('company'):
            company = Company(Transaction().context['company'])
            return company.party.id

    def get_cbu_number(self):
        '''
        Return cbu number
        '''
        for account_number in self.numbers:
            if account_number.type == 'cbu':
                return account_number.number_compact
Exemple #3
0
    def __setup__(cls):
        super(AccountVoucher, cls).__setup__()

        cls._buttons.update({
            'transferir': {
                'invisible': ~Eval('transfer', True),
                'readonly': In(Eval('state'), ['posted']),
            },
        })

        cls._buttons.update({
            'post': {
                'invisible': Eval('transfer', True),
                'readonly': In(Eval('state'), ['posted']),
            },
        })

        del cls.party.states['required']
        cls.party.states['required'] = ~Eval('transfer', True)
        cls.party.states['invisible'] = Eval('transfer', True)
        cls.voucher_type.states['invisible'] = Eval('transfer', True)
        cls.pay_lines.states['invisible'] = Eval('transfer', True)
        cls.lines.states['invisible'] = Eval('transfer', True)
        cls.lines_credits.states['invisible'] = Eval('transfer', True)
        cls.lines_debits.states['invisible'] = Eval('transfer', True)
        cls.amount.states['invisible'] = Eval('transfer', True)
        cls.amount_to_pay.states['invisible'] = Eval('transfer', True)
        cls.amount_invoices.states['invisible'] = Eval('transfer', True)
        cls.move.states['invisible'] = Eval('transfer', True)
        cls.from_pay_invoice.states['invisible'] = Eval('transfer', True)
        cls.amount_to_pay_words.states['invisible'] = Eval('transfer', True)
    def __setup__(cls):
        super(ReceiptLine, cls).__setup__()
        cls.type.selection += [
            ('advance_in_apply', 'Apply Collected in Advanced from Customer'),
            ('advance_in_create', 'Create Collected in Advance from Customer'),
            ('advance_out_apply', 'Apply Paid in Advanced to Supplier'),
            ('advance_out_create', 'Create Paid in Advance to Supplier'),
        ]

        cls.party.states['readonly'] = Or(
            Eval('receipt_state') != 'draft',
            Bool(Eval('invoice')),
            Bool(Eval('advance')),
        )
        cls.party.depends += ['advance']

        cls.account.states['readonly'] = Or(
            Eval('receipt_state') != 'draft',
            Not(
                In(Eval('type'),
                   ['move_line', 'advance_in_create', 'advance_out_create'])),
        )

        cls.account.domain.append(
            If(In(Eval('type'), ['advance_in_create', 'advance_out_create']),
               [('reconcile', '=', True), ('party_required', '=', True)], []))
Exemple #5
0
    def __setup__(cls):
        super(Move, cls).__setup__()
        for fname in ('package', 'number_of_packages'):
            if 'readonly' in getattr(cls, fname).states:
                getattr(cls, fname).states['readonly'] |= In(
                    Eval('state'), ['cancel', 'assigned', 'done'])
            else:
                getattr(cls, fname).states['readonly'] = In(
                    Eval('state'), ['cancel', 'assigned', 'done'])
            getattr(cls, fname).depends.append('state')

        cls._deny_modify_assigned |= set(
            ['number_of_packages', 'number_of_packages'])
Exemple #6
0
 def view_attributes(cls):
     return super(PaymentTransaction, cls).view_attributes() + [(
         '/tree', 'colors', If(
             In(
                 Eval('state', ''),
                 ['in-progress', 'authorized', 'completed']
             ),
             'blue',
             If(
                 In(Eval('state', ''), ['failed', 'cancel']),
                 'red',
                 If(Equal(Eval('state', ''), 'posted'), 'green', 'black')
             )
         )
     )]
Exemple #7
0
 def __setup__(cls):
     super(TriageEntry, cls).__setup__()
     cls._buttons.update({
         'set_done': {
             'readonly':
             ~Eval('can_do_details', False),
             'invisible':
             Or(In(Eval('status'), ['pending', 'triage']),
                Eval('done', False))
         },
         'go_referral': {
             'readonly': ~Eval('can_do_details', False),
             'invisible': ~In(Eval('status'), ['refer', 'referin'])
         }
     })
Exemple #8
0
class Party(metaclass=PoolMeta):
    __name__ = 'party.party'
    party_type = fields.Selection([
        (None, ''),
        ('person', 'Person'),
        ('private', 'Private Organisation'),
        ('foundation', 'Foundation'),
        ('government', 'Government'),
    ],
                                  'Type',
                                  states={
                                      'readonly': ~Eval('active', True),
                                  },
                                  depends=['active'])
    dob = fields.Date('Date of Birth/Establishment')
    gender = fields.Selection(
        [
            (None, ''),
            ('male', 'Male'),
            ('female', 'Female'),
        ],
        'Gender',
        states={
            'readonly': ~Eval('active', True),
            'invisible': Not(In(Eval('party_type'), ['person'])),
        },
        depends=['party_type'])
    person_legal_state = fields.Selection(
        [
            (None, ''),
            ('married', 'Married'),
            ('single', 'Single'),
            ('divorced', 'Divorced'),
            ('widow', 'Widow(er)'),
        ],
        'Legal state',
        states={
            'readonly': ~Eval('active', True),
            'invisible': Not(In(Eval('party_type'), ['person'])),
        },
        depends=['party_type'])

    @classmethod
    def __setup__(cls):
        super(Party, cls).__setup__()
        cls.last_name.states['invisible'] = \
                Not(In(Eval('party_type'), ['person']))
        cls.last_name.depends += ['party_type']
Exemple #9
0
 def __setup__(cls):
     super(InpatientRegistration, cls).__setup__()
     # Make readonly for bed depends on a person being hospitalised or
     # discharged from the hospital
     cls.bed.states = {'required': True,
                       'readonly': Or(Equal(Eval('state'), 'hospitalized'),
                                      Equal(Eval('state'), 'confirmed'),
                                      Equal(Eval('state'), 'done'))}
     # Changed depends to accommodate state
     cls.bed.depends = ['name', 'state']
     # make discharge_date not required
     cls.discharge_date.required = False
     if not cls.discharge_date.states:
         cls.discharge_date.states = {}
     cls.discharge_date.states['invisible'] = Not(
         In(Eval('state'), ['done', 'hospitalized']))
     # rename the set of states
     cls.state.selection = [
         ('free', 'Pending'),
         ('cancelled', 'Cancelled'),
         ('confirmed', 'Confirmed'),
         ('hospitalized', 'Admitted'),
         ('done', 'Discharged/Done')
     ]
     # discharge_date is the real thing
     cls.discharge_date.string = 'Discharged'
Exemple #10
0
class Property(ModelSQL, ModelView):
    _name = 'ir.property'
    company = fields.Many2One('company.company',
                              'Company',
                              domain=[
                                  ('id',
                                   If(In('company', Eval('context', {})), '=',
                                      '!='),
                                   Get(Eval('context', {}), 'company', 0)),
                              ])

    def _set_values(self, name, model, res_id, val, field_id):
        user_obj = self.pool.get('res.user')
        user = user_obj.browse(Transaction().user)
        res = super(Property, self)._set_values(name, model, res_id, val,
                                                field_id)
        if user:
            res['company'] = user.company.id
        return res

    def search(self, domain, offset=0, limit=None, order=None, count=False):
        if Transaction().user == 0:
            domain = ['AND', domain[:], ('company', '=', False)]
        return super(Property, self).search(domain,
                                            offset=offset,
                                            limit=limit,
                                            order=order,
                                            count=count)
class Journal:
    __metaclass__ = PoolMeta
    __name__ = 'account.journal'
    sequences = fields.One2Many('account.journal.invoice.sequence', 'journal',
        'Sequences', states={
            'invisible': Not(In(Eval('type'), ['revenue', 'expense'])),
            })

    def get_invoice_sequence(self, invoice):
        pool = Pool()
        Date = pool.get('ir.date')
        date = invoice.invoice_date or Date.today()
        for sequence in self.sequences:
            period = sequence.period
            if period and (period.start_date <= date and
                    period.end_date >= date):
                return getattr(sequence, invoice.type + '_sequence')
        for sequence in self.sequences:
            fiscalyear = sequence.fiscalyear
            if (fiscalyear.start_date <= date and
                    fiscalyear.end_date >= date):
                return getattr(sequence, invoice.type + '_sequence')

    @classmethod
    def view_attributes(cls):
        return super(Journal, cls).view_attributes() + [
            ('//page[@id="sequences"]', 'states', {
                    'invisible': Not(In(Eval('type'), ['revenue', 'expense'])),
                    })]
Exemple #12
0
class SaleOpportunity:
    'Sale Oppotunity'
    __name__ = 'sale.opportunity'

    incoterms = fields.One2Many('sale.opportunity.incoterm',
                                'opportunity',
                                'Incoterm Sale Opportunity',
                                states={
                                    'readonly':
                                    Not(
                                        In(Eval('state'),
                                           ['lead', 'opportunity'])),
                                },
                                depends=['state'])

    def create_sale(self):
        '''
        Create a sale for the opportunity and return the sale
        '''
        SaleIncoterm = Pool().get('sale.incoterm')

        sale = super(SaleOpportunity, self).create_sale()

        SaleIncoterm.create(
            map(
                lambda incoterm: {
                    'year': incoterm.year,
                    'abbrevation': incoterm.abbrevation,
                    'value': incoterm.value,
                    'currency': incoterm.currency.id,
                    'city': incoterm.city,
                    'sale': sale.id,
                }, self.incoterms))

        return sale
Exemple #13
0
 def __setup__(cls):
     super(Signature, cls).__setup__()
     cls._transitions |= set((
         ('issued', 'ready'),
         ('issued', 'expired'),
         ('issued', 'canceled'),
         ('issued', 'failed'),
         ('issued', 'completed'),
         ('issued', 'pending_validation'),
         ('ready', 'expired'),
         ('ready', 'canceled'),
         ('ready', 'failed'),
         ('ready', 'completed'),
         ('ready', 'pending_validation'),
         ('pending_validation', 'expired'),
         ('pending_validation', 'canceled'),
         ('pending_validation', 'failed'),
         ('pending_validation', 'completed'),
     ))
     cls._buttons.update({
         'update_transaction_info': {
             'invisible':
             Not(
                 In(Eval('status'),
                    ['', 'issued', 'ready', 'pending_validation']))
         },
         'relaunch_transaction': {
             'invisible': Eval('status') != 'ready'
         },
     })
Exemple #14
0
 def __setup__(cls):
     super(Attachment, cls).__setup__()
     cls._buttons.update({
         'cryptolog_update_transaction_info': {
             'invisible':
             Not(In(Eval('cryptolog_status'), ['', 'issued', 'ready']))
         }
     })
class BankAccount(metaclass=PoolMeta):
    __name__ = 'bank.account'
    pyafipws_cbu = fields.Boolean('CBU del Emisor',
                                  states={
                                      'required':
                                      If(
                                          In(Eval('party_company'),
                                             Eval('owners', [])), True, False),
                                  },
                                  depends=['owners', 'party_company'])
Exemple #16
0
    def __setup__(cls):
        super(Todo, cls).__setup__()
        cls._order = [
            ('sequence', 'ASC'),
            ('create_date', 'DESC'),
            ('id', 'DESC'),
        ]

        cls._transitions |= set((
            ('open', 'done'),
            ('done', 'open'),
        ))

        cls._buttons.update({
            'done': {
                'invisible': In(Eval('state'), ['done']),
            },
            'open': {
                'invisible': In(Eval('state'), ['open']),
            },
        })
    def __setup__(cls):
        super(PatientEncounter, cls).__setup__()
        cls._error_messages.update({
            'health_professional_warning':
            'No health professional '
            'associated with this user',
            'end_date_before_start':
            'End time cannot be before'
            'Start time\n"%(start_time)s"',
            'end_date_required':
            'End time is required for finishing',
            'unsigned_components':
            'There are unsigned components.'
            # 'This encounter cannot be signed'
        })

        cls._buttons.update({
            'set_done': {
                'invisible':
                Not(Equal(Eval('state'), 'in_progress')),
                'readonly':
                Or(Greater(0, Eval('id', -1)),
                   Greater(1, Len(Eval('components'))))
            },
            'sign_finish': {
                'invisible': Not(Equal(Eval('state'), 'done'))
            },
            'add_component': {
                'readonly':
                Or(Greater(0, Eval('id', -1)),
                   In(Eval('state'), ['done', 'signed', 'invalid'])),
                'invisible':
                Equal(Eval('state'), 'signed')
            },
            'add_extra_component': {
                'invisible':
                In(Eval('state'), ['signed', 'in_progress', 'invalid'])
            }
        })
Exemple #18
0
class Move(metaclass=PoolMeta):
    __name__ = 'stock.move'

    fraction = fields.Many2One(
        'lims.fraction',
        'Fraction',
        select=True,
        ondelete='CASCADE',
        states={
            'readonly': (In(Eval('state'), ['cancel', 'assigned', 'done'])
                         | Bool(Eval('fraction_readonly')))
        },
        domain=[
            If(~Eval('fraction'),
               ('current_location', '=', Eval('from_location')),
               ('id', '=', Eval('fraction'))),
        ],
        depends=['state', 'fraction_readonly', 'from_location'])
    fraction_readonly = fields.Function(fields.Boolean('Fraction Read Only'),
                                        'on_change_with_fraction_readonly')

    @classmethod
    def __setup__(cls):
        super().__setup__()
        cls.origin.readonly = True

    @classmethod
    def _get_origin(cls):
        models = super()._get_origin()
        models.append('lims.fraction')
        return models

    @fields.depends('from_location', 'to_location', 'product')
    def on_change_with_fraction_readonly(self, name=None):
        Config = Pool().get('lims.configuration')

        config = Config(1)
        if not config.fraction_product:
            return True
        if not self.product or self.product != config.fraction_product:
            return True
        if (self.from_location and self.to_location
                and self.from_location.type == 'storage'
                and self.to_location.type == 'storage'):
            return False
        return True

    @classmethod
    def copy(cls, moves, default=None):
        with Transaction().set_context(check_current_location=False):
            return super().copy(moves, default=default)
class InvoiceLine(ModelSQL, ModelView):
    """Invoice Line"""
    _name = 'account.invoice.line'

    work = fields.Many2One('timesheet.work', 'Work')
    timesheet_lines = fields.One2Many(
        'timesheet.line',
        'invoice_line',
        'Timesheet Lines',
        add_remove=[
            ('invoice_line', '=', False),
            ('work', '=', Eval('work')),
            ('billable', '=', True),
            ('hours', '>', 0),
        ],
    )

    # add timesheet_lines to on_change_with list on parent
    quantity = fields.Float('Quantity',
                            digits=(16, Eval('unit_digits', 2)),
                            states={
                                'invisible': Not(Equal(Eval('type'), 'line')),
                                'required': Equal(Eval('type'), 'line'),
                            },
                            on_change_with=['timesheet_lines'])

    # add timesheet_lines to on_change_with list on parent
    amount = fields.Function(
        fields.Numeric('Amount',
                       digits=(16,
                               Get(Eval('_parent_invoice',
                                        {}), 'currency_digits',
                                   Eval('currency_digits', 2))),
                       states={
                           'invisible':
                           Not(In(Eval('type'), ['line', 'subtotal'])),
                       },
                       on_change_with=[
                           'type',
                           'quantity',
                           'unit_price',
                           '_parent_invoice.currency',
                           'currency',
                           'timesheet_lines',
                       ]), 'get_amount')

    def on_change_with_quantity(self, vals):
        hours = 0.0
        for line in vals.get('timesheet_lines'):
            hours = hours + line.get('hours')
        return hours
Exemple #20
0
class Sequence(ModelSQL, ModelView):
    _name = 'ir.sequence'
    company = fields.Many2One('company.company',
                              'Company',
                              domain=[
                                  ('id',
                                   If(In('company', Eval('context', {})), '=',
                                      '!='),
                                   Get(Eval('context', {}), 'company', 0)),
                              ])

    def __init__(self):
        super(Sequence, self).__init__()
        self._order.insert(0, ('company', 'ASC'))

    def default_company(self):
        return Transaction().context.get('company') or False
Exemple #21
0
conversor = None
try:
    from numword import numword_es
    conversor = numword_es.NumWordES()
except:
    print("Warning: Does not possible import numword module!")
    print("Please install it...!")

__all__ = [
    'AccountVoucherSequence', 'AccountVoucherPayMode', 'AccountVoucher',
    'AccountVoucherLine', 'AccountVoucherLineCredits',
    'AccountVoucherLineDebits', 'AccountVoucherLinePaymode', 'VoucherReport'
]

_STATES = {
    'readonly': In(Eval('state'), ['posted']),
}


class AccountVoucherSequence(ModelSingleton, ModelSQL, ModelView):
    'Account Voucher Sequence'
    __name__ = 'account.voucher.sequence'

    voucher_payment_sequence = fields.Property(
        fields.Many2One('ir.sequence',
                        'Voucher Payment Sequence',
                        required=True,
                        domain=[
                            ('code', '=', 'account.voucher.payment'),
                            ('company', 'in',
                             [Eval('context', {}).get('company'), None]),
Exemple #22
0
from trytond.model import ModelView, ModelSQL, fields
from trytond.pyson import Eval, Not, Bool, PYSONEncoder, Equal, And, Or, In
from trytond.pool import Pool

_Jamaica_instance = False

def JAMAICA():
    global _Jamaica_instance
    if not _Jamaica_instance:
        _Jamaica_instance, = Pool().get('country.country').search([('code','=',
                                                                 'JM')])
    return _Jamaica_instance

JAMAICA_ID = 89

INVISIBLEJM = {'invisible':In(Eval('address_country'), [JAMAICA_ID])}
VISIBLEJM = {'invisible':Not(In(Eval('address_country'), [JAMAICA_ID]))}


class DomiciliaryUnit(ModelSQL, ModelView):
    'Domiciliary Unit'
    __name__ = 'gnuhealth.du'

    address_street_num = fields.Char('Street Number', size=8)
    address_post_office = fields.Many2One(
        'country.post_office', 'Post Office (JM)',
        help="Closest Post Office, Jamaica only",
        domain=[('subdivision', '=', Eval('address_subdivision'))],
        depends=['address_subdivision'],
        states=VISIBLEJM)
    address_district_community = fields.Many2One(
Exemple #23
0
class SaleOpportunity(Workflow, ModelSQL, ModelView):
    'Sale Opportunity'
    __name__ = "sale.opportunity"
    _history = True
    _rec_name = 'number'
    number = fields.Char('Number', readonly=True, required=True, select=True)
    reference = fields.Char('Reference', select=True)
    party = fields.Many2One(
        'party.party',
        'Party',
        select=True,
        states={
            'readonly': Eval('state').in_(['converted', 'lost', 'cancelled']),
            'required': ~Eval('state').in_(['lead', 'lost', 'cancelled']),
        },
        depends=['state'])
    address = fields.Many2One('party.address',
                              'Address',
                              domain=[('party', '=', Eval('party'))],
                              select=True,
                              depends=['party', 'state'],
                              states=_STATES_STOP)
    company = fields.Many2One('company.company',
                              'Company',
                              required=True,
                              select=True,
                              states=_STATES_STOP,
                              domain=[
                                  ('id',
                                   If(In('company', Eval('context', {})), '=',
                                      '!='),
                                   Get(Eval('context', {}), 'company', 0)),
                              ],
                              depends=_DEPENDS_STOP)
    currency = fields.Function(
        fields.Many2One('currency.currency', 'Currency'), 'get_currency')
    currency_digits = fields.Function(fields.Integer('Currency Digits'),
                                      'get_currency_digits')
    amount = fields.Numeric('Amount',
                            digits=(16, Eval('currency_digits', 2)),
                            states=_STATES_STOP,
                            depends=_DEPENDS_STOP + ['currency_digits'],
                            help='Estimated revenue amount')
    payment_term = fields.Many2One('account.invoice.payment_term',
                                   'Payment Term',
                                   states={
                                       'readonly':
                                       In(Eval('state'),
                                          ['converted', 'lost', 'cancelled']),
                                   },
                                   depends=['state'])
    employee = fields.Many2One(
        'company.employee',
        'Employee',
        states={
            'readonly': _STATES_STOP['readonly'],
            'required': ~Eval('state').in_(['lead', 'lost', 'cancelled']),
        },
        depends=['state', 'company'],
        domain=[('company', '=', Eval('company'))])
    start_date = fields.Date('Start Date',
                             required=True,
                             select=True,
                             states=_STATES_START,
                             depends=_DEPENDS_START)
    end_date = fields.Date('End Date',
                           select=True,
                           states=_STATES_STOP,
                           depends=_DEPENDS_STOP)
    description = fields.Char('Description',
                              required=True,
                              states=_STATES_STOP,
                              depends=_DEPENDS_STOP)
    comment = fields.Text('Comment',
                          states=_STATES_STOP,
                          depends=_DEPENDS_STOP)
    lines = fields.One2Many('sale.opportunity.line',
                            'opportunity',
                            'Lines',
                            states=_STATES_STOP,
                            depends=_DEPENDS_STOP)
    state = fields.Selection(STATES,
                             'State',
                             required=True,
                             select=True,
                             sort=False,
                             readonly=True)
    conversion_probability = fields.Float(
        'Conversion Probability',
        digits=(1, 4),
        required=True,
        domain=[
            ('conversion_probability', '>=', 0),
            ('conversion_probability', '<=', 1),
        ],
        states={
            'readonly':
            ~Eval('state').in_(['opportunity', 'lead', 'converted']),
        },
        depends=['state'],
        help="Percentage between 0 and 100")
    lost_reason = fields.Text('Reason for loss',
                              states={
                                  'invisible': Eval('state') != 'lost',
                              },
                              depends=['state'])
    sales = fields.One2Many('sale.sale', 'origin', 'Sales')

    @classmethod
    def __register__(cls, module_name):
        pool = Pool()
        Sale = pool.get('sale.sale')
        cursor = Transaction().connection.cursor()
        sql_table = cls.__table__()
        sale = Sale.__table__()

        table = cls.__table_handler__(module_name)
        number_exists = table.column_exist('number')

        # Migration from 3.8: rename reference into number
        if table.column_exist('reference') and not number_exists:
            table.column_rename('reference', 'number')
            number_exists = True

        super(SaleOpportunity, cls).__register__(module_name)
        table = cls.__table_handler__(module_name)

        # Migration from 3.4: replace sale by origin
        if table.column_exist('sale'):
            cursor.execute(*sql_table.select(
                sql_table.id, sql_table.sale, where=sql_table.sale != Null))
            for id_, sale_id in cursor.fetchall():
                cursor.execute(
                    *sale.update(columns=[sale.origin],
                                 values=['%s,%s' % (cls.__name__, id_)],
                                 where=sale.id == sale_id))
            table.drop_column('sale')

        # Migration from 4.0: change probability into conversion probability
        if table.column_exist('probability'):
            cursor.execute(
                *sql_table.update([sql_table.conversion_probability],
                                  [sql_table.probability / 100.0]))
            table.drop_constraint('check_percentage')
            table.drop_column('probability')

        # Migration from 4.2: make employee not required
        table.not_null_action('employee', action='remove')

    @classmethod
    def __setup__(cls):
        super(SaleOpportunity, cls).__setup__()
        cls._order.insert(0, ('start_date', 'DESC'))
        cls._error_messages.update({
            'delete_cancel': ('Sale Opportunity "%s" must be cancelled '
                              'before deletion.'),
        })
        cls._transitions |= set((
            ('lead', 'opportunity'),
            ('lead', 'lost'),
            ('lead', 'cancelled'),
            ('lead', 'converted'),
            ('opportunity', 'converted'),
            ('opportunity', 'lead'),
            ('opportunity', 'lost'),
            ('opportunity', 'cancelled'),
            ('converted', 'won'),
            ('converted', 'lost'),
            ('won', 'converted'),
            ('lost', 'converted'),
            ('lost', 'lead'),
            ('cancelled', 'lead'),
        ))
        cls._buttons.update({
            'lead': {
                'invisible':
                ~Eval('state').in_(['cancelled', 'lost', 'opportunity']),
                'icon':
                If(
                    Eval('state').in_(['cancelled', 'lost']), 'tryton-undo',
                    'tryton-back'),
                'depends': ['state'],
            },
            'opportunity': {
                'invisible': ~Eval('state').in_(['lead']),
                'depends': ['state'],
            },
            'convert': {
                'invisible': ~Eval('state').in_(['opportunity']),
                'depends': ['state'],
            },
            'lost': {
                'invisible': ~Eval('state').in_(['lead', 'opportunity']),
                'depends': ['state'],
            },
            'cancel': {
                'invisible': ~Eval('state').in_(['lead', 'opportunity']),
                'depends': ['state'],
            },
        })

    @staticmethod
    def default_state():
        return 'lead'

    @staticmethod
    def default_start_date():
        Date = Pool().get('ir.date')
        return Date.today()

    @staticmethod
    def default_conversion_probability():
        return 0.5

    @staticmethod
    def default_company():
        return Transaction().context.get('company')

    @staticmethod
    def default_employee():
        return Transaction().context.get('employee')

    @classmethod
    def default_payment_term(cls):
        PaymentTerm = Pool().get('account.invoice.payment_term')
        payment_terms = PaymentTerm.search(cls.payment_term.domain)
        if len(payment_terms) == 1:
            return payment_terms[0].id

    @classmethod
    def create(cls, vlist):
        pool = Pool()
        Sequence = pool.get('ir.sequence')
        Config = pool.get('sale.configuration')

        config = Config(1)
        vlist = [x.copy() for x in vlist]
        for vals in vlist:
            if vals.get('number') is None:
                vals['number'] = Sequence.get_id(
                    config.sale_opportunity_sequence.id)
        return super(SaleOpportunity, cls).create(vlist)

    @classmethod
    def copy(cls, opportunities, default=None):
        if default is None:
            default = {}
        else:
            default = default.copy()
        default.setdefault('number', None)
        default.setdefault('sales', None)
        return super(SaleOpportunity, cls).copy(opportunities, default=default)

    def get_currency(self, name):
        return self.company.currency.id

    def get_currency_digits(self, name):
        return self.company.currency.digits

    @fields.depends('company')
    def on_change_company(self):
        if self.company:
            self.currency = self.company.currency
            self.currency_digits = self.company.currency.digits

    @fields.depends('party')
    def on_change_party(self):
        if self.party and self.party.customer_payment_term:
            self.payment_term = self.party.customer_payment_term
        else:
            self.payment_term = self.default_payment_term()

    def _get_sale_opportunity(self):
        '''
        Return sale for an opportunity
        '''
        Sale = Pool().get('sale.sale')
        return Sale(
            description=self.description,
            party=self.party,
            payment_term=self.payment_term,
            company=self.company,
            invoice_address=self.address,
            shipment_address=self.address,
            currency=self.company.currency,
            comment=self.comment,
            sale_date=None,
            origin=self,
            warehouse=Sale.default_warehouse(),
        )

    def create_sale(self):
        '''
        Create a sale for the opportunity and return the sale
        '''
        sale = self._get_sale_opportunity()
        sale_lines = []
        for line in self.lines:
            sale_lines.append(line.get_sale_line(sale))
        sale.lines = sale_lines
        return sale

    @classmethod
    def delete(cls, opportunities):
        # Cancel before delete
        cls.cancel(opportunities)
        for opportunity in opportunities:
            if opportunity.state != 'cancelled':
                cls.raise_user_error('delete_cancel', opportunity.rec_name)
        super(SaleOpportunity, cls).delete(opportunities)

    @classmethod
    @ModelView.button
    @Workflow.transition('lead')
    def lead(cls, opportunities):
        pass

    @classmethod
    @ModelView.button
    @Workflow.transition('opportunity')
    def opportunity(cls, opportunities):
        pass

    @classmethod
    @ModelView.button
    @Workflow.transition('converted')
    def convert(cls, opportunities):
        pool = Pool()
        Sale = pool.get('sale.sale')
        sales = [o.create_sale() for o in opportunities if not o.sales]
        Sale.save(sales)

    @property
    def is_forecast(self):
        pool = Pool()
        Date = pool.get('ir.date')
        today = Date.today()
        return self.end_date or datetime.date.max > today

    @classmethod
    @Workflow.transition('won')
    def won(cls, opportunities):
        pool = Pool()
        Date = pool.get('ir.date')
        cls.write([o for o in opportunities if o.is_forecast], {
            'end_date': Date.today(),
            'state': 'won',
        })

    @classmethod
    @ModelView.button
    @Workflow.transition('lost')
    def lost(cls, opportunities):
        Date = Pool().get('ir.date')
        cls.write([o for o in opportunities if o.is_forecast], {
            'end_date': Date.today(),
            'state': 'lost',
        })

    @classmethod
    @ModelView.button
    @Workflow.transition('cancelled')
    def cancel(cls, opportunities):
        Date = Pool().get('ir.date')
        cls.write([o for o in opportunities if o.is_forecast], {
            'end_date': Date.today(),
        })

    @staticmethod
    def _sale_won_states():
        return ['confirmed', 'processing', 'done']

    @staticmethod
    def _sale_lost_states():
        return ['cancel']

    def is_won(self):
        sale_won_states = self._sale_won_states()
        sale_lost_states = self._sale_lost_states()
        end_states = sale_won_states + sale_lost_states
        return (self.sales and all(s.state in end_states for s in self.sales)
                and any(s.state in sale_won_states for s in self.sales))

    def is_lost(self):
        sale_lost_states = self._sale_lost_states()
        return (self.sales
                and all(s.state in sale_lost_states for s in self.sales))

    @property
    def sale_amount(self):
        pool = Pool()
        Currency = pool.get('currency.currency')

        if not self.sales:
            return

        sale_lost_states = self._sale_lost_states()
        amount = 0
        for sale in self.sales:
            if sale.state not in sale_lost_states:
                amount += Currency.compute(sale.currency, sale.untaxed_amount,
                                           self.currency)
        return amount

    @classmethod
    def process(cls, opportunities):
        won = []
        lost = []
        converted = []
        for opportunity in opportunities:
            sale_amount = opportunity.sale_amount
            if opportunity.amount != sale_amount:
                opportunity.amount = sale_amount
            if opportunity.is_won():
                won.append(opportunity)
            elif opportunity.is_lost():
                lost.append(opportunity)
            elif (opportunity.state != 'converted' and opportunity.sales):
                converted.append(opportunity)
        cls.save(opportunities)
        if won:
            cls.won(won)
        if lost:
            cls.lost(lost)
        if converted:
            cls.convert(converted)
Exemple #24
0
]

STATES = [
    ('lead', 'Lead'),
    ('opportunity', 'Opportunity'),
    ('converted', 'Converted'),
    ('won', 'Won'),
    ('cancelled', 'Cancelled'),
    ('lost', 'Lost'),
]
_STATES_START = {
    'readonly': Eval('state') != 'lead',
}
_DEPENDS_START = ['state']
_STATES_STOP = {
    'readonly': In(Eval('state'), ['converted', 'won', 'lost', 'cancelled']),
}
_DEPENDS_STOP = ['state']


class SaleOpportunity(Workflow, ModelSQL, ModelView):
    'Sale Opportunity'
    __name__ = "sale.opportunity"
    _history = True
    _rec_name = 'number'
    number = fields.Char('Number', readonly=True, required=True, select=True)
    reference = fields.Char('Reference', select=True)
    party = fields.Many2One(
        'party.party',
        'Party',
        select=True,
Exemple #25
0
class AccountVoucher(metaclass=PoolMeta):
    __name__ = 'account.voucher'

    issued_check = fields.One2Many(
        'account.issued.check',
        'voucher',
        'Issued Checks',
        add_remove=[
            ('state', '=', 'draft'),
        ],
        states={
            'invisible':
            Not(In(Eval('voucher_type'), ['payment'])),
            'readonly':
            Or(In(Eval('state'), ['posted']),
               Not(In(Eval('currency_code'), ['ARS']))),
        })
    third_pay_checks = fields.Many2Many(
        'account.voucher-account.third.check',
        'voucher',
        'third_check',
        'Third Checks',
        states={
            'invisible':
            Not(In(Eval('voucher_type'), ['payment'])),
            'readonly':
            Or(In(Eval('state'), ['posted']),
               Not(In(Eval('currency_code'), ['ARS']))),
        },
        domain=[
            ('state', '=', 'held'),
            ('not_to_order', '=', False),
        ])
    third_check = fields.One2Many(
        'account.third.check',
        'voucher_in',
        'Third Checks',
        add_remove=[
            ('state', '=', 'draft'),
        ],
        states={
            'invisible':
            Not(In(Eval('voucher_type'), ['receipt'])),
            'readonly':
            Or(In(Eval('state'), ['posted']),
               Not(In(Eval('currency_code'), ['ARS']))),
        })

    @classmethod
    def __setup__(cls):
        super(AccountVoucher, cls).__setup__()
        cls._error_messages.update({
            'no_journal_check_account':
            'You need to define a check account '
            'in the journal "%s",',
            'check_not_in_draft':
            'Check "%s" is not in draft state',
            'issued_check_not_issued': ('Issued check "%s" is not in '
                                        'Issued state'),
            'third_check_not_held':
            'Third check "%s" is not in Held state',
            'third_pay_check_not_delivered': ('Third check "%s" is not in '
                                              'Delivered state'),
        })

    @fields.depends('party', 'pay_lines', 'lines_credits', 'lines_debits',
                    'issued_check', 'third_check', 'third_pay_checks')
    def on_change_with_amount(self, name=None):
        amount = super(AccountVoucher, self).on_change_with_amount(name)
        if self.third_check:
            for t_check in self.third_check:
                amount += t_check.amount
        if self.issued_check:
            for i_check in self.issued_check:
                amount += i_check.amount
        if self.third_pay_checks:
            for check in self.third_pay_checks:
                amount += check.amount
        return amount

    def prepare_move_lines(self):
        move_lines = super(AccountVoucher, self).prepare_move_lines()
        Period = Pool().get('account.period')
        if self.voucher_type == 'receipt':
            if self.third_check:
                if not self.journal.third_check_account:
                    self.raise_user_error('no_journal_check_account',
                                          error_args=(self.journal.name, ))
                for check in self.third_check:
                    if check.state != 'draft':
                        self.raise_user_error('check_not_in_draft',
                                              error_args=(check.name, ))
                    move_lines.append({
                        'debit':
                        check.amount,
                        'credit':
                        _ZERO,
                        'account':
                        self.journal.third_check_account.id,
                        'move':
                        self.move.id,
                        'journal':
                        self.journal.id,
                        'period':
                        Period.find(self.company.id, date=self.date),
                        'party':
                        (self.journal.third_check_account.party_required
                         and self.party.id or None),
                        'maturity_date':
                        check.date,
                    })

        if self.voucher_type == 'payment':
            if self.issued_check:
                if not self.journal.issued_check_account:
                    self.raise_user_error('no_journal_check_account',
                                          error_args=(self.journal.name, ))
                for check in self.issued_check:
                    move_lines.append({
                        'debit':
                        _ZERO,
                        'credit':
                        check.amount,
                        'account':
                        self.journal.issued_check_account.id,
                        'move':
                        self.move.id,
                        'journal':
                        self.journal.id,
                        'period':
                        Period.find(self.company.id, date=self.date),
                        'party':
                        (self.journal.issued_check_account.party_required
                         and self.party.id or None),
                        'maturity_date':
                        check.date,
                    })
            if self.third_pay_checks:
                for check in self.third_pay_checks:
                    move_lines.append({
                        'debit':
                        _ZERO,
                        'credit':
                        check.amount,
                        'account':
                        self.journal.third_check_account.id,
                        'move':
                        self.move.id,
                        'journal':
                        self.journal.id,
                        'period':
                        Period.find(self.company.id, date=self.date),
                        'party':
                        (self.journal.third_check_account.party_required
                         and self.party.id or None),
                        'maturity_date':
                        check.date,
                    })

        return move_lines

    @classmethod
    @ModelView.button
    def post(cls, vouchers):
        pool = Pool()
        ThirdCheck = pool.get('account.third.check')
        IssuedCheck = pool.get('account.issued.check')
        Date = pool.get('ir.date')

        super(AccountVoucher, cls).post(vouchers)

        today = Date.today()
        for voucher in vouchers:
            if voucher.issued_check:
                IssuedCheck.write(list(voucher.issued_check), {
                    'receiving_party': voucher.party.id,
                    'state': 'issued',
                })
                IssuedCheck.issued(voucher.issued_check)
            if voucher.third_check:
                ThirdCheck.write(list(voucher.third_check), {
                    'source_party': voucher.party.id,
                    'state': 'held',
                })
            if voucher.third_pay_checks:
                ThirdCheck.write(
                    list(voucher.third_pay_checks), {
                        'destiny_party': voucher.party.id,
                        'date_out': today,
                        'state': 'delivered',
                    })

    @classmethod
    @ModelView.button
    def cancel(cls, vouchers):
        pool = Pool()
        ThirdCheck = pool.get('account.third.check')
        IssuedCheck = pool.get('account.issued.check')

        super(AccountVoucher, cls).cancel(vouchers)

        for voucher in vouchers:
            if voucher.issued_check:
                for check in voucher.issued_check:
                    if check.state != 'issued':
                        cls.raise_user_error('issued_check_not_issued',
                                             (check.name, ))
                IssuedCheck.write(list(voucher.issued_check), {
                    'receiving_party': None,
                    'state': 'draft',
                })
            if voucher.third_check:
                for check in voucher.third_check:
                    if check.state != 'held':
                        cls.raise_user_error('third_check_not_held',
                                             (check.name, ))
                ThirdCheck.write(list(voucher.third_check), {
                    'source_party': None,
                    'state': 'draft',
                })
            if voucher.third_pay_checks:
                for check in voucher.third_pay_checks:
                    if check.state != 'delivered':
                        cls.raise_user_error('third_pay_check_not_delivered',
                                             (check.name, ))
                ThirdCheck.write(list(voucher.third_pay_checks), {
                    'destiny_party': None,
                    'date_out': None,
                    'state': 'held',
                })
class ReceiptLine(metaclass=PoolMeta):
    __name__ = 'cash_bank.receipt.line'
    advance = fields.Many2One(
        'cash_bank.advance',
        'Advance',
        domain=[
            If(
                In(Eval('type'), [
                    'advance_in_apply', 'advance_in_create',
                    'advance_out_apply', 'advance_out_create'
                ]),
                If(In(Eval('type'), ['advance_in_apply', 'advance_out_apply']),
                   [('company', '=', Eval('_parent_receipt', {}).get(
                       'company', -1)), ('state', '=', 'pending'),
                    ('currency', '=', Eval('_parent_receipt', {}).get(
                        'currency', -1)), ('party', '=', Eval('party')),
                    If(
                        Eval('type') == 'advance_in_apply',
                        ('type', '=', 'in'), ('type', '=', 'out'))],
                   [('id', '!=', -1)]),
                [('id', '=', -1)],
            ),
        ],
        states={
            'readonly':
            Eval('receipt_state') != 'draft',
            'invisible':
            Not(In(Eval('type'), ['advance_in_apply', 'advance_out_apply']))
        },
        depends=['receipt_state', 'party', 'account', 'type'])
    advance_origin = fields.Reference(
        'Origin',
        selection='get_advance_origin',
        states={
            'readonly':
            Eval('receipt_state') != 'draft',
            'invisible':
            Not(In(Eval('type'), ['advance_in_create', 'advance_out_create']))
        },
        depends=['receipt_state', 'type'])

    @classmethod
    def __setup__(cls):
        super(ReceiptLine, cls).__setup__()
        cls.type.selection += [
            ('advance_in_apply', 'Apply Collected in Advanced from Customer'),
            ('advance_in_create', 'Create Collected in Advance from Customer'),
            ('advance_out_apply', 'Apply Paid in Advanced to Supplier'),
            ('advance_out_create', 'Create Paid in Advance to Supplier'),
        ]

        cls.party.states['readonly'] = Or(
            Eval('receipt_state') != 'draft',
            Bool(Eval('invoice')),
            Bool(Eval('advance')),
        )
        cls.party.depends += ['advance']

        cls.account.states['readonly'] = Or(
            Eval('receipt_state') != 'draft',
            Not(
                In(Eval('type'),
                   ['move_line', 'advance_in_create', 'advance_out_create'])),
        )

        cls.account.domain.append(
            If(In(Eval('type'), ['advance_in_create', 'advance_out_create']),
               [('reconcile', '=', True), ('party_required', '=', True)], []))

    @classmethod
    def get_advance_origin(cls):
        pool = Pool()
        Model = pool.get('ir.model')
        Advance = pool.get('cash_bank.advance')
        models = Advance._get_origin()
        models = Model.search([
            ('model', 'in', models),
        ])
        return [('', '')] + [(m.model, m.name) for m in models]

    @fields.depends('party', 'type')
    def on_change_party(self):
        pool = Pool()
        Config = pool.get('cash_bank.configuration')
        if self.party and self.type and \
                self.type in ['advance_in_create', 'advance_out_create']:
            config = Config(1)
            if self.type == 'advance_in_create':
                self.account = config.default_collected_in_advanced_account
            else:
                self.account = config.default_paid_in_advanced_account

    @fields.depends('type')
    def on_change_type(self):
        super(ReceiptLine, self).on_change_type()
        self.advance = None
        self.advance_origin = None

    @fields.depends('advance', 'receipt', '_parent_receipt.type')
    def on_change_advance(self):
        if self.advance:
            self.amount = self.advance.amount_to_apply
            self.account = self.advance.receipt_line.account
            if self.receipt:
                if self.receipt.type.type == 'in':
                    if self.advance.type == 'in':
                        self.amount *= -1
                else:
                    if self.advance.type == 'out':
                        self.amount *= -1

    def validate_line(self):
        super(ReceiptLine, self).validate_line()
        pool = Pool()
        Currency = pool.get('currency.currency')
        if self.advance:
            with Transaction().set_context(date=self.advance.date):
                amount_to_apply = Currency.compute(
                    self.advance.currency, self.advance.amount_to_apply,
                    self.receipt.currency)

            if self.receipt.type.type == 'in':
                if self.advance.type == 'in' and \
                        self.type == 'advance_in_create':
                    amount_to_apply = 1
                elif self.advance.type == 'in' and \
                        self.type == 'advance_out_create':
                    amount_to_apply = -1
                elif self.advance.type == 'in' and \
                        self.type == 'advance_in_apply':
                    amount_to_apply *= -1
                elif self.advance.type == 'out' and \
                        self.type == 'advance_out_create':
                    amount_to_apply = -1
            else:
                if self.advance.type == 'out' and \
                        self.type == 'advance_out_create':
                    amount_to_apply = 1
                elif self.advance.type == 'out' and \
                        self.type == 'advance_in_create':
                    amount_to_apply = -1
                elif self.advance.type == 'out' and \
                        self.type == 'advance_out_apply':
                    amount_to_apply *= -1
                elif self.advance.type == 'in' and \
                        self.type == 'advance_in_create':
                    amount_to_apply = -1

            check_greater = True
            if self.type in \
                    ['advance_in_create', 'advance_out_create']:
                check_greater = False

            self._check_invalid_amount(amount_to_apply,
                                       self.advance.rec_name,
                                       check_greater=check_greater)

    def reconcile(self):
        super(ReceiptLine, self).reconcile()
        pool = Pool()
        Currency = pool.get('currency.currency')
        AdvanceLine = pool.get('cash_bank.advance.line_applied')
        MoveLine = pool.get('account.move.line')

        if self.advance:
            if self.type in \
                    ['advance_in_create', 'advance_out_create']:
                return

            with Transaction().set_context(date=self.advance.date):
                amount = Currency.compute(self.receipt.currency, self.amount,
                                          self.receipt.company.currency)

            amount_to_reconcile = abs(amount)
            reconcile_lines, remainder = \
                self.advance.get_reconcile_lines_for_amount(
                    amount_to_reconcile)

            line_applied = AdvanceLine(advance=self.advance, receipt_line=self)
            line_applied.save()

            if remainder == 0:
                lines = reconcile_lines + [self.line_move]
                MoveLine.reconcile(lines)
                self.advance.state = 'applied'
                self.advance.save()
class PatientEncounter(ModelSQL, ModelView):
    'Patient Encounter'
    __name__ = 'gnuhealth.encounter'

    STATES = {'readonly': In(Eval('state'), ['signed', 'done', 'invalid'])}
    SIGNED_STATES = {'readonly': Equal(Eval('state'), 'signed')}
    SIGNED_VISIBLE = {'invisible': Not(Equal(Eval('state'), 'signed'))}

    active = fields.Boolean('Active', select=True)
    state = fields.Selection(
        [('in_progress', 'In progress'), ('done', 'Done'),
         ('signed', 'Signed'), ('invalid', 'Invalid')],
        'State',
        readonly=True,
        sort=False,
        states={'invisible': Equal(Eval('state'), 'signed')})
    patient = fields.Many2One('gnuhealth.patient',
                              'Patient',
                              required=True,
                              states={'readonly': Eval('id', 0) > 0})
    primary_complaint = fields.Char('Primary complaint', states=STATES)
    start_time = fields.DateTime('Start', required=True, states=STATES)
    end_time = fields.DateTime('End', states=STATES)
    institution = fields.Many2One('gnuhealth.institution',
                                  'Institution',
                                  required=True,
                                  states=STATES)
    appointment = fields.Many2One(
        'gnuhealth.appointment',
        'Appointment',
        domain=[('patient', '=', Eval('patient'))],
        depends=['patient'],
        help='Enter or select the appointment related to this encounter',
        states=STATES)
    next_appointment = fields.Many2One(
        'gnuhealth.appointment',
        'Next Appointment',
        # domain=['OR', ('state', '=', 'free'),
        #         ('patient', '=', Eval('patient'))],
        depends=['patient'],
        states=SIGNED_STATES)
    signed_by = fields.Many2One(
        'gnuhealth.healthprofessional',
        'Signed By',
        readonly=True,
        states=SIGNED_VISIBLE,
        help="Health Professional that finished the patient evaluation")
    sign_time = fields.DateTime('Sign time',
                                readonly=True,
                                states=SIGNED_VISIBLE)
    components = fields.One2Many('gnuhealth.encounter.component', 'encounter',
                                 'Components')
    summary = fields.Function(fields.Text('Summary'), 'get_encounter_summary')
    short_summary = fields.Function(fields.Text('Summary'),
                                    'get_short_summary')
    # Patient identifier fields
    upi = fields.Function(fields.Char('UPI'), 'get_upi_mrn')
    medical_record_num = fields.Function(fields.Char('Medical Record Number'),
                                         'get_upi_mrn')
    sex_display = fields.Function(fields.Char('Sex'),
                                  'get_person_patient_field')
    age = fields.Function(fields.Char('Age', help="Age at start of encounter"),
                          'get_patient_age')
    crypto_enabled = fields.Function(fields.Boolean('Crypto Enabled'),
                                     'get_crypto_enabled')
    clinicians = fields.Function(fields.One2Many(
        'gnuhealth.healthprofessional', 'encounter', 'Clinicians'),
                                 'get_clinicians',
                                 searcher='search_clinicians')

    @classmethod
    def __setup__(cls):
        super(PatientEncounter, cls).__setup__()
        cls._error_messages.update({
            'health_professional_warning':
            'No health professional '
            'associated with this user',
            'end_date_before_start':
            'End time cannot be before'
            'Start time\n"%(start_time)s"',
            'end_date_required':
            'End time is required for finishing',
            'unsigned_components':
            'There are unsigned components.'
            # 'This encounter cannot be signed'
        })

        cls._buttons.update({
            'set_done': {
                'invisible':
                Not(Equal(Eval('state'), 'in_progress')),
                'readonly':
                Or(Greater(0, Eval('id', -1)),
                   Greater(1, Len(Eval('components'))))
            },
            'sign_finish': {
                'invisible': Not(Equal(Eval('state'), 'done'))
            },
            'add_component': {
                'readonly':
                Or(Greater(0, Eval('id', -1)),
                   In(Eval('state'), ['done', 'signed', 'invalid'])),
                'invisible':
                Equal(Eval('state'), 'signed')
            },
            'add_extra_component': {
                'invisible':
                In(Eval('state'), ['signed', 'in_progress', 'invalid'])
            }
        })

    @classmethod
    def create(cls, vlist):
        '''
        update appointment, set state = processing when encounter is
        first saved
        '''
        retval = super(PatientEncounter, cls).create(vlist)
        Appointment = Pool().get('gnuhealth.appointment')
        appointments = []
        for encounter in vlist:
            if encounter['appointment'] and not encounter.get('end_time'):
                appointments.append(encounter['appointment'])
        appts = Appointment.browse(appointments)
        Appointment.write(appts, {'state': 'processing'})
        return retval

    @classmethod
    def validate(cls, records):
        for e in records:
            # 1. that the end-date is not before the start date
            if e.end_time and e.end_time <= e.start_time:
                cls.raise_user_error(
                    'end_date_before_start', {
                        'start_time': e.start_time.strftime('%c'),
                        'end_time': e.end_time.strftime('%c')
                    })
            # 2. That the encounter didn't start before the appointment
            # should we really though?
        return super(PatientEncounter, cls).validate(records)

    @classmethod
    @ModelView.button
    def sign_finish(cls, encounters):
        signing_hp = HealthProfessional().get_health_professional()
        if not signing_hp:
            cls.raise_user_error('health_professional_warning')
        #ToDO: set all the not-done components to DONE as well and sign
        # the unsigned ones
        # No! Components should be individually signed.
        for encounter in encounters:
            for comp in encounter.components:
                if not comp.signed_by:
                    cls.raise_user_error('unsigned_components')

        cls.write(
            encounters, {
                'state': 'signed',
                'signed_by': signing_hp,
                'sign_time': datetime.now()
            })

    @classmethod
    @ModelView.button
    def set_done(cls, encounters):
        # Change the state of the evaluation to "Done"
        save_data = {'state': 'done'}
        appointments = []  # appointments to be set to done
        for encounter in encounters:
            if not encounter.end_time:
                cls.raise_user_warning(
                    'encounter_end_date_warn',
                    'End time has not been set.\nDo you want to use the'
                    ' current date and time?')
                save_data.update(end_time=datetime.now())

            if encounter.appointment:
                appointments.append(encounter.appointment)

        cls.write(encounters, save_data)
        Appointment = Pool().get('gnuhealth.appointment')
        Appointment.write(appointments, {'state': 'done'})

    @classmethod
    @ModelView.button_action(
        'health_encounter.health_wizard_encounter_edit_component')
    def add_component(cls, components, *a, **k):
        hp = HealthProfessional.get_health_professional()
        if not hp:
            cls.raise_user_error('health_professional_warning')

    @classmethod
    @ModelView.button_action(
        'health_encounter.health_wizard_encounter_edit_component')
    def add_extra_component(cls, components, *a, **k):
        hp = HealthProfessional.get_health_professional()
        if not hp:
            cls.raise_user_error('health_professional_warning')

    @staticmethod
    def default_start_time():
        return datetime.now()

    @staticmethod
    def default_institution():
        return HealthInstitution().get_institution()

    @staticmethod
    def default_state():
        return 'in_progress'

    @staticmethod
    def default_active():
        return True

    def get_crypto_enabled(self, name):
        return False

    def get_rec_name(self, name):
        localstart = utils.localtime(self.start_time)
        line = [
            'EV%05d' % self.id, self.patient.name.name,
            '(%s /MRN:%s)' % (self.upi, self.medical_record_num),
            self.sex_display, self.age,
            'on %s' % localstart.ctime()
        ]
        return ' '.join(line)

    def get_person_patient_field(self, name):
        if name in ['sex_display']:
            sex = getattr(self.patient.name, name,
                          getattr(self.patient.name, 'sex', '?'))
            return len(sex) == 1 and sex.upper() or sex
        if name in ['age']:
            return getattr(self.patient, name)
        return ''

    def get_upi_mrn(self, name):
        if name == 'upi':
            return self.patient.puid
        elif name == 'medical_record_num':
            return getattr(self.patient, 'medical_record_num', '')
        return ''

    def get_encounter_summary(self, name):
        summary_texts = []
        for component in self.components:
            real_component = component.union_unshard(component.id)
            report_info = real_component.report_info.split(u'\n')
            report_info.insert(1, real_component.byline)
            summary_texts.append(u'\n'.join(report_info))
            # TODO: Show extra components differently from regular ones
        return u'\n\n'.join(summary_texts)

    def get_short_summary(self, name):
        summary_texts = []
        for component in self.components:
            summary_texts.append(
                (component.component_type, component.critical_info))
        return u'\n'.join([': '.join(x) for x in summary_texts])

    def real_component(self, name=None):
        '''retuns the real component objects.
        Always returns a list of objects.
        If name not provided returns all real components
        name can be the name of the model or the shortname displayed
        on screen, case insensitive.
        '''
        comps = [(x.component_type, x.union_unshard(x.id))
                 for x in self.components]
        typedict = {}
        real_comps = []
        # modeldict = {}
        for i, (comptype, comp) in enumerate(comps):
            typedict.setdefault(comptype.lower(), []).append(i)
            # modeldict # ToDo: Figure out how to get at the model
            # name from an instance
            real_comps.append(comp)
        if name:
            return [real_comps[i] for i in typedict.get(name, [])]
        else:
            return real_comps

    def get_clinicians(self, name):
        '''returns a list of IDs for the clinicians that performed
        components linked here'''
        health_profs = [x.performed_by for x in self.components]
        health_profs.extend(
            [x.signed_by for x in self.components if x.sign_time])
        return map(int, set(filter(None, health_profs)))

    @classmethod
    def search_clinicians(self, name, clause):
        fld, operator, operand = clause
        component_model = Pool().get('gnuhealth.encounter.component')
        components = component_model.search([
            'OR', ('performed_by', operator, operand),
            ('signed_by', operator, operand)
        ])
        encounter_list = [
            x.encounter.id for x in component_model.browse(components)
        ]
        return [('id', 'in', encounter_list)]

    @classmethod
    def get_patient_age(cls, instances, name):
        '''
        Uses the AGE function in the database to calculate the age at
        the date at which the encounter started
        '''
        c = Transaction().cursor
        tbl = cls.__table__()
        qry = "\n".join([
            "SET intervalstyle TO 'iso_8601';",
            "SELECT a.id as id, COALESCE(btrim(lower("
            "regexp_replace(AGE(a.start_time::date, c.dob)::varchar, "
            "'([YMD])', '\\1 ', 'g')), 'p '), '--')  as showage ",
            "from " + str(tbl) + " as a ",
            " inner join gnuhealth_patient as b on a.patient=b.id",
            " inner join party_party c on b.name=c.id"
            " where a.id in %s ;"
        ])
        qry_parm = tuple(map(int, instances))
        c.execute(qry, (qry_parm, ))
        return dict([x for x in c.fetchall()])
Exemple #28
0
    @classmethod
    def generate_code(cls, institution, sector):
        return '-'.join([institution.code, sector.code])

    @classmethod
    def create(cls, vlist):
        vlist = [x.copy() for x in vlist]
        for values in vlist:
            if not values.get('sync_code'):
                values['sync_code'] = cls.generate_code(
                    values['name'], values['operational_sector'])
        return super(HealthInstitutionOperationalSector, cls).create(vlist)


ENCTR_STATES = {'readonly': In(Eval('state'), ['signed', 'done', 'invalid'])}
COMPT_STATES = {'readonly': Bool(Eval('signed_by'))}


class PatientEncounter(ModelSQL, ModelView):
    'Patient Encounter'
    __name__ = 'gnuhealth.encounter'
    fvty = fields.Boolean('First visit this year',
                          states=ENCTR_STATES,
                          help='Check if this is known to be the first time '
                          'this patient is visiting this institution '
                          'for this year')

    @fields.depends('patient', 'start_time', 'institution')
    def on_change_with_fvty(self, *arg, **kwarg):
        if self.institution and self.patient and self.start_time:
Exemple #29
0
class AccountVoucher(ModelSQL, ModelView):
    'Account Voucher'
    __name__ = 'account.voucher'
    _rec_name = 'number'

    number = fields.Char('Number', readonly=True, help="Voucher Number")
    party = fields.Many2One('party.party',
                            'Party',
                            states={
                                'required': ~Eval('active', True),
                                'readonly': In(Eval('state'), ['posted']),
                            })
    voucher_type = fields.Selection([
        ('payment', 'Payment'),
        ('receipt', 'Receipt'),
    ],
                                    'Type',
                                    select=True,
                                    required=True,
                                    states=_STATES)
    pay_lines = fields.One2Many('account.voucher.line.paymode',
                                'voucher',
                                'Pay Mode Lines',
                                states=_STATES)
    date = fields.Date('Date', required=True, states=_STATES)
    journal = fields.Many2One('account.journal',
                              'Journal',
                              required=True,
                              states=_STATES)
    currency = fields.Many2One('currency.currency', 'Currency', states=_STATES)
    company = fields.Many2One('company.company', 'Company', states=_STATES)
    lines = fields.One2Many('account.voucher.line',
                            'voucher',
                            'Lines',
                            states=_STATES)
    lines_credits = fields.One2Many('account.voucher.line.credits',
                                    'voucher',
                                    'Credits',
                                    states={
                                        'invisible': ~Eval('lines_credits'),
                                    })
    lines_debits = fields.One2Many('account.voucher.line.debits',
                                   'voucher',
                                   'Debits',
                                   states={
                                       'invisible': ~Eval('lines_debits'),
                                   })
    comment = fields.Text('Comment', states=_STATES)
    state = fields.Selection([
        ('draft', 'Draft'),
        ('posted', 'Posted'),
        ('canceled', 'Canceled'),
    ],
                             'State',
                             select=True,
                             readonly=True)
    amount = fields.Function(fields.Numeric('Payment', digits=(16, 2)),
                             'on_change_with_amount')
    amount_to_pay = fields.Function(fields.Numeric('To Pay', digits=(16, 2)),
                                    'on_change_with_amount_to_pay')
    amount_invoices = fields.Function(
        fields.Numeric('Invoices', digits=(16, 2)),
        'on_change_with_amount_invoices')
    move = fields.Many2One('account.move', 'Move', readonly=True)
    move_canceled = fields.Many2One('account.move',
                                    'Move Canceled',
                                    readonly=True,
                                    states={
                                        'invisible': ~Eval('move_canceled'),
                                    })
    from_pay_invoice = fields.Boolean('Voucher launched from Pay invoice')
    amount_to_pay_words = fields.Char('Amount to Pay (Words)',
                                      states={'readonly': True})

    transfer = fields.Boolean(
        'Realizar movimiento',
        help=
        'Realizar movimiento de caja a bancos, o transferencia entre bancos',
        states={
            'readonly': In(Eval('state'), ['posted']),
        })

    @classmethod
    def __setup__(cls):
        super(AccountVoucher, cls).__setup__()
        cls._error_messages.update({
            'missing_pay_lines':
            'You have to enter pay mode lines!',
            'delete_voucher':
            'You can not delete a voucher that is posted!',
            'payment_advanced':
            u'¿Desea generar un anticipo?',
        })

        cls._buttons.update({
            'post': {
                'invisible': Eval('state') != 'draft',
            },
            'cancel': {
                'invisible': Eval('state') != 'posted',
            },
        })
        cls._order.insert(0, ('date', 'DESC'))
        cls._order.insert(1, ('number', 'DESC'))

    @staticmethod
    def default_state():
        return 'draft'

    @staticmethod
    def default_transfer():
        return False

    @staticmethod
    def default_currency():
        Company = Pool().get('company.company')
        company_id = Transaction().context.get('company')
        if company_id:
            return Company(company_id).currency.id

    @staticmethod
    def default_company():
        return Transaction().context.get('company')

    @staticmethod
    def default_journal():
        pool = Pool()
        Journal = pool.get('account.journal')
        journal = Journal.search([('type', '=', 'expense')])
        journal_r = Journal.search([('type', '=', 'revenue')])
        voucher_type_id = Transaction().context.get('voucher_type')
        if voucher_type_id == 'receipt':
            for j in journal_r:
                return j.id

        if voucher_type_id == 'payment':
            for j in journal:
                return j.id

    @staticmethod
    def default_date():
        Date = Pool().get('ir.date')
        return Date.today()

    @staticmethod
    def default_from_pay_invoice():
        return False

    def set_number(self):
        Sequence = Pool().get('ir.sequence')
        AccountVoucherSequence = Pool().get('account.voucher.sequence')

        sequence = AccountVoucherSequence(1)
        if self.voucher_type == 'payment':
            self.write([self], {
                'number':
                Sequence.get_id(sequence.voucher_payment_sequence.id)
            })
        else:
            self.write([self], {
                'number':
                Sequence.get_id(sequence.voucher_receipt_sequence.id)
            })

    @fields.depends('party', 'lines', 'pay_lines', 'lines_credits',
                    'lines_debits')
    def on_change_with_amount(self, name=None):
        amount = Decimal('0.0')
        if self.pay_lines:
            for line in self.pay_lines:
                if line.pay_amount:
                    amount += line.pay_amount
        if self.lines_credits:
            for line in self.lines_credits:
                if line.amount_original:
                    amount += line.amount_original
        if self.lines_debits:
            for line in self.lines_debits:
                if line.amount_original:
                    amount += line.amount_original
        return amount

    @fields.depends('party', 'lines')
    def on_change_with_amount_to_pay(self, name=None):
        total = 0
        if self.lines:
            for line in self.lines:
                total += line.amount_unreconciled or Decimal('0.00')
        return total

    @fields.depends('lines', 'pay_lines')
    def on_change_with_amount_invoices(self, name=None):
        total = 0
        if self.lines:
            for line in self.lines:
                total += line.amount or Decimal('0.00')
        return total

    @fields.depends('party', 'voucher_type', 'lines', 'lines_credits',
                    'lines_debits', 'from_pay_invoice')
    def on_change_party(self):
        pool = Pool()
        Invoice = pool.get('account.invoice')
        MoveLine = pool.get('account.move.line')
        InvoiceAccountMoveLine = pool.get('account.invoice-account.move.line')
        Currency = pool.get('currency.currency')
        PaymentLine = pool.get('account.voucher.line')
        PaymentLineCredits = pool.get('account.voucher.line.credits')
        PaymentLineDebits = pool.get('account.voucher.line.debits')

        if self.from_pay_invoice:
            # The voucher was launched from Invoice's PayInvoice wizard:
            # 'lines', 'lines_credits', 'lines_debits' should be set there
            return {}

        lines = []
        lines_credits = []
        lines_debits = []

        if self.lines:
            return

        if self.voucher_type == 'receipt':
            account_types = ['receivable']
        else:
            account_types = ['payable']

        move_lines = MoveLine.search([
            ('party', '=', self.party),
            ('account.kind', 'in', account_types),
            ('state', '=', 'valid'),
            ('reconciliation', '=', None),
        ])

        for line in move_lines:

            invoice = InvoiceAccountMoveLine.search([
                ('line', '=', line.id),
            ])
            if invoice:
                continue

            if line.credit:
                line_type = 'cr'
                amount = line.credit
            else:
                amount = line.debit
                line_type = 'dr'

            amount_residual = abs(line.amount_residual)
            name = ''
            model = str(line.origin)
            if model[:model.find(',')] == 'account.invoice':
                invoice = Invoice(line.origin.id)
                if invoice.type[0:3] == 'out':
                    name = invoice.number
                else:
                    name = invoice.reference
            payment_line = AccountVoucherLine()
            payment_line.name = name
            payment_line.account = line.account.id
            payment_line.amount = Decimal('0.00')
            payment_line.amount_original = amount
            payment_line.amount_unreconciled = amount_residual
            payment_line.line_type = line_type
            payment_line.move_line = line.id
            payment_line.date = line.date
            payment_line.date_expire = line.maturity_date

            if line.credit and self.voucher_type == 'receipt':
                lines_credits.append(payment_line)
            elif line.debit and self.voucher_type == 'payment':
                lines_debits.append(payment_line)
            else:
                lines.append(payment_line)

        self.lines = lines
        self.lines_credits = lines_credits
        self.lines_debits = lines_debits

    @classmethod
    def delete(cls, vouchers):
        if not vouchers:
            return True
        for voucher in vouchers:
            if voucher.state != 'draft':
                cls.raise_user_error('delete_voucher')
        return super(AccountVoucher, cls).delete(vouchers)

    def prepare_move_lines(self):
        pool = Pool()
        Period = pool.get('account.period')
        Move = pool.get('account.move')
        Invoice = pool.get('account.invoice')
        Sale = pool.get('sale.sale')
        original = Decimal(0.0)
        unreconcilied = Decimal(0.0)
        paid_amount = Decimal(0.0)
        residual_amount = Decimal(0.0)
        name = None
        invoice_d = None
        # Check amount
        if not self.amount > Decimal("0.0"):
            self.raise_user_error('missing_pay_lines')

        move_lines = []
        line_move_ids = []
        move, = Move.create([{
            'period':
            Period.find(self.company.id, date=self.date),
            'journal':
            self.journal.id,
            'date':
            self.date,
            'origin':
            str(self),
        }])
        self.write([self], {
            'move': move.id,
        })

        #
        # Pay Modes
        #
        if self.pay_lines:
            for line in self.pay_lines:
                if self.voucher_type == 'receipt':
                    debit = line.pay_amount
                    credit = Decimal('0.0')
                else:
                    debit = Decimal('0.0')
                    credit = line.pay_amount

                move_lines.append({
                    'debit':
                    debit,
                    'credit':
                    credit,
                    'account':
                    line.pay_mode.account.id,
                    'move':
                    move.id,
                    'journal':
                    self.journal.id,
                    'period':
                    Period.find(self.company.id, date=self.date),
                })

        #
        # Credits
        #
        if self.lines_credits:
            for line in self.lines_credits:
                debit = line.amount_original
                credit = Decimal('0.0')
                move_lines.append({
                    'description':
                    'advance',
                    'debit':
                    debit,
                    'credit':
                    credit,
                    'account':
                    line.account.id,
                    'move':
                    move.id,
                    'journal':
                    self.journal.id,
                    'period':
                    Period.find(self.company.id, date=self.date),
                    'party':
                    self.party.id,
                })

        #
        # Debits
        #
        if self.lines_debits:
            for line in self.lines_debits:
                debit = Decimal('0.0')
                credit = line.amount_original
                move_lines.append({
                    'description':
                    'advance',
                    'debit':
                    debit,
                    'credit':
                    credit,
                    'account':
                    line.account.id,
                    'move':
                    move.id,
                    'journal':
                    self.journal.id,
                    'period':
                    Period.find(self.company.id, date=self.date),
                    'party':
                    self.party.id,
                })

        #
        # Voucher Lines
        #
        total = self.amount
        if self.lines:
            for line in self.lines:
                if not line.amount:
                    continue
                line_move_ids.append(line.move_line)
                if self.voucher_type == 'receipt':
                    debit = Decimal('0.00')
                    credit = line.amount
                else:
                    debit = line.amount
                    credit = Decimal('0.00')
                total -= line.amount
                move_lines.append({
                    'description':
                    Invoice(line.move_line.origin.id).number,
                    'debit':
                    debit,
                    'credit':
                    credit,
                    'account':
                    line.account.id,
                    'move':
                    move.id,
                    'journal':
                    self.journal.id,
                    'period':
                    Period.find(self.company.id, date=self.date),
                    'party':
                    self.party.id,
                })
        if total != Decimal('0.00'):
            if self.voucher_type == 'receipt':
                debit = Decimal('0.00')
                credit = total
                account_id = self.party.account_receivable.id
            else:
                debit = total
                credit = Decimal('0.00')
                account_id = self.party.account_payable.id
            move_lines.append({
                'description':
                self.number,
                'debit':
                debit,
                'credit':
                credit,
                'account':
                account_id,
                'move':
                move.id,
                'journal':
                self.journal.id,
                'period':
                Period.find(self.company.id, date=self.date),
                'date':
                self.date,
                'party':
                self.party.id,
            })

        return move_lines

    def create_move(self, move_lines):
        pool = Pool()
        Move = pool.get('account.move')
        MoveLine = pool.get('account.move.line')
        Invoice = pool.get('account.invoice')
        created_lines = MoveLine.create(move_lines)
        Move.post([self.move])
        Sale = pool.get('sale.sale')
        invoice_d = None
        sales = None
        name = None
        invoice = None
        for line in self.lines:
            original = line.amount_original
            unreconciled = line.amount_unreconciled
            name = line.name
        if name != None:
            invoice = Invoice.search([('number', '=', name),
                                      ('description', '!=', None)])
        if invoice:
            for i in invoice:
                invoice_d = i.description

        if invoice_d != None:
            sales = Sale.search([('reference', '=', invoice_d)])

        if sales:
            for s in sales:
                sale = s
            paid_amount = Decimal(original - unreconciled)
            residual_amount = Decimal(unreconciled)
            sale.get_residual_amount([sale], ['residual_amount'])
            sale.get_paid_amount([sale], ['paid_amount'])

        # reconcile check
        for line in self.lines:
            if line.amount == Decimal("0.00"):
                continue
            invoice = Invoice(line.move_line.origin.id)
            if self.voucher_type == 'receipt':
                amount = line.amount
            else:
                amount = -line.amount
            reconcile_lines, remainder = \
                Invoice.get_reconcile_lines_for_amount(
                    invoice, amount)
            for move_line in created_lines:
                if move_line.description == 'advance':
                    continue
                if move_line.description == invoice.number:
                    reconcile_lines.append(move_line)
                    Invoice.write([invoice], {
                        'payment_lines': [('add', [move_line.id])],
                    })
            if remainder == Decimal('0.00'):
                MoveLine.reconcile(reconcile_lines)

        reconcile_lines = []
        for line in self.lines_credits:
            reconcile_lines.append(line.move_line)
            for move_line in created_lines:
                if move_line.description == 'advance':
                    reconcile_lines.append(move_line)
            MoveLine.reconcile(reconcile_lines)

        reconcile_lines = []
        for line in self.lines_debits:
            reconcile_lines.append(line.move_line)
            for move_line in created_lines:
                if move_line.description == 'advance':
                    reconcile_lines.append(move_line)
            MoveLine.reconcile(reconcile_lines)

        return True

    def create_cancel_move(self):
        pool = Pool()
        Move = pool.get('account.move')
        MoveLine = pool.get('account.move.line')
        Period = pool.get('account.period')
        Reconciliation = pool.get('account.move.reconciliation')
        Invoice = pool.get('account.invoice')
        Date = pool.get('ir.date')

        canceled_date = Date.today()
        canceled_move, = Move.copy(
            [self.move], {
                'period': Period.find(self.company.id, date=canceled_date),
                'date': canceled_date,
            })
        self.write([self], {
            'move_canceled': canceled_move.id,
        })

        for line in canceled_move.lines:
            aux = line.debit
            line.debit = line.credit
            line.credit = aux
            line.save()

        Move.post([self.move_canceled])

        reconciliations = [
            x.reconciliation for x in self.move.lines if x.reconciliation
        ]
        with Transaction().set_user(0, set_context=True):
            if reconciliations:
                Reconciliation.delete(reconciliations)

        for line in self.lines:
            origin = str(line.move_line.origin)
            origin = origin[:origin.find(',')]
            if origin not in ['account.invoice', 'account.voucher']:
                continue
            if line.amount == Decimal("0.00"):
                continue
            invoice = Invoice(line.move_line.origin.id)
            for move_line in self.move_canceled.lines:
                if move_line.description == 'advance':
                    continue
                if move_line.description == invoice.number:
                    Invoice.write([invoice], {
                        'payment_lines': [('add', [move_line.id])],
                    })

        lines_to_reconcile = []
        for line in self.move.lines:
            if line.account.reconcile:
                lines_to_reconcile.append(line)
        for cancel_line in canceled_move.lines:
            if cancel_line.account.reconcile:
                lines_to_reconcile.append(cancel_line)

        if lines_to_reconcile:
            MoveLine.reconcile(lines_to_reconcile)

        return True

    def prepare_postdated_lines(self):
        pool = Pool()
        Period = pool.get('account.period')
        Move = pool.get('account.move')
        Invoice = pool.get('account.invoice')

        postdated_lines = None

        if self.pay_lines:
            for line in self.pay_lines:
                if line.pay_mode.account.name == 'EFECTOS DE COBRO INMEDIATO (CHEQUES)':
                    postdated_lines = []
                    postdated_lines.append({
                        'reference': line.voucher.move,
                        'name': line.voucher.number,
                        'amount': line.pay_amount,
                        'account': line.pay_mode.account.id,
                        'date': line.fecha,
                    })

        return postdated_lines

    def create_postdated_check(self, postdated_lines):
        pool = Pool()
        Postdated = pool.get('account.postdated')
        PostdatedLine = pool.get('account.postdated.line')
        postdated = Postdated()

        if postdated_lines != None:
            for line in postdated_lines:
                date = line['date']
                postdated.party = self.party
                postdated.post_check_type = 'receipt'
                postdated.journal = 1
                postdated.lines = postdated_lines
                postdated.state = 'draft'
                postdated.date = date
                postdated.save()

    def get_value_lines(self):
        amount_invoice = self.amount
        if self.lines:
            res = {}
            for line in self.lines:
                if line.amount_unreconciled < amount_invoice:
                    value = Decimal('0.0')
                    amount_invoice -= line.amount_unreconciled
                    line.write([line], {'amount': line.amount_unreconciled})
                    line.write([line], {'amount_unreconciled': value})

                if line.amount_unreconciled >= amount_invoice:
                    value = line.amount_unreconciled - amount_invoice
                    line.write([line], {'amount': amount_invoice})
                    line.write([line], {'amount_unreconciled': value})
                    amount_invoice = Decimal('0.0')

            if amount_invoice != 0:
                warning_name = u'Tiene un excedente ¿Desea generar un anticipo?'
                self.raise_user_warning(warning_name, 'payment_advanced')

    def get_amount2words(self, value):
        if conversor:
            return (conversor.cardinal(int(value))).upper()
        else:
            return ''

    def get_toWords(self):
        if self.lines:
            amount = Decimal('0.0')
            for line in self.lines:
                amount += line.amount
                value_words = self.get_amount2words(amount)
                self.write([self], {'amount_to_pay_words': value_words})

    @classmethod
    @ModelView.button
    def post(cls, vouchers):
        pool = Pool()
        module = None
        Module = pool.get('ir.module')
        module = Module.search([('name', '=', 'nodux_account_postdated_check'),
                                ('state', '=', 'installed')])
        for voucher in vouchers:
            voucher.get_value_lines()
            voucher.get_toWords()
            voucher.set_number()
            move_lines = voucher.prepare_move_lines()
            voucher.create_move(move_lines)
            if module:
                postdated_lines = voucher.prepare_postdated_lines()
                voucher.create_postdated_check(postdated_lines)
        cls.write(vouchers, {'state': 'posted'})

    @classmethod
    @ModelView.button
    def cancel(cls, vouchers):
        for voucher in vouchers:
            voucher.create_cancel_move()
        cls.write(vouchers, {'state': 'canceled'})

    @classmethod
    def view_attributes(cls):
        return super(AccountVoucher, cls).view_attributes() + [
            ('//page[@id="pay_lines"]', 'states', {
                'invisible': Eval('transfer'),
            }),
            ('//page[@id="lines"]', 'states', {
                'invisible': Eval('transfer'),
            }),
            ('//page[@id="info"]', 'states', {
                'invisible': Eval('transfer'),
            })
        ]
Exemple #30
0
class PurchaseRequest(ModelSQL, ModelView):
    'Purchase Request'
    __name__ = 'purchase.request'

    product = fields.Many2One('product.product',
                              'Product',
                              select=True,
                              readonly=True,
                              domain=[('purchasable', '=', True)])
    description = fields.Text('Description',
                              readonly=True,
                              states=STATES,
                              depends=DEPENDS)
    party = fields.Many2One('party.party',
                            'Party',
                            select=True,
                            states=STATES,
                            depends=DEPENDS)
    quantity = fields.Float('Quantity',
                            required=True,
                            states=STATES,
                            digits=(16, Eval('uom_digits', 2)),
                            depends=DEPENDS + ['uom_digits'])
    uom = fields.Many2One('product.uom',
                          'UOM',
                          select=True,
                          ondelete='RESTRICT',
                          domain=[
                              ('category', '=', Eval('product_uom_category')),
                          ],
                          states={
                              'required': Bool(Eval('product')),
                              'readonly': STATES['readonly'],
                          },
                          depends=['product', 'product_uom_category'] +
                          DEPENDS)
    uom_digits = fields.Function(fields.Integer('UOM Digits'),
                                 'on_change_with_uom_digits')
    product_uom_category = fields.Function(
        fields.Many2One('product.uom.category', "Product Uom Category"),
        'on_change_with_product_uom_category')
    computed_quantity = fields.Float('Computed Quantity', readonly=True)
    computed_uom = fields.Many2One('product.uom',
                                   'Computed UOM',
                                   readonly=True)
    purchase_date = fields.Date('Best Purchase Date', readonly=True)
    supply_date = fields.Date('Expected Supply Date', readonly=True)
    default_uom_digits = fields.Function(fields.Integer('Default UOM Digits'),
                                         'on_change_with_default_uom_digits')
    stock_level = fields.Float('Stock at Supply Date',
                               readonly=True,
                               digits=(16, Eval('default_uom_digits', 2)),
                               depends=['default_uom_digits'])
    warehouse = fields.Many2One('stock.location',
                                "Warehouse",
                                states={
                                    'required': Eval('warehouse_required',
                                                     False),
                                },
                                domain=[('type', '=', 'warehouse')],
                                depends=['warehouse_required'],
                                readonly=True)
    warehouse_required = fields.Function(fields.Boolean('Warehouse Required'),
                                         'get_warehouse_required')
    purchase_line = fields.Many2One('purchase.line',
                                    'Purchase Line',
                                    readonly=True)
    purchase = fields.Function(fields.Many2One('purchase.purchase',
                                               'Purchase'),
                               'get_purchase',
                               searcher='search_purchase')
    company = fields.Many2One('company.company',
                              'Company',
                              required=True,
                              readonly=True,
                              domain=[
                                  ('id',
                                   If(In('company', Eval('context', {})), '=',
                                      '!='), Eval('context',
                                                  {}).get('company', -1)),
                              ])
    origin = fields.Reference('Origin', selection='get_origin', readonly=True)
    exception_ignored = fields.Boolean('Ignored Exception')
    state = fields.Selection([
        ('purchased', "Purchased"),
        ('done', "Done"),
        ('draft', "Draft"),
        ('cancel', "Cancel"),
        ('exception', "Exception"),
    ],
                             "State",
                             required=True,
                             readonly=True,
                             select=True)

    @classmethod
    def __setup__(cls):
        super(PurchaseRequest, cls).__setup__()
        cls._order[0] = ('id', 'DESC')
        cls._buttons.update({
            'handle_purchase_cancellation_exception': {
                'invisible': Eval('state') != 'exception',
                'depends': ['state'],
            },
        })

    @classmethod
    def __register__(cls, module_name):
        pool = Pool()
        ModelData = pool.get('ir.model.data')
        Purchase = pool.get('purchase.purchase')
        PurchaseLine = pool.get('purchase.line')
        model_data = ModelData.__table__()
        purchase = Purchase.__table__()
        purchase_line = PurchaseLine.__table__()
        request = cls.__table__()

        tablehandler = cls.__table_handler__(module_name)
        state_exist = tablehandler.column_exist('state')

        super(PurchaseRequest, cls).__register__(module_name)

        # Migration from 3.6: removing the constraint on the quantity
        tablehandler = cls.__table_handler__(module_name)
        tablehandler.drop_constraint('check_purchase_request_quantity')

        # Migration from 3.8: renaming module of Purchase Request group entry
        cursor = Transaction().connection.cursor()
        cursor.execute(*model_data.update(
            columns=[model_data.module],
            values=['purchase_request'],
            where=((model_data.fs_id == 'group_purchase_request')
                   & (model_data.module == 'stock_supply'))))

        # Migration from 4.0: remove required on product and uom
        tablehandler.not_null_action('product', action='remove')
        tablehandler.not_null_action('uom', action='remove')

        # Migration from 4.2: add state
        if not state_exist:
            cursor = Transaction().connection.cursor()
            update = Transaction().connection.cursor()
            query = request.join(
                purchase_line,
                type_='INNER',
                condition=request.purchase_line == purchase_line.id).join(
                    purchase,
                    type_='INNER',
                    condition=purchase_line.purchase == purchase.id).select(
                        request.id, purchase.state, request.exception_ignored)
            cursor.execute(*query)
            for request_id, purchase_state, exception_ignored in cursor:
                if purchase_state == 'cancel' and not exception_ignored:
                    state = 'exception'
                elif purchase_state == 'cancel':
                    state = 'cancel'
                elif purchase_state == 'done':
                    state = 'done'
                else:
                    state = 'purchased'
                update.execute(*request.update([request.state], [state],
                                               where=request.id == request_id))

        # Migration from 4.4: remove required on origin
        tablehandler.not_null_action('origin', action='remove')

    def get_rec_name(self, name):
        pool = Pool()
        Lang = pool.get('ir.lang')
        if self.product:
            lang = Lang.get()
            rec_name = (lang.format('%.*f', (self.uom.digits, self.quantity)) +
                        '%s %s' % (self.uom.symbol, self.product.name))
        elif self.description:
            rec_name = self.description.splitlines()[0]
        else:
            rec_name = str(self.id)

        if self.warehouse:
            return "%s @% s" % (rec_name, self.warehouse.name)
        else:
            return rec_name

    @classmethod
    def search_rec_name(cls, name, clause):
        res = []
        names = clause[2].split('@', 1)
        res.append(('product.template.name', clause[1], names[0]))
        if len(names) != 1 and names[1]:
            res.append(('warehouse', clause[1], names[1]))
        return [
            'OR',
            res,
            ('description', ) + tuple(clause[1:]),
        ]

    @staticmethod
    def default_company():
        return Transaction().context.get('company')

    @staticmethod
    def default_exception_ignored():
        return False

    def get_purchase(self, name):
        if self.purchase_line:
            return self.purchase_line.purchase.id

    @classmethod
    def search_purchase(cls, name, clause):
        return [('purchase_line.' + clause[0], ) + tuple(clause[1:])]

    @property
    def currency(self):
        return self.company.currency

    @classmethod
    def default_state(cls):
        return 'draft'

    def get_state(self):
        if self.purchase_line:
            if (self.purchase_line.purchase.state == 'cancel'
                    and not self.exception_ignored):
                return 'exception'
            elif self.purchase_line.purchase.state == 'cancel':
                return 'cancel'
            elif self.purchase_line.purchase.state == 'done':
                return 'done'
            else:
                return 'purchased'
        return 'draft'

    @classmethod
    def update_state(cls, requests):
        for request in requests:
            state = request.get_state()
            if state != request.state:
                request.state = state
        cls.save(requests)

    def get_warehouse_required(self, name):
        return self.product and self.product.type in ('goods', 'assets')

    @fields.depends('uom')
    def on_change_with_uom_digits(self, name=None):
        if self.uom:
            return self.uom.digits
        return 2

    @fields.depends('product')
    def on_change_with_product_uom_category(self, name=None):
        if self.product:
            return self.product.default_uom_category.id

    @fields.depends('product')
    def on_change_with_default_uom_digits(self, name=None):
        if self.product:
            return self.product.default_uom.digits
        return 2

    @classmethod
    def _get_origin(cls):
        'Return the set of Model names for origin Reference'
        return set()

    @classmethod
    def get_origin(cls):
        pool = Pool()
        IrModel = pool.get('ir.model')
        models = IrModel.search([
            ('model', 'in', list(cls._get_origin())),
        ])
        return [(None, '')] + [(m.model, m.name) for m in models]

    @classmethod
    def view_attributes(cls):
        return [
            ('/tree', 'visual', If(Eval('state') == 'cancel', 'muted', '')),
        ]

    @classmethod
    def create(cls, vlist):
        for vals in vlist:
            for field_name in ('quantity', 'company'):
                if vals.get(field_name) is None:
                    raise AccessError(
                        gettext('purchase_request.msg_request_no_create'))
        return super(PurchaseRequest, cls).create(vlist)

    @classmethod
    def delete(cls, requests):
        for request in requests:
            if request.purchase_line:
                raise AccessError(
                    gettext('purchase_request.msg_request_delete_purchased',
                            request=request.rec_name))
        super(PurchaseRequest, cls).delete(requests)

    @classmethod
    def find_best_product_supplier(cls, product, date, **pattern):
        "Return the best product supplier to request product at date"
        pool = Pool()
        Date = pool.get('ir.date')
        today = Date.today()
        for product_supplier in product.product_suppliers_used(**pattern):
            supply_date = product_supplier.compute_supply_date(date=today)
            timedelta = date - supply_date
            if timedelta >= datetime.timedelta(0):
                return product_supplier

    @classmethod
    def find_best_supplier(cls, product, date, **pattern):
        '''
        Return the best supplier and purchase_date for the product.
        '''
        pool = Pool()
        Date = pool.get('ir.date')

        product_supplier = cls.find_best_product_supplier(
            product, date, **pattern)
        if product_supplier:
            supplier = product_supplier.party
            purchase_date = product_supplier.compute_purchase_date(date)
        else:
            supplier = None
            purchase_date = Date.today()
        return supplier, purchase_date

    @classmethod
    @ModelView.button_action(
        'purchase_request.wizard_purchase_cancellation_handle_exception')
    def handle_purchase_cancellation_exception(cls, purchases):
        pass