fix funcionality in general

This commit is contained in:
?ngel ?lvarez 2015-03-06 19:05:49 +01:00
parent a7c97b1007
commit 39c5612efb
20 changed files with 980 additions and 1095 deletions

View File

@ -1,5 +1,5 @@
#This file is part of Tryton. The COPYRIGHT file at the top level of # 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 repository contains the full copyright notices and license terms.
from trytond.model import ModelView, ModelSQL, ModelSingleton, fields from trytond.model import ModelView, ModelSQL, ModelSingleton, fields
from trytond.pyson import Eval from trytond.pyson import Eval

View File

@ -1,8 +1,8 @@
# The COPYRIGHT file at the top level of this repository contains # The COPYRIGHT file at the top level of this repository contains
# the full copyright notices and license terms. # the full copyright notices and license terms.
from datetime import datetime import datetime
from dateutil.rrule import rrule, SECONDLY, MINUTELY, HOURLY, DAILY, WEEKLY, \ from dateutil.relativedelta import relativedelta
MONTHLY, YEARLY from dateutil.rrule import rrule, DAILY, WEEKLY, MONTHLY, YEARLY
from itertools import groupby from itertools import groupby
from sql.aggregate import Max from sql.aggregate import Max
@ -15,190 +15,24 @@ from trytond.tools import reduce_ids
from trytond.wizard import Wizard, StateView, StateAction, Button from trytond.wizard import Wizard, StateView, StateAction, Button
DIGITS = config.getint('digits', 'unit_price_digits', 4) DIGITS = config.getint('digits', 'unit_price_digits', 4)
__all__ = ['ContractService', 'Contract', 'ContractLine', __all__ = ['ContractService', 'Contract', 'ContractLine', 'RRuleMixin',
'ContractConsumption', 'CreateConsumptionsStart', 'CreateConsumptions'] 'ContractConsumption', 'CreateConsumptionsStart', 'CreateConsumptions']
class RRuleMixin(Model): class RRuleMixin(Model):
_rec_name = 'freq' _rec_name = 'freq'
freq = fields.Selection([ freq = fields.Selection([
('secondly', 'Secondly'), (None, 'None'),
('minutely', 'Minutely'),
('hourly', 'Hourly'),
('daily', 'Daily'), ('daily', 'Daily'),
('weekly', 'Weekly'), ('weekly', 'Weekly'),
('monthly', 'Monthly'), ('monthly', 'Monthly'),
('yearly', 'Yearly'), ('yearly', 'Yearly'),
], 'Frequency', required=True) ], 'Frequency')
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')
interval = fields.Integer('Interval') 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): def _rule2update(self):
res = {} res = {}
for field in ('freq', 'until_date', 'until', 'count', 'interval', for field in ('freq', 'interval'):
'bysecond', 'byminute', 'byhour', 'byday', 'bymonthday',
'byyearday', 'byweekno', 'bymonth', 'bysetpos', 'wkst'):
res[field] = getattr(self, field) res[field] = getattr(self, field)
return res return res
@ -206,19 +40,13 @@ class RRuleMixin(Model):
values = {} values = {}
mappings = { mappings = {
'freq': { 'freq': {
'secondly': SECONDLY,
'minutely': MINUTELY,
'hourly': HOURLY,
'daily': DAILY, 'daily': DAILY,
'weekly': WEEKLY, 'weekly': WEEKLY,
'monthly': MONTHLY, 'monthly': MONTHLY,
'yearly': YEARLY, 'yearly': YEARLY,
}, },
'byday': 'bymonthday',
} }
for field in ('freq', 'until_date', 'until', 'count', 'interval', for field in ('freq', 'interval'):
'bysecond', 'byminute', 'byhour', 'byday', 'bymonthday',
'byyearday', 'byweekno', 'bymonth', 'bysetpos', 'wkst'):
value = getattr(self, field) value = getattr(self, field)
if not value: if not value:
continue continue
@ -228,10 +56,6 @@ class RRuleMixin(Model):
else: else:
value = mappings[field][value] value = mappings[field][value]
values[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 return values
@property @property
@ -241,7 +65,7 @@ class RRuleMixin(Model):
return rrule(**values) return rrule(**values)
class ContractService(RRuleMixin, ModelSQL, ModelView): class ContractService(ModelSQL, ModelView):
'Contract Service' 'Contract Service'
__name__ = 'contract.service' __name__ = 'contract.service'
@ -260,6 +84,10 @@ _STATES = {
_DEPENDS = ['state'] _DEPENDS = ['state']
def todatetime(date):
return datetime.datetime.combine(date, datetime.datetime.min.time())
class Contract(RRuleMixin, Workflow, ModelSQL, ModelView): class Contract(RRuleMixin, Workflow, ModelSQL, ModelView):
'Contract' 'Contract'
__name__ = 'contract' __name__ = 'contract'
@ -274,6 +102,8 @@ class Contract(RRuleMixin, Workflow, ModelSQL, ModelView):
start_date = fields.Date('Start Date', required=True, start_date = fields.Date('Start Date', required=True,
states=_STATES, depends=_DEPENDS) states=_STATES, depends=_DEPENDS)
end_date = fields.Date('End Date') 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, first_invoice_date = fields.Date('First Invoice Date', states=_STATES,
depends=_DEPENDS) depends=_DEPENDS)
lines = fields.One2Many('contract.line', 'contract', 'Lines', lines = fields.One2Many('contract.line', 'contract', 'Lines',
@ -291,9 +121,7 @@ class Contract(RRuleMixin, Workflow, ModelSQL, ModelView):
@classmethod @classmethod
def __setup__(cls): def __setup__(cls):
super(Contract, cls).__setup__() super(Contract, cls).__setup__()
for field_name in ('freq', 'until_date', 'until', 'count', 'interval', for field_name in ('freq', 'interval'):
'bysecond', 'byminute', 'byhour', 'byday', 'bymonthday',
'byyearday', 'byweekno', 'bymonth', 'bysetpos', 'wkst'):
field = getattr(cls, field_name) field = getattr(cls, field_name)
field.states = _STATES field.states = _STATES
field.depends = _DEPENDS field.depends = _DEPENDS
@ -317,6 +145,10 @@ class Contract(RRuleMixin, Workflow, ModelSQL, ModelView):
'icon': 'tryton-cancel', 'icon': 'tryton-cancel',
}, },
}) })
cls._error_messages.update({
'start_date_not_valid': ('Contract %(contract)s with '
'invalid date "%(date)s"'),
})
@staticmethod @staticmethod
def default_company(): def default_company():
@ -364,18 +196,13 @@ class Contract(RRuleMixin, Workflow, ModelSQL, ModelView):
@ModelView.button @ModelView.button
@Workflow.transition('draft') @Workflow.transition('draft')
def draft(cls, contracts): def draft(cls, contracts):
pool = Pool() pass
ContractLine = pool.get('contract.line')
ContractLine.hold([l for c in contracts for l in c.lines])
@classmethod @classmethod
@ModelView.button @ModelView.button
@Workflow.transition('validated') @Workflow.transition('validated')
def validate_contract(cls, contracts): def validate_contract(cls, contracts):
pool = Pool()
ContractLine = pool.get('contract.line')
cls.set_reference(contracts) cls.set_reference(contracts)
ContractLine.active([l for c in contracts for l in c.lines])
@classmethod @classmethod
@ModelView.button @ModelView.button
@ -385,10 +212,15 @@ class Contract(RRuleMixin, Workflow, ModelSQL, ModelView):
def rrule_values(self): def rrule_values(self):
values = super(Contract, self).rrule_values() values = super(Contract, self).rrule_values()
values['dtstart'] = datetime.combine(self.start_date, values['dtstart'] = todatetime(self.start_period_date)
datetime.min.time())
return values 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): def get_consumptions(self, end_date=None):
pool = Pool() pool = Pool()
Date = pool.get('ir.date') Date = pool.get('ir.date')
@ -396,20 +228,53 @@ class Contract(RRuleMixin, Workflow, ModelSQL, ModelView):
if end_date is None: if end_date is None:
end_date = Date.today() end_date = Date.today()
end_date = datetime.combine(end_date, datetime.min.time()) end_date = todatetime(end_date)
consumptions = [] consumptions = []
for line in self.lines: for line in self.lines:
if line.state != 'active':
continue start_period_date = self.start_period_date
start_date = datetime.combine(line.last_consumption_date
or line.start_date or line.contract.start_date, last_consumption_date = line.last_consumption_date
datetime.min.time()) if last_consumption_date:
print self.rrule_values() last_consumption_date = todatetime(line.last_consumption_date)
print start_date, end_date last_consumption_date += relativedelta(days=+1)
print self.rrule.between(start_date, end_date)
for date in self.rrule.between(start_date, end_date): start = start_period_date
consumptions.append(line.get_consumption(start_date, date)) if last_consumption_date:
start_date = 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 return consumptions
@classmethod @classmethod
@ -418,11 +283,31 @@ class Contract(RRuleMixin, Workflow, ModelSQL, ModelView):
pool = Pool() pool = Pool()
ContractConsumption = pool.get('contract.consumption') ContractConsumption = pool.get('contract.consumption')
date += relativedelta(days=+1) # to support included.
to_create = [] to_create = []
for contract in contracts: for contract in contracts:
to_create += contract.get_consumptions(date) to_create += contract.get_consumptions(date)
return ContractConsumption.create([c._save_values for c in to_create]) 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): class ContractLine(Workflow, ModelSQL, ModelView):
'Contract Line' 'Contract Line'
@ -435,59 +320,15 @@ class ContractLine(Workflow, ModelSQL, ModelView):
description = fields.Text('Description', required=True) description = fields.Text('Description', required=True)
unit_price = fields.Numeric('Unit Price', digits=(16, DIGITS), unit_price = fields.Numeric('Unit Price', digits=(16, DIGITS),
required=True) 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 = fields.Function(fields.Date(
'Last Consumption Date'), 'get_last_consumption_date') 'Last Consumption Date'), 'get_last_consumption_date')
last_consumption_invoice_date = fields.Function(fields.Date(
@classmethod 'Last Consumption Date'), 'get_last_consumption_date')
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')
})
@staticmethod @staticmethod
def default_state(): def default_state():
return 'draft' 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') @fields.depends('service', 'unit_price', 'description')
def on_change_service(self): def on_change_service(self):
changes = { changes = {
@ -501,14 +342,6 @@ class ContractLine(Workflow, ModelSQL, ModelView):
changes['description'] = self.service.product.rec_name changes['description'] = self.service.product.rec_name
return changes 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 @classmethod
def get_last_consumption_date(cls, lines, name): def get_last_consumption_date(cls, lines, name):
pool = Pool() pool = Pool()
@ -518,50 +351,31 @@ class ContractLine(Workflow, ModelSQL, ModelView):
line_ids = [l.id for l in lines] line_ids = [l.id for l in lines]
values = dict.fromkeys(line_ids, None) 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), where=reduce_ids(table.contract_line, line_ids),
group_by=table.contract_line)) group_by=table.contract_line))
values.update(dict(cursor.fetchall())) values.update(dict(cursor.fetchall()))
return values return values
@classmethod @classmethod
def validate(cls, lines): def get_last_consumption_invoice_date(cls, lines, name):
super(ContractLine, cls).validate(lines) pool = Pool()
for line in lines: Consumption = pool.get('contract.consumption')
line.check_contract_period() table = Consumption.__table__()
cursor = Transaction().cursor
def check_contract_period(self): line_ids = [l.id for l in lines]
if self.start_date < self.contract.start_date: values = dict.fromkeys(line_ids, None)
self.raise_user_error('line_outside_contract', { cursor.execute(*table.select(table.contract_line,
'line': self.rec_name, Max(table.invoice_date),
'contract': self.contract.rec_name, where=reduce_ids(table.contract_line, line_ids),
}) group_by=table.contract_line))
if (self.contract.end_date and values.update(dict(cursor.fetchall()))
self.end_date > self.contract.end_date): return values
self.raise_user_error('line_outside_contract', {
'line': self.rec_name,
'contract': self.contract.rec_name,
})
@classmethod def get_consumption(self, start_date, end_date, invoice_date, start_period,
@ModelView.button finish_period):
@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):
'Returns the consumption for date date' 'Returns the consumption for date date'
pool = Pool() pool = Pool()
Consumption = pool.get('contract.consumption') Consumption = pool.get('contract.consumption')
@ -569,10 +383,8 @@ class ContractLine(Workflow, ModelSQL, ModelView):
consumption.contract_line = self consumption.contract_line = self
consumption.start_date = start_date consumption.start_date = start_date
consumption.end_date = end_date consumption.end_date = end_date
invoice_date = end_date consumption.init_period_date = start_period
if self.contract.first_invoice_date: consumption.end_period_date = finish_period
invoice_date += (self.contract.first_invoice_date -
self.contract.start_date)
consumption.invoice_date = invoice_date consumption.invoice_date = invoice_date
return consumption return consumption
@ -584,8 +396,10 @@ class ContractConsumption(ModelSQL, ModelView):
contract_line = fields.Many2One('contract.line', 'Contract Line', contract_line = fields.Many2One('contract.line', 'Contract Line',
required=True) required=True)
invoice_line = fields.Many2One('account.invoice.line', 'Invoice Line') invoice_line = fields.Many2One('account.invoice.line', 'Invoice Line')
start_date = fields.DateTime('Start Date') init_period_date = fields.Date('Start Period Date')
end_date = fields.DateTime('End 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') invoice_date = fields.Date('Invoice Date')
@classmethod @classmethod
@ -667,10 +481,8 @@ class ContractConsumption(ModelSQL, ModelView):
invoice_line.taxes = taxes invoice_line.taxes = taxes
invoice_line.invoice_type = 'out_invoice' invoice_line.invoice_type = 'out_invoice'
# Compute quantity based on dates # Compute quantity based on dates
contract_start = self.contract_line.contract.start_date quantity = ((self.end_date - self.start_date).total_seconds() /
invoice_date = self.contract_line.contract.rrule.after(contract_start) (self.end_period_date - self.init_period_date).total_seconds())
quantity = ((self.end_date - self.start_date).total_seconds()
/ (invoice_date - contract_start).total_seconds())
rounding = invoice_line.unit.rounding if invoice_line.unit else 1 rounding = invoice_line.unit.rounding if invoice_line.unit else 1
invoice_line.quantity = Uom.round(quantity, rounding) invoice_line.quantity = Uom.round(quantity, rounding)
return invoice_line return invoice_line
@ -735,8 +547,8 @@ class ContractConsumption(ModelSQL, ModelView):
invoices = [] invoices = []
for key, grouped_lines in groupby(lines, key=cls._group_invoice_key): for key, grouped_lines in groupby(lines, key=cls._group_invoice_key):
invoice = cls._get_invoice(key) invoice = cls._get_invoice(key)
invoice.lines = (list(getattr(invoice, 'lines', [])) invoice.lines = (list(getattr(invoice, 'lines', [])) +
+ list(x[1] for x in grouped_lines)) list(x[1] for x in grouped_lines))
invoices.append(invoice) invoices.append(invoice)
invoices = Invoice.create([x._save_values for x in invoices]) invoices = Invoice.create([x._save_values for x in invoices])

