From 39c5612efb0c2553f2e881d17c6ea9b6c90a84f4 Mon Sep 17 00:00:00 2001 From: ?ngel ?lvarez Date: Fri, 6 Mar 2015 19:05:49 +0100 Subject: [PATCH] fix funcionality in general --- configuration.py | 4 +- contract.py | 432 +++++------------- invoice.py | 6 +- locale/ca_ES.po | 330 +------------ locale/es_ES.po | 348 ++------------ setup.py | 4 +- ... scenario_monthly_full_month_contract.rst} | 42 +- ..._full_month_with_invoice_date_contract.rst | 257 +++++++++++ ...scenario_monthly_natural_days_contract.rst | 252 ++++++++++ ...enario_monthly_start_in_month_contract.rst | 252 ++++++++++ tests/test_contract.py | 16 +- view/contract_consumption_list.xml | 2 + view/contract_form.xml | 51 +-- view/contract_line_form.xml | 10 - view/contract_line_list.xml | 3 - view/contract_line_service_form.xml | 26 -- view/contract_line_service_list.xml | 2 - view/contract_list.xml | 3 + view/contract_service_form.xml | 32 -- view/contract_service_list.xml | 3 - 20 files changed, 980 insertions(+), 1095 deletions(-) rename tests/{scenario_contract.rst => scenario_monthly_full_month_contract.rst} (90%) create mode 100644 tests/scenario_monthly_full_month_with_invoice_date_contract.rst create mode 100644 tests/scenario_monthly_natural_days_contract.rst create mode 100644 tests/scenario_monthly_start_in_month_contract.rst diff --git a/configuration.py b/configuration.py index 1cfb456..5239e3a 100644 --- a/configuration.py +++ b/configuration.py @@ -1,5 +1,5 @@ -#This file is part of Tryton. The COPYRIGHT file at the top level of -#this repository contains the full copyright notices and license terms. +# This file is part of Tryton. The COPYRIGHT file at the top level of +# this repository contains the full copyright notices and license terms. from trytond.model import ModelView, ModelSQL, ModelSingleton, fields from trytond.pyson import Eval diff --git a/contract.py b/contract.py index 476f04d..421544a 100644 --- a/contract.py +++ b/contract.py @@ -1,8 +1,8 @@ # The COPYRIGHT file at the top level of this repository contains # the full copyright notices and license terms. -from datetime import datetime -from dateutil.rrule import rrule, SECONDLY, MINUTELY, HOURLY, DAILY, WEEKLY, \ - MONTHLY, YEARLY +import datetime +from dateutil.relativedelta import relativedelta +from dateutil.rrule import rrule, DAILY, WEEKLY, MONTHLY, YEARLY from itertools import groupby from sql.aggregate import Max @@ -15,190 +15,24 @@ from trytond.tools import reduce_ids from trytond.wizard import Wizard, StateView, StateAction, Button DIGITS = config.getint('digits', 'unit_price_digits', 4) -__all__ = ['ContractService', 'Contract', 'ContractLine', +__all__ = ['ContractService', 'Contract', 'ContractLine', 'RRuleMixin', 'ContractConsumption', 'CreateConsumptionsStart', 'CreateConsumptions'] class RRuleMixin(Model): _rec_name = 'freq' freq = fields.Selection([ - ('secondly', 'Secondly'), - ('minutely', 'Minutely'), - ('hourly', 'Hourly'), + (None, 'None'), ('daily', 'Daily'), ('weekly', 'Weekly'), ('monthly', 'Monthly'), ('yearly', 'Yearly'), - ], 'Frequency', required=True) - until_date = fields.Boolean('Is Date', - help='Ignore time of field "Until Date", but handle as date only.') - until = fields.DateTime('Until Date') - count = fields.Integer('Count') + ], 'Frequency') interval = fields.Integer('Interval') - bysecond = fields.Char('By Second') - byminute = fields.Char('By Minute') - byhour = fields.Char('By Hour') - byday = fields.Char('By Day') - bymonthday = fields.Char('By Month Day') - byyearday = fields.Char('By Year Day') - byweekno = fields.Char('By Week Number') - bymonth = fields.Char('By Month') - bysetpos = fields.Char('By Position') - wkst = fields.Selection([ - (None, ''), - ('su', 'Sunday'), - ('mo', 'Monday'), - ('tu', 'Tuesday'), - ('we', 'Wednesday'), - ('th', 'Thursday'), - ('fr', 'Friday'), - ('sa', 'Saturday'), - ], 'Week Day', sort=False) - - @classmethod - def __setup__(cls): - super(RRuleMixin, cls).__setup__() - cls._sql_constraints += [ - ('until_count_only_one', - 'CHECK(until IS NULL OR count IS NULL OR count = 0)', - 'Only one of "until" and "count" can be set.'), - ] - cls._error_messages.update({ - 'invalid_bysecond': ('Invalid "By Second" in recurrence rule ' - '"%s"'), - 'invalid_byminute': ('Invalid "By Minute" in recurrence rule ' - '"%s"'), - 'invalid_byhour': 'Invalid "By Hour" in recurrence rule "%s"', - 'invalid_byday': 'Invalid "By Day" in recurrence rule "%s"', - 'invalid_bymonthday': ('Invalid "By Month Day" in recurrence ' - 'rule "%s"'), - 'invalid_byyearday': ('Invalid "By Year Day" in recurrence ' - 'rule "%s"'), - 'invalid_byweekno': ('Invalid "By Week Number" in recurrence ' - 'rule "%s"'), - 'invalid_bymonth': ( - 'Invalid "By Month" in recurrence rule "%s"'), - 'invalid_bysetpos': ( - 'Invalid "By Position" in recurrence rule "%s"'), - }) - - @classmethod - def validate(cls, rules): - super(RRuleMixin, cls).validate(rules) - for rule in rules: - rule.check_bysecond() - rule.check_byminute() - rule.check_byhour() - rule.check_byday() - rule.check_bymonthday() - rule.check_byyearday() - rule.check_byweekno() - rule.check_bymonth() - rule.check_bysetpos() - - def check_bysecond(self): - if self.bysecond: - for second in self.bysecond.split(','): - try: - second = int(second) - except Exception: - second = -1 - if not (second >= 0 and second <= 59): - self.raise_user_error('invalid_bysecond', (self.rec_name,)) - - def check_byminute(self): - if self.byminute: - for minute in self.byminute.split(','): - try: - minute = int(minute) - except Exception: - minute = -1 - if not (minute >= 0 and minute <= 59): - self.raise_user_error('invalid_byminute', (self.rec_name,)) - - def check_byhour(self): - if self.byhour: - for hour in self.byhour.split(','): - try: - hour = int(hour) - except Exception: - hour = -1 - if not (hour >= 0 and hour <= 23): - self.raise_user_error('invalid_byhour', (self.rec_name,)) - - def check_byday(self): - if self.byday: - for weekdaynum in self.byday.split(','): - weekday = weekdaynum[-2:] - if weekday not in ('SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'): - self.raise_user_error('invalid_byday', (self.rec_name,)) - ordwk = weekday[:-2] - if not ordwk: - continue - try: - ordwk = int(ordwk) - except Exception: - ordwk = -1 - if not (abs(ordwk) >= 1 and abs(ordwk) <= 53): - self.raise_user_error('invalid_byday', (self.rec_name,)) - - def check_bymonthday(self): - if self.bymonthday: - for monthdaynum in self.bymonthday.split(','): - try: - monthdaynum = int(monthdaynum) - except Exception: - monthdaynum = -100 - if not (abs(monthdaynum) >= 1 and abs(monthdaynum) <= 31): - self.raise_user_error('invalid_bymonthday', ( - self.rec_name,)) - - def check_byyearday(self): - if self.byyearday: - for yeardaynum in self.byyearday.split(','): - try: - yeardaynum = int(yeardaynum) - except Exception: - yeardaynum = -1000 - if not (abs(yeardaynum) >= 1 and abs(yeardaynum) <= 366): - self.raise_user_error('invalid_byyearday', - (self.rec_name,)) - - def check_byweekno(self): - if self.byweekno: - for weeknum in self.byweekno.split(','): - try: - weeknum = int(weeknum) - except Exception: - weeknum = -100 - if not (abs(weeknum) >= 1 and abs(weeknum) <= 53): - self.raise_user_error('invalid_byweekno', (self.rec_name,)) - - def check_bymonth(self): - if self.bymonth: - for monthnum in self.bymonth.split(','): - try: - monthnum = int(monthnum) - except Exception: - monthnum = -1 - if not (monthnum >= 1 and monthnum <= 12): - self.raise_user_error('invalid_bymonth', (self.rec_name,)) - - def check_bysetpos(self): - if self.bysetpos: - for setposday in self.bysetpos.split(','): - try: - setposday = int(setposday) - except Exception: - setposday = -1000 - if not (abs(setposday) >= 1 and abs(setposday) <= 366): - self.raise_user_error('invalid_bysetpos', (self.rec_name,)) def _rule2update(self): res = {} - for field in ('freq', 'until_date', 'until', 'count', 'interval', - 'bysecond', 'byminute', 'byhour', 'byday', 'bymonthday', - 'byyearday', 'byweekno', 'bymonth', 'bysetpos', 'wkst'): + for field in ('freq', 'interval'): res[field] = getattr(self, field) return res @@ -206,19 +40,13 @@ class RRuleMixin(Model): values = {} mappings = { 'freq': { - 'secondly': SECONDLY, - 'minutely': MINUTELY, - 'hourly': HOURLY, 'daily': DAILY, 'weekly': WEEKLY, 'monthly': MONTHLY, 'yearly': YEARLY, }, - 'byday': 'bymonthday', } - for field in ('freq', 'until_date', 'until', 'count', 'interval', - 'bysecond', 'byminute', 'byhour', 'byday', 'bymonthday', - 'byyearday', 'byweekno', 'bymonth', 'bysetpos', 'wkst'): + for field in ('freq', 'interval'): value = getattr(self, field) if not value: continue @@ -228,10 +56,6 @@ class RRuleMixin(Model): else: value = mappings[field][value] values[field] = value - # Convert string to list of tuples - for field in ('bymonthday', 'byyearday', 'byweekno', 'bymonth'): - if field in values: - values[field] = tuple(map(int, values[field].split(','))) return values @property @@ -241,7 +65,7 @@ class RRuleMixin(Model): return rrule(**values) -class ContractService(RRuleMixin, ModelSQL, ModelView): +class ContractService(ModelSQL, ModelView): 'Contract Service' __name__ = 'contract.service' @@ -260,6 +84,10 @@ _STATES = { _DEPENDS = ['state'] +def todatetime(date): + return datetime.datetime.combine(date, datetime.datetime.min.time()) + + class Contract(RRuleMixin, Workflow, ModelSQL, ModelView): 'Contract' __name__ = 'contract' @@ -274,6 +102,8 @@ class Contract(RRuleMixin, Workflow, ModelSQL, ModelView): start_date = fields.Date('Start Date', required=True, states=_STATES, depends=_DEPENDS) end_date = fields.Date('End Date') + start_period_date = fields.Date('Start Period Date', required=True, + states=_STATES, depends=_DEPENDS) first_invoice_date = fields.Date('First Invoice Date', states=_STATES, depends=_DEPENDS) lines = fields.One2Many('contract.line', 'contract', 'Lines', @@ -291,9 +121,7 @@ class Contract(RRuleMixin, Workflow, ModelSQL, ModelView): @classmethod def __setup__(cls): super(Contract, cls).__setup__() - for field_name in ('freq', 'until_date', 'until', 'count', 'interval', - 'bysecond', 'byminute', 'byhour', 'byday', 'bymonthday', - 'byyearday', 'byweekno', 'bymonth', 'bysetpos', 'wkst'): + for field_name in ('freq', 'interval'): field = getattr(cls, field_name) field.states = _STATES field.depends = _DEPENDS @@ -317,6 +145,10 @@ class Contract(RRuleMixin, Workflow, ModelSQL, ModelView): 'icon': 'tryton-cancel', }, }) + cls._error_messages.update({ + 'start_date_not_valid': ('Contract %(contract)s with ' + 'invalid date "%(date)s"'), + }) @staticmethod def default_company(): @@ -364,18 +196,13 @@ class Contract(RRuleMixin, Workflow, ModelSQL, ModelView): @ModelView.button @Workflow.transition('draft') def draft(cls, contracts): - pool = Pool() - ContractLine = pool.get('contract.line') - ContractLine.hold([l for c in contracts for l in c.lines]) + pass @classmethod @ModelView.button @Workflow.transition('validated') def validate_contract(cls, contracts): - pool = Pool() - ContractLine = pool.get('contract.line') cls.set_reference(contracts) - ContractLine.active([l for c in contracts for l in c.lines]) @classmethod @ModelView.button @@ -385,10 +212,15 @@ class Contract(RRuleMixin, Workflow, ModelSQL, ModelView): def rrule_values(self): values = super(Contract, self).rrule_values() - values['dtstart'] = datetime.combine(self.start_date, - datetime.min.time()) + values['dtstart'] = todatetime(self.start_period_date) return values + def get_invoice_date(self, last_invoice_date): + last_invoice_date = todatetime(last_invoice_date) + r = rrule(self.rrule._freq, dtstart=last_invoice_date) + date = r.after(last_invoice_date) + return date.date() + def get_consumptions(self, end_date=None): pool = Pool() Date = pool.get('ir.date') @@ -396,20 +228,53 @@ class Contract(RRuleMixin, Workflow, ModelSQL, ModelView): if end_date is None: end_date = Date.today() - end_date = datetime.combine(end_date, datetime.min.time()) + end_date = todatetime(end_date) consumptions = [] + for line in self.lines: - if line.state != 'active': - continue - start_date = datetime.combine(line.last_consumption_date - or line.start_date or line.contract.start_date, - datetime.min.time()) - print self.rrule_values() - print start_date, end_date - print self.rrule.between(start_date, end_date) - for date in self.rrule.between(start_date, end_date): - consumptions.append(line.get_consumption(start_date, date)) - start_date = date + + start_period_date = self.start_period_date + + last_consumption_date = line.last_consumption_date + if last_consumption_date: + last_consumption_date = todatetime(line.last_consumption_date) + last_consumption_date += relativedelta(days=+1) + + start = start_period_date + if last_consumption_date: + start = (last_consumption_date + relativedelta(days=+1)).date() + + end_contract = None + if end_contract: + end_contract = todatetime(self.end) + self.rrule.until = end_contract + + last_invoice_date = line.last_consumption_invoice_date + + for date in self.rrule.between(todatetime(start), end_date): + date -= relativedelta(days=+1) + date = date.date() + invoice_date = last_invoice_date or self.first_invoice_date \ + or date + if last_invoice_date: + invoice_date = self.get_invoice_date(last_invoice_date) + + finish_date = date + if end_contract and end_contract <= date: + date = end_contract + + start_period = start + if last_consumption_date is None: + start_period = start_period_date + start = self.start_date + + consumptions.append(line.get_consumption(start, date, + invoice_date, start_period, finish_date)) + date += relativedelta(days=+1) + start_period = date + start = date + last_invoice_date = invoice_date + last_consumption_date = date return consumptions @classmethod @@ -418,11 +283,31 @@ class Contract(RRuleMixin, Workflow, ModelSQL, ModelView): pool = Pool() ContractConsumption = pool.get('contract.consumption') + date += relativedelta(days=+1) # to support included. to_create = [] for contract in contracts: to_create += contract.get_consumptions(date) + return ContractConsumption.create([c._save_values for c in to_create]) + def check_start_date(self): + if not hasattr(self, 'rrule'): + return + d = self.rrule.after(todatetime(self.start_period_date)).date() + if self.start_date >= self.start_period_date and self.start_date < d: + return True + self.raise_user_error('start_date_not_valid', { + 'contract': self.rec_name, + 'date': self.start_date, + }) + + @classmethod + def validate(cls, contracts): + super(Contract, cls).validate(contracts) + for contract in contracts: + contract.check_start_date() + pass + class ContractLine(Workflow, ModelSQL, ModelView): 'Contract Line' @@ -435,59 +320,15 @@ class ContractLine(Workflow, ModelSQL, ModelView): description = fields.Text('Description', required=True) unit_price = fields.Numeric('Unit Price', digits=(16, DIGITS), required=True) - start_date = fields.Date('Start Date', required=True) - end_date = fields.Date('End Date') - state = fields.Selection([ - ('draft', 'Draft'), - ('active', 'Active'), - ('hold', 'Hold'), - ], 'State', required=True, readonly=True) last_consumption_date = fields.Function(fields.Date( 'Last Consumption Date'), 'get_last_consumption_date') - - @classmethod - def __setup__(cls): - super(ContractLine, cls).__setup__() - for attr in dir(RRuleMixin): - if not hasattr(cls, attr): - continue - if isinstance(getattr(cls, attr), fields.Field): - field = getattr(cls, attr) - field.states = _STATES - field.depends = _DEPENDS - - cls._transitions |= set(( - ('draft', 'active'), - ('active', 'hold'), - ('hold', 'active'), - )) - cls._buttons.update({ - 'active': { - 'invisible': Eval('state') == 'active', - 'icon': 'tryton-go-next', - }, - 'hold': { - 'invisible': Eval('state') != 'hold', - 'icon': 'tryton-go-previous', - }, - }) - cls._error_messages.update({ - 'line_outside_contract': ('Line "%(line)s" is outside its ' - 'contract "%(contract)s" period') - }) + last_consumption_invoice_date = fields.Function(fields.Date( + 'Last Consumption Date'), 'get_last_consumption_date') @staticmethod def default_state(): return 'draft' - @staticmethod - def default_start_date(): - return Transaction().context.get('start_date') - - @staticmethod - def default_end_date(): - return Transaction().context.get('end_date') - @fields.depends('service', 'unit_price', 'description') def on_change_service(self): changes = { @@ -501,14 +342,6 @@ class ContractLine(Workflow, ModelSQL, ModelView): changes['description'] = self.service.product.rec_name return changes - @property - def rrule(self): - if not self.service: - return - values = self.service.rrule_values() - values['dtstart'] = self.start_date - return rrule(**values) - @classmethod def get_last_consumption_date(cls, lines, name): pool = Pool() @@ -518,50 +351,31 @@ class ContractLine(Workflow, ModelSQL, ModelView): line_ids = [l.id for l in lines] values = dict.fromkeys(line_ids, None) - cursor.execute(*table.select(table.contract_line, Max(table.end_date), + cursor.execute(*table.select(table.contract_line, + Max(table.end_period_date), where=reduce_ids(table.contract_line, line_ids), group_by=table.contract_line)) values.update(dict(cursor.fetchall())) return values @classmethod - def validate(cls, lines): - super(ContractLine, cls).validate(lines) - for line in lines: - line.check_contract_period() + def get_last_consumption_invoice_date(cls, lines, name): + pool = Pool() + Consumption = pool.get('contract.consumption') + table = Consumption.__table__() + cursor = Transaction().cursor - def check_contract_period(self): - if self.start_date < self.contract.start_date: - self.raise_user_error('line_outside_contract', { - 'line': self.rec_name, - 'contract': self.contract.rec_name, - }) - if (self.contract.end_date and - self.end_date > self.contract.end_date): - self.raise_user_error('line_outside_contract', { - 'line': self.rec_name, - 'contract': self.contract.rec_name, - }) + line_ids = [l.id for l in lines] + values = dict.fromkeys(line_ids, None) + cursor.execute(*table.select(table.contract_line, + Max(table.invoice_date), + where=reduce_ids(table.contract_line, line_ids), + group_by=table.contract_line)) + values.update(dict(cursor.fetchall())) + return values - @classmethod - @ModelView.button - @Workflow.transition('draft') - def draft(cls, lines): - pass - - @classmethod - @ModelView.button - @Workflow.transition('active') - def active(cls, lines): - pass - - @classmethod - @ModelView.button - @Workflow.transition('hold') - def hold(cls, lines): - pass - - def get_consumption(self, start_date, end_date): + def get_consumption(self, start_date, end_date, invoice_date, start_period, + finish_period): 'Returns the consumption for date date' pool = Pool() Consumption = pool.get('contract.consumption') @@ -569,10 +383,8 @@ class ContractLine(Workflow, ModelSQL, ModelView): consumption.contract_line = self consumption.start_date = start_date consumption.end_date = end_date - invoice_date = end_date - if self.contract.first_invoice_date: - invoice_date += (self.contract.first_invoice_date - - self.contract.start_date) + consumption.init_period_date = start_period + consumption.end_period_date = finish_period consumption.invoice_date = invoice_date return consumption @@ -584,8 +396,10 @@ class ContractConsumption(ModelSQL, ModelView): contract_line = fields.Many2One('contract.line', 'Contract Line', required=True) invoice_line = fields.Many2One('account.invoice.line', 'Invoice Line') - start_date = fields.DateTime('Start Date') - end_date = fields.DateTime('End Date') + init_period_date = fields.Date('Start Period Date') + end_period_date = fields.Date('Finish Period Date') + start_date = fields.Date('Start Date') + end_date = fields.Date('End Date') invoice_date = fields.Date('Invoice Date') @classmethod @@ -667,10 +481,8 @@ class ContractConsumption(ModelSQL, ModelView): invoice_line.taxes = taxes invoice_line.invoice_type = 'out_invoice' # Compute quantity based on dates - contract_start = self.contract_line.contract.start_date - invoice_date = self.contract_line.contract.rrule.after(contract_start) - quantity = ((self.end_date - self.start_date).total_seconds() - / (invoice_date - contract_start).total_seconds()) + quantity = ((self.end_date - self.start_date).total_seconds() / + (self.end_period_date - self.init_period_date).total_seconds()) rounding = invoice_line.unit.rounding if invoice_line.unit else 1 invoice_line.quantity = Uom.round(quantity, rounding) return invoice_line @@ -735,8 +547,8 @@ class ContractConsumption(ModelSQL, ModelView): invoices = [] for key, grouped_lines in groupby(lines, key=cls._group_invoice_key): invoice = cls._get_invoice(key) - invoice.lines = (list(getattr(invoice, 'lines', [])) - + list(x[1] for x in grouped_lines)) + invoice.lines = (list(getattr(invoice, 'lines', [])) + + list(x[1] for x in grouped_lines)) invoices.append(invoice) invoices = Invoice.create([x._save_values for x in invoices]) diff --git a/invoice.py b/invoice.py index f5379c1..2a15212 100644 --- a/invoice.py +++ b/invoice.py @@ -1,6 +1,6 @@ -#This file is part of contract_invoice module for Tryton. -#The COPYRIGHT file at the top level of this repository contains -#the full copyright notices and license terms. +# This file is part of contract_invoice module for Tryton. +# The COPYRIGHT file at the top level of this repository contains +# the full copyright notices and license terms. from trytond.pool import PoolMeta __all__ = ['InvoiceLine'] diff --git a/locale/ca_ES.po b/locale/ca_ES.po index 5e261bc..384e0a3 100644 --- a/locale/ca_ES.po +++ b/locale/ca_ES.po @@ -18,142 +18,10 @@ msgstr "" "Falta el compte d'ingressos al producte \"%(product)s\" de la línia de " "contracte \"%(contract_line)s\"." -msgctxt "error:contract.line:" -msgid "Line \"%(line)s\" is outside its contract \"%(contract)s\" period" -msgstr "La línia \"%(line)s\" es fora del període del seu contracte \"%(contract)s\"" - -msgctxt "error:contract.service:" -msgid "Invalid \"By Day\" in recurrence rule \"%s\"" -msgstr "El camp \"per dia\" de la regla de recurrència \"%s\" no és correcte." - -msgctxt "error:contract.service:" -msgid "Invalid \"By Hour\" in recurrence rule \"%s\"" -msgstr "El camp \"per hora\" de la regla de recurrència \"%s\" no és correcte." - -msgctxt "error:contract.service:" -msgid "Invalid \"By Minute\" in recurrence rule \"%s\"" -msgstr "El camp \"per minut\" de la regla de recurrència \"%s\" no és correcte." - -msgctxt "error:contract.service:" -msgid "Invalid \"By Month Day\" in recurrence rule \"%s\"" -msgstr "El camp \"per dia del mes\" de la regla de recurrència \"%s\" no és correcte." - -msgctxt "error:contract.service:" -msgid "Invalid \"By Month\" in recurrence rule \"%s\"" -msgstr "El camp \"per mes\" de la regla de recurrència \"%s\" no és correcte." - -msgctxt "error:contract.service:" -msgid "Invalid \"By Position\" in recurrence rule \"%s\"" -msgstr "El camp \"per ubicació\" de la regla de recurrència \"%s\" no és correcte." - -msgctxt "error:contract.service:" -msgid "Invalid \"By Second\" in recurrence rule \"%s\"" -msgstr "El camp \"per segon\" de la regla de recurrència \"%s\" no és correcte." - -msgctxt "error:contract.service:" -msgid "Invalid \"By Week Number\" in recurrence rule \"%s\"" -msgstr "" -"El camp \"per número de la setmana\" de la regla de recurrència \"%s\" no és" -" correcte." - -msgctxt "error:contract.service:" -msgid "Invalid \"By Year Day\" in recurrence rule \"%s\"" -msgstr "" -"El camp \"per dia de l'any\" de la regla de recurrència \"%s\" no és " -"correcte." - -msgctxt "error:contract.service:" -msgid "Only one of \"until\" and \"count\" can be set." -msgstr "Defineix un \"fins\" i un \"comptador\"." - -msgctxt "error:contract:" -msgid "Invalid \"By Day\" in recurrence rule \"%s\"" -msgstr "El camp \"per dia\" de la regla de recurrència \"%s\" no és correcte." - -msgctxt "error:contract:" -msgid "Invalid \"By Hour\" in recurrence rule \"%s\"" -msgstr "El camp \"per hora\" de la regla de recurrència \"%s\" no és correcte." - -msgctxt "error:contract:" -msgid "Invalid \"By Minute\" in recurrence rule \"%s\"" -msgstr "El camp \"per minut\" de la regla de recurrència \"%s\" no és correcte." - -msgctxt "error:contract:" -msgid "Invalid \"By Month Day\" in recurrence rule \"%s\"" -msgstr "El camp \"per dia del mes\" de la regla de recurrència \"%s\" no és correcte." - -msgctxt "error:contract:" -msgid "Invalid \"By Month\" in recurrence rule \"%s\"" -msgstr "El camp \"per mes\" de la regla de recurrència \"%s\" no és correcte." - -msgctxt "error:contract:" -msgid "Invalid \"By Position\" in recurrence rule \"%s\"" -msgstr "El camp \"per ubicació\" de la regla de recurrència \"%s\" no és correcte." - -msgctxt "error:contract:" -msgid "Invalid \"By Second\" in recurrence rule \"%s\"" -msgstr "El camp \"per segon\" de la regla de recurrència \"%s\" no és correcte." - -msgctxt "error:contract:" -msgid "Invalid \"By Week Number\" in recurrence rule \"%s\"" -msgstr "" -"El camp \"per número de la setmana\" de la regla de recurrència \"%s\" no és" -" correcte." - -msgctxt "error:contract:" -msgid "Invalid \"By Year Day\" in recurrence rule \"%s\"" -msgstr "" -"El camp \"per dia de l'any\" de la regla de recurrència \"%s\" no és " -"correcte." - -msgctxt "error:contract:" -msgid "Only one of \"until\" and \"count\" can be set." -msgstr "Defineix un \"fins\" i un \"comptador\"." - -msgctxt "field:contract,byday:" -msgid "By Day" -msgstr "Per dia" - -msgctxt "field:contract,byhour:" -msgid "By Hour" -msgstr "Per hora" - -msgctxt "field:contract,byminute:" -msgid "By Minute" -msgstr "Per minut" - -msgctxt "field:contract,bymonth:" -msgid "By Month" -msgstr "Per mes" - -msgctxt "field:contract,bymonthday:" -msgid "By Month Day" -msgstr "Per dia del mes" - -msgctxt "field:contract,bysecond:" -msgid "By Second" -msgstr "Per segon" - -msgctxt "field:contract,bysetpos:" -msgid "By Position" -msgstr "Per ubicació" - -msgctxt "field:contract,byweekno:" -msgid "By Week Number" -msgstr "Per número de la setmana" - -msgctxt "field:contract,byyearday:" -msgid "By Year Day" -msgstr "Per dia de l'any" - msgctxt "field:contract,company:" msgid "Company" msgstr "Empresa" -msgctxt "field:contract,count:" -msgid "Count" -msgstr "Comptador" - msgctxt "field:contract,create_date:" msgid "Create Date" msgstr "Data creació" @@ -210,18 +78,6 @@ msgctxt "field:contract,state:" msgid "State" msgstr "Estat" -msgctxt "field:contract,until:" -msgid "Until Date" -msgstr "Fins a la data" - -msgctxt "field:contract,until_date:" -msgid "Is Date" -msgstr "Es una data" - -msgctxt "field:contract,wkst:" -msgid "Week Day" -msgstr "Dia de la setmana" - msgctxt "field:contract,write_date:" msgid "Write Date" msgstr "Data modificació" @@ -326,10 +182,6 @@ msgctxt "field:contract.line,description:" msgid "Description" msgstr "Descripció" -msgctxt "field:contract.line,end_date:" -msgid "End Date" -msgstr "Data final" - msgctxt "field:contract.line,id:" msgid "ID" msgstr "ID" @@ -350,14 +202,6 @@ msgctxt "field:contract.line,service:" msgid "Service" msgstr "Serveis" -msgctxt "field:contract.line,start_date:" -msgid "Start Date" -msgstr "Data inici" - -msgctxt "field:contract.line,state:" -msgid "State" -msgstr "Estat" - msgctxt "field:contract.line,unit_price:" msgid "Unit Price" msgstr "Preu unitat" @@ -370,46 +214,6 @@ msgctxt "field:contract.line,write_uid:" msgid "Write User" msgstr "Usuari modificació" -msgctxt "field:contract.service,byday:" -msgid "By Day" -msgstr "Per dia" - -msgctxt "field:contract.service,byhour:" -msgid "By Hour" -msgstr "Per hora" - -msgctxt "field:contract.service,byminute:" -msgid "By Minute" -msgstr "Per minut" - -msgctxt "field:contract.service,bymonth:" -msgid "By Month" -msgstr "Per mes" - -msgctxt "field:contract.service,bymonthday:" -msgid "By Month Day" -msgstr "Per dia del mes" - -msgctxt "field:contract.service,bysecond:" -msgid "By Second" -msgstr "Per segon" - -msgctxt "field:contract.service,bysetpos:" -msgid "By Position" -msgstr "Per ubicació" - -msgctxt "field:contract.service,byweekno:" -msgid "By Week Number" -msgstr "Per número de la setmana" - -msgctxt "field:contract.service,byyearday:" -msgid "By Year Day" -msgstr "Per dia de l'any" - -msgctxt "field:contract.service,count:" -msgid "Count" -msgstr "Comptador" - msgctxt "field:contract.service,create_date:" msgid "Create Date" msgstr "Data creació" @@ -438,18 +242,6 @@ msgctxt "field:contract.service,rec_name:" msgid "Name" msgstr "Nom" -msgctxt "field:contract.service,until:" -msgid "Until Date" -msgstr "Fins a la data" - -msgctxt "field:contract.service,until_date:" -msgid "Is Date" -msgstr "Es una data" - -msgctxt "field:contract.service,wkst:" -msgid "Week Day" -msgstr "Dia de la setmana" - msgctxt "field:contract.service,write_date:" msgid "Write Date" msgstr "Data modificació" @@ -458,16 +250,6 @@ msgctxt "field:contract.service,write_uid:" msgid "Write User" msgstr "Usuari modificació" -msgctxt "help:contract,until_date:" -msgid "Ignore time of field \"Until Date\", but handle as date only." -msgstr "" -"Ignora la hora del camp \"Fins a la data\", però utilitza com a única data." - -msgctxt "help:contract.service,until_date:" -msgid "Ignore time of field \"Until Date\", but handle as date only." -msgstr "" -"Ignora la hora del camp \"Fins a la data\", però utilitza com a única data." - msgctxt "model:contract,name:" msgid "Contract" msgstr "Contracte" @@ -497,7 +279,7 @@ msgid "Contract" msgstr "Contractes" msgctxt "model:ir.action,name:act_contract_configuration_form" -msgid "Contract Configuration" +msgid "Contracts Configuration" msgstr "Configuració de contractes" msgctxt "model:ir.action,name:act_contract_consumption" @@ -509,7 +291,7 @@ msgid "Contract Line" msgstr "Línia de contracte" msgctxt "model:ir.action,name:act_contract_service" -msgid "Services" +msgid "Contract Service" msgstr "Servei de contracte" msgctxt "model:ir.action,name:wizard_create_consumptions" @@ -555,7 +337,7 @@ msgid "Contract" msgstr "Contracte" msgctxt "model:ir.ui.menu,name:menu_contract_configuration" -msgid "Contract Configuration" +msgid "Contracts Configuration" msgstr "Configuració de contractes" msgctxt "model:ir.ui.menu,name:menu_contract_consumption" @@ -567,7 +349,7 @@ msgid "Contract" msgstr "Contracte" msgctxt "model:ir.ui.menu,name:menu_contract_service" -msgid "Services" +msgid "Contract Service" msgstr "Servei de contracte" msgctxt "model:ir.ui.menu,name:menu_create_consumptions" @@ -575,33 +357,21 @@ msgid "Create Consumptions" msgstr "Crea consums" msgctxt "model:res.group,name:group_contract" -msgid "Contract User" +msgid "Contract" msgstr "Contractes" msgctxt "model:res.group,name:group_contract_admin" -msgid "Contract Administrator" +msgid "Contract Administration" msgstr "Administració de contractes" msgctxt "selection:contract,freq:" msgid "Daily" msgstr "Diàriament" -msgctxt "selection:contract,freq:" -msgid "Hourly" -msgstr "Cada hora" - -msgctxt "selection:contract,freq:" -msgid "Minutely" -msgstr "Cada minut" - msgctxt "selection:contract,freq:" msgid "Monthly" msgstr "Mensualment" -msgctxt "selection:contract,freq:" -msgid "Secondly" -msgstr "Cada segon" - msgctxt "selection:contract,freq:" msgid "Weekly" msgstr "Setmanalment" @@ -622,70 +392,14 @@ msgctxt "selection:contract,state:" msgid "Validated" msgstr "Validat" -msgctxt "selection:contract,wkst:" -msgid "" -msgstr " " - -msgctxt "selection:contract,wkst:" -msgid "Friday" -msgstr "Divendres" - -msgctxt "selection:contract,wkst:" -msgid "Monday" -msgstr "Dilluns" - -msgctxt "selection:contract,wkst:" -msgid "Saturday" -msgstr "Dissabte" - -msgctxt "selection:contract,wkst:" -msgid "Sunday" -msgstr "Diumenge" - -msgctxt "selection:contract,wkst:" -msgid "Thursday" -msgstr "Dijous" - -msgctxt "selection:contract,wkst:" -msgid "Tuesday" -msgstr "Dimarts" - -msgctxt "selection:contract,wkst:" -msgid "Wednesday" -msgstr "Dimecres" - -msgctxt "selection:contract.line,state:" -msgid "Active" -msgstr "Actiu" - -msgctxt "selection:contract.line,state:" -msgid "Draft" -msgstr "Esborrany" - -msgctxt "selection:contract.line,state:" -msgid "Hold" -msgstr "En espera" - msgctxt "selection:contract.service,freq:" msgid "Daily" msgstr "Diàriament" -msgctxt "selection:contract.service,freq:" -msgid "Hourly" -msgstr "Cada hora" - -msgctxt "selection:contract.service,freq:" -msgid "Minutely" -msgstr "Cada minut" - msgctxt "selection:contract.service,freq:" msgid "Monthly" msgstr "Mensualment" -msgctxt "selection:contract.service,freq:" -msgid "Secondly" -msgstr "Cada segon" - msgctxt "selection:contract.service,freq:" msgid "Weekly" msgstr "Setmanalment" @@ -694,38 +408,6 @@ msgctxt "selection:contract.service,freq:" msgid "Yearly" msgstr "Anualment" -msgctxt "selection:contract.service,wkst:" -msgid "" -msgstr " " - -msgctxt "selection:contract.service,wkst:" -msgid "Friday" -msgstr "Divendres" - -msgctxt "selection:contract.service,wkst:" -msgid "Monday" -msgstr "Dilluns" - -msgctxt "selection:contract.service,wkst:" -msgid "Saturday" -msgstr "Dissabte" - -msgctxt "selection:contract.service,wkst:" -msgid "Sunday" -msgstr "Diumenge" - -msgctxt "selection:contract.service,wkst:" -msgid "Thursday" -msgstr "Dijous" - -msgctxt "selection:contract.service,wkst:" -msgid "Tuesday" -msgstr "Dimarts" - -msgctxt "selection:contract.service,wkst:" -msgid "Wednesday" -msgstr "Dimecres" - msgctxt "view:contract.configuration:" msgid "Contract Configuration" msgstr "Configuració de contractes" diff --git a/locale/es_ES.po b/locale/es_ES.po index 5f3ba7e..d554910 100644 --- a/locale/es_ES.po +++ b/locale/es_ES.po @@ -18,146 +18,14 @@ msgstr "" "Falta la cuenta de ingresos par el producto \"%(product)s\" de la linea de " "contracto \"%(contract_line)s\"." -msgctxt "error:contract.line:" -msgid "Line \"%(line)s\" is outside its contract \"%(contract)s\" period" -msgstr "La línea \"%(line)s\" esta fuera del período de su contrato \"%(contract)s\"." - -msgctxt "error:contract.service:" -msgid "Invalid \"By Day\" in recurrence rule \"%s\"" -msgstr "El campo \"por dia\" de la regla de recurrencia \"%s\" no es correcto." - -msgctxt "error:contract.service:" -msgid "Invalid \"By Hour\" in recurrence rule \"%s\"" -msgstr "El campo \"por hora\" de la regla de recurrencia \"%s\" no es correcto." - -msgctxt "error:contract.service:" -msgid "Invalid \"By Minute\" in recurrence rule \"%s\"" -msgstr "El campo \"por minuto\" de la regla de recurrencia \"%s\" no es correcto." - -msgctxt "error:contract.service:" -msgid "Invalid \"By Month Day\" in recurrence rule \"%s\"" -msgstr "" -"El campo \"por día del mes\" de la regla de recurrencia \"%s\" no es " -"correcto." - -msgctxt "error:contract.service:" -msgid "Invalid \"By Month\" in recurrence rule \"%s\"" -msgstr "El campo \"por mes\" de la regla de recurrencia \"%s\" no es correcto." - -msgctxt "error:contract.service:" -msgid "Invalid \"By Position\" in recurrence rule \"%s\"" -msgstr "El campo \"por ubicación\" de la regla de recurrencia \"%s\" no es correcto." - -msgctxt "error:contract.service:" -msgid "Invalid \"By Second\" in recurrence rule \"%s\"" -msgstr "El campo \"por segundo\" de la regla de recurrencia \"%s\" no es correcto." - -msgctxt "error:contract.service:" -msgid "Invalid \"By Week Number\" in recurrence rule \"%s\"" -msgstr "" -"El campo \"por número de la semana\" de la regla de recurrencia \"%s\" no es" -" correcto." - -msgctxt "error:contract.service:" -msgid "Invalid \"By Year Day\" in recurrence rule \"%s\"" -msgstr "" -"El campo \"por día del año\" de la regla de recurrencia \"%s\" no es " -"correcto." - -msgctxt "error:contract.service:" -msgid "Only one of \"until\" and \"count\" can be set." -msgstr "Define un \"hasta\" y un \"contador\"." - msgctxt "error:contract:" -msgid "Invalid \"By Day\" in recurrence rule \"%s\"" -msgstr "El campo \"por dia\" de la regla de recurrencia \"%s\" no es correcto." - -msgctxt "error:contract:" -msgid "Invalid \"By Hour\" in recurrence rule \"%s\"" -msgstr "El campo \"por hora\" de la regla de recurrencia \"%s\" no es correcto." - -msgctxt "error:contract:" -msgid "Invalid \"By Minute\" in recurrence rule \"%s\"" -msgstr "El campo \"por minuto\" de la regla de recurrencia \"%s\" no es correcto." - -msgctxt "error:contract:" -msgid "Invalid \"By Month Day\" in recurrence rule \"%s\"" -msgstr "" -"El campo \"por día del mes\" de la regla de recurrencia \"%s\" no es " -"correcto." - -msgctxt "error:contract:" -msgid "Invalid \"By Month\" in recurrence rule \"%s\"" -msgstr "El campo \"por mes\" de la regla de recurrencia \"%s\" no es correcto." - -msgctxt "error:contract:" -msgid "Invalid \"By Position\" in recurrence rule \"%s\"" -msgstr "El campo \"por ubicación\" de la regla de recurrencia \"%s\" no es correcto." - -msgctxt "error:contract:" -msgid "Invalid \"By Second\" in recurrence rule \"%s\"" -msgstr "El campo \"por segundo\" de la regla de recurrencia \"%s\" no es correcto." - -msgctxt "error:contract:" -msgid "Invalid \"By Week Number\" in recurrence rule \"%s\"" -msgstr "" -"El campo \"por número de la semana\" de la regla de recurrencia \"%s\" no es" -" correcto." - -msgctxt "error:contract:" -msgid "Invalid \"By Year Day\" in recurrence rule \"%s\"" -msgstr "" -"El campo \"por día del año\" de la regla de recurrencia \"%s\" no es " -"correcto." - -msgctxt "error:contract:" -msgid "Only one of \"until\" and \"count\" can be set." -msgstr "Define un \"hasta\" y un \"contador\"." - -msgctxt "field:contract,byday:" -msgid "By Day" -msgstr "Por día" - -msgctxt "field:contract,byhour:" -msgid "By Hour" -msgstr "Por hora" - -msgctxt "field:contract,byminute:" -msgid "By Minute" -msgstr "Por minuto" - -msgctxt "field:contract,bymonth:" -msgid "By Month" -msgstr "Por mes" - -msgctxt "field:contract,bymonthday:" -msgid "By Month Day" -msgstr "Por día del mes" - -msgctxt "field:contract,bysecond:" -msgid "By Second" -msgstr "Por segundo" - -msgctxt "field:contract,bysetpos:" -msgid "By Position" -msgstr "Por ubicación" - -msgctxt "field:contract,byweekno:" -msgid "By Week Number" -msgstr "Por número de la semana" - -msgctxt "field:contract,byyearday:" -msgid "By Year Day" -msgstr "Por día del año" +msgid "Contract %(contract)s with invalid date \"%(date)s\"" +msgstr "El contracto %(contract)s tiene fecha de comienzo inválida \"%(date)s\"" msgctxt "field:contract,company:" msgid "Company" msgstr "Empresa" -msgctxt "field:contract,count:" -msgid "Count" -msgstr "Contador" - msgctxt "field:contract,create_date:" msgid "Create Date" msgstr "Fecha creación" @@ -210,22 +78,14 @@ msgctxt "field:contract,start_date:" msgid "Start Date" msgstr "Fecha inicial" +msgctxt "field:contract,start_period_date:" +msgid "Start Period Date" +msgstr "Fecha inicio de período" + msgctxt "field:contract,state:" msgid "State" msgstr "Estado" -msgctxt "field:contract,until:" -msgid "Until Date" -msgstr "Hasta la fecha" - -msgctxt "field:contract,until_date:" -msgid "Is Date" -msgstr "Es una fecha" - -msgctxt "field:contract,wkst:" -msgid "Week Day" -msgstr "Día de la semana" - msgctxt "field:contract,write_date:" msgid "Write Date" msgstr "Fecha modificación" @@ -278,10 +138,18 @@ msgctxt "field:contract.consumption,end_date:" msgid "End Date" msgstr "Fecha finalización" +msgctxt "field:contract.consumption,end_period_date:" +msgid "Finish Period Date" +msgstr "Fecha final de período" + msgctxt "field:contract.consumption,id:" msgid "ID" msgstr "ID" +msgctxt "field:contract.consumption,init_period_date:" +msgid "Start Period Date" +msgstr "Fecha inicio de período" + msgctxt "field:contract.consumption,invoice_date:" msgid "Invoice Date" msgstr "Fecha factura" @@ -330,10 +198,6 @@ msgctxt "field:contract.line,description:" msgid "Description" msgstr "Descripción" -msgctxt "field:contract.line,end_date:" -msgid "End Date" -msgstr "Fecha final" - msgctxt "field:contract.line,id:" msgid "ID" msgstr "ID" @@ -342,6 +206,10 @@ msgctxt "field:contract.line,last_consumption_date:" msgid "Last Consumption Date" msgstr "Fecha último consumo" +msgctxt "field:contract.line,last_consumption_invoice_date:" +msgid "Last Consumption Date" +msgstr "Fecha último consumo" + msgctxt "field:contract.line,name:" msgid "Name" msgstr "Nombre" @@ -354,14 +222,6 @@ msgctxt "field:contract.line,service:" msgid "Service" msgstr "Servicios" -msgctxt "field:contract.line,start_date:" -msgid "Start Date" -msgstr "Fecha inicial" - -msgctxt "field:contract.line,state:" -msgid "State" -msgstr "Estado" - msgctxt "field:contract.line,unit_price:" msgid "Unit Price" msgstr "Precio unidad" @@ -374,46 +234,6 @@ msgctxt "field:contract.line,write_uid:" msgid "Write User" msgstr "Usuario modificación" -msgctxt "field:contract.service,byday:" -msgid "By Day" -msgstr "Por día" - -msgctxt "field:contract.service,byhour:" -msgid "By Hour" -msgstr "Por hora" - -msgctxt "field:contract.service,byminute:" -msgid "By Minute" -msgstr "Por minuto" - -msgctxt "field:contract.service,bymonth:" -msgid "By Month" -msgstr "Por mes" - -msgctxt "field:contract.service,bymonthday:" -msgid "By Month Day" -msgstr "Por día del mes" - -msgctxt "field:contract.service,bysecond:" -msgid "By Second" -msgstr "Por segundo" - -msgctxt "field:contract.service,bysetpos:" -msgid "By Position" -msgstr "Por ubicación" - -msgctxt "field:contract.service,byweekno:" -msgid "By Week Number" -msgstr "Por número de la semana" - -msgctxt "field:contract.service,byyearday:" -msgid "By Year Day" -msgstr "Por día del año" - -msgctxt "field:contract.service,count:" -msgid "Count" -msgstr "Contador" - msgctxt "field:contract.service,create_date:" msgid "Create Date" msgstr "Fecha creación" @@ -442,18 +262,6 @@ msgctxt "field:contract.service,rec_name:" msgid "Name" msgstr "Nombre" -msgctxt "field:contract.service,until:" -msgid "Until Date" -msgstr "Hasta la fecha" - -msgctxt "field:contract.service,until_date:" -msgid "Is Date" -msgstr "Es una fecha" - -msgctxt "field:contract.service,wkst:" -msgid "Week Day" -msgstr "Día de la semana" - msgctxt "field:contract.service,write_date:" msgid "Write Date" msgstr "Fecha modificación" @@ -462,14 +270,6 @@ msgctxt "field:contract.service,write_uid:" msgid "Write User" msgstr "Usuario modificación" -msgctxt "help:contract,until_date:" -msgid "Ignore time of field \"Until Date\", but handle as date only." -msgstr "Ignora la hora del campo \"Hasta la fecha\", pero usar como única fecha." - -msgctxt "help:contract.service,until_date:" -msgid "Ignore time of field \"Until Date\", but handle as date only." -msgstr "Ignora la hora del campo \"Hasta la fecha\", pero usar como única fecha." - msgctxt "model:contract,name:" msgid "Contract" msgstr "Contrato" @@ -499,7 +299,7 @@ msgid "Contract" msgstr "Contratos" msgctxt "model:ir.action,name:act_contract_configuration_form" -msgid "Contract Configuration" +msgid "Contracts Configuration" msgstr "Configuración de contratos" msgctxt "model:ir.action,name:act_contract_consumption" @@ -511,7 +311,7 @@ msgid "Contract Line" msgstr "Línea de contrato" msgctxt "model:ir.action,name:act_contract_service" -msgid "Services" +msgid "Contract Service" msgstr "Servicio de contrato" msgctxt "model:ir.action,name:wizard_create_consumptions" @@ -557,7 +357,7 @@ msgid "Contract" msgstr "Contrato" msgctxt "model:ir.ui.menu,name:menu_contract_configuration" -msgid "Contract Configuration" +msgid "Contracts Configuration" msgstr "Configuración de contratos" msgctxt "model:ir.ui.menu,name:menu_contract_consumption" @@ -569,7 +369,7 @@ msgid "Contract" msgstr "Contratos" msgctxt "model:ir.ui.menu,name:menu_contract_service" -msgid "Services" +msgid "Contract Service" msgstr "Servicio de contrato" msgctxt "model:ir.ui.menu,name:menu_create_consumptions" @@ -577,32 +377,24 @@ msgid "Create Consumptions" msgstr "Crear consumos" msgctxt "model:res.group,name:group_contract" -msgid "Contract User" +msgid "Contract" msgstr "Contratos" msgctxt "model:res.group,name:group_contract_admin" -msgid "Contract Administrator" +msgid "Contract Administration" msgstr "Administración de contratos" msgctxt "selection:contract,freq:" msgid "Daily" msgstr "Diariamente" -msgctxt "selection:contract,freq:" -msgid "Hourly" -msgstr "Cada hora" - -msgctxt "selection:contract,freq:" -msgid "Minutely" -msgstr "Cada minuto" - msgctxt "selection:contract,freq:" msgid "Monthly" msgstr "Mensualmente" msgctxt "selection:contract,freq:" -msgid "Secondly" -msgstr "Cada segundo" +msgid "None" +msgstr "Ninguno" msgctxt "selection:contract,freq:" msgid "Weekly" @@ -624,69 +416,17 @@ msgctxt "selection:contract,state:" msgid "Validated" msgstr "Valido" -msgctxt "selection:contract,wkst:" -msgid "" -msgstr "" - -msgctxt "selection:contract,wkst:" -msgid "Friday" -msgstr "Viernes" - -msgctxt "selection:contract,wkst:" -msgid "Monday" -msgstr "Lunes" - -msgctxt "selection:contract,wkst:" -msgid "Saturday" -msgstr "Sábado" - -msgctxt "selection:contract,wkst:" -msgid "Sunday" -msgstr "Domingo" - -msgctxt "selection:contract,wkst:" -msgid "Thursday" -msgstr "Jueves" - -msgctxt "selection:contract,wkst:" -msgid "Tuesday" -msgstr "Martes" - -msgctxt "selection:contract,wkst:" -msgid "Wednesday" -msgstr "Miércoles" - -msgctxt "selection:contract.line,state:" -msgid "Active" -msgstr "Activo" - -msgctxt "selection:contract.line,state:" -msgid "Draft" -msgstr "Borrador" - -msgctxt "selection:contract.line,state:" -msgid "Hold" -msgstr "En espera" - msgctxt "selection:contract.service,freq:" msgid "Daily" msgstr "Diariamente" -msgctxt "selection:contract.service,freq:" -msgid "Hourly" -msgstr "Cada hora" - -msgctxt "selection:contract.service,freq:" -msgid "Minutely" -msgstr "Cada minuto" - msgctxt "selection:contract.service,freq:" msgid "Monthly" msgstr "Mensualmente" msgctxt "selection:contract.service,freq:" -msgid "Secondly" -msgstr "Cada segundo" +msgid "None" +msgstr "Ninguno" msgctxt "selection:contract.service,freq:" msgid "Weekly" @@ -696,38 +436,6 @@ msgctxt "selection:contract.service,freq:" msgid "Yearly" msgstr "Anualmente" -msgctxt "selection:contract.service,wkst:" -msgid "" -msgstr "" - -msgctxt "selection:contract.service,wkst:" -msgid "Friday" -msgstr "Viernes" - -msgctxt "selection:contract.service,wkst:" -msgid "Monday" -msgstr "Lunes" - -msgctxt "selection:contract.service,wkst:" -msgid "Saturday" -msgstr "Sábado" - -msgctxt "selection:contract.service,wkst:" -msgid "Sunday" -msgstr "Domingo" - -msgctxt "selection:contract.service,wkst:" -msgid "Thursday" -msgstr "Jueves" - -msgctxt "selection:contract.service,wkst:" -msgid "Tuesday" -msgstr "Martes" - -msgctxt "selection:contract.service,wkst:" -msgid "Wednesday" -msgstr "Miércoles" - msgctxt "view:contract.configuration:" msgid "Contract Configuration" msgstr "Configuración de contratos" diff --git a/setup.py b/setup.py index e6d5047..c373a41 100644 --- a/setup.py +++ b/setup.py @@ -61,8 +61,8 @@ setup(name='%s_%s' % (PREFIX, MODULE), 'trytond.modules.%s.tests' % MODULE, ], package_data={ - 'trytond.modules.%s' % MODULE: (info.get('xml', []) - + ['tryton.cfg', 'locale/*.po', 'tests/*.rst']), + 'trytond.modules.%s' % MODULE: (info.get('xml', []) + + ['tryton.cfg', 'locale/*.po', 'tests/*.rst']), }, classifiers=[ 'Development Status :: 5 - Production/Stable', diff --git a/tests/scenario_contract.rst b/tests/scenario_monthly_full_month_contract.rst similarity index 90% rename from tests/scenario_contract.rst rename to tests/scenario_monthly_full_month_contract.rst index 52426b2..25d76c0 100644 --- a/tests/scenario_contract.rst +++ b/tests/scenario_monthly_full_month_contract.rst @@ -1,6 +1,14 @@ -================ -Contract Scenario -================ +===================================== +Monthly Contract, Full Month Scenario +===================================== + +.. Define contract with monthly periodicity +.. Start date = Start Period Date = Invoce Date. +.. Create Consumptions. +.. Check consumptions dates. +.. Create Invoice. +.. Check Invoice Lines Amounts +.. Check Invoice Date. Imports:: >>> import datetime @@ -183,51 +191,50 @@ Create monthly service:: >>> Service = Model.get('contract.service') >>> service = Service() >>> service.product = product - >>> service.freq = 'monthly' + >>> service.freq = None >>> service.save() + Create a contract:: >>> Contract = Model.get('contract') >>> contract = Contract() >>> contract.party = party - >>> contract.start_date = today + relativedelta(day=1) + >>> contract.start_period_date = datetime.date(2015,01,01) + >>> contract.start_date = datetime.date(2015,01,01) >>> contract.freq = 'monthly' >>> line = contract.lines.new() - >>> line.start_date == today + relativedelta(day=1) - True >>> line.service = service >>> line.unit_price Decimal('40') >>> contract.click('validate_contract') >>> contract.state u'validated' - >>> contract_line, = contract.lines - >>> contract_line.state - u'active' + >>> contract.save() + >>> contract.reload() Generate consumed lines:: >>> create_consumptions = Wizard('contract.create_consumptions') - >>> create_consumptions.form.date += relativedelta(months=1) + >>> create_consumptions.form.date = datetime.date(2015,02,01) >>> create_consumptions.execute('create_consumptions') >>> Consumption = Model.get('contract.consumption') >>> consumption, = Consumption.find([]) - >>> consumption.contract_line == contract_line + >>> consumption.start_date == datetime.date(2015,01,01) + True + >>> consumption.end_date == datetime.date(2015,01,31) + True + >>> consumption.invoice_date == datetime.date(2015,01,31) True - >>> consumption.invoice_line Generate invoice for consumed lines:: - >>> consumption.invoice_date = datetime.date.today() >>> consumption.click('invoice') >>> invoice = consumption.invoice_line.invoice >>> invoice.type u'out_invoice' >>> invoice.party == party True - >>> invoice.invoice_date == datetime.date.today() - True >>> invoice.untaxed_amount Decimal('40.00') >>> invoice.tax_amount @@ -236,5 +243,6 @@ Generate invoice for consumed lines:: Decimal('44.00') >>> consumption.invoice_line.product == product True - + >>> consumption.invoice_date == invoice.invoice_date + True diff --git a/tests/scenario_monthly_full_month_with_invoice_date_contract.rst b/tests/scenario_monthly_full_month_with_invoice_date_contract.rst new file mode 100644 index 0000000..2037246 --- /dev/null +++ b/tests/scenario_monthly_full_month_with_invoice_date_contract.rst @@ -0,0 +1,257 @@ +===================================== +Monthly Contract, Full Month Scenario +===================================== + +.. Define contract with monthly periodicity +.. Start date = Start Period Date = Invoce Date. +.. Create Consumptions. +.. Check consumptions dates. +.. Create Invoice. +.. Check Invoice Lines Amounts +.. Check Invoice Date. + +Imports:: + >>> import datetime + >>> from dateutil.relativedelta import relativedelta + >>> from decimal import Decimal + >>> from operator import attrgetter + >>> from proteus import config, Model, Wizard + >>> today = datetime.datetime.combine(datetime.date.today(), + ... datetime.datetime.min.time()) + >>> tomorrow = datetime.date.today() + relativedelta(days=1) + +Create database:: + + >>> config = config.set_trytond() + >>> config.pool.test = True + +Install account_invoice:: + + >>> Module = Model.get('ir.module.module') + >>> contract_module, = Module.find([('name', '=', 'contract')]) + >>> Module.install([contract_module.id], config.context) + >>> Wizard('ir.module.module.install_upgrade').execute('upgrade') + +Create company:: + + >>> Currency = Model.get('currency.currency') + >>> CurrencyRate = Model.get('currency.currency.rate') + >>> currencies = Currency.find([('code', '=', 'USD')]) + >>> if not currencies: + ... currency = Currency(name='US Dollar', symbol=u'$', code='USD', + ... rounding=Decimal('0.01'), mon_grouping='[]', + ... mon_decimal_point='.') + ... currency.save() + ... CurrencyRate(date=today + relativedelta(month=1, day=1), + ... rate=Decimal('1.0'), currency=currency).save() + ... else: + ... currency, = currencies + >>> Company = Model.get('company.company') + >>> Party = Model.get('party.party') + >>> company_config = Wizard('company.company.config') + >>> company_config.execute('company') + >>> company = company_config.form + >>> party = Party(name='Dunder Mifflin') + >>> party.save() + >>> company.party = party + >>> company.currency = currency + >>> company_config.execute('add') + >>> company, = Company.find([]) + +Reload the context:: + + >>> User = Model.get('res.user') + >>> config._context = User.get_preferences(True, config.context) + +Create fiscal year:: + + >>> FiscalYear = Model.get('account.fiscalyear') + >>> Sequence = Model.get('ir.sequence') + >>> SequenceStrict = Model.get('ir.sequence.strict') + >>> fiscalyear = FiscalYear(name=str(today.year)) + >>> fiscalyear.start_date = today + relativedelta(month=1, day=1) + >>> fiscalyear.end_date = today + relativedelta(month=12, day=31) + >>> fiscalyear.company = company + >>> post_move_seq = Sequence(name=str(today.year), code='account.move', + ... company=company) + >>> post_move_seq.save() + >>> fiscalyear.post_move_sequence = post_move_seq + >>> invoice_seq = SequenceStrict(name=str(today.year), + ... code='account.invoice', company=company) + >>> invoice_seq.save() + >>> fiscalyear.out_invoice_sequence = invoice_seq + >>> fiscalyear.in_invoice_sequence = invoice_seq + >>> fiscalyear.out_credit_note_sequence = invoice_seq + >>> fiscalyear.in_credit_note_sequence = invoice_seq + >>> fiscalyear.save() + >>> FiscalYear.create_period([fiscalyear.id], config.context) + +Create chart of accounts:: + + >>> AccountTemplate = Model.get('account.account.template') + >>> Account = Model.get('account.account') + >>> account_template, = AccountTemplate.find([('parent', '=', None)]) + >>> create_chart = Wizard('account.create_chart') + >>> create_chart.execute('account') + >>> create_chart.form.account_template = account_template + >>> create_chart.form.company = company + >>> create_chart.execute('create_account') + >>> receivable, = Account.find([ + ... ('kind', '=', 'receivable'), + ... ('company', '=', company.id), + ... ]) + >>> payable, = Account.find([ + ... ('kind', '=', 'payable'), + ... ('company', '=', company.id), + ... ]) + >>> revenue, = Account.find([ + ... ('kind', '=', 'revenue'), + ... ('company', '=', company.id), + ... ]) + >>> expense, = Account.find([ + ... ('kind', '=', 'expense'), + ... ('company', '=', company.id), + ... ]) + >>> account_tax, = Account.find([ + ... ('kind', '=', 'other'), + ... ('company', '=', company.id), + ... ('name', '=', 'Main Tax'), + ... ]) + >>> create_chart.form.account_receivable = receivable + >>> create_chart.form.account_payable = payable + >>> create_chart.execute('create_properties') + +Create tax:: + + >>> TaxCode = Model.get('account.tax.code') + >>> Tax = Model.get('account.tax') + >>> tax = Tax() + >>> tax.name = 'Tax' + >>> tax.description = 'Tax' + >>> tax.type = 'percentage' + >>> tax.rate = Decimal('.10') + >>> tax.invoice_account = account_tax + >>> tax.credit_note_account = account_tax + >>> invoice_base_code = TaxCode(name='invoice base') + >>> invoice_base_code.save() + >>> tax.invoice_base_code = invoice_base_code + >>> invoice_tax_code = TaxCode(name='invoice tax') + >>> invoice_tax_code.save() + >>> tax.invoice_tax_code = invoice_tax_code + >>> credit_note_base_code = TaxCode(name='credit note base') + >>> credit_note_base_code.save() + >>> tax.credit_note_base_code = credit_note_base_code + >>> credit_note_tax_code = TaxCode(name='credit note tax') + >>> credit_note_tax_code.save() + >>> tax.credit_note_tax_code = credit_note_tax_code + >>> tax.save() + +Create party:: + + >>> Party = Model.get('party.party') + >>> party = Party(name='Party') + >>> party.save() + +Create product:: + + >>> ProductUom = Model.get('product.uom') + >>> unit, = ProductUom.find([('name', '=', 'Unit')]) + >>> ProductTemplate = Model.get('product.template') + >>> Product = Model.get('product.product') + >>> product = Product() + >>> template = ProductTemplate() + >>> template.name = 'product' + >>> template.default_uom = unit + >>> template.type = 'service' + >>> template.list_price = Decimal('40') + >>> template.cost_price = Decimal('25') + >>> template.account_expense = expense + >>> template.account_revenue = revenue + >>> template.customer_taxes.append(tax) + >>> template.save() + >>> product.template = template + >>> product.save() + +Create payment term:: + + >>> PaymentTerm = Model.get('account.invoice.payment_term') + >>> PaymentTermLine = Model.get('account.invoice.payment_term.line') + >>> payment_term = PaymentTerm(name='Term') + >>> payment_term_line = PaymentTermLine(type='percent', days=20, + ... percentage=Decimal(50)) + >>> payment_term.lines.append(payment_term_line) + >>> payment_term_line = PaymentTermLine(type='remainder', days=40) + >>> payment_term.lines.append(payment_term_line) + >>> payment_term.save() + >>> party.customer_payment_term = payment_term + >>> party.save() + +Create monthly service:: + + >>> Service = Model.get('contract.service') + >>> service = Service() + >>> service.product = product + >>> service.freq = None + >>> service.save() + + +Create a contract:: + + >>> Contract = Model.get('contract') + >>> contract = Contract() + >>> contract.party = party + >>> contract.start_period_date = datetime.date(2015,01,01) + >>> contract.start_date = datetime.date(2015,01,01) + >>> contract.first_invoice_date = datetime.date(2015,02,05) + >>> contract.freq = 'monthly' + >>> line = contract.lines.new() + >>> line.service = service + >>> line.unit_price + Decimal('40') + >>> contract.click('validate_contract') + >>> contract.state + u'validated' + >>> contract.save() + >>> contract.reload() + +Generate consumed lines:: + + >>> create_consumptions = Wizard('contract.create_consumptions') + >>> create_consumptions.form.date = datetime.date(2015,03,01) + >>> create_consumptions.execute('create_consumptions') + >>> Consumption = Model.get('contract.consumption') + >>> consumptions = Consumption.find([]) + >>> consumption = consumptions[0] + >>> consumption.start_date == datetime.date(2015,01,01) + True + >>> consumption.end_date == datetime.date(2015,01,31) + True + >>> consumption.invoice_date == datetime.date(2015,02,05) + True + >>> consumption1 = consumptions[1] + >>> consumption1.start_date == datetime.date(2015,02,01) + True + >>> consumption1.end_date == datetime.date(2015,02,28) + True + >>> consumption1.invoice_date == datetime.date(2015,03,05) + True + +Generate invoice for consumed lines:: + + >>> consumption.click('invoice') + >>> invoice = consumption.invoice_line.invoice + >>> invoice.type + u'out_invoice' + >>> invoice.party == party + True + >>> invoice.untaxed_amount + Decimal('40.00') + >>> invoice.tax_amount + Decimal('4.00') + >>> invoice.total_amount + Decimal('44.00') + >>> consumption.invoice_line.product == product + True + >>> consumption.invoice_date == invoice.invoice_date + True + diff --git a/tests/scenario_monthly_natural_days_contract.rst b/tests/scenario_monthly_natural_days_contract.rst new file mode 100644 index 0000000..279931e --- /dev/null +++ b/tests/scenario_monthly_natural_days_contract.rst @@ -0,0 +1,252 @@ +===================================== +Monthly Contract, Full Month Scenario +===================================== + +.. Define contract with monthly periodicity +.. Start date = Start Period Date = Invoce Date. +.. Create Consumptions. +.. Check consumptions dates. +.. Create Invoice. +.. Check Invoice Lines Amounts +.. Check Invoice Date. + +Imports:: + >>> import datetime + >>> from dateutil.relativedelta import relativedelta + >>> from decimal import Decimal + >>> from operator import attrgetter + >>> from proteus import config, Model, Wizard + >>> today = datetime.datetime.combine(datetime.date.today(), + ... datetime.datetime.min.time()) + >>> tomorrow = datetime.date.today() + relativedelta(days=1) + +Create database:: + + >>> config = config.set_trytond() + >>> config.pool.test = True + +Install account_invoice:: + + >>> Module = Model.get('ir.module.module') + >>> contract_module, = Module.find([('name', '=', 'contract')]) + >>> Module.install([contract_module.id], config.context) + >>> Wizard('ir.module.module.install_upgrade').execute('upgrade') + +Create company:: + + >>> Currency = Model.get('currency.currency') + >>> CurrencyRate = Model.get('currency.currency.rate') + >>> currencies = Currency.find([('code', '=', 'USD')]) + >>> if not currencies: + ... currency = Currency(name='US Dollar', symbol=u'$', code='USD', + ... rounding=Decimal('0.01'), mon_grouping='[]', + ... mon_decimal_point='.') + ... currency.save() + ... CurrencyRate(date=today + relativedelta(month=1, day=1), + ... rate=Decimal('1.0'), currency=currency).save() + ... else: + ... currency, = currencies + >>> Company = Model.get('company.company') + >>> Party = Model.get('party.party') + >>> company_config = Wizard('company.company.config') + >>> company_config.execute('company') + >>> company = company_config.form + >>> party = Party(name='Dunder Mifflin') + >>> party.save() + >>> company.party = party + >>> company.currency = currency + >>> company_config.execute('add') + >>> company, = Company.find([]) + +Reload the context:: + + >>> User = Model.get('res.user') + >>> config._context = User.get_preferences(True, config.context) + +Create fiscal year:: + + >>> FiscalYear = Model.get('account.fiscalyear') + >>> Sequence = Model.get('ir.sequence') + >>> SequenceStrict = Model.get('ir.sequence.strict') + >>> fiscalyear = FiscalYear(name=str(today.year)) + >>> fiscalyear.start_date = today + relativedelta(month=1, day=1) + >>> fiscalyear.end_date = today + relativedelta(month=12, day=31) + >>> fiscalyear.company = company + >>> post_move_seq = Sequence(name=str(today.year), code='account.move', + ... company=company) + >>> post_move_seq.save() + >>> fiscalyear.post_move_sequence = post_move_seq + >>> invoice_seq = SequenceStrict(name=str(today.year), + ... code='account.invoice', company=company) + >>> invoice_seq.save() + >>> fiscalyear.out_invoice_sequence = invoice_seq + >>> fiscalyear.in_invoice_sequence = invoice_seq + >>> fiscalyear.out_credit_note_sequence = invoice_seq + >>> fiscalyear.in_credit_note_sequence = invoice_seq + >>> fiscalyear.save() + >>> FiscalYear.create_period([fiscalyear.id], config.context) + +Create chart of accounts:: + + >>> AccountTemplate = Model.get('account.account.template') + >>> Account = Model.get('account.account') + >>> account_template, = AccountTemplate.find([('parent', '=', None)]) + >>> create_chart = Wizard('account.create_chart') + >>> create_chart.execute('account') + >>> create_chart.form.account_template = account_template + >>> create_chart.form.company = company + >>> create_chart.execute('create_account') + >>> receivable, = Account.find([ + ... ('kind', '=', 'receivable'), + ... ('company', '=', company.id), + ... ]) + >>> payable, = Account.find([ + ... ('kind', '=', 'payable'), + ... ('company', '=', company.id), + ... ]) + >>> revenue, = Account.find([ + ... ('kind', '=', 'revenue'), + ... ('company', '=', company.id), + ... ]) + >>> expense, = Account.find([ + ... ('kind', '=', 'expense'), + ... ('company', '=', company.id), + ... ]) + >>> account_tax, = Account.find([ + ... ('kind', '=', 'other'), + ... ('company', '=', company.id), + ... ('name', '=', 'Main Tax'), + ... ]) + >>> create_chart.form.account_receivable = receivable + >>> create_chart.form.account_payable = payable + >>> create_chart.execute('create_properties') + +Create tax:: + + >>> TaxCode = Model.get('account.tax.code') + >>> Tax = Model.get('account.tax') + >>> tax = Tax() + >>> tax.name = 'Tax' + >>> tax.description = 'Tax' + >>> tax.type = 'percentage' + >>> tax.rate = Decimal('.10') + >>> tax.invoice_account = account_tax + >>> tax.credit_note_account = account_tax + >>> invoice_base_code = TaxCode(name='invoice base') + >>> invoice_base_code.save() + >>> tax.invoice_base_code = invoice_base_code + >>> invoice_tax_code = TaxCode(name='invoice tax') + >>> invoice_tax_code.save() + >>> tax.invoice_tax_code = invoice_tax_code + >>> credit_note_base_code = TaxCode(name='credit note base') + >>> credit_note_base_code.save() + >>> tax.credit_note_base_code = credit_note_base_code + >>> credit_note_tax_code = TaxCode(name='credit note tax') + >>> credit_note_tax_code.save() + >>> tax.credit_note_tax_code = credit_note_tax_code + >>> tax.save() + +Create party:: + + >>> Party = Model.get('party.party') + >>> party = Party(name='Party') + >>> party.save() + +Create product:: + + >>> ProductUom = Model.get('product.uom') + >>> unit, = ProductUom.find([('name', '=', 'Unit')]) + >>> ProductTemplate = Model.get('product.template') + >>> Product = Model.get('product.product') + >>> product = Product() + >>> template = ProductTemplate() + >>> template.name = 'product' + >>> template.default_uom = unit + >>> template.type = 'service' + >>> template.list_price = Decimal('40') + >>> template.cost_price = Decimal('25') + >>> template.account_expense = expense + >>> template.account_revenue = revenue + >>> template.customer_taxes.append(tax) + >>> template.save() + >>> product.template = template + >>> product.save() + +Create payment term:: + + >>> PaymentTerm = Model.get('account.invoice.payment_term') + >>> PaymentTermLine = Model.get('account.invoice.payment_term.line') + >>> payment_term = PaymentTerm(name='Term') + >>> payment_term_line = PaymentTermLine(type='percent', days=20, + ... percentage=Decimal(50)) + >>> payment_term.lines.append(payment_term_line) + >>> payment_term_line = PaymentTermLine(type='remainder', days=40) + >>> payment_term.lines.append(payment_term_line) + >>> payment_term.save() + >>> party.customer_payment_term = payment_term + >>> party.save() + +Create monthly service:: + + >>> Service = Model.get('contract.service') + >>> service = Service() + >>> service.product = product + >>> service.freq = None + >>> service.save() + + +Create a contract:: + + >>> Contract = Model.get('contract') + >>> contract = Contract() + >>> contract.party = party + >>> contract.start_period_date = datetime.date(2015,01,05) + >>> contract.start_date = datetime.date(2015,01,05) + >>> contract.freq = 'monthly' + >>> line = contract.lines.new() + >>> line.service = service + >>> line.unit_price + Decimal('40') + >>> contract.click('validate_contract') + >>> contract.state + u'validated' + >>> contract.save() + >>> contract.reload() + +Generate consumed lines:: + + >>> create_consumptions = Wizard('contract.create_consumptions') + >>> create_consumptions.form.date = datetime.date(2015,02,06) + >>> create_consumptions.execute('create_consumptions') + >>> Consumption = Model.get('contract.consumption') + >>> consumption, = Consumption.find([]) + >>> consumption.start_date == datetime.date(2015,01,05) + True + >>> consumption.end_date == datetime.date(2015,02,04) + True + >>> consumption.invoice_date == datetime.date(2015,02,04) + True + >>> consumption.init_period_date == datetime.date(2015,01,05) + True + >>> consumption.end_period_date == datetime.date(2015,02,04) + True + +Generate invoice for consumed lines:: + + >>> consumption.click('invoice') + >>> invoice = consumption.invoice_line.invoice + >>> invoice.type + u'out_invoice' + >>> invoice.party == party + True + >>> invoice.untaxed_amount + Decimal('40.00') + >>> invoice.tax_amount + Decimal('4.00') + >>> invoice.total_amount + Decimal('44.00') + >>> consumption.invoice_line.product == product + True + >>> consumption.invoice_date == invoice.invoice_date + True + diff --git a/tests/scenario_monthly_start_in_month_contract.rst b/tests/scenario_monthly_start_in_month_contract.rst new file mode 100644 index 0000000..efbc34e --- /dev/null +++ b/tests/scenario_monthly_start_in_month_contract.rst @@ -0,0 +1,252 @@ +===================================== +Monthly Contract, Full Month Scenario +===================================== + +.. Define contract with monthly periodicity +.. Start date = Start Period Date = Invoce Date. +.. Create Consumptions. +.. Check consumptions dates. +.. Create Invoice. +.. Check Invoice Lines Amounts +.. Check Invoice Date. + +Imports:: + >>> import datetime + >>> from dateutil.relativedelta import relativedelta + >>> from decimal import Decimal + >>> from operator import attrgetter + >>> from proteus import config, Model, Wizard + >>> today = datetime.datetime.combine(datetime.date.today(), + ... datetime.datetime.min.time()) + >>> tomorrow = datetime.date.today() + relativedelta(days=1) + +Create database:: + + >>> config = config.set_trytond() + >>> config.pool.test = True + +Install account_invoice:: + + >>> Module = Model.get('ir.module.module') + >>> contract_module, = Module.find([('name', '=', 'contract')]) + >>> Module.install([contract_module.id], config.context) + >>> Wizard('ir.module.module.install_upgrade').execute('upgrade') + +Create company:: + + >>> Currency = Model.get('currency.currency') + >>> CurrencyRate = Model.get('currency.currency.rate') + >>> currencies = Currency.find([('code', '=', 'USD')]) + >>> if not currencies: + ... currency = Currency(name='US Dollar', symbol=u'$', code='USD', + ... rounding=Decimal('0.01'), mon_grouping='[]', + ... mon_decimal_point='.') + ... currency.save() + ... CurrencyRate(date=today + relativedelta(month=1, day=1), + ... rate=Decimal('1.0'), currency=currency).save() + ... else: + ... currency, = currencies + >>> Company = Model.get('company.company') + >>> Party = Model.get('party.party') + >>> company_config = Wizard('company.company.config') + >>> company_config.execute('company') + >>> company = company_config.form + >>> party = Party(name='Dunder Mifflin') + >>> party.save() + >>> company.party = party + >>> company.currency = currency + >>> company_config.execute('add') + >>> company, = Company.find([]) + +Reload the context:: + + >>> User = Model.get('res.user') + >>> config._context = User.get_preferences(True, config.context) + +Create fiscal year:: + + >>> FiscalYear = Model.get('account.fiscalyear') + >>> Sequence = Model.get('ir.sequence') + >>> SequenceStrict = Model.get('ir.sequence.strict') + >>> fiscalyear = FiscalYear(name=str(today.year)) + >>> fiscalyear.start_date = today + relativedelta(month=1, day=1) + >>> fiscalyear.end_date = today + relativedelta(month=12, day=31) + >>> fiscalyear.company = company + >>> post_move_seq = Sequence(name=str(today.year), code='account.move', + ... company=company) + >>> post_move_seq.save() + >>> fiscalyear.post_move_sequence = post_move_seq + >>> invoice_seq = SequenceStrict(name=str(today.year), + ... code='account.invoice', company=company) + >>> invoice_seq.save() + >>> fiscalyear.out_invoice_sequence = invoice_seq + >>> fiscalyear.in_invoice_sequence = invoice_seq + >>> fiscalyear.out_credit_note_sequence = invoice_seq + >>> fiscalyear.in_credit_note_sequence = invoice_seq + >>> fiscalyear.save() + >>> FiscalYear.create_period([fiscalyear.id], config.context) + +Create chart of accounts:: + + >>> AccountTemplate = Model.get('account.account.template') + >>> Account = Model.get('account.account') + >>> account_template, = AccountTemplate.find([('parent', '=', None)]) + >>> create_chart = Wizard('account.create_chart') + >>> create_chart.execute('account') + >>> create_chart.form.account_template = account_template + >>> create_chart.form.company = company + >>> create_chart.execute('create_account') + >>> receivable, = Account.find([ + ... ('kind', '=', 'receivable'), + ... ('company', '=', company.id), + ... ]) + >>> payable, = Account.find([ + ... ('kind', '=', 'payable'), + ... ('company', '=', company.id), + ... ]) + >>> revenue, = Account.find([ + ... ('kind', '=', 'revenue'), + ... ('company', '=', company.id), + ... ]) + >>> expense, = Account.find([ + ... ('kind', '=', 'expense'), + ... ('company', '=', company.id), + ... ]) + >>> account_tax, = Account.find([ + ... ('kind', '=', 'other'), + ... ('company', '=', company.id), + ... ('name', '=', 'Main Tax'), + ... ]) + >>> create_chart.form.account_receivable = receivable + >>> create_chart.form.account_payable = payable + >>> create_chart.execute('create_properties') + +Create tax:: + + >>> TaxCode = Model.get('account.tax.code') + >>> Tax = Model.get('account.tax') + >>> tax = Tax() + >>> tax.name = 'Tax' + >>> tax.description = 'Tax' + >>> tax.type = 'percentage' + >>> tax.rate = Decimal('.10') + >>> tax.invoice_account = account_tax + >>> tax.credit_note_account = account_tax + >>> invoice_base_code = TaxCode(name='invoice base') + >>> invoice_base_code.save() + >>> tax.invoice_base_code = invoice_base_code + >>> invoice_tax_code = TaxCode(name='invoice tax') + >>> invoice_tax_code.save() + >>> tax.invoice_tax_code = invoice_tax_code + >>> credit_note_base_code = TaxCode(name='credit note base') + >>> credit_note_base_code.save() + >>> tax.credit_note_base_code = credit_note_base_code + >>> credit_note_tax_code = TaxCode(name='credit note tax') + >>> credit_note_tax_code.save() + >>> tax.credit_note_tax_code = credit_note_tax_code + >>> tax.save() + +Create party:: + + >>> Party = Model.get('party.party') + >>> party = Party(name='Party') + >>> party.save() + +Create product:: + + >>> ProductUom = Model.get('product.uom') + >>> unit, = ProductUom.find([('name', '=', 'Unit')]) + >>> ProductTemplate = Model.get('product.template') + >>> Product = Model.get('product.product') + >>> product = Product() + >>> template = ProductTemplate() + >>> template.name = 'product' + >>> template.default_uom = unit + >>> template.type = 'service' + >>> template.list_price = Decimal('40') + >>> template.cost_price = Decimal('25') + >>> template.account_expense = expense + >>> template.account_revenue = revenue + >>> template.customer_taxes.append(tax) + >>> template.save() + >>> product.template = template + >>> product.save() + +Create payment term:: + + >>> PaymentTerm = Model.get('account.invoice.payment_term') + >>> PaymentTermLine = Model.get('account.invoice.payment_term.line') + >>> payment_term = PaymentTerm(name='Term') + >>> payment_term_line = PaymentTermLine(type='percent', days=20, + ... percentage=Decimal(50)) + >>> payment_term.lines.append(payment_term_line) + >>> payment_term_line = PaymentTermLine(type='remainder', days=40) + >>> payment_term.lines.append(payment_term_line) + >>> payment_term.save() + >>> party.customer_payment_term = payment_term + >>> party.save() + +Create monthly service:: + + >>> Service = Model.get('contract.service') + >>> service = Service() + >>> service.product = product + >>> service.freq = None + >>> service.save() + + +Create a contract:: + + >>> Contract = Model.get('contract') + >>> contract = Contract() + >>> contract.party = party + >>> contract.start_period_date = datetime.date(2015,01,01) + >>> contract.start_date = datetime.date(2015,01,10) + >>> contract.freq = 'monthly' + >>> line = contract.lines.new() + >>> line.service = service + >>> line.unit_price + Decimal('40') + >>> contract.click('validate_contract') + >>> contract.state + u'validated' + >>> contract.save() + >>> contract.reload() + +Generate consumed lines:: + + >>> create_consumptions = Wizard('contract.create_consumptions') + >>> create_consumptions.form.date = datetime.date(2015,02,01) + >>> create_consumptions.execute('create_consumptions') + >>> Consumption = Model.get('contract.consumption') + >>> consumption, = Consumption.find([]) + >>> consumption.start_date == datetime.date(2015,01,10) + True + >>> consumption.end_date == datetime.date(2015,01,31) + True + >>> consumption.invoice_date == datetime.date(2015,01,31) + True + >>> consumption.init_period_date == datetime.date(2015,01,1) + True + >>> consumption.end_period_date == datetime.date(2015,01,31) + True + +Generate invoice for consumed lines:: + + >>> consumption.click('invoice') + >>> invoice = consumption.invoice_line.invoice + >>> invoice.type + u'out_invoice' + >>> invoice.party == party + True + >>> invoice.untaxed_amount + Decimal('40.00') + >>> invoice.tax_amount + Decimal('4.00') + >>> invoice.total_amount + Decimal('44.00') + >>> consumption.invoice_line.product == product + True + >>> consumption.invoice_date == invoice.invoice_date + True + diff --git a/tests/test_contract.py b/tests/test_contract.py index 82fc7ea..8fc1aeb 100644 --- a/tests/test_contract.py +++ b/tests/test_contract.py @@ -26,7 +26,21 @@ def suite(): suite = trytond.tests.test_tryton.suite() suite.addTests(unittest.TestLoader().loadTestsFromTestCase( TestContractCase)) - suite.addTests(doctest.DocFileSuite('scenario_contract.rst', + suite.addTests(doctest.DocFileSuite( + 'scenario_monthly_full_month_contract.rst', setUp=doctest_setup, tearDown=doctest_teardown, encoding='utf-8', optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)) + suite.addTests(doctest.DocFileSuite( + 'scenario_monthly_start_in_month_contract.rst', + setUp=doctest_setup, tearDown=doctest_teardown, encoding='utf-8', + optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)) + suite.addTests(doctest.DocFileSuite( + 'scenario_monthly_natural_days_contract.rst', + setUp=doctest_setup, tearDown=doctest_teardown, encoding='utf-8', + optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)) + suite.addTests(doctest.DocFileSuite( + 'scenario_monthly_full_month_with_invoice_date_contract.rst', + setUp=doctest_setup, tearDown=doctest_teardown, encoding='utf-8', + optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)) + return suite diff --git a/view/contract_consumption_list.xml b/view/contract_consumption_list.xml index 49e199b..1d939a1 100644 --- a/view/contract_consumption_list.xml +++ b/view/contract_consumption_list.xml @@ -7,5 +7,7 @@ this repository contains the full copyright notices and license terms. --> + +