View File

@ -1,6 +1,6 @@
#This file is part of contract_invoice module for Tryton. # This file is part of contract_invoice module for Tryton.
#The COPYRIGHT file at the top level of this repository contains # The COPYRIGHT file at the top level of this repository contains
#the full copyright notices and license terms. # the full copyright notices and license terms.
from trytond.pool import PoolMeta from trytond.pool import PoolMeta
__all__ = ['InvoiceLine'] __all__ = ['InvoiceLine']

View File

@ -18,142 +18,10 @@ msgstr ""
"Falta el compte d'ingressos al producte \"%(product)s\" de la línia de " "Falta el compte d'ingressos al producte \"%(product)s\" de la línia de "
"contracte \"%(contract_line)s\"." "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:" msgctxt "field:contract,company:"
msgid "Company" msgid "Company"
msgstr "Empresa" msgstr "Empresa"
msgctxt "field:contract,count:"
msgid "Count"
msgstr "Comptador"
msgctxt "field:contract,create_date:" msgctxt "field:contract,create_date:"
msgid "Create Date" msgid "Create Date"
msgstr "Data creació" msgstr "Data creació"
@ -210,18 +78,6 @@ msgctxt "field:contract,state:"
msgid "State" msgid "State"
msgstr "Estat" 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:" msgctxt "field:contract,write_date:"
msgid "Write Date" msgid "Write Date"
msgstr "Data modificació" msgstr "Data modificació"
@ -326,10 +182,6 @@ msgctxt "field:contract.line,description:"
msgid "Description" msgid "Description"
msgstr "Descripció" msgstr "Descripció"
msgctxt "field:contract.line,end_date:"
msgid "End Date"
msgstr "Data final"
msgctxt "field:contract.line,id:" msgctxt "field:contract.line,id:"
msgid "ID" msgid "ID"
msgstr "ID" msgstr "ID"
@ -350,14 +202,6 @@ msgctxt "field:contract.line,service:"
msgid "Service" msgid "Service"
msgstr "Serveis" 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:" msgctxt "field:contract.line,unit_price:"
msgid "Unit Price" msgid "Unit Price"
msgstr "Preu unitat" msgstr "Preu unitat"
@ -370,46 +214,6 @@ msgctxt "field:contract.line,write_uid:"
msgid "Write User" msgid "Write User"
msgstr "Usuari modificació" 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:" msgctxt "field:contract.service,create_date:"
msgid "Create Date" msgid "Create Date"
msgstr "Data creació" msgstr "Data creació"
@ -438,18 +242,6 @@ msgctxt "field:contract.service,rec_name:"
msgid "Name" msgid "Name"
msgstr "Nom" 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:" msgctxt "field:contract.service,write_date:"
msgid "Write Date" msgid "Write Date"
msgstr "Data modificació" msgstr "Data modificació"
@ -458,16 +250,6 @@ msgctxt "field:contract.service,write_uid:"
msgid "Write User" msgid "Write User"
msgstr "Usuari modificació" 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:" msgctxt "model:contract,name:"
msgid "Contract" msgid "Contract"
msgstr "Contracte" msgstr "Contracte"
@ -497,7 +279,7 @@ msgid "Contract"
msgstr "Contractes" msgstr "Contractes"
msgctxt "model:ir.action,name:act_contract_configuration_form" msgctxt "model:ir.action,name:act_contract_configuration_form"
msgid "Contract Configuration" msgid "Contracts Configuration"
msgstr "Configuració de contractes" msgstr "Configuració de contractes"
msgctxt "model:ir.action,name:act_contract_consumption" msgctxt "model:ir.action,name:act_contract_consumption"
@ -509,7 +291,7 @@ msgid "Contract Line"
msgstr "Línia de contracte" msgstr "Línia de contracte"
msgctxt "model:ir.action,name:act_contract_service" msgctxt "model:ir.action,name:act_contract_service"
msgid "Services" msgid "Contract Service"
msgstr "Servei de contracte" msgstr "Servei de contracte"
msgctxt "model:ir.action,name:wizard_create_consumptions" msgctxt "model:ir.action,name:wizard_create_consumptions"
@ -555,7 +337,7 @@ msgid "Contract"
msgstr "Contracte" msgstr "Contracte"
msgctxt "model:ir.ui.menu,name:menu_contract_configuration" msgctxt "model:ir.ui.menu,name:menu_contract_configuration"
msgid "Contract Configuration" msgid "Contracts Configuration"
msgstr "Configuració de contractes" msgstr "Configuració de contractes"
msgctxt "model:ir.ui.menu,name:menu_contract_consumption" msgctxt "model:ir.ui.menu,name:menu_contract_consumption"
@ -567,7 +349,7 @@ msgid "Contract"
msgstr "Contracte" msgstr "Contracte"
msgctxt "model:ir.ui.menu,name:menu_contract_service" msgctxt "model:ir.ui.menu,name:menu_contract_service"
msgid "Services" msgid "Contract Service"
msgstr "Servei de contracte" msgstr "Servei de contracte"
msgctxt "model:ir.ui.menu,name:menu_create_consumptions" msgctxt "model:ir.ui.menu,name:menu_create_consumptions"
@ -575,33 +357,21 @@ msgid "Create Consumptions"
msgstr "Crea consums" msgstr "Crea consums"
msgctxt "model:res.group,name:group_contract" msgctxt "model:res.group,name:group_contract"
msgid "Contract User" msgid "Contract"
msgstr "Contractes" msgstr "Contractes"
msgctxt "model:res.group,name:group_contract_admin" msgctxt "model:res.group,name:group_contract_admin"
msgid "Contract Administrator" msgid "Contract Administration"
msgstr "Administració de contractes" msgstr "Administració de contractes"
msgctxt "selection:contract,freq:" msgctxt "selection:contract,freq:"
msgid "Daily" msgid "Daily"
msgstr "Diàriament" 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:" msgctxt "selection:contract,freq:"
msgid "Monthly" msgid "Monthly"
msgstr "Mensualment" msgstr "Mensualment"
msgctxt "selection:contract,freq:"
msgid "Secondly"
msgstr "Cada segon"
msgctxt "selection:contract,freq:" msgctxt "selection:contract,freq:"
msgid "Weekly" msgid "Weekly"
msgstr "Setmanalment" msgstr "Setmanalment"
@ -622,70 +392,14 @@ msgctxt "selection:contract,state:"
msgid "Validated" msgid "Validated"
msgstr "Validat" 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:" msgctxt "selection:contract.service,freq:"
msgid "Daily" msgid "Daily"
msgstr "Diàriament" 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:" msgctxt "selection:contract.service,freq:"
msgid "Monthly" msgid "Monthly"
msgstr "Mensualment" msgstr "Mensualment"
msgctxt "selection:contract.service,freq:"
msgid "Secondly"
msgstr "Cada segon"
msgctxt "selection:contract.service,freq:" msgctxt "selection:contract.service,freq:"
msgid "Weekly" msgid "Weekly"
msgstr "Setmanalment" msgstr "Setmanalment"
@ -694,38 +408,6 @@ msgctxt "selection:contract.service,freq:"
msgid "Yearly" msgid "Yearly"
msgstr "Anualment" 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:" msgctxt "view:contract.configuration:"
msgid "Contract Configuration" msgid "Contract Configuration"
msgstr "Configuració de contractes" msgstr "Configuració de contractes"

View File

@ -18,146 +18,14 @@ msgstr ""
"Falta la cuenta de ingresos par el producto \"%(product)s\" de la linea de " "Falta la cuenta de ingresos par el producto \"%(product)s\" de la linea de "
"contracto \"%(contract_line)s\"." "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:" msgctxt "error:contract:"
msgid "Invalid \"By Day\" in recurrence rule \"%s\"" msgid "Contract %(contract)s with invalid date \"%(date)s\""
msgstr "El campo \"por dia\" de la regla de recurrencia \"%s\" no es correcto." msgstr "El contracto %(contract)s tiene fecha de comienzo inválida \"%(date)s\""
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"
msgctxt "field:contract,company:" msgctxt "field:contract,company:"
msgid "Company" msgid "Company"
msgstr "Empresa" msgstr "Empresa"
msgctxt "field:contract,count:"
msgid "Count"
msgstr "Contador"
msgctxt "field:contract,create_date:" msgctxt "field:contract,create_date:"
msgid "Create Date" msgid "Create Date"
msgstr "Fecha creación" msgstr "Fecha creación"
@ -210,22 +78,14 @@ msgctxt "field:contract,start_date:"
msgid "Start Date" msgid "Start Date"
msgstr "Fecha inicial" msgstr "Fecha inicial"
msgctxt "field:contract,start_period_date:"
msgid "Start Period Date"
msgstr "Fecha inicio de período"
msgctxt "field:contract,state:" msgctxt "field:contract,state:"
msgid "State" msgid "State"
msgstr "Estado" 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:" msgctxt "field:contract,write_date:"
msgid "Write Date" msgid "Write Date"
msgstr "Fecha modificación" msgstr "Fecha modificación"
@ -278,10 +138,18 @@ msgctxt "field:contract.consumption,end_date:"
msgid "End Date" msgid "End Date"
msgstr "Fecha finalización" 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:" msgctxt "field:contract.consumption,id:"
msgid "ID" msgid "ID"
msgstr "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:" msgctxt "field:contract.consumption,invoice_date:"
msgid "Invoice Date" msgid "Invoice Date"
msgstr "Fecha factura" msgstr "Fecha factura"
@ -330,10 +198,6 @@ msgctxt "field:contract.line,description:"
msgid "Description" msgid "Description"
msgstr "Descripción" msgstr "Descripción"
msgctxt "field:contract.line,end_date:"
msgid "End Date"
msgstr "Fecha final"
msgctxt "field:contract.line,id:" msgctxt "field:contract.line,id:"
msgid "ID" msgid "ID"
msgstr "ID" msgstr "ID"
@ -342,6 +206,10 @@ msgctxt "field:contract.line,last_consumption_date:"
msgid "Last Consumption Date" msgid "Last Consumption Date"
msgstr "Fecha último consumo" 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:" msgctxt "field:contract.line,name:"
msgid "Name" msgid "Name"
msgstr "Nombre" msgstr "Nombre"
@ -354,14 +222,6 @@ msgctxt "field:contract.line,service:"
msgid "Service" msgid "Service"
msgstr "Servicios" 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:" msgctxt "field:contract.line,unit_price:"
msgid "Unit Price" msgid "Unit Price"
msgstr "Precio unidad" msgstr "Precio unidad"
@ -374,46 +234,6 @@ msgctxt "field:contract.line,write_uid:"
msgid "Write User" msgid "Write User"
msgstr "Usuario modificación" 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:" msgctxt "field:contract.service,create_date:"
msgid "Create Date" msgid "Create Date"
msgstr "Fecha creación" msgstr "Fecha creación"
@ -442,18 +262,6 @@ msgctxt "field:contract.service,rec_name:"
msgid "Name" msgid "Name"
msgstr "Nombre" 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:" msgctxt "field:contract.service,write_date:"
msgid "Write Date" msgid "Write Date"
msgstr "Fecha modificación" msgstr "Fecha modificación"
@ -462,14 +270,6 @@ msgctxt "field:contract.service,write_uid:"
msgid "Write User" msgid "Write User"
msgstr "Usuario modificación" 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:" msgctxt "model:contract,name:"
msgid "Contract" msgid "Contract"
msgstr "Contrato" msgstr "Contrato"
@ -499,7 +299,7 @@ msgid "Contract"
msgstr "Contratos" msgstr "Contratos"
msgctxt "model:ir.action,name:act_contract_configuration_form" msgctxt "model:ir.action,name:act_contract_configuration_form"
msgid "Contract Configuration" msgid "Contracts Configuration"
msgstr "Configuración de contratos" msgstr "Configuración de contratos"
msgctxt "model:ir.action,name:act_contract_consumption" msgctxt "model:ir.action,name:act_contract_consumption"
@ -511,7 +311,7 @@ msgid "Contract Line"
msgstr "Línea de contrato" msgstr "Línea de contrato"
msgctxt "model:ir.action,name:act_contract_service" msgctxt "model:ir.action,name:act_contract_service"
msgid "Services" msgid "Contract Service"
msgstr "Servicio de contrato" msgstr "Servicio de contrato"
msgctxt "model:ir.action,name:wizard_create_consumptions" msgctxt "model:ir.action,name:wizard_create_consumptions"
@ -557,7 +357,7 @@ msgid "Contract"
msgstr "Contrato" msgstr "Contrato"
msgctxt "model:ir.ui.menu,name:menu_contract_configuration" msgctxt "model:ir.ui.menu,name:menu_contract_configuration"
msgid "Contract Configuration" msgid "Contracts Configuration"
msgstr "Configuración de contratos" msgstr "Configuración de contratos"
msgctxt "model:ir.ui.menu,name:menu_contract_consumption" msgctxt "model:ir.ui.menu,name:menu_contract_consumption"
@ -569,7 +369,7 @@ msgid "Contract"
msgstr "Contratos" msgstr "Contratos"
msgctxt "model:ir.ui.menu,name:menu_contract_service" msgctxt "model:ir.ui.menu,name:menu_contract_service"
msgid "Services" msgid "Contract Service"
msgstr "Servicio de contrato" msgstr "Servicio de contrato"
msgctxt "model:ir.ui.menu,name:menu_create_consumptions" msgctxt "model:ir.ui.menu,name:menu_create_consumptions"
@ -577,32 +377,24 @@ msgid "Create Consumptions"
msgstr "Crear consumos" msgstr "Crear consumos"
msgctxt "model:res.group,name:group_contract" msgctxt "model:res.group,name:group_contract"
msgid "Contract User" msgid "Contract"
msgstr "Contratos" msgstr "Contratos"
msgctxt "model:res.group,name:group_contract_admin" msgctxt "model:res.group,name:group_contract_admin"
msgid "Contract Administrator" msgid "Contract Administration"
msgstr "Administración de contratos" msgstr "Administración de contratos"
msgctxt "selection:contract,freq:" msgctxt "selection:contract,freq:"
msgid "Daily" msgid "Daily"
msgstr "Diariamente" msgstr "Diariamente"
msgctxt "selection:contract,freq:"
msgid "Hourly"
msgstr "Cada hora"
msgctxt "selection:contract,freq:"
msgid "Minutely"
msgstr "Cada minuto"
msgctxt "selection:contract,freq:" msgctxt "selection:contract,freq:"
msgid "Monthly" msgid "Monthly"
msgstr "Mensualmente" msgstr "Mensualmente"
msgctxt "selection:contract,freq:" msgctxt "selection:contract,freq:"
msgid "Secondly" msgid "None"
msgstr "Cada segundo" msgstr "Ninguno"
msgctxt "selection:contract,freq:" msgctxt "selection:contract,freq:"
msgid "Weekly" msgid "Weekly"
@ -624,69 +416,17 @@ msgctxt "selection:contract,state:"
msgid "Validated" msgid "Validated"
msgstr "Valido" 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:" msgctxt "selection:contract.service,freq:"
msgid "Daily" msgid "Daily"
msgstr "Diariamente" 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:" msgctxt "selection:contract.service,freq:"
msgid "Monthly" msgid "Monthly"
msgstr "Mensualmente" msgstr "Mensualmente"
msgctxt "selection:contract.service,freq:" msgctxt "selection:contract.service,freq:"
msgid "Secondly" msgid "None"
msgstr "Cada segundo" msgstr "Ninguno"
msgctxt "selection:contract.service,freq:" msgctxt "selection:contract.service,freq:"
msgid "Weekly" msgid "Weekly"
@ -696,38 +436,6 @@ msgctxt "selection:contract.service,freq:"
msgid "Yearly" msgid "Yearly"
msgstr "Anualmente" 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:" msgctxt "view:contract.configuration:"
msgid "Contract Configuration" msgid "Contract Configuration"
msgstr "Configuración de contratos" msgstr "Configuración de contratos"

View File

@ -61,8 +61,8 @@ setup(name='%s_%s' % (PREFIX, MODULE),
'trytond.modules.%s.tests' % MODULE, 'trytond.modules.%s.tests' % MODULE,
], ],
package_data={ package_data={
'trytond.modules.%s' % MODULE: (info.get('xml', []) 'trytond.modules.%s' % MODULE: (info.get('xml', []) +
+ ['tryton.cfg', 'locale/*.po', 'tests/*.rst']), ['tryton.cfg', 'locale/*.po', 'tests/*.rst']),
}, },
classifiers=[ classifiers=[
'Development Status :: 5 - Production/Stable', 'Development Status :: 5 - Production/Stable',

View File

@ -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:: Imports::
>>> import datetime >>> import datetime
@ -183,51 +191,50 @@ Create monthly service::
>>> Service = Model.get('contract.service') >>> Service = Model.get('contract.service')
>>> service = Service() >>> service = Service()
>>> service.product = product >>> service.product = product
>>> service.freq = 'monthly' >>> service.freq = None
>>> service.save() >>> service.save()
Create a contract:: Create a contract::
>>> Contract = Model.get('contract') >>> Contract = Model.get('contract')
>>> contract = Contract() >>> contract = Contract()
>>> contract.party = party >>> 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' >>> contract.freq = 'monthly'
>>> line = contract.lines.new() >>> line = contract.lines.new()
>>> line.start_date == today + relativedelta(day=1)
True
>>> line.service = service >>> line.service = service
>>> line.unit_price >>> line.unit_price
Decimal('40') Decimal('40')
>>> contract.click('validate_contract') >>> contract.click('validate_contract')
>>> contract.state >>> contract.state
u'validated' u'validated'
>>> contract_line, = contract.lines >>> contract.save()
>>> contract_line.state >>> contract.reload()
u'active'
Generate consumed lines:: Generate consumed lines::
>>> create_consumptions = Wizard('contract.create_consumptions') >>> 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') >>> create_consumptions.execute('create_consumptions')
>>> Consumption = Model.get('contract.consumption') >>> Consumption = Model.get('contract.consumption')
>>> consumption, = Consumption.find([]) >>> 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 True
>>> consumption.invoice_line
Generate invoice for consumed lines:: Generate invoice for consumed lines::
>>> consumption.invoice_date = datetime.date.today()
>>> consumption.click('invoice') >>> consumption.click('invoice')
>>> invoice = consumption.invoice_line.invoice >>> invoice = consumption.invoice_line.invoice
>>> invoice.type >>> invoice.type
u'out_invoice' u'out_invoice'
>>> invoice.party == party >>> invoice.party == party
True True
>>> invoice.invoice_date == datetime.date.today()
True
>>> invoice.untaxed_amount >>> invoice.untaxed_amount
Decimal('40.00') Decimal('40.00')
>>> invoice.tax_amount >>> invoice.tax_amount
@ -236,5 +243,6 @@ Generate invoice for consumed lines::
Decimal('44.00') Decimal('44.00')
>>> consumption.invoice_line.product == product >>> consumption.invoice_line.product == product
True True
>>> consumption.invoice_date == invoice.invoice_date
True

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -26,7 +26,21 @@ def suite():
suite = trytond.tests.test_tryton.suite() suite = trytond.tests.test_tryton.suite()
suite.addTests(unittest.TestLoader().loadTestsFromTestCase( suite.addTests(unittest.TestLoader().loadTestsFromTestCase(
TestContractCase)) 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', setUp=doctest_setup, tearDown=doctest_teardown, encoding='utf-8',
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)) 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 return suite

View File

@ -7,5 +7,7 @@ this repository contains the full copyright notices and license terms. -->
<field name="end_date"/> <field name="end_date"/>
<field name="invoice_date"/> <field name="invoice_date"/>
<field name="invoice_line"/> <field name="invoice_line"/>
<field name="init_period_date"/>
<field name="end_period_date"/>
<button name="invoice" string="Invoice" tree_invisible="1"/> <button name="invoice" string="Invoice" tree_invisible="1"/>
</tree> </tree>

View File

@ -10,50 +10,21 @@
<field name="party"/> <field name="party"/>
<label name="currency"/> <label name="currency"/>
<field name="currency"/> <field name="currency"/>
<label name="start_period_date"/>
<field name="start_period_date"/>
<label name="first_invoice_date"/>
<field name="first_invoice_date"/>
<label name="start_date"/> <label name="start_date"/>
<field name="start_date"/> <field name="start_date"/>
<label name="end_date"/> <label name="end_date"/>
<field name="end_date"/> <field name="end_date"/>
<label name="first_invoice_date"/> <separator id="recurrence" string="Invoice recurrence" colspan="4"/>
<field name="first_invoice_date"/> <label name="freq"/>
<notebook> <field name="freq"/>
<page id="recurrence" string="Invoice recurrence"> <label name="interval"/>
<label name="freq"/> <field name="interval"/>
<field name="freq"/> <newline/>
<label name="interval"/> <field name="lines" colspan="4"/>
<field name="interval"/>
<label name="count"/>
<field name="count"/>
<newline/>
<label name="until"/>
<field name="until"/>
<label name="until_date"/>
<field name="until_date"/>
<label name="byday"/>
<field name="byday"/>
<label name="byhour"/>
<field name="byhour"/>
<label name="byminute"/>
<field name="byminute"/>
<label name="bymonth"/>
<field name="bymonth"/>
<label name="bymonthday"/>
<field name="bymonthday"/>
<label name="bysecond"/>
<field name="bysecond"/>
<label name="bysetpos"/>
<field name="bysetpos"/>
<label name="byweekno"/>
<field name="byweekno"/>
<label name="byyearday"/>
<field name="byyearday"/>
<label name="wkst"/>
<field name="wkst"/>
</page>
<page name="lines">
<field name="lines" colspan="4"/>
</page>
</notebook>
<label name="state"/> <label name="state"/>
<field name="state"/> <field name="state"/>
<group id="buttons" colspan="2"> <group id="buttons" colspan="2">

View File

@ -10,16 +10,6 @@ this repository contains the full copyright notices and license terms. -->
<field name="name"/> <field name="name"/>
<label name="unit_price"/> <label name="unit_price"/>
<field name="unit_price"/> <field name="unit_price"/>
<label name="start_date"/>
<field name="start_date"/>
<label name="end_date"/>
<field name="end_date"/>
<separator name="description" colspan="4"/> <separator name="description" colspan="4"/>
<field name="description" colspan="4"/> <field name="description" colspan="4"/>
<label name="state"/>
<field name="state"/>
<group id="buttons" colspan="2">
<button name="active" string="Active"/>
<button name="hold" string="Hold"/>
</group>
</form> </form>

View File

@ -4,8 +4,5 @@ this repository contains the full copyright notices and license terms. -->
<tree string="Contract Line"> <tree string="Contract Line">
<field name="contract"/> <field name="contract"/>
<field name="service"/> <field name="service"/>
<field name="start_date"/>
<field name="end_date"/>
<field name="unit_price"/> <field name="unit_price"/>
<field name="state"/>
</tree> </tree>

View File

@ -9,31 +9,5 @@ this repository contains the full copyright notices and license terms. -->
<field name="freq"/> <field name="freq"/>
<label name="interval"/> <label name="interval"/>
<field name="interval"/> <field name="interval"/>
<label name="count"/>
<field name="count"/>
<newline/> <newline/>
<label name="until"/>
<field name="until"/>
<label name="until_date"/>
<field name="until_date"/>
<label name="byday"/>
<field name="byday"/>
<label name="byhour"/>
<field name="byhour"/>
<label name="byminute"/>
<field name="byminute"/>
<label name="bymonth"/>
<field name="bymonth"/>
<label name="bymonthday"/>
<field name="bymonthday"/>
<label name="bysecond"/>
<field name="bysecond"/>
<label name="bysetpos"/>
<field name="bysetpos"/>
<label name="byweekno"/>
<field name="byweekno"/>
<label name="byyearday"/>
<field name="byyearday"/>
<label name="wkst"/>
<field name="wkst"/>
</form> </form>

View File

@ -4,6 +4,4 @@ this repository contains the full copyright notices and license terms. -->
<tree string="Contract Line Service"> <tree string="Contract Line Service">
<field name="product"/> <field name="product"/>
<field name="interval"/> <field name="interval"/>
<field name="until"/>
<field name="count"/>
</tree> </tree>

View File

@ -10,4 +10,7 @@ this repository contains the full copyright notices and license terms. -->
<field name="interval"/> <field name="interval"/>
<field name="freq"/> <field name="freq"/>
<field name="state"/> <field name="state"/>
<button name="draft" string="Draft" tree_invisible="1"/>
<button name="validate_contract" string="Validate" tree_invisible="1"/>
<button name="cancel" string="Cancel" tree_invisible="1"/>
</tree> </tree>

View File

@ -4,36 +4,4 @@
<form string="Contract Service"> <form string="Contract Service">
<label name="product"/> <label name="product"/>
<field name="product"/> <field name="product"/>
<newline/>
<label name="freq"/>
<field name="freq"/>
<label name="interval"/>
<field name="interval"/>
<label name="count"/>
<field name="count"/>
<newline/>
<label name="until"/>
<field name="until"/>
<label name="until_date"/>
<field name="until_date"/>
<label name="byday"/>
<field name="byday"/>
<label name="byhour"/>
<field name="byhour"/>
<label name="byminute"/>
<field name="byminute"/>
<label name="bymonth"/>
<field name="bymonth"/>
<label name="bymonthday"/>
<field name="bymonthday"/>
<label name="bysecond"/>
<field name="bysecond"/>
<label name="bysetpos"/>
<field name="bysetpos"/>
<label name="byweekno"/>
<field name="byweekno"/>
<label name="byyearday"/>
<field name="byyearday"/>
<label name="wkst"/>
<field name="wkst"/>
</form> </form>

View File

@ -3,7 +3,4 @@
copyright notices and license terms. --> copyright notices and license terms. -->
<tree string="Contract Service"> <tree string="Contract Service">
<field name="product"/> <field name="product"/>
<field name="freq"/>
<field name="interval"/>
<field name="count"/>
</tree> </tree>