Merge lp:~savoirfairelinux-openerp/openerp-isp/invoice_refactoring into lp:openerp-isp
- invoice_refactoring
- Merge into 7.0
Status: | Needs review |
---|---|
Proposed branch: | lp:~savoirfairelinux-openerp/openerp-isp/invoice_refactoring |
Merge into: | lp:openerp-isp |
Diff against target: |
6437 lines (+4500/-1134) 34 files modified
contract_isp/contract.py (+219/-75) contract_isp/contract_isp_view.xml (+80/-74) contract_isp/i18n/contract_isp.pot (+278/-184) contract_isp/i18n/fr.po (+338/-0) contract_isp/wizard/activate_contract_service.py (+141/-67) contract_isp/wizard/activate_contract_service.xml (+70/-35) contract_isp_automatic_invoicing/contract.py (+6/-2) contract_isp_automatic_invoicing/i18n/contract_isp_automatic_invoicing.pot (+24/-0) contract_isp_automatic_invoicing/i18n/fr.po (+24/-0) contract_isp_invoice/__init__.py (+5/-2) contract_isp_invoice/contract.py (+590/-294) contract_isp_invoice/contract_isp_invoice_view.xml (+1/-2) contract_isp_invoice/i18n/contract_isp_invoice.pot (+217/-25) contract_isp_invoice/i18n/fr.po (+291/-0) contract_isp_invoice/invoice.py (+40/-0) contract_isp_invoice/tests/__init__.py (+33/-0) contract_isp_invoice/tests/common.py (+142/-0) contract_isp_invoice/tests/test_deactivate.py (+165/-0) contract_isp_invoice/tests/test_prorata.py (+179/-0) contract_isp_invoice/tests/test_reseller.py (+70/-0) contract_isp_invoice/wizard/activate_contract_service.py (+30/-22) contract_isp_invoice/wizard/close_contract.py (+10/-7) contract_isp_package_configurator/__init__.py (+7/-3) contract_isp_package_configurator/__openerp__.py (+1/-0) contract_isp_package_configurator/account_analytic.py (+61/-0) contract_isp_package_configurator/contract.py (+35/-0) contract_isp_package_configurator/contract_isp_package_configurator_view.xml (+40/-22) contract_isp_package_configurator/i18n/contract_isp_package_configurator.pot (+343/-0) contract_isp_package_configurator/i18n/fr.po (+346/-0) contract_isp_package_configurator/security/groups.xml (+23/-0) contract_isp_package_configurator/wizard/package_configurator.py (+260/-164) contract_isp_package_configurator/wizard/package_configurator.xml (+286/-156) product_dependencies/i18n/fr.po (+72/-0) product_dependencies/i18n/product_dependecies.pot (+73/-0) |
To merge this branch: | bzr merge lp:~savoirfairelinux-openerp/openerp-isp/invoice_refactoring |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
OpenERP ISP Core Editors | Pending | ||
Review via email: mp+226031@code.launchpad.net |
Commit message
Description of the change
* Split the big invoice routine into 3 separate methods.
* Minor adjustments and code clean-up.
- 32. By Joao Alfredo Gama Batista
-
[FIX] Fix error in voucher creation
- 33. By Joao Alfredo Gama Batista
-
[FIX] Fix typo in action context
- 34. By Vincent Vinet
-
pep8 + add deactivation date on contracts
- 35. By Vincent Vinet
-
flake cleanup
- 36. By Vincent Vinet
-
make sure we assign account invoice lines
- 37. By Vincent Vinet
-
add prorata invoicing tests
- 38. By Vincent Vinet
-
refac tests to allow deactivate tests, complete activate tests and pass them
- 39. By Vincent Vinet
-
fix refunds
- 40. By Vincent Vinet
-
create prorata invoices on deactivation
- 41. By Vincent Vinet
-
remove debug print
- 42. By Vincent Vinet
-
remove seemingly unused field
- 43. By Vincent Vinet
-
also remove from view ¬¬
- 44. By Vincent Vinet
-
remove serial assignment from packager configurator, move into 3 simple wizards
- 45. By Vincent Vinet
-
merge Marc Cassuto 2014-09-12 contract_isp
- 46. By Vincent Vinet
-
add groups and states handling to show add/reserve/return buttons
- 47. By Vincent Vinet
-
test that reseller prorata invoice is assigned correctly
- 48. By Vincent Vinet
-
fix tests to run in oe test env
- 49. By Marc Cassuto (SFL)
-
contract_
isp_package_ configurator : Add fr translation - 50. By Marc Cassuto (SFL)
-
contract_
isp_package_ configurator : Add fr translation - 51. By Marc Cassuto (SFL)
-
product_
dependencies - Add fr translation - 52. By Marc Cassuto (SFL)
-
contract_isp - Add fr translation
- 53. By Vincent Vinet
-
refac to allow integrating class of service better, pep8 cleanup
- 54. By Marc Cassuto (SFL)
-
contract_
isp_invoice - Add fr translation - 55. By Marc Cassuto (SFL)
-
Merge diverted branches
- 56. By Vincent Vinet
-
do not show reserve/return buttons for non-stockable products
- 57. By Vincent Vinet
-
restrict production lots to available ones in add/replace wizards
- 58. By Vincent Vinet
-
fix serial number checking
- 59. By Vincent Vinet
-
disallow activation dates in the future
- 60. By Vincent Vinet
-
log reserve/
exchange/ return to contract - 61. By Marc Cassuto (SFL)
-
Update .pot files and fr translations for all modules
- 62. By Marc Cassuto (SFL)
-
contract_
isp_package_ configurator - Tried to get the translation from the wizard - 63. By Vincent Vinet
-
use the right account and journal to create vouchers
- 64. By Vincent Vinet
-
prevent rounding a None currency
- 65. By Vincent Vinet
-
prevent double billing exception lines and one time lines
- 66. By Vincent Vinet
-
allow searching non-prorata invoice dates
- 67. By Vincent Vinet
-
in package configurator, call contract.service onchange product id to get duration before create
- 68. By Vincent Vinet
-
specify source process when creating invoices
- 69. By Vincent Vinet
-
actually use the source_process
- 70. By Vincent Vinet
-
prevent error when getting invoice dates for empty ids
- 71. By Vincent Vinet
-
wrong period id when confirming voucher
- 72. By Vincent Vinet
-
do not bill activation multiple times
- 73. By Vincent Vinet
-
revert checking activation line status on subscription
- 74. By Vincent Vinet
-
clean date_interval/
format_ interval usage - 75. By Vincent Vinet
-
default date format for format_interval
- 76. By Vincent Vinet
-
use price, not list price, for analytic lines
- 77. By Vincent Vinet
-
only create prorata lines on activation, allow passing in date strings for operation date, do not filter already created
- 78. By Vincent Vinet
-
do not show line_cr/dr_ids in the payment voucher launched from contract
- 79. By Marc Cassuto (SFL)
-
contract_
isp_invoice - change 'Create voucher' button name to 'Create Initial Invoice' - 80. By Marc Cassuto (SFL)
-
contract_
isp_invoice - change 'Create voucher' button name to 'Create Initial Invoice' - 81. By Vincent Vinet
-
allow passing operation_date in str form
- 82. By Vincent Vinet
-
do not multiply total price by quantity when creating analytic lines
- 83. By Vincent Vinet
-
revert r78 as it hides payments at too many places
- 84. By Vincent Vinet
-
show smarter error on account blank pricelist voucher creation
- 85. By Vincent Vinet
-
create recurrent invoices at invoice day
- 86. By Vincent Vinet
-
do not allow deactivate in the future
- 87. By Vincent Vinet
-
use partner fiscal position to calculate taxes on default voucher amount
- 88. By Vincent Vinet
-
do not create invoices grouped by journal type for contracts
- 89. By Vincent Vinet
-
copy context to avoid side effects in batch invoice creation
- 90. By Vincent Vinet
-
bill onetime services in recurrent billing
Unmerged revisions
- 90. By Vincent Vinet
-
bill onetime services in recurrent billing
- 89. By Vincent Vinet
-
copy context to avoid side effects in batch invoice creation
- 88. By Vincent Vinet
-
do not create invoices grouped by journal type for contracts
- 87. By Vincent Vinet
-
use partner fiscal position to calculate taxes on default voucher amount
- 86. By Vincent Vinet
-
do not allow deactivate in the future
- 85. By Vincent Vinet
-
create recurrent invoices at invoice day
- 84. By Vincent Vinet
-
show smarter error on account blank pricelist voucher creation
- 83. By Vincent Vinet
-
revert r78 as it hides payments at too many places
- 82. By Vincent Vinet
-
do not multiply total price by quantity when creating analytic lines
- 81. By Vincent Vinet
-
allow passing operation_date in str form
Preview Diff
1 | === modified file 'contract_isp/contract.py' |
2 | --- contract_isp/contract.py 2013-11-07 15:10:04 +0000 |
3 | +++ contract_isp/contract.py 2014-11-24 15:05:14 +0000 |
4 | @@ -21,14 +21,19 @@ |
5 | ############################################################################## |
6 | |
7 | import logging |
8 | +_logger = logging.getLogger(__name__) |
9 | import calendar |
10 | import datetime |
11 | + |
12 | import openerp.addons.decimal_precision as dp |
13 | from openerp.osv import orm, fields |
14 | -from openerp.report import report_sxw |
15 | -from openerp.tools import convert |
16 | +from openerp.tools import SUPERUSER_ID, DEFAULT_SERVER_DATE_FORMAT |
17 | from openerp.tools.translate import _ |
18 | |
19 | +LINE_TYPE_EXCEPTION = 'x' |
20 | +LINE_TYPE_RECURRENT = 'r' |
21 | +LINE_TYPE_ONETIME = 'o' |
22 | + |
23 | |
24 | def add_months(sourcedate, months): |
25 | month = sourcedate.month - 1 + months |
26 | @@ -38,7 +43,7 @@ |
27 | return datetime.date(year, month, day) |
28 | |
29 | |
30 | -def date_interval(start_date, month_end=True, date_format='%m/%d/%Y'): |
31 | +def date_interval(start_date, month_end=True): |
32 | if month_end: |
33 | end_date = datetime.date(start_date.year, |
34 | start_date.month, |
35 | @@ -47,10 +52,12 @@ |
36 | else: |
37 | end_date = add_months(start_date, 1) - datetime.timedelta(days=1) |
38 | |
39 | - interval = '(%s - %s)' % (start_date.strftime(date_format), |
40 | - end_date.strftime(date_format)) |
41 | - |
42 | - return interval |
43 | + return start_date, end_date |
44 | + |
45 | + |
46 | +def format_interval(start, end, date_format=DEFAULT_SERVER_DATE_FORMAT): |
47 | + return '(%s - %s)' % (start.strftime(date_format), |
48 | + end.strftime(date_format)) |
49 | |
50 | |
51 | class res_company(orm.Model): |
52 | @@ -105,10 +112,11 @@ |
53 | _inherit = 'product.product' |
54 | |
55 | _columns = { |
56 | - 'analytic_line_type': fields.selection((('r', 'Recurrent'), |
57 | - ('x', 'Exception'), |
58 | - ('o', 'One time')), |
59 | - 'Type in contract'), |
60 | + 'analytic_line_type': fields.selection(((LINE_TYPE_RECURRENT, 'Recurrent'), |
61 | + (LINE_TYPE_EXCEPTION, 'Exception'), |
62 | + (LINE_TYPE_ONETIME, 'One time')), |
63 | + 'Type in contract', |
64 | + required=True), |
65 | 'require_activation': fields.boolean('Require activation') |
66 | } |
67 | |
68 | @@ -117,7 +125,6 @@ |
69 | _name = 'contract.service' |
70 | |
71 | def _get_product_price(self, cr, uid, ids, field_name, arg, context=None): |
72 | - product_obj = self.pool.get('product.product') |
73 | product_pricelist_obj = self.pool.get('product.pricelist') |
74 | partner_id = self.browse( |
75 | cr, uid, ids[0], |
76 | @@ -150,6 +157,8 @@ |
77 | |
78 | _columns = { |
79 | 'activation_date': fields.datetime('Activation date'), |
80 | + 'billed_to_date': fields.date('Billed until date'), |
81 | + 'deactivation_date': fields.datetime('Deactivation date'), |
82 | 'duration': fields.integer('Duration'), |
83 | 'product_id': fields.many2one('product.product', |
84 | 'Product', |
85 | @@ -159,10 +168,12 @@ |
86 | digits_compute=dp.get_precision('Product Unit of Measure')), |
87 | 'category_id': fields.many2one('product.category', 'Product Category'), |
88 | 'name': fields.char('Description', size=64), |
89 | - 'analytic_line_type': fields.selection((('r', 'Recurrent'), |
90 | - ('x', 'Exception'), |
91 | - ('o', 'One time')), |
92 | - 'Type'), |
93 | + 'analytic_line_type': fields.selection( |
94 | + ((LINE_TYPE_RECURRENT, 'Recurrent'), |
95 | + (LINE_TYPE_EXCEPTION, 'Exception'), |
96 | + (LINE_TYPE_ONETIME, 'One time')), |
97 | + 'Type'), |
98 | + # XXX Should this be a function based on product.product? |
99 | 'require_activation': fields.boolean('Require activation'), |
100 | 'account_id': fields.many2one('account.analytic.account', 'Contract'), |
101 | 'unit_price': fields.function( |
102 | @@ -201,7 +212,7 @@ |
103 | ret['value']['require_activation'] = product.require_activation |
104 | ret['value']['category_id'] = product.categ_id.id |
105 | ret['value']['unit_price'] = product.list_price |
106 | - if product.analytic_line_type in ('r', 'o'): |
107 | + if product.analytic_line_type == LINE_TYPE_RECURRENT: |
108 | ret['value']['duration'] = 0 |
109 | else: |
110 | ret['value']['duration'] = 1 |
111 | @@ -215,13 +226,63 @@ |
112 | |
113 | return ret |
114 | |
115 | + def _prorata_rate(self, days_used, days_in_month): |
116 | + """ Returns a rate to compute prorata invoices. |
117 | + Current method is days_used / days_in_month, rounded DOWN |
118 | + to 2 digits |
119 | + """ |
120 | + return (100 * days_used / days_in_month) / 100.0 |
121 | + |
122 | + def _get_prorata_interval_rate(self, cr, uid, change_date, context=None): |
123 | + """ Get the prorata interval and price rate. |
124 | + |
125 | + Returns a tuple (start_date, end_date, price percent) |
126 | + """ |
127 | + month_days = calendar.monthrange(change_date.year, |
128 | + change_date.month)[1] |
129 | + start_date = add_months(change_date, 1) |
130 | + end_date = start_date.replace(day=month_days) |
131 | + used_days = month_days - change_date.day |
132 | + ptx = self._prorata_rate(used_days, month_days) |
133 | + |
134 | + return start_date, end_date, ptx |
135 | + |
136 | + def _get_prorata_interval_rate_deactivate(self, cr, uid, change_date, |
137 | + context=None): |
138 | + start_date, end_date, ptx = self._get_prorata_interval_rate( |
139 | + cr, uid, change_date, context=context) |
140 | + ptx = ptx * -1 |
141 | + return start_date, end_date, ptx |
142 | + |
143 | + def _get_date_format(self, cr, uid, obj, context): |
144 | + partner_lang = obj.account_id.partner_id.lang |
145 | + res_lang_obj = self.pool['res.lang'] |
146 | + query = [ |
147 | + ('code', '=', partner_lang), |
148 | + ('active', '=', True) |
149 | + ] |
150 | + lang_id = res_lang_obj.search(cr, uid, query, context=context) |
151 | + if lang_id: |
152 | + date_format = res_lang_obj.browse(cr, uid, |
153 | + lang_id[0], |
154 | + context=context).date_format |
155 | + |
156 | + else: |
157 | + date_format = '%Y/%m/%d' |
158 | + return date_format |
159 | + |
160 | def create_analytic_line(self, cr, uid, ids, |
161 | mode='manual', |
162 | date=None, |
163 | context=None): |
164 | - |
165 | - if not date: |
166 | - date = datetime.date.today() |
167 | + context = context or {} |
168 | + if date is None: |
169 | + date = context.get("operation_date", datetime.date.today()) |
170 | + if not isinstance(date, datetime.date): |
171 | + date = datetime.datetime.strptime( |
172 | + date, |
173 | + DEFAULT_SERVER_DATE_FORMAT, |
174 | + ).date() |
175 | |
176 | if type(ids) is int: |
177 | ids = [ids] |
178 | @@ -229,72 +290,130 @@ |
179 | ret = [] |
180 | record = {} |
181 | next_month = None |
182 | - company_obj = self.pool.get('res.company') |
183 | - company_id = company_obj._company_default_get(cr, uid, context) |
184 | - company = company_obj.browse(cr, uid, company_id, context) |
185 | - |
186 | account_analytic_line_obj = self.pool.get('account.analytic.line') |
187 | for line in self.browse(cr, uid, ids, context): |
188 | - account_id = line.account_id.id |
189 | - partner_lang = line.account_id.partner_id.lang |
190 | - res_lang_obj = self.pool.get('res.lang') |
191 | - query = [ |
192 | - ('code', '=', partner_lang), |
193 | - ('active', '=', True) |
194 | - ] |
195 | - lang_id = res_lang_obj.search(cr, uid, query, context=context) |
196 | - if lang_id: |
197 | - date_format = res_lang_obj.browse(cr, uid, |
198 | - lang_id[0], |
199 | - context=context).date_format |
200 | - |
201 | - else: |
202 | - date_format = '%Y/%m/%d' |
203 | - |
204 | - if line.analytic_line_type == 'r': |
205 | + date_format = self._get_date_format(cr, uid, line, context=context) |
206 | + start, end = None, None |
207 | + |
208 | + amount = line.price |
209 | + |
210 | + if line.analytic_line_type == LINE_TYPE_RECURRENT: |
211 | if mode == 'prorata': |
212 | activation_date = date |
213 | - |
214 | - month_days = calendar.monthrange(activation_date.year, |
215 | - activation_date.month)[1] |
216 | - |
217 | - used_days = month_days - activation_date.day |
218 | - ptx = (100 * used_days / month_days) / 100.0 |
219 | - |
220 | - amount = line.product_id.list_price * ptx |
221 | - interval = date_interval(add_months(date, 1), |
222 | - True, |
223 | - date_format) |
224 | + start, end, ptx = self._get_prorata_interval_rate( |
225 | + cr, uid, |
226 | + activation_date, |
227 | + context=context, |
228 | + ) |
229 | + |
230 | + amount = amount * ptx |
231 | |
232 | elif mode == 'cron': |
233 | - amount = line.product_id.list_price |
234 | next_month = add_months(date, 1) |
235 | next_month = datetime.date( |
236 | next_month.year, |
237 | next_month.month, |
238 | 1) |
239 | - interval = date_interval(next_month, |
240 | - False, |
241 | - date_format) |
242 | + start, end = date_interval(next_month, False) |
243 | |
244 | elif mode == 'manual': |
245 | - amount = line.product_id.list_price |
246 | - interval = date_interval(date, False, date_format) |
247 | + start, end = date_interval(date, False) |
248 | |
249 | elif mode == 'subscription': |
250 | - amount = line.product_id.list_price |
251 | - interval = '' |
252 | + line.write({'activation_line_generated': True}) |
253 | |
254 | + if start and end: |
255 | + interval = format_interval(start, end, date_format) |
256 | else: |
257 | interval = '' |
258 | - amount = line.product_id.list_price |
259 | |
260 | general_account_id = line.product_id.property_account_expense.id \ |
261 | or line.product_id.categ_id.property_account_expense_categ.id |
262 | |
263 | record = { |
264 | 'name': ' '.join([line.product_id.name, |
265 | - True and line.name or '', |
266 | + line.name or '', |
267 | + interval]), |
268 | + 'amount': (amount * -1), |
269 | + 'account_id': line.account_id.id, |
270 | + 'user_id': uid, |
271 | + 'general_account_id': general_account_id, |
272 | + 'product_id': line.product_id.id, |
273 | + 'contract_service_id': line.id, |
274 | + 'to_invoice': 1, |
275 | + 'unit_amount': line.qty, |
276 | + 'is_prorata': mode == 'prorata', |
277 | + 'date': (next_month or date).strftime('%Y-%m-%d'), |
278 | + 'journal_id': 1 |
279 | + } |
280 | + |
281 | + if line.analytic_line_type == LINE_TYPE_EXCEPTION: |
282 | + new_duration = line.duration - 1 |
283 | + line.write({'duration': new_duration}) |
284 | + if new_duration <= 0: |
285 | + self.unlink(cr, SUPERUSER_ID, line.id) |
286 | + record['contract_service_id'] = False |
287 | + elif line.analytic_line_type == LINE_TYPE_ONETIME: |
288 | + if line.duration > 0: |
289 | + line.write({'duration': line.duration - 1}) |
290 | + else: |
291 | + # Do not create an already billed line |
292 | + continue |
293 | + |
294 | + if 'default_type' in context: |
295 | + context.pop('default_type') |
296 | + |
297 | + ret.append(account_analytic_line_obj.create(cr, uid, record, |
298 | + context)) |
299 | + return ret |
300 | + |
301 | + def create_refund_line(self, cr, uid, ids, |
302 | + mode='manual', |
303 | + date=None, |
304 | + context=None): |
305 | + context = context or {} |
306 | + if date is None: |
307 | + date = context.get("operation_date", datetime.date.today()) |
308 | + if not isinstance(date, datetime.date): |
309 | + date = datetime.datetime.strptime( |
310 | + date, |
311 | + DEFAULT_SERVER_DATE_FORMAT, |
312 | + ).date() |
313 | + |
314 | + if type(ids) is int: |
315 | + ids = [ids] |
316 | + |
317 | + ret = [] |
318 | + record = {} |
319 | + account_analytic_line_obj = self.pool.get('account.analytic.line') |
320 | + for line in self.browse(cr, uid, ids, context): |
321 | + if any((line.analytic_line_type != LINE_TYPE_RECURRENT, |
322 | + mode != "prorata")): |
323 | + # Not handled for now, only pro-rata deactivate |
324 | + continue |
325 | + |
326 | + date_format = self._get_date_format(cr, uid, line, context=context) |
327 | + |
328 | + deactivation_date = date |
329 | + start, end, ptx = self._get_prorata_interval_rate_deactivate( |
330 | + cr, uid, |
331 | + deactivation_date, |
332 | + context=context, |
333 | + ) |
334 | + |
335 | + amount = line.product_id.list_price * ptx |
336 | + |
337 | + interval = format_interval(start, end, |
338 | + date_format=date_format) |
339 | + |
340 | + general_account_id = ( |
341 | + line.product_id.property_account_expense.id or |
342 | + line.product_id.categ_id.property_account_expense_categ.id |
343 | + ) |
344 | + |
345 | + record = { |
346 | + 'name': ' '.join([line.product_id.name, |
347 | + line.name or '', |
348 | interval]), |
349 | 'amount': (amount * -1) * line.qty, |
350 | 'account_id': line.account_id.id, |
351 | @@ -305,16 +424,10 @@ |
352 | 'to_invoice': 1, |
353 | 'unit_amount': line.qty, |
354 | 'is_prorata': mode == 'prorata', |
355 | - 'date': next_month and next_month.strftime('%Y-%m-%d') or date.strftime('%Y-%m-%d'), |
356 | + 'date': date.strftime('%Y-%m-%d'), |
357 | 'journal_id': 1 |
358 | } |
359 | |
360 | - if line.analytic_line_type == 'x': |
361 | - line.write({'duration': line.duration - 1}) |
362 | - if line.duration <= 0: |
363 | - line.unlink() |
364 | - record['contract_service_id'] = False |
365 | - |
366 | if 'default_type' in context: |
367 | context.pop('default_type') |
368 | |
369 | @@ -330,10 +443,16 @@ |
370 | |
371 | return ret |
372 | |
373 | - def action_desactivate(self, cr, uid, ids, context): |
374 | - return self.write(cr, uid, ids, |
375 | - {'state': 'inactive', 'activation_date': None}, |
376 | - context) |
377 | + def action_deactivate(self, cr, uid, ids, context): |
378 | + values = {'state': 'inactive'} |
379 | + if "deactivation_date" in context: |
380 | + values["deactivation_date"] = context["deactivation_date"] |
381 | + else: |
382 | + values["deactivation_date"] = fields.datetime.now() |
383 | + |
384 | + self.write(cr, uid, ids, values, context) |
385 | + |
386 | + return True |
387 | |
388 | |
389 | class account_analytic_account(orm.Model): |
390 | @@ -364,12 +483,13 @@ |
391 | if context and context.get('create_analytic_line_mode', False): |
392 | mode = context.get('create_analytic_line_mode') |
393 | |
394 | - account_analytic_line_obj = self.pool.get('account.analytic.line') |
395 | contract_service_obj = self.pool.get('contract.service') |
396 | query = [ |
397 | ('account_id', 'in', ids), |
398 | ('state', '=', 'active'), |
399 | - ('analytic_line_type', 'in', ('r', 'x')) |
400 | + ('analytic_line_type', 'in', (LINE_TYPE_RECURRENT, |
401 | + LINE_TYPE_ONETIME, |
402 | + LINE_TYPE_EXCEPTION)) |
403 | ] |
404 | contract_service_ids = contract_service_obj.search(cr, uid, |
405 | query, |
406 | @@ -384,6 +504,30 @@ |
407 | |
408 | return {} |
409 | |
410 | + def create_refund_lines(self, cr, uid, ids, context=None): |
411 | + context = context or {} |
412 | + mode = context.get('create_analytic_line_mode', 'manual') |
413 | + |
414 | + contract_service_obj = self.pool["contract.service"] |
415 | + query = [ |
416 | + ('account_id', 'in', ids), |
417 | + ('state', '=', 'inactive'), |
418 | + # only recurrent is handled in refund right now |
419 | + ('analytic_line_type', 'in', (LINE_TYPE_RECURRENT,)), |
420 | + ] |
421 | + contract_service_ids = contract_service_obj.search(cr, uid, |
422 | + query, |
423 | + order='account_id', |
424 | + context=context) |
425 | + |
426 | + if contract_service_ids: |
427 | + contract_service_obj.create_refund_line(cr, uid, |
428 | + contract_service_ids, |
429 | + mode=mode, |
430 | + context=context) |
431 | + |
432 | + return {} |
433 | + |
434 | def create(self, cr, uid, values, context=None): |
435 | if values['type'] == 'contract' and values['use_contract_services']: |
436 | values['name'] = values['code'] |
437 | |
438 | === modified file 'contract_isp/contract_isp_view.xml' |
439 | --- contract_isp/contract_isp_view.xml 2013-11-07 15:10:04 +0000 |
440 | +++ contract_isp/contract_isp_view.xml 2014-11-24 15:05:14 +0000 |
441 | @@ -22,68 +22,68 @@ |
442 | </field> |
443 | </record> |
444 | |
445 | - <record id="view_contract_isp_form" model="ir.ui.view"> |
446 | - <field name="name">contract.isp.form</field> |
447 | - <field name="model">account.analytic.account</field> |
448 | - <field name="inherit_id" ref="account_analytic_analysis.account_analytic_account_form_form"/> |
449 | - <field name="arch" type="xml"> |
450 | - <xpath expr='//div[@name="project"]' position='inside'> |
451 | - <field name="use_contract_services" /> |
452 | - <label for="use_contract_services" /> |
453 | - </xpath> |
454 | + <record id="view_contract_isp_form" model="ir.ui.view"> |
455 | + <field name="name">contract.isp.form</field> |
456 | + <field name="model">account.analytic.account</field> |
457 | + <field name="inherit_id" ref="account_analytic_analysis.account_analytic_account_form_form"/> |
458 | + <field name="arch" type="xml"> |
459 | + <xpath expr='//div[@name="project"]' position='inside'> |
460 | + <field name="use_contract_services" /> |
461 | + <label for="use_contract_services" /> |
462 | + </xpath> |
463 | |
464 | - <xpath expr="//separator[@string='Invoicing']" position="before"> |
465 | - <separator |
466 | - name="services" |
467 | - string="Services" |
468 | - attrs="{'invisible': [('use_contract_services', '=', False)]}"/> |
469 | - <field |
470 | - name="contract_service_ids" |
471 | - mode="tree" |
472 | - select="1" |
473 | - options="{'always_reload': True, 'reload_on_button': True}" |
474 | - attrs="{'invisible': [('use_contract_services', '=', False)]}"> |
475 | - <tree editable="botton" colors="green:state=='active'" > |
476 | - <field name="account_id" invisible="1"/> |
477 | - <field name="state" readonly="True" /> |
478 | - <field name="activation_date" |
479 | - attrs="{'readonly': [('state', 'in', ('draft', 'active'))]}" /> |
480 | - <field name="category_id" invisible="1" /> |
481 | - <field name="product_id" |
482 | - on_change="on_change_product_id(product_id)" |
483 | - attrs="{'readonly': [('state', '=', 'active')]}" |
484 | - domain="['&', ('analytic_line_type', 'in', ('r', 'x', 'o')), ('categ_id', '=', category_id)]" /> |
485 | - <field name="name" /> |
486 | - <field name="qty" on_change="on_change_qty(qty, unit_price)" /> |
487 | - <field name="unit_price" invisible="1" /> |
488 | - <field name="price" readonly="1" sum="Total Price" /> |
489 | - <field name="analytic_line_type" /> |
490 | - <field name="require_activation" invisible="True" /> |
491 | - <field |
492 | - name="duration" |
493 | - attrs="{'readonly': [('state', 'in', ('draft', 'active')), |
494 | - ('analytic_line_type', 'in', ('r', 'o'))], |
495 | - 'required': [('analytic_line_type', '=', 'x')]}" /> |
496 | - <field name="account_id" invisible="True" /> |
497 | - <button |
498 | - name="%(action_view_contract_service_activate)d" |
499 | - string="Activate" |
500 | - type="action" |
501 | - states="draft,inactive" |
502 | - icon="gtk-yes" |
503 | - groups="contract_isp.group_isp_agent"/> |
504 | - <button |
505 | - name="action_desactivate" |
506 | - string="Desactivate" |
507 | - type="object" |
508 | - states="active" |
509 | - icon="gtk-no" |
510 | - groups="contract_isp.group_isp_agent"/> |
511 | - </tree> |
512 | - </field> |
513 | - </xpath> |
514 | - </field> |
515 | - </record> |
516 | + <xpath expr="//separator[@string='Invoicing']" position="before"> |
517 | + <separator |
518 | + name="services" |
519 | + string="Services" |
520 | + attrs="{'invisible': [('use_contract_services', '=', False)]}"/> |
521 | + <field |
522 | + name="contract_service_ids" |
523 | + mode="tree" |
524 | + select="1" |
525 | + options="{'always_reload': True, 'reload_on_button': True}" |
526 | + attrs="{'invisible': [('use_contract_services', '=', False)]}"> |
527 | + <tree editable="botton" colors="black:require_activation==False; green:state=='active'" > |
528 | + <field name="account_id" invisible="1"/> |
529 | + <field name="state" readonly="True" /> |
530 | + <field name="activation_date" |
531 | + attrs="{'readonly': [('state', 'in', ('draft', 'active'))]}" /> |
532 | + <field name="category_id" invisible="1" /> |
533 | + <field name="product_id" |
534 | + on_change="on_change_product_id(product_id)" |
535 | + attrs="{'readonly': [('state', '=', 'active')]}" |
536 | + domain="['&', ('analytic_line_type', 'in', ('r', 'x', 'o')), ('categ_id', '=', category_id)]" /> |
537 | + <field name="name" /> |
538 | + <field name="qty" on_change="on_change_qty(qty, unit_price)" /> |
539 | + <field name="unit_price" invisible="1" /> |
540 | + <field name="price" readonly="1" sum="Total Price" /> |
541 | + <field name="analytic_line_type" /> |
542 | + <field name="require_activation" invisible="True" /> |
543 | + <field |
544 | + name="duration" |
545 | + attrs="{'readonly': [('state', 'in', ('draft', 'active')), |
546 | + ('analytic_line_type', 'in', ('r', 'o'))], |
547 | + 'required': [('analytic_line_type', '=', 'x')]}" /> |
548 | + <field name="account_id" invisible="True" /> |
549 | + <button |
550 | + name="%(action_view_contract_service_activate)d" |
551 | + string="Activate" |
552 | + type="action" |
553 | + icon="gtk-yes" |
554 | + attrs="{'invisible': ['|', ('state', 'not in', ('draft', 'inactive')), ('require_activation', '=', False)]}" |
555 | + groups="contract_isp.group_isp_agent"/> |
556 | + <button |
557 | + name="%(action_view_contract_service_deactivate)d" |
558 | + string="Desactivate" |
559 | + type="action" |
560 | + icon="gtk-no" |
561 | + attrs="{'invisible': ['|', ('state', '!=', 'active'), ('require_activation', '=', False)]}" |
562 | + groups="contract_isp.group_isp_agent"/> |
563 | + </tree> |
564 | + </field> |
565 | + </xpath> |
566 | + </field> |
567 | + </record> |
568 | |
569 | <record id="view_contract_service_form" model="ir.ui.view"> |
570 | <field name="name">contract.service.form</field> |
571 | @@ -126,11 +126,11 @@ |
572 | states="draft" |
573 | groups="contract_isp.group_isp_agent" /> |
574 | <button |
575 | - name="action_desactivate" |
576 | + name="%(action_view_contract_service_deactivate)d" |
577 | string="Desactivate" |
578 | icon="gtk-no" |
579 | states="active" |
580 | - type="object" |
581 | + type="action" |
582 | groups="contract_isp.group_isp_agent" /> |
583 | </tree> |
584 | </field> |
585 | @@ -148,17 +148,23 @@ |
586 | </field> |
587 | </record> |
588 | |
589 | - <record id="contract_isp_form_suspend" model="ir.ui.view"> |
590 | - <field name="name">contract.isp.form.suspend</field> |
591 | - <field name="model">account.analytic.account</field> |
592 | - <field name="inherit_id" ref="hr_timesheet_invoice.account_analytic_account_form_form"/> |
593 | - <field name="arch" type="xml"> |
594 | - <xpath expr="//header/button[@name='set_pending']" position='attributes'> |
595 | - <attribute name="string">Suspend</attribute> |
596 | - </xpath> |
597 | - </field> |
598 | - </record> |
599 | - |
600 | + <record id="contract_isp_form_buttons_adjust" model="ir.ui.view"> |
601 | + <field name="name">contract.isp.form.suspend</field> |
602 | + <field name="model">account.analytic.account</field> |
603 | + <field name="inherit_id" ref="hr_timesheet_invoice.account_analytic_account_form_form"/> |
604 | + <field name="arch" type="xml"> |
605 | + <xpath expr="//header/button[@name='set_close']" position='attributes'> |
606 | + <attribute name="groups">contract_isp.group_isp_agent2</attribute> |
607 | + </xpath> |
608 | + <xpath expr="//header/button[@name='set_cancel']" position='attributes'> |
609 | + <attribute name="groups">contract_isp.group_isp_agent2</attribute> |
610 | + </xpath> |
611 | + <xpath expr="//header/button[@name='set_pending']" position='attributes'> |
612 | + <attribute name="string">Suspend</attribute> |
613 | + <attribute name="groups">contract_isp.group_isp_agent2</attribute> |
614 | + </xpath> |
615 | + </field> |
616 | + </record> |
617 | |
618 | <act_window |
619 | id="action_contract_service_manage" |
620 | |
621 | === modified file 'contract_isp/i18n/contract_isp.pot' |
622 | --- contract_isp/i18n/contract_isp.pot 2013-09-16 17:59:01 +0000 |
623 | +++ contract_isp/i18n/contract_isp.pot 2014-11-24 15:05:14 +0000 |
624 | @@ -6,8 +6,8 @@ |
625 | msgstr "" |
626 | "Project-Id-Version: OpenERP Server 7.0\n" |
627 | "Report-Msgid-Bugs-To: \n" |
628 | -"POT-Creation-Date: 2013-08-13 12:37+0000\n" |
629 | -"PO-Revision-Date: 2013-08-13 12:37+0000\n" |
630 | +"POT-Creation-Date: 2014-09-21 02:02+0000\n" |
631 | +"PO-Revision-Date: 2014-09-21 02:02+0000\n" |
632 | "Last-Translator: <>\n" |
633 | "Language-Team: \n" |
634 | "MIME-Version: 1.0\n" |
635 | @@ -16,26 +16,32 @@ |
636 | "Plural-Forms: \n" |
637 | |
638 | #. module: contract_isp |
639 | -#: field:account.analytic.line,contract_service_id:0 |
640 | -#: field:contract.service.activate,service_id:0 |
641 | -msgid "Service" |
642 | -msgstr "" |
643 | - |
644 | -#. module: contract_isp |
645 | -#: selection:contract.service,analytic_line_type:0 |
646 | -#: selection:product.product,analytic_line_type:0 |
647 | -msgid "Recurrent" |
648 | -msgstr "" |
649 | - |
650 | -#. module: contract_isp |
651 | -#: selection:contract.service,analytic_line_type:0 |
652 | -#: selection:product.product,analytic_line_type:0 |
653 | -msgid "Exception" |
654 | -msgstr "" |
655 | - |
656 | -#. module: contract_isp |
657 | -#: field:contract.service,state:0 |
658 | -msgid "State" |
659 | +#: field:contract.service.activate,account_id:0 |
660 | +#: field:contract.service.deactivate,account_id:0 |
661 | +msgid "Account" |
662 | +msgstr "" |
663 | + |
664 | +#. module: contract_isp |
665 | +#: view:account.analytic.account:0 |
666 | +#: view:contract.service:0 |
667 | +#: view:contract.service.activate:0 |
668 | +msgid "Activate" |
669 | +msgstr "" |
670 | + |
671 | +#. module: contract_isp |
672 | +#: view:contract.service.activate:0 |
673 | +#: model:ir.actions.act_window,name:contract_isp.action_view_contract_service_activate |
674 | +msgid "Activate Service" |
675 | +msgstr "" |
676 | + |
677 | +#. module: contract_isp |
678 | +#: field:contract.service.activate,activation_date:0 |
679 | +msgid "Activation Date" |
680 | +msgstr "" |
681 | + |
682 | +#. module: contract_isp |
683 | +#: field:contract.service,activation_line_generated:0 |
684 | +msgid "Activation Line Generated?" |
685 | msgstr "" |
686 | |
687 | #. module: contract_isp |
688 | @@ -44,23 +50,56 @@ |
689 | msgstr "" |
690 | |
691 | #. module: contract_isp |
692 | -#: field:res.partner,account_analytic_account_ids:0 |
693 | -msgid "Analytic Accounts/Contracts" |
694 | -msgstr "" |
695 | - |
696 | -#. module: contract_isp |
697 | -#: field:contract.service,analytic_line_type:0 |
698 | -msgid "Type" |
699 | -msgstr "" |
700 | - |
701 | -#. module: contract_isp |
702 | -#: model:res.groups,comment:contract_isp.group_isp_agent |
703 | -msgid "The user will be able to manage customers and contracts" |
704 | -msgstr "" |
705 | - |
706 | -#. module: contract_isp |
707 | -#: view:account.analytic.account:0 |
708 | -msgid "Total Price" |
709 | +#: selection:contract.service,state:0 |
710 | +msgid "Active" |
711 | +msgstr "" |
712 | + |
713 | +#. module: contract_isp |
714 | +#: model:res.groups,name:contract_isp.group_isp_agent |
715 | +msgid "Agent Level 1" |
716 | +msgstr "" |
717 | + |
718 | +#. module: contract_isp |
719 | +#: model:res.groups,name:contract_isp.group_isp_agent2 |
720 | +msgid "Agent Level 2" |
721 | +msgstr "" |
722 | + |
723 | +#. module: contract_isp |
724 | +#: code:_description:0 |
725 | +#: view:contract.service:0 |
726 | +#: model:ir.model,name:contract_isp.model_account_analytic_account |
727 | +#, python-format |
728 | +msgid "Analytic Account" |
729 | +msgstr "" |
730 | + |
731 | +#. module: contract_isp |
732 | +#: code:_description:0 |
733 | +#: model:ir.model,name:contract_isp.model_account_analytic_line |
734 | +#, python-format |
735 | +msgid "Analytic Line" |
736 | +msgstr "" |
737 | + |
738 | +#. module: contract_isp |
739 | +#: view:contract.service.activate:0 |
740 | +#: view:contract.service.deactivate:0 |
741 | +msgid "Cancel" |
742 | +msgstr "" |
743 | + |
744 | +#. module: contract_isp |
745 | +#: code:_description:0 |
746 | +#: model:ir.model,name:contract_isp.model_res_company |
747 | +#, python-format |
748 | +msgid "Companies" |
749 | +msgstr "" |
750 | + |
751 | +#. module: contract_isp |
752 | +#: field:contract.service,account_id:0 |
753 | +msgid "Contract" |
754 | +msgstr "" |
755 | + |
756 | +#. module: contract_isp |
757 | +#: view:contract.service:0 |
758 | +msgid "Contract Services" |
759 | msgstr "" |
760 | |
761 | #. module: contract_isp |
762 | @@ -69,19 +108,137 @@ |
763 | msgstr "" |
764 | |
765 | #. module: contract_isp |
766 | +#: field:res.company,cutoff_day:0 |
767 | +msgid "Cutoff day" |
768 | +msgstr "" |
769 | + |
770 | +#. module: contract_isp |
771 | +#: model:account.analytic.journal,name:contract_isp.analytic_journal_data |
772 | +msgid "Data Use" |
773 | +msgstr "" |
774 | + |
775 | +#. module: contract_isp |
776 | +#: view:contract.service.deactivate:0 |
777 | +msgid "Deactivate" |
778 | +msgstr "" |
779 | + |
780 | +#. module: contract_isp |
781 | +#: model:ir.actions.act_window,name:contract_isp.action_view_contract_service_deactivate |
782 | +msgid "Deactivate Service" |
783 | +msgstr "" |
784 | + |
785 | +#. module: contract_isp |
786 | +#: field:contract.service.deactivate,deactivation_date:0 |
787 | +msgid "Deactivation Date" |
788 | +msgstr "" |
789 | + |
790 | +#. module: contract_isp |
791 | +#: field:contract.service,deactivation_date:0 |
792 | +msgid "Deactivation date" |
793 | +msgstr "" |
794 | + |
795 | +#. module: contract_isp |
796 | +#: view:contract.service.deactivate:0 |
797 | +msgid "Dectivate Service" |
798 | +msgstr "" |
799 | + |
800 | +#. module: contract_isp |
801 | +#: field:res.company,default_journal_id:0 |
802 | +msgid "Default Journal" |
803 | +msgstr "" |
804 | + |
805 | +#. module: contract_isp |
806 | +#: view:account.analytic.account:0 |
807 | +#: view:contract.service:0 |
808 | +msgid "Desactivate" |
809 | +msgstr "" |
810 | + |
811 | +#. module: contract_isp |
812 | +#: field:contract.service,name:0 |
813 | +msgid "Description" |
814 | +msgstr "" |
815 | + |
816 | +#. module: contract_isp |
817 | +#: field:contract.service,duration:0 |
818 | +msgid "Duration" |
819 | +msgstr "" |
820 | + |
821 | +#. module: contract_isp |
822 | +#: selection:contract.service,analytic_line_type:0 |
823 | +#: selection:product.product,analytic_line_type:0 |
824 | +msgid "Exception" |
825 | +msgstr "" |
826 | + |
827 | +#. module: contract_isp |
828 | +#: view:res.company:0 |
829 | +msgid "ISP Contract Management" |
830 | +msgstr "" |
831 | + |
832 | +#. module: contract_isp |
833 | +#: selection:contract.service,state:0 |
834 | +msgid "Inactive" |
835 | +msgstr "" |
836 | + |
837 | +#. module: contract_isp |
838 | +#: selection:contract.service,analytic_line_type:0 |
839 | +#: selection:product.product,analytic_line_type:0 |
840 | +msgid "One time" |
841 | +msgstr "" |
842 | + |
843 | +#. module: contract_isp |
844 | +#: field:res.company,parent_account_id:0 |
845 | +msgid "Parent Analytic Account" |
846 | +msgstr "" |
847 | + |
848 | +#. module: contract_isp |
849 | +#: code:_description:0 |
850 | +#: model:ir.model,name:contract_isp.model_res_partner |
851 | +#, python-format |
852 | +msgid "Partner" |
853 | +msgstr "" |
854 | + |
855 | +#. module: contract_isp |
856 | +#: field:res.partner,partner_analytic_account_id:0 |
857 | +msgid "Partner Analytic Account" |
858 | +msgstr "" |
859 | + |
860 | +#. module: contract_isp |
861 | +#: field:contract.service,price:0 |
862 | +msgid "Price" |
863 | +msgstr "" |
864 | + |
865 | +#. module: contract_isp |
866 | +#: code:_description:0 |
867 | #: field:contract.service,product_id:0 |
868 | #: model:ir.model,name:contract_isp.model_product_product |
869 | +#, python-format |
870 | msgid "Product" |
871 | msgstr "" |
872 | |
873 | #. module: contract_isp |
874 | -#: model:ir.model,name:contract_isp.model_account_analytic_line |
875 | -msgid "Analytic Line" |
876 | -msgstr "" |
877 | - |
878 | -#. module: contract_isp |
879 | -#: field:contract.service,price:0 |
880 | -msgid "Price" |
881 | +#: field:contract.service,category_id:0 |
882 | +msgid "Product Category" |
883 | +msgstr "" |
884 | + |
885 | +#. module: contract_isp |
886 | +#: field:account.analytic.line,is_prorata:0 |
887 | +msgid "Prorata" |
888 | +msgstr "" |
889 | + |
890 | +#. module: contract_isp |
891 | +#: field:contract.service,qty:0 |
892 | +msgid "Qty" |
893 | +msgstr "" |
894 | + |
895 | +#. module: contract_isp |
896 | +#: selection:contract.service,analytic_line_type:0 |
897 | +#: selection:product.product,analytic_line_type:0 |
898 | +msgid "Recurrent" |
899 | +msgstr "" |
900 | + |
901 | +#. module: contract_isp |
902 | +#: model:account.analytic.journal,name:contract_isp.analytic_journal_recurrent |
903 | +msgid "Recurrent Service" |
904 | msgstr "" |
905 | |
906 | #. module: contract_isp |
907 | @@ -91,87 +248,58 @@ |
908 | msgstr "" |
909 | |
910 | #. module: contract_isp |
911 | +#: field:account.analytic.line,contract_service_id:0 |
912 | +#: field:contract.service.activate,service_id:0 |
913 | +#: field:contract.service.deactivate,service_id:0 |
914 | +msgid "Service" |
915 | +msgstr "" |
916 | + |
917 | +#. module: contract_isp |
918 | +#: view:account.analytic.account:0 |
919 | +#: field:account.analytic.account,contract_service_ids:0 |
920 | +#: model:ir.actions.act_window,name:contract_isp.action_contract_service_manage |
921 | +msgid "Services" |
922 | +msgstr "" |
923 | + |
924 | +#. module: contract_isp |
925 | +#: field:contract.service,state:0 |
926 | +msgid "State" |
927 | +msgstr "" |
928 | + |
929 | +#. module: contract_isp |
930 | +#: view:account.analytic.account:0 |
931 | +msgid "Suspend" |
932 | +msgstr "" |
933 | + |
934 | +#. module: contract_isp |
935 | +#: model:res.groups,comment:contract_isp.group_isp_agent |
936 | +#: model:res.groups,comment:contract_isp.group_isp_agent2 |
937 | +msgid "The users in this group will be able to manage customers and contracts" |
938 | +msgstr "" |
939 | + |
940 | +#. module: contract_isp |
941 | +#: view:account.analytic.account:0 |
942 | +msgid "Total Price" |
943 | +msgstr "" |
944 | + |
945 | +#. module: contract_isp |
946 | +#: field:contract.service,analytic_line_type:0 |
947 | +msgid "Type" |
948 | +msgstr "" |
949 | + |
950 | +#. module: contract_isp |
951 | #: field:product.product,analytic_line_type:0 |
952 | msgid "Type in contract" |
953 | msgstr "" |
954 | |
955 | #. module: contract_isp |
956 | -#: selection:contract.service,state:0 |
957 | -msgid "Inactive" |
958 | -msgstr "" |
959 | - |
960 | -#. module: contract_isp |
961 | -#: field:res.company,parent_account_id:0 |
962 | -msgid "Parent Analytic Account" |
963 | -msgstr "" |
964 | - |
965 | -#. module: contract_isp |
966 | -#: selection:contract.service,state:0 |
967 | -msgid "Active" |
968 | -msgstr "" |
969 | - |
970 | -#. module: contract_isp |
971 | -#: view:res.company:0 |
972 | -msgid "ISP Contract Management" |
973 | -msgstr "" |
974 | - |
975 | -#. module: contract_isp |
976 | -#: field:res.partner,analytic_data_lines_ids:0 |
977 | -#: field:res.partner,analytic_tel_lines_ids:0 |
978 | -msgid "Account Lines" |
979 | -msgstr "" |
980 | - |
981 | -#. module: contract_isp |
982 | -#: field:contract.service.activate,account_id:0 |
983 | -msgid "Account" |
984 | -msgstr "" |
985 | - |
986 | -#. module: contract_isp |
987 | -#: selection:contract.service,analytic_line_type:0 |
988 | -#: selection:product.product,analytic_line_type:0 |
989 | -msgid "One time" |
990 | -msgstr "" |
991 | - |
992 | -#. module: contract_isp |
993 | -#: view:account.analytic.account:0 |
994 | -#: view:contract.service:0 |
995 | -msgid "Desactivate" |
996 | -msgstr "" |
997 | - |
998 | -#. module: contract_isp |
999 | -#: model:ir.model,name:contract_isp.model_contract_service_activate |
1000 | -msgid "contract.service.activate" |
1001 | -msgstr "" |
1002 | - |
1003 | -#. module: contract_isp |
1004 | -#: model:ir.model,name:contract_isp.model_res_company |
1005 | -msgid "Companies" |
1006 | -msgstr "" |
1007 | - |
1008 | -#. module: contract_isp |
1009 | -#: field:contract.service,account_id:0 |
1010 | -msgid "Contract" |
1011 | -msgstr "" |
1012 | - |
1013 | -#. module: contract_isp |
1014 | -#: view:contract.service.activate:0 |
1015 | -msgid "Cancel" |
1016 | -msgstr "" |
1017 | - |
1018 | -#. module: contract_isp |
1019 | -#: view:contract.service.activate:0 |
1020 | -#: model:ir.actions.act_window,name:contract_isp.action_view_contract_service_activate |
1021 | -msgid "Activate Service" |
1022 | -msgstr "" |
1023 | - |
1024 | -#. module: contract_isp |
1025 | -#: field:res.company,cutoff_day:0 |
1026 | -msgid "Cutoff day" |
1027 | -msgstr "" |
1028 | - |
1029 | -#. module: contract_isp |
1030 | -#: field:res.partner,payments_ids:0 |
1031 | -msgid "Payments" |
1032 | +#: field:contract.service,unit_price:0 |
1033 | +msgid "Unit Price" |
1034 | +msgstr "" |
1035 | + |
1036 | +#. module: contract_isp |
1037 | +#: model:account.analytic.journal,name:contract_isp.analytic_journal_tel |
1038 | +msgid "Voice Use" |
1039 | msgstr "" |
1040 | |
1041 | #. module: contract_isp |
1042 | @@ -180,72 +308,38 @@ |
1043 | msgstr "" |
1044 | |
1045 | #. module: contract_isp |
1046 | -#: field:res.partner,partner_analytic_account_id:0 |
1047 | -msgid "Partner Analytic Account" |
1048 | -msgstr "" |
1049 | - |
1050 | -#. module: contract_isp |
1051 | -#: view:account.analytic.account:0 |
1052 | -#: view:contract.service:0 |
1053 | -#: view:contract.service.activate:0 |
1054 | -msgid "Activate" |
1055 | -msgstr "" |
1056 | - |
1057 | -#. module: contract_isp |
1058 | -#: field:contract.service,account_line_id:0 |
1059 | -msgid "Account Entry" |
1060 | -msgstr "" |
1061 | - |
1062 | -#. module: contract_isp |
1063 | +#: constraint:contract.service.activate:0 |
1064 | +msgid "You cannot activate a service in the future." |
1065 | +msgstr "" |
1066 | + |
1067 | +#. module: contract_isp |
1068 | +#: constraint:contract.service.deactivate:0 |
1069 | +msgid "You cannot deactivate a service in the future." |
1070 | +msgstr "" |
1071 | + |
1072 | +#. module: contract_isp |
1073 | +#: code:_description:0 |
1074 | #: model:ir.model,name:contract_isp.model_contract_service |
1075 | +#, python-format |
1076 | msgid "contract.service" |
1077 | msgstr "" |
1078 | |
1079 | #. module: contract_isp |
1080 | -#: model:res.groups,name:contract_isp.group_isp_agent |
1081 | -msgid "Agent" |
1082 | -msgstr "" |
1083 | - |
1084 | -#. module: contract_isp |
1085 | -#: view:account.analytic.account:0 |
1086 | -msgid "Suspend" |
1087 | -msgstr "" |
1088 | - |
1089 | -#. module: contract_isp |
1090 | -#: view:contract.service:0 |
1091 | -#: model:ir.model,name:contract_isp.model_account_analytic_account |
1092 | -msgid "Analytic Account" |
1093 | -msgstr "" |
1094 | - |
1095 | -#. module: contract_isp |
1096 | -#: field:contract.service.activate,activation_date:0 |
1097 | -msgid "Activation Date" |
1098 | -msgstr "" |
1099 | - |
1100 | -#. module: contract_isp |
1101 | -#: view:account.analytic.account:0 |
1102 | -#: field:account.analytic.account,contract_service_ids:0 |
1103 | -#: model:ir.actions.act_window,name:contract_isp.action_contract_service_manage |
1104 | -msgid "Services" |
1105 | -msgstr "" |
1106 | - |
1107 | -#. module: contract_isp |
1108 | -#: field:contract.service,duration:0 |
1109 | -msgid "Duration" |
1110 | -msgstr "" |
1111 | - |
1112 | -#. module: contract_isp |
1113 | -#: model:ir.model,name:contract_isp.model_res_partner |
1114 | -msgid "Partner" |
1115 | -msgstr "" |
1116 | - |
1117 | -#. module: contract_isp |
1118 | -#: field:contract.service,activation_line_generated:0 |
1119 | -msgid "Activation Line Generated?" |
1120 | -msgstr "" |
1121 | - |
1122 | -#. module: contract_isp |
1123 | -#: view:contract.service:0 |
1124 | -msgid "Contract Services" |
1125 | +#: code:_description:0 |
1126 | +#: model:ir.model,name:contract_isp.model_contract_service_activate |
1127 | +#, python-format |
1128 | +msgid "contract.service.activate" |
1129 | +msgstr "" |
1130 | + |
1131 | +#. module: contract_isp |
1132 | +#: code:_description:0 |
1133 | +#: model:ir.model,name:contract_isp.model_contract_service_deactivate |
1134 | +#, python-format |
1135 | +msgid "contract.service.deactivate" |
1136 | +msgstr "" |
1137 | + |
1138 | +#. module: contract_isp |
1139 | +#: view:account.analytic.account:0 |
1140 | +msgid "contract_isp.group_isp_agent2" |
1141 | msgstr "" |
1142 | |
1143 | |
1144 | === added file 'contract_isp/i18n/fr.po' |
1145 | --- contract_isp/i18n/fr.po 1970-01-01 00:00:00 +0000 |
1146 | +++ contract_isp/i18n/fr.po 2014-11-24 15:05:14 +0000 |
1147 | @@ -0,0 +1,338 @@ |
1148 | +# Translation of OpenERP Server. |
1149 | +# This file contains the translation of the following modules: |
1150 | +# * contract_isp |
1151 | +# |
1152 | +msgid "" |
1153 | +msgstr "" |
1154 | +"Project-Id-Version: OpenERP Server 7.0\n" |
1155 | +"Report-Msgid-Bugs-To: \n" |
1156 | +"POT-Creation-Date: 2014-09-21 02:02+0000\n" |
1157 | +"PO-Revision-Date: 2014-09-20 22:45-0500\n" |
1158 | +"Last-Translator: Marc Cassuto <marc.cassuto@savoirfairelinux.com>\n" |
1159 | +"Language-Team: \n" |
1160 | +"Language: fr\n" |
1161 | +"MIME-Version: 1.0\n" |
1162 | +"Content-Type: text/plain; charset=UTF-8\n" |
1163 | +"Content-Transfer-Encoding: 8bit\n" |
1164 | +"X-Generator: Poedit 1.5.4\n" |
1165 | + |
1166 | +#. module: contract_isp |
1167 | +#: field:contract.service.activate,account_id:0 |
1168 | +#: field:contract.service.deactivate,account_id:0 |
1169 | +msgid "Account" |
1170 | +msgstr "Compte" |
1171 | + |
1172 | +#. module: contract_isp |
1173 | +#: view:account.analytic.account:0 view:contract.service:0 |
1174 | +#: view:contract.service.activate:0 |
1175 | +msgid "Activate" |
1176 | +msgstr "Activer" |
1177 | + |
1178 | +#. module: contract_isp |
1179 | +#: view:contract.service.activate:0 |
1180 | +#: model:ir.actions.act_window,name:contract_isp.action_view_contract_service_activate |
1181 | +msgid "Activate Service" |
1182 | +msgstr "Activer un Service" |
1183 | + |
1184 | +#. module: contract_isp |
1185 | +#: field:contract.service.activate,activation_date:0 |
1186 | +msgid "Activation Date" |
1187 | +msgstr "Date d'Activation" |
1188 | + |
1189 | +#. module: contract_isp |
1190 | +#: field:contract.service,activation_line_generated:0 |
1191 | +msgid "Activation Line Generated?" |
1192 | +msgstr "Ligne d'Activation Générée ?" |
1193 | + |
1194 | +#. module: contract_isp |
1195 | +#: field:contract.service,activation_date:0 |
1196 | +msgid "Activation date" |
1197 | +msgstr "Date d'Activation" |
1198 | + |
1199 | +#. module: contract_isp |
1200 | +#: selection:contract.service,state:0 |
1201 | +msgid "Active" |
1202 | +msgstr "Actif" |
1203 | + |
1204 | +#. module: contract_isp |
1205 | +#: model:res.groups,name:contract_isp.group_isp_agent |
1206 | +msgid "Agent Level 1" |
1207 | +msgstr "Agent Niveau 1" |
1208 | + |
1209 | +#. module: contract_isp |
1210 | +#: model:res.groups,name:contract_isp.group_isp_agent2 |
1211 | +msgid "Agent Level 2" |
1212 | +msgstr "Agent niveau 2" |
1213 | + |
1214 | +#. module: contract_isp |
1215 | +#: code:_description:0 view:contract.service:0 |
1216 | +#: model:ir.model,name:contract_isp.model_account_analytic_account |
1217 | +#, python-format |
1218 | +msgid "Analytic Account" |
1219 | +msgstr "Contrat" |
1220 | + |
1221 | +#. module: contract_isp |
1222 | +#: code:_description:0 |
1223 | +#: model:ir.model,name:contract_isp.model_account_analytic_line |
1224 | +#, python-format |
1225 | +msgid "Analytic Line" |
1226 | +msgstr "Lignes facturables" |
1227 | + |
1228 | +#. module: contract_isp |
1229 | +#: view:contract.service.activate:0 view:contract.service.deactivate:0 |
1230 | +msgid "Cancel" |
1231 | +msgstr "Annuler" |
1232 | + |
1233 | +#. module: contract_isp |
1234 | +#: code:_description:0 model:ir.model,name:contract_isp.model_res_company |
1235 | +#, python-format |
1236 | +msgid "Companies" |
1237 | +msgstr "Companies" |
1238 | + |
1239 | +#. module: contract_isp |
1240 | +#: field:contract.service,account_id:0 |
1241 | +msgid "Contract" |
1242 | +msgstr "Contrat" |
1243 | + |
1244 | +#. module: contract_isp |
1245 | +#: view:contract.service:0 |
1246 | +msgid "Contract Services" |
1247 | +msgstr "Services du Contrat" |
1248 | + |
1249 | +#. module: contract_isp |
1250 | +#: field:account.analytic.account,use_contract_services:0 |
1251 | +msgid "Contract services" |
1252 | +msgstr "Services du Contrat" |
1253 | + |
1254 | +#. module: contract_isp |
1255 | +#: field:res.company,cutoff_day:0 |
1256 | +msgid "Cutoff day" |
1257 | +msgstr "Date de Cut-off" |
1258 | + |
1259 | +#. module: contract_isp |
1260 | +#: model:account.analytic.journal,name:contract_isp.analytic_journal_data |
1261 | +msgid "Data Use" |
1262 | +msgstr "Consommations de données" |
1263 | + |
1264 | +#. module: contract_isp |
1265 | +#: view:contract.service.deactivate:0 |
1266 | +msgid "Deactivate" |
1267 | +msgstr "Désactiver" |
1268 | + |
1269 | +#. module: contract_isp |
1270 | +#: model:ir.actions.act_window,name:contract_isp.action_view_contract_service_deactivate |
1271 | +msgid "Deactivate Service" |
1272 | +msgstr "Désactiver un Service" |
1273 | + |
1274 | +#. module: contract_isp |
1275 | +#: field:contract.service.deactivate,deactivation_date:0 |
1276 | +msgid "Deactivation Date" |
1277 | +msgstr "Date de Désactivation" |
1278 | + |
1279 | +#. module: contract_isp |
1280 | +#: field:contract.service,deactivation_date:0 |
1281 | +msgid "Deactivation date" |
1282 | +msgstr "Date de Désactivation" |
1283 | + |
1284 | +#. module: contract_isp |
1285 | +#: view:contract.service.deactivate:0 |
1286 | +msgid "Dectivate Service" |
1287 | +msgstr "Désactiver un Service" |
1288 | + |
1289 | +#. module: contract_isp |
1290 | +#: field:res.company,default_journal_id:0 |
1291 | +msgid "Default Journal" |
1292 | +msgstr "Journal Comptable par défaut" |
1293 | + |
1294 | +#. module: contract_isp |
1295 | +#: view:account.analytic.account:0 view:contract.service:0 |
1296 | +msgid "Desactivate" |
1297 | +msgstr "Désactiver" |
1298 | + |
1299 | +#. module: contract_isp |
1300 | +#: field:contract.service,name:0 |
1301 | +msgid "Description" |
1302 | +msgstr "Description" |
1303 | + |
1304 | +#. module: contract_isp |
1305 | +#: field:contract.service,duration:0 |
1306 | +msgid "Duration" |
1307 | +msgstr "Durée" |
1308 | + |
1309 | +#. module: contract_isp |
1310 | +#: selection:contract.service,analytic_line_type:0 |
1311 | +#: selection:product.product,analytic_line_type:0 |
1312 | +msgid "Exception" |
1313 | +msgstr "Exception" |
1314 | + |
1315 | +#. module: contract_isp |
1316 | +#: view:res.company:0 |
1317 | +msgid "ISP Contract Management" |
1318 | +msgstr "Gestion de contrats pour les FSI" |
1319 | + |
1320 | +#. module: contract_isp |
1321 | +#: selection:contract.service,state:0 |
1322 | +msgid "Inactive" |
1323 | +msgstr "Inactif" |
1324 | + |
1325 | +#. module: contract_isp |
1326 | +#: selection:contract.service,analytic_line_type:0 |
1327 | +#: selection:product.product,analytic_line_type:0 |
1328 | +msgid "One time" |
1329 | +msgstr "Facturé une fois" |
1330 | + |
1331 | +#. module: contract_isp |
1332 | +#: field:res.company,parent_account_id:0 |
1333 | +msgid "Parent Analytic Account" |
1334 | +msgstr "Contrat parent" |
1335 | + |
1336 | +#. module: contract_isp |
1337 | +#: code:_description:0 model:ir.model,name:contract_isp.model_res_partner |
1338 | +#, python-format |
1339 | +msgid "Partner" |
1340 | +msgstr "Partenaire" |
1341 | + |
1342 | +#. module: contract_isp |
1343 | +#: field:res.partner,partner_analytic_account_id:0 |
1344 | +msgid "Partner Analytic Account" |
1345 | +msgstr "Contrat du partenaire" |
1346 | + |
1347 | +#. module: contract_isp |
1348 | +#: field:contract.service,price:0 |
1349 | +msgid "Price" |
1350 | +msgstr "Prix" |
1351 | + |
1352 | +#. module: contract_isp |
1353 | +#: code:_description:0 field:contract.service,product_id:0 |
1354 | +#: model:ir.model,name:contract_isp.model_product_product |
1355 | +#, python-format |
1356 | +msgid "Product" |
1357 | +msgstr "Produit" |
1358 | + |
1359 | +#. module: contract_isp |
1360 | +#: field:contract.service,category_id:0 |
1361 | +msgid "Product Category" |
1362 | +msgstr "Catégorie de Produit" |
1363 | + |
1364 | +#. module: contract_isp |
1365 | +#: field:account.analytic.line,is_prorata:0 |
1366 | +msgid "Prorata" |
1367 | +msgstr "Pro-rata" |
1368 | + |
1369 | +#. module: contract_isp |
1370 | +#: field:contract.service,qty:0 |
1371 | +msgid "Qty" |
1372 | +msgstr "Qté" |
1373 | + |
1374 | +#. module: contract_isp |
1375 | +#: selection:contract.service,analytic_line_type:0 |
1376 | +#: selection:product.product,analytic_line_type:0 |
1377 | +msgid "Recurrent" |
1378 | +msgstr "Récurrent" |
1379 | + |
1380 | +#. module: contract_isp |
1381 | +#: model:account.analytic.journal,name:contract_isp.analytic_journal_recurrent |
1382 | +msgid "Recurrent Service" |
1383 | +msgstr "Service Récurrent" |
1384 | + |
1385 | +#. module: contract_isp |
1386 | +#: field:contract.service,require_activation:0 |
1387 | +#: field:product.product,require_activation:0 |
1388 | +msgid "Require activation" |
1389 | +msgstr "Nécessite une acitvation" |
1390 | + |
1391 | +#. module: contract_isp |
1392 | +#: field:account.analytic.line,contract_service_id:0 |
1393 | +#: field:contract.service.activate,service_id:0 |
1394 | +#: field:contract.service.deactivate,service_id:0 |
1395 | +msgid "Service" |
1396 | +msgstr "Service" |
1397 | + |
1398 | +#. module: contract_isp |
1399 | +#: view:account.analytic.account:0 |
1400 | +#: field:account.analytic.account,contract_service_ids:0 |
1401 | +#: model:ir.actions.act_window,name:contract_isp.action_contract_service_manage |
1402 | +msgid "Services" |
1403 | +msgstr "Services" |
1404 | + |
1405 | +#. module: contract_isp |
1406 | +#: field:contract.service,state:0 |
1407 | +msgid "State" |
1408 | +msgstr "Statut" |
1409 | + |
1410 | +#. module: contract_isp |
1411 | +#: view:account.analytic.account:0 |
1412 | +msgid "Suspend" |
1413 | +msgstr "Suspendre" |
1414 | + |
1415 | +#. module: contract_isp |
1416 | +#: model:res.groups,comment:contract_isp.group_isp_agent |
1417 | +#: model:res.groups,comment:contract_isp.group_isp_agent2 |
1418 | +msgid "The users in this group will be able to manage customers and contracts" |
1419 | +msgstr "" |
1420 | +"Les utilisateurs de ce groupe pourront gérer les clients et les contrats" |
1421 | + |
1422 | +#. module: contract_isp |
1423 | +#: view:account.analytic.account:0 |
1424 | +msgid "Total Price" |
1425 | +msgstr "Prix Total" |
1426 | + |
1427 | +#. module: contract_isp |
1428 | +#: field:contract.service,analytic_line_type:0 |
1429 | +msgid "Type" |
1430 | +msgstr "Type" |
1431 | + |
1432 | +#. module: contract_isp |
1433 | +#: field:product.product,analytic_line_type:0 |
1434 | +msgid "Type in contract" |
1435 | +msgstr "Type dans le contrat" |
1436 | + |
1437 | +#. module: contract_isp |
1438 | +#: field:contract.service,unit_price:0 |
1439 | +msgid "Unit Price" |
1440 | +msgstr "Prix Unitaire" |
1441 | + |
1442 | +#. module: contract_isp |
1443 | +#: model:account.analytic.journal,name:contract_isp.analytic_journal_tel |
1444 | +msgid "Voice Use" |
1445 | +msgstr "Consommation Téléphonique" |
1446 | + |
1447 | +#. module: contract_isp |
1448 | +#: selection:contract.service,state:0 |
1449 | +msgid "Waiting for activating" |
1450 | +msgstr "En attente d'activation" |
1451 | + |
1452 | +#. module: contract_isp |
1453 | +#: constraint:contract.service.activate:0 |
1454 | +msgid "You cannot activate a service in the future." |
1455 | +msgstr "Vous ne pouvez pas activer un service dans le futur." |
1456 | + |
1457 | +#. module: contract_isp |
1458 | +#: constraint:contract.service.deactivate:0 |
1459 | +msgid "You cannot deactivate a service in the future." |
1460 | +msgstr "Vous ne pouvez pas désactiver un service dans le futur." |
1461 | + |
1462 | +#. module: contract_isp |
1463 | +#: code:_description:0 model:ir.model,name:contract_isp.model_contract_service |
1464 | +#, python-format |
1465 | +msgid "contract.service" |
1466 | +msgstr "contract.service" |
1467 | + |
1468 | +#. module: contract_isp |
1469 | +#: code:_description:0 |
1470 | +#: model:ir.model,name:contract_isp.model_contract_service_activate |
1471 | +#, python-format |
1472 | +msgid "contract.service.activate" |
1473 | +msgstr "contract.service.activate" |
1474 | + |
1475 | +#. module: contract_isp |
1476 | +#: code:_description:0 |
1477 | +#: model:ir.model,name:contract_isp.model_contract_service_deactivate |
1478 | +#, python-format |
1479 | +msgid "contract.service.deactivate" |
1480 | +msgstr "contract.service.deactivate" |
1481 | + |
1482 | +#. module: contract_isp |
1483 | +#: view:account.analytic.account:0 |
1484 | +msgid "contract_isp.group_isp_agent2" |
1485 | +msgstr "contract_isp.group_isp_agent2" |
1486 | |
1487 | === modified file 'contract_isp/wizard/activate_contract_service.py' |
1488 | --- contract_isp/wizard/activate_contract_service.py 2013-09-16 17:59:01 +0000 |
1489 | +++ contract_isp/wizard/activate_contract_service.py 2014-11-24 15:05:14 +0000 |
1490 | @@ -21,30 +21,38 @@ |
1491 | ############################################################################## |
1492 | |
1493 | import datetime |
1494 | + |
1495 | +from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT |
1496 | +from openerp.tools.translate import _ |
1497 | from openerp.osv import orm, fields |
1498 | -from openerp.addons.contract_isp.contract import add_months |
1499 | + |
1500 | +from ..contract import LINE_TYPE_RECURRENT |
1501 | + |
1502 | + |
1503 | +def _get_account_id(self, cr, uid, context=None): |
1504 | + if context.get('active_model', '') == 'contract.service': |
1505 | + contract_id = context.get('active_id') |
1506 | + contract_service = self.pool.get('contract.service').browse( |
1507 | + cr, uid, contract_id, context) |
1508 | + |
1509 | + return contract_service.account_id.id |
1510 | + return None |
1511 | + |
1512 | + |
1513 | +def _get_service_id(self, cr, uid, context=None): |
1514 | + if context.get('active_model', '') == 'contract.service': |
1515 | + service_id = context.get('active_id') |
1516 | + contract_service = self.pool.get('contract.service').browse( |
1517 | + cr, uid, service_id, context) |
1518 | + |
1519 | + return contract_service.id |
1520 | + return None |
1521 | |
1522 | |
1523 | class contract_service_activate(orm.TransientModel): |
1524 | _name = 'contract.service.activate' |
1525 | - |
1526 | - def _get_account_id(self, cr, uid, context=None): |
1527 | - if context.get('active_model', '') == 'contract.service': |
1528 | - contract_id = context.get('active_id') |
1529 | - contract_service = self.pool.get('contract.service').browse( |
1530 | - cr, uid, contract_id, context) |
1531 | - |
1532 | - return contract_service.account_id.id |
1533 | - return None |
1534 | - |
1535 | - def _get_service_id(self, cr, uid, context=None): |
1536 | - if context.get('active_model', '') == 'contract.service': |
1537 | - service_id = context.get('active_id') |
1538 | - contract_service = self.pool.get('contract.service').browse( |
1539 | - cr, uid, service_id, context) |
1540 | - |
1541 | - return contract_service.id |
1542 | - return None |
1543 | + _get_account_id = _get_account_id |
1544 | + _get_service_id = _get_service_id |
1545 | |
1546 | _columns = { |
1547 | 'activation_date': fields.datetime('Activation Date'), |
1548 | @@ -54,15 +62,27 @@ |
1549 | |
1550 | _defaults = { |
1551 | 'activation_date': fields.datetime.now, |
1552 | - 'account_id': lambda s, cr, uid, ctx: s._get_account_id(cr, uid, ctx), |
1553 | - 'service_id': lambda s, cr, uid, ctx: s._get_service_id(cr, uid, ctx) |
1554 | + 'account_id': _get_account_id, |
1555 | + 'service_id': _get_service_id, |
1556 | } |
1557 | |
1558 | def activate(self, cr, uid, ids, context=None): |
1559 | wizard = self.browse(cr, uid, ids[0], context) |
1560 | - company_obj = self.pool.get('res.company') |
1561 | - company_id = company_obj._company_default_get(cr, uid, context) |
1562 | - cutoff = company_obj.read(cr, uid, company_id, 'cutoff_day', context) |
1563 | + contract_service_obj = self.pool.get('contract.service') |
1564 | + contract_service = contract_service_obj.browse( |
1565 | + cr, uid, wizard.service_id.id, context) |
1566 | + |
1567 | + contract_service.write({ |
1568 | + 'activation_date': wizard.activation_date, |
1569 | + 'state': 'active' |
1570 | + }) |
1571 | + |
1572 | + self._create_analytic_lines(cr, uid, ids[0], context) |
1573 | + |
1574 | + return True |
1575 | + |
1576 | + def _create_analytic_lines(self, cr, uid, wiz_id, context=None): |
1577 | + wizard = self.browse(cr, uid, wiz_id, context) |
1578 | contract_service_obj = self.pool.get('contract.service') |
1579 | contract_service = contract_service_obj.browse( |
1580 | cr, uid, wizard.service_id.id, context) |
1581 | @@ -72,48 +92,102 @@ |
1582 | int(wizard.activation_date[5:7]), |
1583 | int(wizard.activation_date[8:10])) |
1584 | |
1585 | - cuttoff_day = company_obj.read( |
1586 | - cr, uid, |
1587 | - company_id, |
1588 | - fields=['cutoff_day'], |
1589 | - context=context)['cutoff_day'] |
1590 | - |
1591 | - invoice_day = company_obj.read( |
1592 | - cr, uid, |
1593 | - company_id, |
1594 | - fields=['invoice_day'], |
1595 | - context=context)['invoice_day'] |
1596 | - |
1597 | - cutoff_date = datetime.date( |
1598 | - datetime.date.today().year, |
1599 | - datetime.date.today().month, |
1600 | - int(cuttoff_day)) |
1601 | - |
1602 | - invoice_date = datetime.date( |
1603 | - datetime.date.today().year, |
1604 | - datetime.date.today().month, |
1605 | - int(invoice_day)) |
1606 | - |
1607 | - contract_service.write({ |
1608 | - 'activation_date': wizard.activation_date, |
1609 | - 'state': 'active' |
1610 | + # When registering an initial payment, we generate activation lines |
1611 | + # we do not wish to generate another month entry if not needed |
1612 | + # vvinet: This is not currently part of our scenarios, remove it |
1613 | + # it can be put back if we want to handle it |
1614 | + # if contract_service.activation_line_generated is False: |
1615 | + # contract_service.create_analytic_line(mode='manual', |
1616 | + # date=activation_date, |
1617 | + # context=context) |
1618 | + # contract_service.write({'activation_line_generated': True}) |
1619 | + |
1620 | + # Upon activating, always create activation lines |
1621 | + if contract_service.analytic_line_type == LINE_TYPE_RECURRENT: |
1622 | + contract_service.create_analytic_line(mode='prorata', |
1623 | + date=activation_date, |
1624 | + context=context) |
1625 | + |
1626 | + def _check_future_date(self, cr, uid, ids, context=None): |
1627 | + today = datetime.datetime.utcnow().date() |
1628 | + for wiz in self.browse(cr, uid, ids, context=None): |
1629 | + act_date = datetime.datetime.strptime( |
1630 | + wiz.activation_date, DEFAULT_SERVER_DATETIME_FORMAT, |
1631 | + ).date() |
1632 | + |
1633 | + if act_date > today: |
1634 | + return False |
1635 | + return True |
1636 | + |
1637 | + _constraints = [ |
1638 | + (_check_future_date, |
1639 | + _('You cannot activate a service in the future.'), |
1640 | + ['activation_date']), |
1641 | + ] |
1642 | + |
1643 | + |
1644 | +class contract_service_deactivate(orm.TransientModel): |
1645 | + _name = 'contract.service.deactivate' |
1646 | + |
1647 | + _columns = { |
1648 | + 'deactivation_date': fields.datetime('Deactivation Date'), |
1649 | + 'account_id': fields.many2one('account.analytic.account', 'Account'), |
1650 | + 'service_id': fields.many2one('contract.service', 'Service') |
1651 | + } |
1652 | + |
1653 | + _defaults = { |
1654 | + 'deactivation_date': fields.datetime.now, |
1655 | + 'account_id': _get_account_id, |
1656 | + 'service_id': _get_service_id, |
1657 | + } |
1658 | + |
1659 | + def deactivate(self, cr, uid, ids, context=None): |
1660 | + context = context or {} |
1661 | + wizard = self.browse(cr, uid, ids[0], context) |
1662 | + contract_service_obj = self.pool.get('contract.service') |
1663 | + context["deactivation_date"] = wizard.deactivation_date |
1664 | + contract_service_obj.action_deactivate(cr, uid, |
1665 | + [wizard.service_id.id], |
1666 | + context=context) |
1667 | + # If we activate again, we will need a new activation line, as |
1668 | + # we will have refunded any extra, and will need to bill in |
1669 | + # advance again. |
1670 | + contract_service_obj.write(cr, uid, [wizard.service_id.id], { |
1671 | + 'activation_line_generated': False, |
1672 | }) |
1673 | |
1674 | - query = [ |
1675 | - ('account_id', '=', wizard.account_id.id), |
1676 | - ('state', '=', 'draft') |
1677 | - ] |
1678 | - draft_line_ids = contract_service_obj.search(cr, uid, query, |
1679 | - context=context) |
1680 | - |
1681 | - if not draft_line_ids: |
1682 | - for line in wizard.account_id.contract_service_ids: |
1683 | - if line.activation_line_generated is False: |
1684 | - line.create_analytic_line(mode='manual', |
1685 | - date=activation_date) |
1686 | - |
1687 | - if line.analytic_line_type == 'r': |
1688 | - line.create_analytic_line(mode='prorata', |
1689 | - date=activation_date) |
1690 | - |
1691 | - return True |
1692 | + self._create_refund_lines(cr, uid, ids[0], context) |
1693 | + return True |
1694 | + |
1695 | + def _create_refund_lines(self, cr, uid, wiz_id, context=None): |
1696 | + wizard = self.browse(cr, uid, wiz_id, context) |
1697 | + contract_service_obj = self.pool.get('contract.service') |
1698 | + |
1699 | + deactivate_date = datetime.datetime.strptime( |
1700 | + wizard.deactivation_date, |
1701 | + DEFAULT_SERVER_DATETIME_FORMAT, |
1702 | + ).date() |
1703 | + |
1704 | + contract_service_obj.create_refund_line( |
1705 | + cr, uid, |
1706 | + [wizard.service_id.id], |
1707 | + mode='prorata', |
1708 | + date=deactivate_date, |
1709 | + context=context) |
1710 | + |
1711 | + def _check_future_date(self, cr, uid, ids, context=None): |
1712 | + today = datetime.datetime.utcnow().date() |
1713 | + for wiz in self.browse(cr, uid, ids, context=None): |
1714 | + act_date = datetime.datetime.strptime( |
1715 | + wiz.deactivation_date, DEFAULT_SERVER_DATETIME_FORMAT, |
1716 | + ).date() |
1717 | + |
1718 | + if act_date > today: |
1719 | + return False |
1720 | + return True |
1721 | + |
1722 | + _constraints = [ |
1723 | + (_check_future_date, |
1724 | + _('You cannot deactivate a service in the future.'), |
1725 | + ['deactivation_date']), |
1726 | + ] |
1727 | |
1728 | === modified file 'contract_isp/wizard/activate_contract_service.xml' |
1729 | --- contract_isp/wizard/activate_contract_service.xml 2013-09-16 17:59:01 +0000 |
1730 | +++ contract_isp/wizard/activate_contract_service.xml 2014-11-24 15:05:14 +0000 |
1731 | @@ -1,40 +1,75 @@ |
1732 | <?xml version="1.0" encoding="utf-8"?> |
1733 | <openerp> |
1734 | - <data> |
1735 | - <record id="view_contract_service_activate" model="ir.ui.view"> |
1736 | - <field name="name">Activate Service</field> |
1737 | - <field name="model">contract.service.activate</field> |
1738 | - <field name="arch" type="xml"> |
1739 | - <form string="Activate Service" version="7.0"> |
1740 | - <group> |
1741 | - <field name="activation_date" /> |
1742 | - <field name="account_id" invisible="1" /> |
1743 | - <field name="service_id" invisible="1" /> |
1744 | - </group> |
1745 | - <footer> |
1746 | - <button |
1747 | - name="activate" |
1748 | - string="Activate" |
1749 | - type="object" |
1750 | - class="oe_highlight" /> |
1751 | - <button |
1752 | - string="Cancel" |
1753 | - class="oe_link" |
1754 | - special="cancel" /> |
1755 | - </footer> |
1756 | - </form> |
1757 | - </field> |
1758 | - </record> |
1759 | - <record id="action_view_contract_service_activate" model="ir.actions.act_window"> |
1760 | - <field name="name">Activate Service</field> |
1761 | - <field name="type">ir.actions.act_window</field> |
1762 | - <field name="src_model">contract.service</field> |
1763 | - <field name="res_model">contract.service.activate</field> |
1764 | - <field name="view_type">form</field> |
1765 | - <field name="view_mode">form</field> |
1766 | - <field name="context">{'default_service_id': active_id}</field> |
1767 | - <field name="target">new</field> |
1768 | - </record> |
1769 | + <data> |
1770 | + <record id="view_contract_service_activate" model="ir.ui.view"> |
1771 | + <field name="name">Activate Service</field> |
1772 | + <field name="model">contract.service.activate</field> |
1773 | + <field name="arch" type="xml"> |
1774 | + <form string="Activate Service" version="7.0"> |
1775 | + <group> |
1776 | + <field name="activation_date" /> |
1777 | + <field name="account_id" invisible="1" /> |
1778 | + <field name="service_id" invisible="1" /> |
1779 | + </group> |
1780 | + <footer> |
1781 | + <button |
1782 | + name="activate" |
1783 | + string="Activate" |
1784 | + type="object" |
1785 | + class="oe_highlight" /> |
1786 | + <button |
1787 | + string="Cancel" |
1788 | + class="oe_link" |
1789 | + special="cancel" /> |
1790 | + </footer> |
1791 | + </form> |
1792 | + </field> |
1793 | + </record> |
1794 | + |
1795 | + <record id="view_contract_service_deactivate" model="ir.ui.view"> |
1796 | + <field name="name">Deactivate Service</field> |
1797 | + <field name="model">contract.service.deactivate</field> |
1798 | + <field name="arch" type="xml"> |
1799 | + <form string="Dectivate Service" version="7.0"> |
1800 | + <group> |
1801 | + <field name="deactivation_date" /> |
1802 | + <field name="account_id" invisible="1" /> |
1803 | + <field name="service_id" invisible="1" /> |
1804 | + </group> |
1805 | + <footer> |
1806 | + <button |
1807 | + name="deactivate" |
1808 | + string="Deactivate" |
1809 | + type="object" |
1810 | + class="oe_highlight" /> |
1811 | + <button |
1812 | + string="Cancel" |
1813 | + class="oe_link" |
1814 | + special="cancel" /> |
1815 | + </footer> |
1816 | + </form> |
1817 | + </field> |
1818 | + </record> |
1819 | + <record id="action_view_contract_service_activate" model="ir.actions.act_window"> |
1820 | + <field name="name">Activate Service</field> |
1821 | + <field name="type">ir.actions.act_window</field> |
1822 | + <field name="src_model">contract.service</field> |
1823 | + <field name="res_model">contract.service.activate</field> |
1824 | + <field name="view_type">form</field> |
1825 | + <field name="view_mode">form</field> |
1826 | + <field name="context">{'default_service_id': active_id}</field> |
1827 | + <field name="target">new</field> |
1828 | + </record> |
1829 | + <record id="action_view_contract_service_deactivate" model="ir.actions.act_window"> |
1830 | + <field name="name">Deactivate Service</field> |
1831 | + <field name="type">ir.actions.act_window</field> |
1832 | + <field name="src_model">contract.service</field> |
1833 | + <field name="res_model">contract.service.deactivate</field> |
1834 | + <field name="view_type">form</field> |
1835 | + <field name="view_mode">form</field> |
1836 | + <field name="context">{'default_service_id': active_id}</field> |
1837 | + <field name="target">new</field> |
1838 | + </record> |
1839 | |
1840 | </data> |
1841 | </openerp> |
1842 | |
1843 | === modified file 'contract_isp_automatic_invoicing/contract.py' |
1844 | --- contract_isp_automatic_invoicing/contract.py 2013-11-01 16:15:27 +0000 |
1845 | +++ contract_isp_automatic_invoicing/contract.py 2014-11-24 15:05:14 +0000 |
1846 | @@ -19,7 +19,11 @@ |
1847 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
1848 | # |
1849 | ############################################################################## |
1850 | -from openerp.osv import orm, fields |
1851 | +from openerp.osv import orm |
1852 | + |
1853 | +from openerp.addons.contract_isp_invoice.invoice import ( |
1854 | + PROCESS_CRON, |
1855 | +) |
1856 | |
1857 | |
1858 | class account_analytic_account(orm.Model): |
1859 | @@ -42,5 +46,5 @@ |
1860 | |
1861 | for contract_id in ids_to_invoice: |
1862 | self.create_analytic_lines(cr, uid, [contract_id], context=context) |
1863 | - self.create_invoice(cr, uid, contract_id, context=context) |
1864 | + self.create_invoice(cr, uid, contract_id, PROCESS_CRON, context=context) |
1865 | cr.commit() |
1866 | |
1867 | === modified file 'contract_isp_automatic_invoicing/i18n/contract_isp_automatic_invoicing.pot' |
1868 | --- contract_isp_automatic_invoicing/i18n/contract_isp_automatic_invoicing.pot 2013-09-16 17:59:01 +0000 |
1869 | +++ contract_isp_automatic_invoicing/i18n/contract_isp_automatic_invoicing.pot 2014-11-24 15:05:14 +0000 |
1870 | @@ -0,0 +1,24 @@ |
1871 | +# Translation of OpenERP Server. |
1872 | +# This file contains the translation of the following modules: |
1873 | +# * contract_isp_automatic_invoicing |
1874 | +# |
1875 | +msgid "" |
1876 | +msgstr "" |
1877 | +"Project-Id-Version: OpenERP Server 7.0\n" |
1878 | +"Report-Msgid-Bugs-To: \n" |
1879 | +"POT-Creation-Date: 2014-09-21 02:50+0000\n" |
1880 | +"PO-Revision-Date: 2014-09-21 02:50+0000\n" |
1881 | +"Last-Translator: <>\n" |
1882 | +"Language-Team: \n" |
1883 | +"MIME-Version: 1.0\n" |
1884 | +"Content-Type: text/plain; charset=UTF-8\n" |
1885 | +"Content-Transfer-Encoding: \n" |
1886 | +"Plural-Forms: \n" |
1887 | + |
1888 | +#. module: contract_isp_automatic_invoicing |
1889 | +#: code:_description:0 |
1890 | +#: model:ir.model,name:contract_isp_automatic_invoicing.model_account_analytic_account |
1891 | +#, python-format |
1892 | +msgid "Analytic Account" |
1893 | +msgstr "" |
1894 | + |
1895 | |
1896 | === added file 'contract_isp_automatic_invoicing/i18n/fr.po' |
1897 | --- contract_isp_automatic_invoicing/i18n/fr.po 1970-01-01 00:00:00 +0000 |
1898 | +++ contract_isp_automatic_invoicing/i18n/fr.po 2014-11-24 15:05:14 +0000 |
1899 | @@ -0,0 +1,24 @@ |
1900 | +# Translation of OpenERP Server. |
1901 | +# This file contains the translation of the following modules: |
1902 | +# * contract_isp_automatic_invoicing |
1903 | +# |
1904 | +msgid "" |
1905 | +msgstr "" |
1906 | +"Project-Id-Version: OpenERP Server 7.0\n" |
1907 | +"Report-Msgid-Bugs-To: \n" |
1908 | +"POT-Creation-Date: 2014-09-21 02:50+0000\n" |
1909 | +"PO-Revision-Date: 2014-09-20 22:52-0500\n" |
1910 | +"Last-Translator: Marc Cassuto <marc.cassuto@savoirfairelinux.com>\n" |
1911 | +"Language-Team: \n" |
1912 | +"MIME-Version: 1.0\n" |
1913 | +"Content-Type: text/plain; charset=UTF-8\n" |
1914 | +"Content-Transfer-Encoding: 8bit\n" |
1915 | +"Language: fr\n" |
1916 | +"X-Generator: Poedit 1.5.4\n" |
1917 | + |
1918 | +#. module: contract_isp_automatic_invoicing |
1919 | +#: code:_description:0 |
1920 | +#: model:ir.model,name:contract_isp_automatic_invoicing.model_account_analytic_account |
1921 | +#, python-format |
1922 | +msgid "Analytic Account" |
1923 | +msgstr "Contrat" |
1924 | |
1925 | === modified file 'contract_isp_invoice/__init__.py' |
1926 | --- contract_isp_invoice/__init__.py 2013-09-16 17:59:01 +0000 |
1927 | +++ contract_isp_invoice/__init__.py 2014-11-24 15:05:14 +0000 |
1928 | @@ -20,5 +20,8 @@ |
1929 | # |
1930 | ############################################################################## |
1931 | |
1932 | -import contract |
1933 | -import wizard |
1934 | +from . import ( |
1935 | + contract, |
1936 | + invoice, |
1937 | + wizard, |
1938 | +) |
1939 | |
1940 | === modified file 'contract_isp_invoice/contract.py' |
1941 | --- contract_isp_invoice/contract.py 2014-01-20 04:25:39 +0000 |
1942 | +++ contract_isp_invoice/contract.py 2014-11-24 15:05:14 +0000 |
1943 | @@ -20,20 +20,38 @@ |
1944 | # |
1945 | ############################################################################## |
1946 | |
1947 | +import calendar |
1948 | +import datetime |
1949 | +import logging |
1950 | import sys |
1951 | -import logging |
1952 | import time |
1953 | -import datetime |
1954 | + |
1955 | from openerp.osv import orm, fields |
1956 | from openerp.tools.translate import _ |
1957 | -import openerp.addons.decimal_precision as dp |
1958 | -from openerp.addons.contract_isp.contract import add_months, date_interval |
1959 | +from openerp.addons.contract_isp.contract import add_months |
1960 | +from openerp.tools import DEFAULT_SERVER_DATE_FORMAT |
1961 | from openerp import netsvc |
1962 | import openerp.exceptions |
1963 | |
1964 | +from .invoice import PROCESS_PRORATA, PROCESS_RECURRENT |
1965 | + |
1966 | _logger = logging.getLogger(__name__) |
1967 | |
1968 | |
1969 | +def count_months_stupid(from_date, to_date): |
1970 | + from_date = from_date.replace(day=1) |
1971 | + to_date = to_date.replace(day=1) |
1972 | + # Don't even bother making this smart for now |
1973 | + count = 0 |
1974 | + while from_date < to_date: |
1975 | + count += 1 |
1976 | + from_date = ( |
1977 | + from_date + datetime.timedelta(days=32) |
1978 | + ).replace(day=1) |
1979 | + |
1980 | + return count |
1981 | + |
1982 | + |
1983 | class res_company(orm.Model): |
1984 | _inherit = "res.company" |
1985 | |
1986 | @@ -68,10 +86,6 @@ |
1987 | |
1988 | _columns = { |
1989 | 'later_validation': fields.boolean('Later Validation'), |
1990 | - 'original_amount': fields.float( |
1991 | - 'Original Amount', digits_compute=dp.get_precision('Account'), |
1992 | - required=True, readonly=True, |
1993 | - states={'draft':[('readonly',False)]}), |
1994 | } |
1995 | |
1996 | _defaults = { |
1997 | @@ -98,11 +112,6 @@ |
1998 | def create(self, cr, uid, data, context=None): |
1999 | if context is None: |
2000 | context = {} |
2001 | - if context.get('original_amount', False) and data.get('amount', False): |
2002 | - if data['amount'] < data['original_amount']: |
2003 | - raise orm.except_orm( |
2004 | - _('Error'), |
2005 | - _('Amount cannot be less than the invoice amount')) |
2006 | |
2007 | return super(account_voucher, self).create( |
2008 | cr, uid, data, context=context) |
2009 | @@ -114,7 +123,6 @@ |
2010 | ret = True |
2011 | account_analytic_account_obj = self.pool.get( |
2012 | 'account.analytic.account') |
2013 | - account_invoice_obj = self.pool.get('account.invoice') |
2014 | |
2015 | voucher = self.browse(cr, uid, ids[0], context=context) |
2016 | |
2017 | @@ -132,10 +140,14 @@ |
2018 | inv = account_analytic_account_obj.create_invoice( |
2019 | cr, uid, context.get('active_id'), context=context) |
2020 | |
2021 | - a = account_invoice_obj._workflow_signal( |
2022 | - cr, uid, [inv], |
2023 | - 'invoice_open', context=context) |
2024 | - |
2025 | + wf_service = netsvc.LocalService("workflow") |
2026 | + if isinstance(inv, list): |
2027 | + for i in inv: |
2028 | + wf_service.trg_validate( |
2029 | + uid, 'account.invoice', i, 'invoice_open', cr) |
2030 | + else: |
2031 | + wf_service.trg_validate( |
2032 | + uid, 'account.invoice', inv, 'invoice_open', cr) |
2033 | else: |
2034 | raise openerp.exceptions.Warning(_('Contract not found')) |
2035 | |
2036 | @@ -143,12 +155,12 @@ |
2037 | ret = super(account_voucher, self).proforma_voucher( |
2038 | cr, uid, ids, context=context) |
2039 | |
2040 | - |
2041 | if voucher.journal_id.later_validation is False: |
2042 | account_move_line_obj = self.pool.get('account.move.line') |
2043 | + account_id = voucher.partner_id.property_account_receivable.id |
2044 | query = [ |
2045 | ('partner_id', '=', voucher.partner_id.id), |
2046 | - ('account_id', '=', voucher.partner_id.property_account_receivable.id), |
2047 | + ('account_id', '=', account_id), |
2048 | ('reconcile_id', '=', False) |
2049 | ] |
2050 | |
2051 | @@ -160,14 +172,13 @@ |
2052 | period_obj = self.pool.get('account.period') |
2053 | date = False |
2054 | period_id = False |
2055 | - journal_id = False |
2056 | - account_id = False |
2057 | + journal_id = voucher.journal_id.id |
2058 | |
2059 | date = time.strftime('%Y-%m-%d') |
2060 | ctx = dict(context or {}, account_period_prefer_normal=True) |
2061 | period_ids = period_obj.find(cr, uid, dt=date, context=ctx) |
2062 | if period_ids: |
2063 | - period_id = ids[0] |
2064 | + period_id = period_ids[0] |
2065 | account_move_line_obj.reconcile(cr, uid, ids_to_reconcile, |
2066 | 'manual', account_id, |
2067 | period_id, journal_id, |
2068 | @@ -204,140 +215,399 @@ |
2069 | } |
2070 | |
2071 | |
2072 | +class contract_service(orm.Model): |
2073 | + _inherit = 'contract.service' |
2074 | + |
2075 | + def _get_invoice_day(self, cr, uid, context): |
2076 | + res_company_obj = self.pool["res.company"] |
2077 | + res_company_data = res_company_obj.read( |
2078 | + cr, uid, |
2079 | + res_company_obj._company_default_get(cr, uid, context), |
2080 | + context=context) |
2081 | + |
2082 | + invoice_day = int(res_company_data['invoice_day']) |
2083 | + return invoice_day |
2084 | + |
2085 | + def _get_prorata_interval_rate(self, cr, uid, change_date, context=None): |
2086 | + """ Get the prorata interval and price rate. |
2087 | + |
2088 | + Returns a tuple (start_date, end_date, price percent) |
2089 | + """ |
2090 | + today = (context or {}).get("operation_date", datetime.date.today()) |
2091 | + invoice_day = self._get_invoice_day(cr, uid, context) |
2092 | + |
2093 | + curmonth_days = calendar.monthrange(today.year, |
2094 | + today.month)[1] |
2095 | + month_days = calendar.monthrange(change_date.year, |
2096 | + change_date.month)[1] |
2097 | + |
2098 | + if invoice_day < today.day: |
2099 | + start_date = add_months(change_date, 1) |
2100 | + end_date = add_months(today, 1) |
2101 | + end_date = end_date.replace( |
2102 | + day=calendar.monthrange(end_date.year, |
2103 | + end_date.month)[1], |
2104 | + ) |
2105 | + month_days = calendar.monthrange(start_date.year, |
2106 | + start_date.month)[1] |
2107 | + ptx = self._prorata_rate( |
2108 | + month_days - start_date.day, |
2109 | + month_days, |
2110 | + ) |
2111 | + ptx += count_months_stupid(start_date, end_date) |
2112 | + |
2113 | + else: # if today_date <= invoice_day: |
2114 | + if change_date < today.replace(day=1): |
2115 | + # Activation in previous month |
2116 | + start_date = add_months(change_date, 1) |
2117 | + end_date = today.replace(day=curmonth_days) |
2118 | + month_days = calendar.monthrange(start_date.year, |
2119 | + start_date.month)[1] |
2120 | + ptx = self._prorata_rate( |
2121 | + month_days - start_date.day, |
2122 | + month_days, |
2123 | + ) |
2124 | + ptx += count_months_stupid(start_date, end_date) |
2125 | + else: |
2126 | + # Activation is in current month (or future - same) |
2127 | + end_date = add_months(change_date, 1) |
2128 | + start_date = end_date.replace(day=1) |
2129 | + ptx = -1 * self._prorata_rate( |
2130 | + end_date.day, |
2131 | + calendar.monthrange(end_date.year, |
2132 | + end_date.month)[1], |
2133 | + ) |
2134 | + |
2135 | + return start_date, end_date, ptx |
2136 | + |
2137 | + def _get_prorata_interval_rate_deactivate(self, cr, uid, change_date, |
2138 | + context=None): |
2139 | + today = (context or {}).get("operation_date", datetime.date.today()) |
2140 | + invoice_day = self._get_invoice_day(cr, uid, context) |
2141 | + |
2142 | + if invoice_day < today.day: |
2143 | + start_date = change_date |
2144 | + end_date = add_months(today, 1) |
2145 | + end_date = end_date.replace( |
2146 | + day=calendar.monthrange(end_date.year, |
2147 | + end_date.month)[1], |
2148 | + ) |
2149 | + |
2150 | + month_days = calendar.monthrange(start_date.year, |
2151 | + start_date.month)[1] |
2152 | + ptx = -1 * self._prorata_rate( |
2153 | + month_days - start_date.day, |
2154 | + month_days, |
2155 | + ) |
2156 | + ptx -= count_months_stupid(start_date, end_date) |
2157 | + else: # if today <= invoice_day |
2158 | + if change_date < today: |
2159 | + # Deactivation in the past, refund period from |
2160 | + # deactivation to end of current month |
2161 | + start_date = change_date |
2162 | + end_date = today.replace( |
2163 | + day=calendar.monthrange(today.year, |
2164 | + today.month)[1], |
2165 | + ) |
2166 | + |
2167 | + month_days = calendar.monthrange(start_date.year, |
2168 | + start_date.month)[1] |
2169 | + ptx = -1 * self._prorata_rate( |
2170 | + month_days - start_date.day, |
2171 | + month_days, |
2172 | + ) |
2173 | + ptx -= count_months_stupid(start_date, end_date) |
2174 | + else: |
2175 | + # Deactivation in future, bill period from now to deactivation |
2176 | + start_date = today |
2177 | + end_date = change_date |
2178 | + start_month_days = calendar.monthrange(start_date.year, |
2179 | + start_date.month)[1] |
2180 | + end_month_days = calendar.monthrange(end_date.year, |
2181 | + end_date.month)[1] |
2182 | + if add_months(start_date, 1).replace(day=1) > end_date: |
2183 | + # Both dates in same month |
2184 | + ptx = self._prorata_rate( |
2185 | + end_date.day - start_date.day, |
2186 | + start_month_days, |
2187 | + ) |
2188 | + else: |
2189 | + ptx = sum(( |
2190 | + # Rate for first month |
2191 | + self._prorata_rate(start_month_days - start_date.day, |
2192 | + start_month_days), |
2193 | + # Each full month excluding end month |
2194 | + count_months_stupid(start_date, end_date) - 1, |
2195 | + # Rate for end month |
2196 | + self._prorata_rate(end_date.day, |
2197 | + end_month_days), |
2198 | + )) |
2199 | + |
2200 | + return start_date, end_date, ptx |
2201 | + |
2202 | + |
2203 | class account_analytic_account(orm.Model): |
2204 | _inherit = "account.analytic.account" |
2205 | |
2206 | _columns = { |
2207 | 'close_date': fields.datetime('Close date'), |
2208 | - 'close_reason': fields.text('Reasons') |
2209 | + 'close_reason': fields.text('Reasons'), |
2210 | } |
2211 | |
2212 | _defaults = { |
2213 | 'close_date': fields.datetime.now |
2214 | } |
2215 | |
2216 | - def create_invoice(self, cr, uid, ids, prorata=False, context=None): |
2217 | - return_int = False |
2218 | - if isinstance(ids, int): |
2219 | - return_int = True |
2220 | + def get_last_invoice_date(self, cr, uid, ids, source_process, inv=False, |
2221 | + context=None): |
2222 | + res = {} |
2223 | + source_process = tuple((source_process or '').split(",")) |
2224 | + account_ids = tuple(ids) |
2225 | + if not ids: |
2226 | + return res |
2227 | + |
2228 | + cr.execute( |
2229 | + """ |
2230 | + SELECT account_analytic_line.account_id |
2231 | + , DATE(MAX(account_invoice.date_invoice)) |
2232 | + FROM account_analytic_line |
2233 | + JOIN account_invoice |
2234 | + ON account_analytic_line.invoice_id = account_invoice.id |
2235 | + WHERE account_analytic_line.account_id IN %s |
2236 | + AND account_analytic_line.invoice_id IS NOT NULL |
2237 | + AND {neg} COALESCE(account_invoice.source_process, '') IN %s |
2238 | + GROUP BY account_analytic_line.account_id |
2239 | + """.format(neg=('NOT' if inv else '')), |
2240 | + (account_ids, source_process), |
2241 | + ) |
2242 | + |
2243 | + for account_id, lid in cr.fetchall(): |
2244 | + res[account_id] = lid |
2245 | + return res |
2246 | + |
2247 | + def get_last_invoice_date_non_prorata(self, cr, uid, ids, context=None): |
2248 | + return self.get_last_invoice_date(cr, uid, ids, |
2249 | + PROCESS_PRORATA, inv=True, |
2250 | + context=context) |
2251 | + |
2252 | + def send_email_contract_invoice(self, cr, uid, ids, context=None): |
2253 | + context = context or {} |
2254 | + |
2255 | + if not isinstance(ids, list): |
2256 | ids = [ids] |
2257 | |
2258 | - account_analytic_account_obj = self.pool.get('account.analytic.account') |
2259 | - account_analytic_line = self.pool.get('account.analytic.line') |
2260 | - contract_service_obj = self.pool.get('contract.service') |
2261 | - res_company_obj = self.pool.get('res.company') |
2262 | account_invoice_obj = self.pool.get('account.invoice') |
2263 | - res_company_data = res_company_obj.read( |
2264 | - cr, uid, |
2265 | - res_company_obj._company_default_get(cr, uid, context), |
2266 | - context=context) |
2267 | + mail_template_obj = self.pool.get('email.template') |
2268 | + ir_model_data_obj = self.pool.get('ir.model.data') |
2269 | + mail_template_id = ir_model_data_obj.get_object_reference( |
2270 | + cr, uid, 'account', |
2271 | + 'email_template_edi_invoice')[1] |
2272 | + mail_mail_obj = self.pool.get('mail.mail') |
2273 | + |
2274 | + for inv in ids: |
2275 | + _logger.info( |
2276 | + "Mailing invoice %s" % account_invoice_obj.browse( |
2277 | + cr, uid, inv, context=context).name) |
2278 | + |
2279 | + try: |
2280 | + mail_id = mail_template_obj.send_mail( |
2281 | + cr, uid, mail_template_id, inv, context=context) |
2282 | + mail_message = mail_mail_obj.browse( |
2283 | + cr, uid, mail_id, |
2284 | + context=context).mail_message_id |
2285 | + mail_message.write({'type': 'email'}) |
2286 | + except: |
2287 | + _logger.error( |
2288 | + 'Error generating mail for invoice %s:' |
2289 | + '\n\n%s' % ( |
2290 | + account_invoice_obj.browse( |
2291 | + cr, uid, inv, context=context).name, |
2292 | + sys.exc_info()[0])) |
2293 | + |
2294 | + return True |
2295 | + |
2296 | + def _create_invoice(self, cr, uid, ids, context=None): |
2297 | + context = context or {} |
2298 | + |
2299 | + data = { |
2300 | + 'name': True, |
2301 | + } |
2302 | + |
2303 | + if context.get('create_invoice_mode', 'contract') == 'reseller': |
2304 | + data.update({'partner': True}) |
2305 | + |
2306 | + res = [] |
2307 | + |
2308 | + account_analytic_line_obj = self.pool['account.analytic.line'] |
2309 | + account_invoice_obj = self.pool['account.invoice'] |
2310 | + account_invoice_line_obj = self.pool['account.invoice.line'] |
2311 | + move_obj = self.pool["account.move"] |
2312 | wf_service = netsvc.LocalService("workflow") |
2313 | |
2314 | - if res_company_data['send_email_contract_invoice']: |
2315 | - mail_template_obj = self.pool.get('email.template') |
2316 | - ir_model_data_obj = self.pool.get('ir.model.data') |
2317 | - mail_template_id = ir_model_data_obj.get_object_reference( |
2318 | - cr, uid, 'account', |
2319 | - 'email_template_edi_invoice')[1] |
2320 | - mail_mail_obj = self.pool.get('mail.mail') |
2321 | - |
2322 | - cuttoff_day = res_company_data['cutoff_day'] |
2323 | - |
2324 | - cutoff_date = datetime.date( |
2325 | - datetime.date.today().year, |
2326 | - datetime.date.today().month, |
2327 | - int(cuttoff_day) |
2328 | + if sum(-line.amount |
2329 | + for line in account_analytic_line_obj.browse( |
2330 | + cr, uid, ids, context=context) |
2331 | + ) < 0: |
2332 | + for line in account_analytic_line_obj.browse(cr, uid, ids, context=context): |
2333 | + line.write({"amount": -line.amount}) |
2334 | + context["type"] = "out_refund" |
2335 | + |
2336 | + inv = account_analytic_line_obj.invoice_cost_create( |
2337 | + cr, uid, ids, data=data, context=context) |
2338 | + |
2339 | + if isinstance(inv, list): |
2340 | + # vvinet - this could mess up refunds/invoices, does it get called? |
2341 | + if len(inv) > 1: |
2342 | + # Merge invoices |
2343 | + query = [('invoice_id', 'in', inv)] |
2344 | + line_ids = account_invoice_line_obj.search( |
2345 | + cr, uid, query, context=context) |
2346 | + account_invoice_line_obj.write( |
2347 | + cr, uid, line_ids, {'invoice_id': inv[0]}, |
2348 | + context=context) |
2349 | + account_invoice_obj.button_compute( |
2350 | + cr, uid, [inv[0]], context=context) |
2351 | + account_invoice_obj.unlink(cr, uid, inv[1:], context=context) |
2352 | + |
2353 | + inv = inv[0] |
2354 | + |
2355 | + # vvinet - any of the passed ids that did not get assigned to an |
2356 | + # invoice gets assigned to the first one |
2357 | + unassigned_ids = account_invoice_line_obj.search( |
2358 | + cr, uid, [('id', 'in', ids), ('invoice_id', '=', False)], |
2359 | ) |
2360 | - |
2361 | + if unassigned_ids: |
2362 | + account_invoice_line_obj.write(cr, uid, {'invoice_id': inv}) |
2363 | + |
2364 | + res.append(inv) |
2365 | + |
2366 | + # jgama - If its a prorata invoice, change the invoice date |
2367 | + # according to the invoice_day variable |
2368 | + to_write = {} |
2369 | + if context.get('source_process'): |
2370 | + to_write['source_process'] = context['source_process'] |
2371 | + if context.get('date_invoice') and ( |
2372 | + context.get('prorata', False) or |
2373 | + context.get('source_process') == PROCESS_RECURRENT): |
2374 | + to_write['date_invoice'] = context.get('date_invoice') |
2375 | + |
2376 | + if to_write: |
2377 | + account_invoice_obj.write(cr, uid, inv, to_write, context=context) |
2378 | + |
2379 | + if context.get('not_subscription_voucher', True): |
2380 | + _logger.debug( |
2381 | + "Opening invoice %s" % account_invoice_obj.browse( |
2382 | + cr, uid, inv, context=context).name) |
2383 | + |
2384 | + wf_service.trg_validate( |
2385 | + uid, 'account.invoice', inv, 'invoice_open', cr) |
2386 | + |
2387 | + return res |
2388 | + |
2389 | + def create_invoice(self, cr, uid, ids, source_process=None, context=None): |
2390 | + context = context or {} |
2391 | + prorata = (source_process == PROCESS_PRORATA) |
2392 | + context["source_process"] = source_process |
2393 | + _logger.debug("create_invoice %r %s", ids, prorata) |
2394 | + |
2395 | + if not isinstance(ids, list): |
2396 | + ids = [ids] |
2397 | + |
2398 | + date = context.get("operation_date", datetime.date.today()) |
2399 | + if not isinstance(date, datetime.date): |
2400 | + date = datetime.datetime.strptime( |
2401 | + date, |
2402 | + DEFAULT_SERVER_DATE_FORMAT, |
2403 | + ).date() |
2404 | + |
2405 | + account_analytic_account_obj = self.pool['account.analytic.account'] |
2406 | + account_analytic_line_obj = self.pool['account.analytic.line'] |
2407 | + res_company_obj = self.pool['res.company'] |
2408 | + res_company_data = res_company_obj.read( |
2409 | + cr, uid, |
2410 | + res_company_obj._company_default_get(cr, uid, context), |
2411 | + context=context) |
2412 | + |
2413 | + cutoff_day = res_company_data['cutoff_day'] |
2414 | + |
2415 | + cutoff_date = datetime.date(date.year, date.month, int(cutoff_day)) |
2416 | invoice_day = res_company_data['invoice_day'] |
2417 | |
2418 | - invoice_date = datetime.date( |
2419 | - datetime.date.today().year, |
2420 | - datetime.date.today().month, |
2421 | - int(invoice_day) |
2422 | - ) |
2423 | + invoice_date = date.replace(day=int(invoice_day)) |
2424 | |
2425 | - if prorata: |
2426 | - if datetime.date.today() <= cutoff_date: |
2427 | - date_invoice = invoice_date.strftime('%Y-%m-%d') |
2428 | + ctx = dict(context.copy(), prorata=prorata) |
2429 | + if prorata or source_process == PROCESS_RECURRENT: |
2430 | + if date <= cutoff_date: |
2431 | + ctx.update(date_invoice=invoice_date.strftime('%Y-%m-%d')) |
2432 | else: |
2433 | - date_invoice = add_months(invoice_date, 1).strftime( |
2434 | - '%Y-%m-%d') |
2435 | - |
2436 | - ret = [] |
2437 | - for contract_id in ids: |
2438 | - query = [('account_id', '=', contract_id), |
2439 | + ctx.update( |
2440 | + date_invoice=add_months(invoice_date, 1).strftime( |
2441 | + '%Y-%m-%d') |
2442 | + ) |
2443 | + |
2444 | + res = [] |
2445 | + |
2446 | + if context.get('create_invoice_mode', 'contract') != 'reseller': |
2447 | + for contract_id in ids: |
2448 | + query = [('account_id', '=', contract_id), |
2449 | + ('to_invoice', '!=', False), |
2450 | + ('invoice_id', '=', False), |
2451 | + ('product_id', '!=', False), |
2452 | + ('is_prorata', '=', prorata)] |
2453 | + |
2454 | + ids_to_invoice = account_analytic_line_obj.search( |
2455 | + cr, uid, query, context=context) |
2456 | + |
2457 | + if ids_to_invoice: |
2458 | + _logger.info( |
2459 | + "Invoicing contract %s lines %r", |
2460 | + account_analytic_account_obj.browse( |
2461 | + cr, uid, contract_id, context=context).name, |
2462 | + ids_to_invoice, |
2463 | + ) |
2464 | + |
2465 | + inv = self._create_invoice( |
2466 | + cr, uid, ids_to_invoice, context=ctx.copy()) |
2467 | + |
2468 | + if isinstance(inv, list): |
2469 | + for i in inv: |
2470 | + res.append(i) |
2471 | + else: |
2472 | + res.append(inv) |
2473 | + |
2474 | + if res_company_data['send_email_contract_invoice']: |
2475 | + self.send_email_contract_invoice( |
2476 | + cr, uid, inv, context=context) |
2477 | + |
2478 | + else: |
2479 | + query = [('account_id', 'in', ids), |
2480 | ('to_invoice', '!=', False), |
2481 | ('invoice_id', '=', False), |
2482 | ('product_id', '!=', False), |
2483 | ('is_prorata', '=', prorata)] |
2484 | |
2485 | - ids_to_invoice = account_analytic_line.search(cr, uid, query, |
2486 | - context=context) |
2487 | + ids_to_invoice = account_analytic_line_obj.search( |
2488 | + cr, uid, query, context=context) |
2489 | if ids_to_invoice: |
2490 | _logger.info( |
2491 | - "Invoicing contract %s" % |
2492 | + "Invoicing partner %s" % |
2493 | account_analytic_account_obj.browse( |
2494 | - cr, uid, contract_id, context=context).name) |
2495 | - |
2496 | - data = { |
2497 | - 'name': True, |
2498 | - } |
2499 | - inv = account_analytic_line.invoice_cost_create( |
2500 | - cr, uid, ids_to_invoice, data=data, context=context) |
2501 | + cr, uid, ids[0], context=context).partner_id.parent_id.name) |
2502 | + |
2503 | + inv = self._create_invoice( |
2504 | + cr, uid, ids_to_invoice, context=ctx) |
2505 | + |
2506 | if isinstance(inv, list): |
2507 | for i in inv: |
2508 | - ret.append(i) |
2509 | - |
2510 | + res.append(i) |
2511 | else: |
2512 | - ret.append(inv) |
2513 | - |
2514 | - # jgama - If its a prorata invoice, change the invoice date |
2515 | - # according to the invoice_day variable |
2516 | - if prorata: |
2517 | - account_invoice_obj.write( |
2518 | - cr, uid, inv, {'date_invoice': date_invoice}, |
2519 | - context=context) |
2520 | - |
2521 | - if context.get('not_subscription_voucher', True): |
2522 | - _logger.debug( |
2523 | - "Opening invoice %s" % account_invoice_obj.browse( |
2524 | - cr, uid, inv[0], context=context).name) |
2525 | - |
2526 | - wf_service.trg_validate( |
2527 | - uid, 'account.invoice', inv[0], 'invoice_open', cr) |
2528 | - #a = account_invoice_obj._workflow_signal( |
2529 | - # cr, uid, inv, 'invoice_open', context) |
2530 | - |
2531 | - if res_company_data['send_email_contract_invoice']: |
2532 | - _logger.info( |
2533 | - "Mailing invoice %s" % account_invoice_obj.browse( |
2534 | - cr, uid, inv[0], context=context).name) |
2535 | - |
2536 | - ctx = dict(context, default_type='email') |
2537 | - |
2538 | - try: |
2539 | - mail_id = mail_template_obj.send_mail( |
2540 | - cr, uid, mail_template_id, inv[0], context=ctx) |
2541 | - mail_message = mail_mail_obj.browse( |
2542 | - cr, uid, mail_id, |
2543 | - context=context).mail_message_id |
2544 | - mail_message.write({'type': 'email'}) |
2545 | - except: |
2546 | - _logger.error( |
2547 | - 'Error generating mail for invoice %s:' |
2548 | - '\n\n%s' % ( |
2549 | - account_invoice_obj.browse( |
2550 | - cr, uid, inv[0], context=context).name, |
2551 | - sys.exc_info()[0])) |
2552 | - |
2553 | - if return_int: |
2554 | - if len(ret) == 0: |
2555 | - return None |
2556 | - else: |
2557 | - return ret[0] |
2558 | - else: |
2559 | - return ret |
2560 | + res.append(inv) |
2561 | + |
2562 | + if res_company_data['send_email_contract_invoice']: |
2563 | + self.send_email_contract_invoice( |
2564 | + cr, uid, inv, context=context) |
2565 | + |
2566 | + return res |
2567 | |
2568 | def set_close(self, cr, uid, ids, context=None): |
2569 | |
2570 | @@ -354,24 +624,36 @@ |
2571 | if context is None: |
2572 | context = {} |
2573 | |
2574 | - res_currency_obj = self.pool.get('res.currency') |
2575 | - account_analytic_account_obj = self.pool.get( |
2576 | - 'account.analytic.account') |
2577 | - account_invoice_obj = self.pool.get('account.invoice') |
2578 | - |
2579 | - cur = self.browse( |
2580 | - cr, uid, ids[0], context=context).pricelist_id.currency_id |
2581 | - |
2582 | + res_currency_obj = self.pool['res.currency'] |
2583 | + fposition_obj = self.pool["account.fiscal.position"] |
2584 | + tax_obj = self.pool["account.tax"] |
2585 | + |
2586 | + voucher = self.browse(cr, uid, ids[0], context=context) |
2587 | + cur = voucher.pricelist_id.currency_id |
2588 | amount_tax = amount_untaxed = 0 |
2589 | - for line in self.browse( |
2590 | - cr, uid, ids[0], context=context).contract_service_ids: |
2591 | - for c in self.pool.get('account.tax').compute_all( |
2592 | - cr, uid, line.product_id.taxes_id, line.unit_price, |
2593 | + for line in self.browse(cr, uid, ids[0], |
2594 | + context=context).contract_service_ids: |
2595 | + line_tax_ids = fposition_obj.map_tax( |
2596 | + cr, uid, |
2597 | + voucher.partner_id.property_account_position, |
2598 | + line.product_id.taxes_id, |
2599 | + context=context) |
2600 | + line_tax_ids = tax_obj.browse(cr, uid, line_tax_ids, |
2601 | + context=context) |
2602 | + |
2603 | + for c in tax_obj.compute_all( |
2604 | + cr, uid, line_tax_ids, line.unit_price, |
2605 | line.qty, line.product_id, |
2606 | line.account_id.partner_id)['taxes']: |
2607 | amount_tax += c.get('amount', 0.0) |
2608 | |
2609 | amount_untaxed += line.unit_price * line.qty |
2610 | + if cur is None: |
2611 | + raise orm.except_orm( |
2612 | + _('No pricelist specified'), |
2613 | + _('You must set a pricelist on the analytic account before' |
2614 | + ' creating vouchers.')) |
2615 | + |
2616 | amount = res_currency_obj.round(cr, uid, cur, amount_tax) + \ |
2617 | res_currency_obj.round(cr, uid, cur, amount_untaxed) |
2618 | |
2619 | @@ -391,7 +673,7 @@ |
2620 | partner.parent_id.id or partner.id |
2621 | |
2622 | return { |
2623 | - 'name': _('Create Voucher'), |
2624 | + 'name': _('Create Initial Invoice'), |
2625 | 'type': 'ir.actions.act_window', |
2626 | 'res_model': 'account.voucher', |
2627 | 'view_type': 'form', |
2628 | @@ -401,7 +683,7 @@ |
2629 | 'context': {'not_subscription_voucher': False, |
2630 | 'default_type': 'receipt', |
2631 | 'default_amount': amount, |
2632 | - 'original_amount': amount, |
2633 | + 'default_original_amount': amount, |
2634 | 'default_partner_id': voucher_partner_id} |
2635 | } |
2636 | |
2637 | @@ -412,6 +694,7 @@ |
2638 | def invoice_cost_create(self, cr, uid, ids, data=None, context=None): |
2639 | # jgama - Sligtly modified version. Original from |
2640 | # hr_timesheet_invoice.py |
2641 | + # vvinet - removed grouping by journal type |
2642 | |
2643 | analytic_account_obj = self.pool.get('account.analytic.account') |
2644 | account_payment_term_obj = self.pool.get('account.payment.term') |
2645 | @@ -427,162 +710,175 @@ |
2646 | if data is None: |
2647 | data = {} |
2648 | |
2649 | - journal_types = {} |
2650 | - |
2651 | - # prepare for iteration on journal and accounts |
2652 | - for line in self.pool.get('account.analytic.line').browse( |
2653 | - cr, uid, ids, context=context): |
2654 | - if line.journal_id.type not in journal_types: |
2655 | - journal_types[line.journal_id.type] = set() |
2656 | - journal_types[line.journal_id.type].add(line.account_id.id) |
2657 | - for journal_type, account_ids in journal_types.items(): |
2658 | - for account in analytic_account_obj.browse( |
2659 | - cr, uid, list(account_ids), context=context): |
2660 | - # jgama - If there's a parent, invoice the parent |
2661 | - partner = account.partner_id.parent_id or account.partner_id |
2662 | - |
2663 | - if (not partner) or not (account.pricelist_id): |
2664 | - raise orm.except_orm( |
2665 | - _('Analytic Account Incomplete!'), |
2666 | - _('Contract incomplete. Please fill in the Customer and Pricelist fields.')) |
2667 | - |
2668 | - date_due = False |
2669 | - if partner.property_payment_term: |
2670 | - pterm_list = account_payment_term_obj.compute( |
2671 | - cr, uid, partner.property_payment_term.id, value=1, |
2672 | - date_ref=time.strftime('%Y-%m-%d')) |
2673 | - if pterm_list: |
2674 | - pterm_list = [line[0] for line in pterm_list] |
2675 | - pterm_list.sort() |
2676 | - date_due = pterm_list[-1] |
2677 | - |
2678 | - curr_invoice = { |
2679 | - 'name': time.strftime('%d/%m/%Y') + ' - ' + account.name, |
2680 | - 'origin': account.name, |
2681 | - 'partner_id': partner.id, |
2682 | - 'company_id': account.company_id.id, |
2683 | - 'payment_term': partner.property_payment_term.id or False, |
2684 | - 'account_id': partner.property_account_receivable.id, |
2685 | - 'currency_id': account.pricelist_id.currency_id.id, |
2686 | - 'date_due': date_due, |
2687 | - 'fiscal_position': partner.property_account_position.id |
2688 | + account_ids = list(set( |
2689 | + line.account_id.id |
2690 | + for line in self.pool.get('account.analytic.line').browse( |
2691 | + cr, uid, ids, context=context) |
2692 | + )) |
2693 | + |
2694 | + for account in analytic_account_obj.browse( |
2695 | + cr, uid, list(account_ids), context=context): |
2696 | + # jgama - If there's a parent, invoice the parent |
2697 | + if account.partner_id.parent_id: |
2698 | + partner = account.partner_id.parent_id |
2699 | + line_prefix = u" - ".join(filter(None, ( |
2700 | + account.partner_id.code, |
2701 | + account.partner_id.name, |
2702 | + ))) |
2703 | + else: |
2704 | + partner = account.partner_id |
2705 | + line_prefix = None |
2706 | + |
2707 | + if (not partner) or not (account.pricelist_id): |
2708 | + raise orm.except_orm( |
2709 | + _('Analytic Account Incomplete!'), |
2710 | + _('Contract incomplete. Please fill in the Customer ' |
2711 | + 'and Pricelist fields.')) |
2712 | + |
2713 | + date_due = False |
2714 | + if partner.property_payment_term: |
2715 | + pterm_list = account_payment_term_obj.compute( |
2716 | + cr, uid, partner.property_payment_term.id, value=1, |
2717 | + date_ref=time.strftime('%Y-%m-%d')) |
2718 | + if pterm_list: |
2719 | + pterm_list = [line[0] for line in pterm_list] |
2720 | + pterm_list.sort() |
2721 | + date_due = pterm_list[-1] |
2722 | + |
2723 | + curr_invoice = { |
2724 | + 'name': time.strftime('%d/%m/%Y') + ' - ' + account.name, |
2725 | + 'origin': account.name, |
2726 | + 'partner_id': partner.id, |
2727 | + 'company_id': account.company_id.id, |
2728 | + 'payment_term': partner.property_payment_term.id or False, |
2729 | + 'account_id': partner.property_account_receivable.id, |
2730 | + 'currency_id': account.pricelist_id.currency_id.id, |
2731 | + 'date_due': date_due, |
2732 | + 'fiscal_position': partner.property_account_position.id |
2733 | + } |
2734 | + context2 = context.copy() |
2735 | + context2['lang'] = partner.lang |
2736 | + # set company_id in context, so the correct default journal |
2737 | + # will be selected |
2738 | + context2['force_company'] = curr_invoice['company_id'] |
2739 | + # set force_company in context so the correct product |
2740 | + # properties are selected (eg. income account) |
2741 | + context2['company_id'] = curr_invoice['company_id'] |
2742 | + |
2743 | + last_invoice = invoice_obj.create( |
2744 | + cr, uid, curr_invoice, context=context2) |
2745 | + invoices.append(last_invoice) |
2746 | + |
2747 | + cr.execute(""" |
2748 | + SELECT product_id, user_id, to_invoice, sum(amount), sum(unit_amount), product_uom_id |
2749 | + FROM account_analytic_line as line |
2750 | + WHERE account_id = %s |
2751 | + AND line.id IN %s |
2752 | + AND to_invoice IS NOT NULL |
2753 | + GROUP BY product_id, user_id, to_invoice, product_uom_id |
2754 | + """, (account.id, tuple(ids))) |
2755 | + |
2756 | + for product_id, user_id, factor_id, total_price, qty, uom in cr.fetchall(): |
2757 | + context2.update({'uom': uom}) |
2758 | + |
2759 | + if data.get('product'): |
2760 | + # force product, use its public price |
2761 | + product_id = data['product'][0] |
2762 | + unit_price = self._get_invoice_price( |
2763 | + cr, uid, account, product_id, user_id, qty, context2) |
2764 | + else: |
2765 | + # expenses, using price from amount field |
2766 | + unit_price = qty and total_price * -1.0 / qty or 0.0 |
2767 | + |
2768 | + factor = invoice_factor_obj.browse( |
2769 | + cr, uid, factor_id, context=context2) |
2770 | + # factor_name = factor.customer_name and line_name + ' - ' + factor.customer_name or line_name |
2771 | + factor_name = '' |
2772 | + if data.get('factor_name', False): |
2773 | + factor_name = factor.customer_name |
2774 | + |
2775 | + curr_line = { |
2776 | + 'price_unit': unit_price, |
2777 | + 'quantity': qty, |
2778 | + 'product_id': product_id or False, |
2779 | + 'discount': factor.factor, |
2780 | + 'invoice_id': last_invoice, |
2781 | + 'name': factor_name, |
2782 | + 'uos_id': uom, |
2783 | + 'account_analytic_id': account.id, |
2784 | } |
2785 | - context2 = context.copy() |
2786 | - context2['lang'] = partner.lang |
2787 | - # set company_id in context, so the correct default journal |
2788 | - # will be selected |
2789 | - context2['force_company'] = curr_invoice['company_id'] |
2790 | - # set force_company in context so the correct product |
2791 | - # properties are selected (eg. income account) |
2792 | - context2['company_id'] = curr_invoice['company_id'] |
2793 | - |
2794 | - last_invoice = invoice_obj.create( |
2795 | - cr, uid, curr_invoice, context=context2) |
2796 | - invoices.append(last_invoice) |
2797 | - |
2798 | - cr.execute("""SELECT product_id, user_id, to_invoice, sum(amount), sum(unit_amount), product_uom_id |
2799 | - FROM account_analytic_line as line LEFT JOIN account_analytic_journal journal ON (line.journal_id = journal.id) |
2800 | - WHERE account_id = %s |
2801 | - AND line.id IN %s AND journal.type = %s AND to_invoice IS NOT NULL |
2802 | - GROUP BY product_id, user_id, to_invoice, product_uom_id""", (account.id, tuple(ids), journal_type)) |
2803 | - |
2804 | - for product_id, user_id, factor_id, total_price, qty, uom in cr.fetchall(): |
2805 | - context2.update({'uom': uom}) |
2806 | - |
2807 | - if data.get('product'): |
2808 | - # force product, use its public price |
2809 | - product_id = data['product'][0] |
2810 | - unit_price = self._get_invoice_price( |
2811 | - cr, uid, account, product_id, user_id, qty, context2) |
2812 | - #elif journal_type == 'general' and product_id: |
2813 | - # # timesheets, use sale price |
2814 | - # unit_price = self._get_invoice_price(cr, uid, account, product_id, user_id, qty, context2) |
2815 | - else: |
2816 | - # expenses, using price from amount field |
2817 | - unit_price = qty and total_price * -1.0 / qty or 0.0 |
2818 | - |
2819 | - factor = invoice_factor_obj.browse( |
2820 | - cr, uid, factor_id, context=context2) |
2821 | - # factor_name = factor.customer_name and line_name + ' - ' + factor.customer_name or line_name |
2822 | - factor_name = '' |
2823 | - if data.get('factor_name', False): |
2824 | - factor_name = factor.customer_name |
2825 | - |
2826 | - curr_line = { |
2827 | - 'price_unit': unit_price, |
2828 | - 'quantity': qty, |
2829 | - 'product_id': product_id or False, |
2830 | - 'discount': factor.factor, |
2831 | - 'invoice_id': last_invoice, |
2832 | + product = product_obj.browse( |
2833 | + cr, uid, product_id, context=context2) |
2834 | + if product: |
2835 | + factor_name = data.get('product_name', '') and \ |
2836 | + product_obj.name_get( |
2837 | + cr, uid, [product_id], context=context2)[0][1] |
2838 | + if factor.customer_name and data.get('factor_name', |
2839 | + False): |
2840 | + factor_name += ' - ' + factor.customer_name |
2841 | + |
2842 | + general_account = product.property_account_income or \ |
2843 | + product.categ_id.property_account_income_categ |
2844 | + if not general_account: |
2845 | + raise orm.except_orm( |
2846 | + _("Configuration Error!"), |
2847 | + _("Please define income account for product '%s'.") % product.name) |
2848 | + taxes = product.taxes_id or general_account.tax_ids |
2849 | + tax = fiscal_pos_obj.map_tax( |
2850 | + cr, uid, |
2851 | + account.partner_id.property_account_position, |
2852 | + taxes) |
2853 | + curr_line.update({ |
2854 | + 'invoice_line_tax_id': [(6, 0, tax)], |
2855 | 'name': factor_name, |
2856 | - 'uos_id': uom, |
2857 | - 'account_analytic_id': account.id, |
2858 | - } |
2859 | - product = product_obj.browse( |
2860 | - cr, uid, product_id, context=context2) |
2861 | - if product: |
2862 | - factor_name = data.get('product_name', '') and \ |
2863 | - product_obj.name_get( |
2864 | - cr, uid, [product_id], context=context2)[0][1] |
2865 | - if factor.customer_name and data.get('factor_name', |
2866 | - False): |
2867 | - factor_name += ' - ' + factor.customer_name |
2868 | - |
2869 | - general_account = product.property_account_income or \ |
2870 | - product.categ_id.property_account_income_categ |
2871 | - if not general_account: |
2872 | - raise orm.except_orm( |
2873 | - _("Configuration Error!"), |
2874 | - _("Please define income account for product '%s'.") % product.name) |
2875 | - taxes = product.taxes_id or general_account.tax_ids |
2876 | - tax = fiscal_pos_obj.map_tax( |
2877 | - cr, uid, |
2878 | - account.partner_id.property_account_position, |
2879 | - taxes) |
2880 | - curr_line.update({ |
2881 | - 'invoice_line_tax_id': [(6, 0, tax)], |
2882 | - 'name': factor_name, |
2883 | - 'invoice_line_tax_id': [(6, 0, tax)], |
2884 | - 'account_id': general_account.id, |
2885 | - }) |
2886 | - # |
2887 | - # Compute for lines |
2888 | - # |
2889 | - cr.execute("SELECT * FROM account_analytic_line WHERE account_id = %s and id IN %s AND product_id=%s and to_invoice=%s ORDER BY account_analytic_line.date", (account.id, tuple(ids), product_id, factor_id)) |
2890 | - |
2891 | - line_ids = cr.dictfetchall() |
2892 | - note = [] |
2893 | - for line in line_ids: |
2894 | - # set invoice_line_note |
2895 | - details = [] |
2896 | - if data.get('date', False): |
2897 | - details.append(line['date']) |
2898 | - if data.get('time', False): |
2899 | - if line['product_uom_id']: |
2900 | - details.append("%s %s" % ( |
2901 | - line['unit_amount'], |
2902 | - product_uom_obj.browse( |
2903 | - cr, uid, [line['product_uom_id']], |
2904 | - context2)[0].name)) |
2905 | - |
2906 | - else: |
2907 | - details.append("%s" % (line['unit_amount'], )) |
2908 | - if data.get('name', False): |
2909 | - details.append(line['name']) |
2910 | - note.append(u' - '.join( |
2911 | - map(lambda x: unicode(x) or '', details))) |
2912 | - if note: |
2913 | - if curr_line['name']: |
2914 | - curr_line['name'] += "\n" + ("\n".join( |
2915 | - map(lambda x: unicode(x) or '', note))) |
2916 | + 'invoice_line_tax_id': [(6, 0, tax)], |
2917 | + 'account_id': general_account.id, |
2918 | + }) |
2919 | + |
2920 | + if line_prefix: |
2921 | + curr_line["name"] = u'{0}\n{1}'.format( |
2922 | + line_prefix, curr_line["name"]) |
2923 | + |
2924 | + # |
2925 | + # Compute for lines |
2926 | + # |
2927 | + cr.execute("SELECT * FROM account_analytic_line WHERE account_id = %s and id IN %s AND product_id=%s and to_invoice=%s ORDER BY account_analytic_line.date", (account.id, tuple(ids), product_id, factor_id)) |
2928 | + |
2929 | + line_ids = cr.dictfetchall() |
2930 | + note = [] |
2931 | + for line in line_ids: |
2932 | + # set invoice_line_note |
2933 | + details = [] |
2934 | + if data.get('date', False): |
2935 | + details.append(line['date']) |
2936 | + if data.get('time', False): |
2937 | + if line['product_uom_id']: |
2938 | + details.append("%s %s" % ( |
2939 | + line['unit_amount'], |
2940 | + product_uom_obj.browse( |
2941 | + cr, uid, [line['product_uom_id']], |
2942 | + context2)[0].name)) |
2943 | + |
2944 | else: |
2945 | - curr_line['name'] = "\n".join( |
2946 | - map(lambda x: unicode(x) or '', note)) |
2947 | - invoice_line_obj.create( |
2948 | - cr, uid, curr_line, context=context) |
2949 | - cr.execute("update account_analytic_line set invoice_id=%s WHERE account_id = %s and id IN %s", (last_invoice, account.id, tuple(ids))) |
2950 | - |
2951 | - invoice_obj.button_reset_taxes( |
2952 | - cr, uid, [last_invoice], context) |
2953 | + details.append("%s" % (line['unit_amount'], )) |
2954 | + if data.get('name', False): |
2955 | + details.append(line['name']) |
2956 | + if data.get('partner', False): |
2957 | + details.append(account.partner_id.name) |
2958 | + note.append(u' - '.join( |
2959 | + map(lambda x: unicode(x) or '', details))) |
2960 | + if note: |
2961 | + if curr_line['name']: |
2962 | + curr_line['name'] += "\n" + ("\n".join( |
2963 | + map(lambda x: unicode(x) or '', note))) |
2964 | + else: |
2965 | + curr_line['name'] = "\n".join( |
2966 | + map(lambda x: unicode(x) or '', note)) |
2967 | + invoice_line_obj.create( |
2968 | + cr, uid, curr_line, context=context) |
2969 | + cr.execute("update account_analytic_line set invoice_id=%s WHERE account_id = %s and id IN %s", (last_invoice, account.id, tuple(ids))) |
2970 | + |
2971 | + invoice_obj.button_reset_taxes( |
2972 | + cr, uid, [last_invoice], context) |
2973 | + |
2974 | return invoices |
2975 | - |
2976 | |
2977 | === modified file 'contract_isp_invoice/contract_isp_invoice_view.xml' |
2978 | --- contract_isp_invoice/contract_isp_invoice_view.xml 2014-01-20 04:25:39 +0000 |
2979 | +++ contract_isp_invoice/contract_isp_invoice_view.xml 2014-11-24 15:05:14 +0000 |
2980 | @@ -19,7 +19,7 @@ |
2981 | <field name="inherit_id" ref="analytic.view_account_analytic_account_form"/> |
2982 | <field name="arch" type="xml"> |
2983 | <xpath expr="//div[@name='buttons']" position='inside'> |
2984 | - <button string="Create Voucher" |
2985 | + <button string="Create Initial Invoice" |
2986 | name="prepare_voucher" |
2987 | context="{'default_partner_id': partner_id}" |
2988 | type="object" /> |
2989 | @@ -34,7 +34,6 @@ |
2990 | <field name="arch" type="xml"> |
2991 | <field name="name" position="after"> |
2992 | <field name="later_validation" invisible="1" /> |
2993 | - <field name="original_amount" invisible="1" /> |
2994 | </field> |
2995 | <button name="proforma_voucher" position="attributes"> |
2996 | <attribute name="attrs">{'invisible': [('later_validation', '=', True)]}</attribute> |
2997 | |
2998 | === modified file 'contract_isp_invoice/i18n/contract_isp_invoice.pot' |
2999 | --- contract_isp_invoice/i18n/contract_isp_invoice.pot 2013-09-16 17:59:01 +0000 |
3000 | +++ contract_isp_invoice/i18n/contract_isp_invoice.pot 2014-11-24 15:05:14 +0000 |
3001 | @@ -6,8 +6,8 @@ |
3002 | msgstr "" |
3003 | "Project-Id-Version: OpenERP Server 7.0\n" |
3004 | "Report-Msgid-Bugs-To: \n" |
3005 | -"POT-Creation-Date: 2013-08-13 12:38+0000\n" |
3006 | -"PO-Revision-Date: 2013-08-13 12:38+0000\n" |
3007 | +"POT-Creation-Date: 2014-09-16 16:39+0000\n" |
3008 | +"PO-Revision-Date: 2014-09-16 16:39+0000\n" |
3009 | "Last-Translator: <>\n" |
3010 | "Language-Team: \n" |
3011 | "MIME-Version: 1.0\n" |
3012 | @@ -16,43 +16,235 @@ |
3013 | "Plural-Forms: \n" |
3014 | |
3015 | #. module: contract_isp_invoice |
3016 | -#: view:account.analytic.account:0 |
3017 | -#: model:ir.actions.act_window,name:contract_isp_invoice.action_view_create_voucher |
3018 | -msgid "Create Voucher" |
3019 | -msgstr "" |
3020 | - |
3021 | -#. module: contract_isp_invoice |
3022 | -#: model:ir.model,name:contract_isp_invoice.model_contract_service_activate |
3023 | -msgid "contract.service.activate" |
3024 | -msgstr "" |
3025 | - |
3026 | -#. module: contract_isp_invoice |
3027 | +#: model:email.template,body_html:contract_isp_invoice.email_template_contract_isp_invoice_close |
3028 | +msgid "\n" |
3029 | +"<div style=\"font-family: 'Lucica Grande', Ubuntu, Arial, Verdana, sans-serif; font-size: 12px; color: rgb(34, 34, 34); background-color: rgb(255, 255, 255); \">\n" |
3030 | +"\n" |
3031 | +" <p>Dear Accountant,</p>\n" |
3032 | +" <p>\n" |
3033 | +" Please take notice that the following contract is being terminated.\n" |
3034 | +"\n" |
3035 | +" </p>\n" |
3036 | +"<br/>\n" |
3037 | +" <table>\n" |
3038 | +" <tr>\n" |
3039 | +" <td>Contract:</td><td>${object.name}</td>\n" |
3040 | +" </tr>\n" |
3041 | +" <tr>\n" |
3042 | +" <td>Partner:</td><td>${object.partner_id.name}</td>\n" |
3043 | +" </tr> \n" |
3044 | +" <tr>\n" |
3045 | +" <td>Close date:</td><td>${object.close_date}</td>\n" |
3046 | +" </tr>\n" |
3047 | +" </table>\n" |
3048 | +" <h3>Reasons/Comments</h3>\n" |
3049 | +" <p>${object.close_reason}</p>\n" |
3050 | +"<br/>\n" |
3051 | +"Best Regards,\n" |
3052 | +"<br/>\n" |
3053 | +" <br/>\n" |
3054 | +"${user.name}\n" |
3055 | +"\n" |
3056 | +"<br/>\n" |
3057 | +"\n" |
3058 | +" <br/>\n" |
3059 | +"\n" |
3060 | +"</div>\n" |
3061 | +" " |
3062 | +msgstr "" |
3063 | + |
3064 | +#. module: contract_isp_invoice |
3065 | +#: code:_description:0 |
3066 | +#: model:ir.model,name:contract_isp_invoice.model_account_voucher |
3067 | +#, python-format |
3068 | +msgid "Accounting Voucher" |
3069 | +msgstr "" |
3070 | + |
3071 | +#. module: contract_isp_invoice |
3072 | +#: code:_description:0 |
3073 | +#: model:ir.model,name:contract_isp_invoice.model_account_analytic_account |
3074 | +#, python-format |
3075 | +msgid "Analytic Account" |
3076 | +msgstr "" |
3077 | + |
3078 | +#. module: contract_isp_invoice |
3079 | +#: code:_description:0 |
3080 | #: model:ir.model,name:contract_isp_invoice.model_account_analytic_line |
3081 | +#, python-format |
3082 | msgid "Analytic Line" |
3083 | msgstr "" |
3084 | |
3085 | #. module: contract_isp_invoice |
3086 | +#: view:contract.isp.close:0 |
3087 | +msgid "Cancel" |
3088 | +msgstr "" |
3089 | + |
3090 | +#. module: contract_isp_invoice |
3091 | +#: view:account.voucher:0 |
3092 | +msgid "Cancel Receipt" |
3093 | +msgstr "" |
3094 | + |
3095 | +#. module: contract_isp_invoice |
3096 | +#: view:contract.isp.close:0 |
3097 | +msgid "Close Contract" |
3098 | +msgstr "" |
3099 | + |
3100 | +#. module: contract_isp_invoice |
3101 | +#: model:ir.actions.act_window,name:contract_isp_invoice.action_view_contract_isp_close |
3102 | +msgid "Close contract" |
3103 | +msgstr "" |
3104 | + |
3105 | +#. module: contract_isp_invoice |
3106 | +#: field:account.analytic.account,close_date:0 |
3107 | +#: field:contract.isp.close,close_date:0 |
3108 | +msgid "Close date" |
3109 | +msgstr "" |
3110 | + |
3111 | +#. module: contract_isp_invoice |
3112 | +#: code:_description:0 |
3113 | +#: model:ir.model,name:contract_isp_invoice.model_res_company |
3114 | +#, python-format |
3115 | +msgid "Companies" |
3116 | +msgstr "" |
3117 | + |
3118 | +#. module: contract_isp_invoice |
3119 | +#: view:contract.isp.close:0 |
3120 | +msgid "Confirm" |
3121 | +msgstr "" |
3122 | + |
3123 | +#. module: contract_isp_invoice |
3124 | +#: view:contract.isp.close:0 |
3125 | +msgid "Confirm the termination of this contract?" |
3126 | +msgstr "" |
3127 | + |
3128 | +#. module: contract_isp_invoice |
3129 | +#: field:contract.isp.close,account_id:0 |
3130 | +msgid "Contract" |
3131 | +msgstr "" |
3132 | + |
3133 | +#. module: contract_isp_invoice |
3134 | +#: model:email.template,subject:contract_isp_invoice.email_template_contract_isp_invoice_close |
3135 | +msgid "Contract n. ${object.name}" |
3136 | +msgstr "" |
3137 | + |
3138 | +#. module: contract_isp_invoice |
3139 | +#: view:account.analytic.account:0 |
3140 | +msgid "Create Initial Invoice" |
3141 | +msgstr "" |
3142 | + |
3143 | +#. module: contract_isp_invoice |
3144 | +#: code:_description:0 |
3145 | +#: model:ir.model,name:contract_isp_invoice.model_hr_timesheet_invoice_create |
3146 | +#, python-format |
3147 | +msgid "Create invoice from timesheet" |
3148 | +msgstr "" |
3149 | + |
3150 | +#. module: contract_isp_invoice |
3151 | #: model:account.payment.term,name:contract_isp_invoice.account_payment_term_end_of_month |
3152 | msgid "End of Month" |
3153 | msgstr "" |
3154 | |
3155 | #. module: contract_isp_invoice |
3156 | +#: model:account.payment.term,note:contract_isp_invoice.account_payment_term_end_of_month |
3157 | +msgid "End of current month" |
3158 | +msgstr "" |
3159 | + |
3160 | +#. module: contract_isp_invoice |
3161 | +#: field:hr.timesheet.invoice.create,factor_name:0 |
3162 | +msgid "Invoice Factor" |
3163 | +msgstr "" |
3164 | + |
3165 | +#. module: contract_isp_invoice |
3166 | #: field:res.company,invoice_day:0 |
3167 | msgid "Invoice day" |
3168 | msgstr "" |
3169 | |
3170 | #. module: contract_isp_invoice |
3171 | -#: model:ir.model,name:contract_isp_invoice.model_res_company |
3172 | -msgid "Companies" |
3173 | -msgstr "" |
3174 | - |
3175 | -#. module: contract_isp_invoice |
3176 | -#: model:ir.model,name:contract_isp_invoice.model_account_analytic_account |
3177 | -msgid "Analytic Account" |
3178 | -msgstr "" |
3179 | - |
3180 | -#. module: contract_isp_invoice |
3181 | -#: model:account.payment.term,note:contract_isp_invoice.account_payment_term_end_of_month |
3182 | -msgid "End of current month" |
3183 | +#: code:_description:0 |
3184 | +#: model:ir.model,name:contract_isp_invoice.model_account_journal |
3185 | +#, python-format |
3186 | +msgid "Journal" |
3187 | +msgstr "" |
3188 | + |
3189 | +#. module: contract_isp_invoice |
3190 | +#: field:account.journal,later_validation:0 |
3191 | +#: field:account.voucher,later_validation:0 |
3192 | +msgid "Later Validation" |
3193 | +msgstr "" |
3194 | + |
3195 | +#. module: contract_isp_invoice |
3196 | +#: code:_description:0 |
3197 | +#: model:ir.model,name:contract_isp_invoice.model_res_partner |
3198 | +#, python-format |
3199 | +msgid "Partner" |
3200 | +msgstr "" |
3201 | + |
3202 | +#. module: contract_isp_invoice |
3203 | +#: field:hr.timesheet.invoice.create,product_name:0 |
3204 | +msgid "Product Name" |
3205 | +msgstr "" |
3206 | + |
3207 | +#. module: contract_isp_invoice |
3208 | +#: view:contract.isp.close:0 |
3209 | +#: field:contract.isp.close,close_reason:0 |
3210 | +msgid "Reason" |
3211 | +msgstr "" |
3212 | + |
3213 | +#. module: contract_isp_invoice |
3214 | +#: field:account.analytic.account,close_reason:0 |
3215 | +msgid "Reasons" |
3216 | +msgstr "" |
3217 | + |
3218 | +#. module: contract_isp_invoice |
3219 | +#: field:res.company,send_email_contract_invoice:0 |
3220 | +msgid "Send invoice by email" |
3221 | +msgstr "" |
3222 | + |
3223 | +#. module: contract_isp_invoice |
3224 | +#: help:hr.timesheet.invoice.create,factor_name:0 |
3225 | +msgid "Show the invoice factor" |
3226 | +msgstr "" |
3227 | + |
3228 | +#. module: contract_isp_invoice |
3229 | +#: help:hr.timesheet.invoice.create,product_name:0 |
3230 | +msgid "Show the product name" |
3231 | +msgstr "" |
3232 | + |
3233 | +#. module: contract_isp_invoice |
3234 | +#: code:_description:0 |
3235 | +#: model:ir.model,name:contract_isp_invoice.model_contract_isp_close |
3236 | +#, python-format |
3237 | +msgid "contract.isp.close" |
3238 | +msgstr "" |
3239 | + |
3240 | +#. module: contract_isp_invoice |
3241 | +#: code:_description:0 |
3242 | +#: model:ir.model,name:contract_isp_invoice.model_contract_service |
3243 | +#, python-format |
3244 | +msgid "contract.service" |
3245 | +msgstr "" |
3246 | + |
3247 | +#. module: contract_isp_invoice |
3248 | +#: code:_description:0 |
3249 | +#: model:ir.model,name:contract_isp_invoice.model_contract_service_activate |
3250 | +#, python-format |
3251 | +msgid "contract.service.activate" |
3252 | +msgstr "" |
3253 | + |
3254 | +#. module: contract_isp_invoice |
3255 | +#: code:_description:0 |
3256 | +#: model:ir.model,name:contract_isp_invoice.model_contract_service_deactivate |
3257 | +#, python-format |
3258 | +msgid "contract.service.deactivate" |
3259 | +msgstr "" |
3260 | + |
3261 | +#. module: contract_isp_invoice |
3262 | +#: view:account.voucher:0 |
3263 | +msgid "object" |
3264 | +msgstr "" |
3265 | + |
3266 | +#. module: contract_isp_invoice |
3267 | +#: view:account.voucher:0 |
3268 | +msgid "{'invisible': [('later_validation', '=', True)]}" |
3269 | msgstr "" |
3270 | |
3271 | |
3272 | === added file 'contract_isp_invoice/i18n/fr.po' |
3273 | --- contract_isp_invoice/i18n/fr.po 1970-01-01 00:00:00 +0000 |
3274 | +++ contract_isp_invoice/i18n/fr.po 2014-11-24 15:05:14 +0000 |
3275 | @@ -0,0 +1,291 @@ |
3276 | +# Translation of OpenERP Server. |
3277 | +# This file contains the translation of the following modules: |
3278 | +# * contract_isp_invoice |
3279 | +# |
3280 | +msgid "" |
3281 | +msgstr "" |
3282 | +"Project-Id-Version: OpenERP Server 7.0\n" |
3283 | +"Report-Msgid-Bugs-To: \n" |
3284 | +"POT-Creation-Date: 2014-09-16 16:39+0000\n" |
3285 | +"PO-Revision-Date: 2014-09-16 12:54-0500\n" |
3286 | +"Last-Translator: Marc Cassuto <marc.cassuto@savoirfairelinux.com>\n" |
3287 | +"Language-Team: \n" |
3288 | +"MIME-Version: 1.0\n" |
3289 | +"Content-Type: text/plain; charset=UTF-8\n" |
3290 | +"Content-Transfer-Encoding: 8bit\n" |
3291 | +"Language: fr\n" |
3292 | +"X-Generator: Poedit 1.5.4\n" |
3293 | + |
3294 | +#. module: contract_isp_invoice |
3295 | +#: model:email.template,body_html:contract_isp_invoice.email_template_contract_isp_invoice_close |
3296 | +msgid "" |
3297 | +"\n" |
3298 | +"<div style=\"font-family: 'Lucica Grande', Ubuntu, Arial, Verdana, sans-" |
3299 | +"serif; font-size: 12px; color: rgb(34, 34, 34); background-color: rgb(255, " |
3300 | +"255, 255); \">\n" |
3301 | +"\n" |
3302 | +" <p>Dear Accountant,</p>\n" |
3303 | +" <p>\n" |
3304 | +" Please take notice that the following contract is being terminated.\n" |
3305 | +"\n" |
3306 | +" </p>\n" |
3307 | +"<br/>\n" |
3308 | +" <table>\n" |
3309 | +" <tr>\n" |
3310 | +" <td>Contract:</td><td>${object.name}</td>\n" |
3311 | +" </tr>\n" |
3312 | +" <tr>\n" |
3313 | +" <td>Partner:</td><td>${object.partner_id.name}</td>\n" |
3314 | +" </tr> \n" |
3315 | +" <tr>\n" |
3316 | +" <td>Close date:</td><td>${object.close_date}</td>\n" |
3317 | +" </tr>\n" |
3318 | +" </table>\n" |
3319 | +" <h3>Reasons/Comments</h3>\n" |
3320 | +" <p>${object.close_reason}</p>\n" |
3321 | +"<br/>\n" |
3322 | +"Best Regards,\n" |
3323 | +"<br/>\n" |
3324 | +" <br/>\n" |
3325 | +"${user.name}\n" |
3326 | +"\n" |
3327 | +"<br/>\n" |
3328 | +"\n" |
3329 | +" <br/>\n" |
3330 | +"\n" |
3331 | +"</div>\n" |
3332 | +" " |
3333 | +msgstr "" |
3334 | +"\n" |
3335 | +"<div style=\"font-family: 'Lucica Grande', Ubuntu, Arial, Verdana, sans-" |
3336 | +"serif; font-size: 12px; color: rgb(34, 34, 34); background-color: rgb(255, " |
3337 | +"255, 255); \">\n" |
3338 | +"\n" |
3339 | +" <p>Bonjour,</p>\n" |
3340 | +" <p>\n" |
3341 | +" Prenez note que le contrat suivant vient d'être clôturé:\n" |
3342 | +"\n" |
3343 | +" </p>\n" |
3344 | +"<br/>\n" |
3345 | +" <table>\n" |
3346 | +" <tr>\n" |
3347 | +" <td>Contrat:</td><td>${object.name}</td>\n" |
3348 | +" </tr>\n" |
3349 | +" <tr>\n" |
3350 | +" <td>Code client:</td><td>${object.partner_id.code}</td>\n" |
3351 | +" </tr> \n" |
3352 | +" <tr>\n" |
3353 | +" <td>Client:</td><td>${object.partner_id.name}</td>\n" |
3354 | +" </tr> \n" |
3355 | +" <tr>\n" |
3356 | +" <td>Date de clôture:</td><td>${object.close_date}</td>\n" |
3357 | +" </tr>\n" |
3358 | +" </table>\n" |
3359 | +" <h3>Raison / Commentaire</h3>\n" |
3360 | +" <p>${object.close_reason}</p>\n" |
3361 | +"<br/>\n" |
3362 | +"Meilleurs salutations,\n" |
3363 | +"<br/>\n" |
3364 | +" <br/>\n" |
3365 | +"${user.name}\n" |
3366 | +"\n" |
3367 | +"<br/>\n" |
3368 | +"\n" |
3369 | +" <br/>\n" |
3370 | +"\n" |
3371 | +"</div>\n" |
3372 | +" " |
3373 | + |
3374 | +#. module: contract_isp_invoice |
3375 | +#: code:_description:0 |
3376 | +#: model:ir.model,name:contract_isp_invoice.model_account_voucher |
3377 | +#, python-format |
3378 | +msgid "Accounting Voucher" |
3379 | +msgstr "Paiement" |
3380 | + |
3381 | +#. module: contract_isp_invoice |
3382 | +#: code:_description:0 |
3383 | +#: model:ir.model,name:contract_isp_invoice.model_account_analytic_account |
3384 | +#, python-format |
3385 | +msgid "Analytic Account" |
3386 | +msgstr "Contrat" |
3387 | + |
3388 | +#. module: contract_isp_invoice |
3389 | +#: code:_description:0 |
3390 | +#: model:ir.model,name:contract_isp_invoice.model_account_analytic_line |
3391 | +#, python-format |
3392 | +msgid "Analytic Line" |
3393 | +msgstr "Ligne facturable" |
3394 | + |
3395 | +#. module: contract_isp_invoice |
3396 | +#: view:contract.isp.close:0 |
3397 | +msgid "Cancel" |
3398 | +msgstr "Annuler" |
3399 | + |
3400 | +#. module: contract_isp_invoice |
3401 | +#: view:account.voucher:0 |
3402 | +msgid "Cancel Receipt" |
3403 | +msgstr "Annuler le payment" |
3404 | + |
3405 | +#. module: contract_isp_invoice |
3406 | +#: view:contract.isp.close:0 |
3407 | +msgid "Close Contract" |
3408 | +msgstr "Clôturer le contrat" |
3409 | + |
3410 | +#. module: contract_isp_invoice |
3411 | +#: model:ir.actions.act_window,name:contract_isp_invoice.action_view_contract_isp_close |
3412 | +msgid "Close contract" |
3413 | +msgstr "Clôturer le contrat" |
3414 | + |
3415 | +#. module: contract_isp_invoice |
3416 | +#: field:account.analytic.account,close_date:0 |
3417 | +#: field:contract.isp.close,close_date:0 |
3418 | +msgid "Close date" |
3419 | +msgstr "Date de Clôture" |
3420 | + |
3421 | +#. module: contract_isp_invoice |
3422 | +#: code:_description:0 |
3423 | +#: model:ir.model,name:contract_isp_invoice.model_res_company |
3424 | +#, python-format |
3425 | +msgid "Companies" |
3426 | +msgstr "Companies" |
3427 | + |
3428 | +#. module: contract_isp_invoice |
3429 | +#: view:contract.isp.close:0 |
3430 | +msgid "Confirm" |
3431 | +msgstr "Confirmer" |
3432 | + |
3433 | +#. module: contract_isp_invoice |
3434 | +#: view:contract.isp.close:0 |
3435 | +msgid "Confirm the termination of this contract?" |
3436 | +msgstr "Souhaitez-vous clôturer ce contrat ?" |
3437 | + |
3438 | +#. module: contract_isp_invoice |
3439 | +#: field:contract.isp.close,account_id:0 |
3440 | +msgid "Contract" |
3441 | +msgstr "Contrat" |
3442 | + |
3443 | +#. module: contract_isp_invoice |
3444 | +#: model:email.template,subject:contract_isp_invoice.email_template_contract_isp_invoice_close |
3445 | +msgid "Contract n. ${object.name}" |
3446 | +msgstr "Contrat # ${object.name}" |
3447 | + |
3448 | +#. module: contract_isp_invoice |
3449 | +#: view:account.analytic.account:0 |
3450 | +msgid "Create Initial Invoice" |
3451 | +msgstr "Créer la facture initiale" |
3452 | + |
3453 | +#. module: contract_isp_invoice |
3454 | +#: code:_description:0 |
3455 | +#: model:ir.model,name:contract_isp_invoice.model_hr_timesheet_invoice_create |
3456 | +#, python-format |
3457 | +msgid "Create invoice from timesheet" |
3458 | +msgstr "Créer des factures à partir des feuilles de temps" |
3459 | + |
3460 | +#. module: contract_isp_invoice |
3461 | +#: model:account.payment.term,name:contract_isp_invoice.account_payment_term_end_of_month |
3462 | +msgid "End of Month" |
3463 | +msgstr "Fin de Mois" |
3464 | + |
3465 | +#. module: contract_isp_invoice |
3466 | +#: model:account.payment.term,note:contract_isp_invoice.account_payment_term_end_of_month |
3467 | +msgid "End of current month" |
3468 | +msgstr "Fin du mois courant" |
3469 | + |
3470 | +#. module: contract_isp_invoice |
3471 | +#: field:hr.timesheet.invoice.create,factor_name:0 |
3472 | +msgid "Invoice Factor" |
3473 | +msgstr "Taux facturable" |
3474 | + |
3475 | +#. module: contract_isp_invoice |
3476 | +#: field:res.company,invoice_day:0 |
3477 | +msgid "Invoice day" |
3478 | +msgstr "Jour de facturation" |
3479 | + |
3480 | +#. module: contract_isp_invoice |
3481 | +#: code:_description:0 |
3482 | +#: model:ir.model,name:contract_isp_invoice.model_account_journal |
3483 | +#, python-format |
3484 | +msgid "Journal" |
3485 | +msgstr "Journal Comptable" |
3486 | + |
3487 | +#. module: contract_isp_invoice |
3488 | +#: field:account.journal,later_validation:0 |
3489 | +#: field:account.voucher,later_validation:0 |
3490 | +msgid "Later Validation" |
3491 | +msgstr "Validation Ultérieure" |
3492 | + |
3493 | +#. module: contract_isp_invoice |
3494 | +#: code:_description:0 |
3495 | +#: model:ir.model,name:contract_isp_invoice.model_res_partner |
3496 | +#, python-format |
3497 | +msgid "Partner" |
3498 | +msgstr "Partenaire" |
3499 | + |
3500 | +#. module: contract_isp_invoice |
3501 | +#: field:hr.timesheet.invoice.create,product_name:0 |
3502 | +msgid "Product Name" |
3503 | +msgstr "Produit" |
3504 | + |
3505 | +#. module: contract_isp_invoice |
3506 | +#: view:contract.isp.close:0 field:contract.isp.close,close_reason:0 |
3507 | +msgid "Reason" |
3508 | +msgstr "Raison" |
3509 | + |
3510 | +#. module: contract_isp_invoice |
3511 | +#: field:account.analytic.account,close_reason:0 |
3512 | +msgid "Reasons" |
3513 | +msgstr "Raisons" |
3514 | + |
3515 | +#. module: contract_isp_invoice |
3516 | +#: field:res.company,send_email_contract_invoice:0 |
3517 | +msgid "Send invoice by email" |
3518 | +msgstr "Envoyer la facture par couriel" |
3519 | + |
3520 | +#. module: contract_isp_invoice |
3521 | +#: help:hr.timesheet.invoice.create,factor_name:0 |
3522 | +msgid "Show the invoice factor" |
3523 | +msgstr "Montre le taux facturable" |
3524 | + |
3525 | +#. module: contract_isp_invoice |
3526 | +#: help:hr.timesheet.invoice.create,product_name:0 |
3527 | +msgid "Show the product name" |
3528 | +msgstr "Montre le produit" |
3529 | + |
3530 | +#. module: contract_isp_invoice |
3531 | +#: code:_description:0 |
3532 | +#: model:ir.model,name:contract_isp_invoice.model_contract_isp_close |
3533 | +#, python-format |
3534 | +msgid "contract.isp.close" |
3535 | +msgstr "contract.isp.close" |
3536 | + |
3537 | +#. module: contract_isp_invoice |
3538 | +#: code:_description:0 |
3539 | +#: model:ir.model,name:contract_isp_invoice.model_contract_service |
3540 | +#, python-format |
3541 | +msgid "contract.service" |
3542 | +msgstr "contract.service" |
3543 | + |
3544 | +#. module: contract_isp_invoice |
3545 | +#: code:_description:0 |
3546 | +#: model:ir.model,name:contract_isp_invoice.model_contract_service_activate |
3547 | +#, python-format |
3548 | +msgid "contract.service.activate" |
3549 | +msgstr "contract.service.activate" |
3550 | + |
3551 | +#. module: contract_isp_invoice |
3552 | +#: code:_description:0 |
3553 | +#: model:ir.model,name:contract_isp_invoice.model_contract_service_deactivate |
3554 | +#, python-format |
3555 | +msgid "contract.service.deactivate" |
3556 | +msgstr "contract.service.deactivate" |
3557 | + |
3558 | +#. module: contract_isp_invoice |
3559 | +#: view:account.voucher:0 |
3560 | +msgid "object" |
3561 | +msgstr "objet" |
3562 | + |
3563 | +#. module: contract_isp_invoice |
3564 | +#: view:account.voucher:0 |
3565 | +msgid "{'invisible': [('later_validation', '=', True)]}" |
3566 | +msgstr "{'invisible': [('later_validation', '=', True)]}" |
3567 | |
3568 | === added file 'contract_isp_invoice/invoice.py' |
3569 | --- contract_isp_invoice/invoice.py 1970-01-01 00:00:00 +0000 |
3570 | +++ contract_isp_invoice/invoice.py 2014-11-24 15:05:14 +0000 |
3571 | @@ -0,0 +1,40 @@ |
3572 | +# -*- coding: utf-8 -*- |
3573 | + |
3574 | +############################################################################## |
3575 | +# |
3576 | +# OpenERP, Open Source Management Solution |
3577 | +# Copyright (C) 2014 Savoir-faire Linux (<www.savoirfairelinux.com>). |
3578 | +# |
3579 | +# This program is free software: you can redistribute it and/or modify |
3580 | +# it under the terms of the GNU Affero General Public License as |
3581 | +# published by the Free Software Foundation, either version 3 of the |
3582 | +# License, or (at your option) any later version. |
3583 | +# |
3584 | +# This program is distributed in the hope that it will be useful, |
3585 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
3586 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3587 | +# GNU Affero General Public License for more details. |
3588 | +# |
3589 | +# You should have received a copy of the GNU Affero General Public License |
3590 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
3591 | +# |
3592 | +############################################################################## |
3593 | + |
3594 | +from openerp.osv import orm, fields |
3595 | + |
3596 | +PROCESS_RECURRENT = 'recurrent' |
3597 | +PROCESS_PRORATA = 'prorata' |
3598 | +PROCESS_CRON = 'cron' |
3599 | +PROCESS_MANUAL = 'manual' |
3600 | + |
3601 | + |
3602 | +class Invoice(orm.Model): |
3603 | + _name = _inherit = 'account.invoice' |
3604 | + _columns = { |
3605 | + 'source_process': fields.selection([ |
3606 | + (PROCESS_RECURRENT, 'Recurrent Billing'), |
3607 | + (PROCESS_PRORATA, 'Pro Rata'), |
3608 | + (PROCESS_MANUAL, 'Manual'), |
3609 | + (PROCESS_CRON, 'Scheduled'), |
3610 | + ], 'Billing Process', required=False), |
3611 | + } |
3612 | |
3613 | === added directory 'contract_isp_invoice/tests' |
3614 | === added file 'contract_isp_invoice/tests/__init__.py' |
3615 | --- contract_isp_invoice/tests/__init__.py 1970-01-01 00:00:00 +0000 |
3616 | +++ contract_isp_invoice/tests/__init__.py 2014-11-24 15:05:14 +0000 |
3617 | @@ -0,0 +1,33 @@ |
3618 | +# -*- encoding: utf-8 -*- |
3619 | +############################################################################### |
3620 | +# |
3621 | +# OpenERP, Open Source Management Solution |
3622 | +# This module copyright (C) 2014 Savoir-faire Linux |
3623 | +# (<http://www.savoirfairelinux.com>). |
3624 | +# |
3625 | +# This program is free software: you can redistribute it and/or modify |
3626 | +# it under the terms of the GNU Affero General Public License as |
3627 | +# published by the Free Software Foundation, either version 3 of the |
3628 | +# License, or (at your option) any later version. |
3629 | +# |
3630 | +# This program is distributed in the hope that it will be useful, |
3631 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
3632 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3633 | +# GNU Affero General Public License for more details. |
3634 | +# |
3635 | +# You should have received a copy of the GNU Affero General Public License |
3636 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
3637 | +# |
3638 | +############################################################################### |
3639 | + |
3640 | +from . import ( |
3641 | + test_prorata, |
3642 | + test_deactivate, |
3643 | + test_reseller, |
3644 | +) |
3645 | + |
3646 | +checks = [ |
3647 | + test_deactivate, |
3648 | + test_prorata, |
3649 | + test_reseller, |
3650 | +] |
3651 | |
3652 | === added file 'contract_isp_invoice/tests/common.py' |
3653 | --- contract_isp_invoice/tests/common.py 1970-01-01 00:00:00 +0000 |
3654 | +++ contract_isp_invoice/tests/common.py 2014-11-24 15:05:14 +0000 |
3655 | @@ -0,0 +1,142 @@ |
3656 | +# -*- coding: utf-8 -*- |
3657 | +############################################################################## |
3658 | +# |
3659 | +# OpenERP, Open Source Management Solution |
3660 | +# Copyright (C) 2014 Savoir-faire Linux (<http://www.savoirfairelinux.com>). |
3661 | +# |
3662 | +# This program is free software: you can redistribute it and/or modify |
3663 | +# it under the terms of the GNU Affero General Public License as |
3664 | +# published by the Free Software Foundation, either version 3 of the |
3665 | +# License, or (at your option) any later version. |
3666 | +# |
3667 | +# This program is distributed in the hope that it will be useful, |
3668 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
3669 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3670 | +# GNU Affero General Public License for more details. |
3671 | +# |
3672 | +# You should have received a copy of the GNU Affero General Public License |
3673 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
3674 | +# |
3675 | +############################################################################## |
3676 | + |
3677 | +from openerp.addons.contract_isp.contract import ( |
3678 | + LINE_TYPE_RECURRENT, |
3679 | + LINE_TYPE_ONETIME, |
3680 | +) |
3681 | + |
3682 | + |
3683 | +class ServiceSetup(object): |
3684 | + """ Mixin class to provide setup and utils for testing invoicing """ |
3685 | + |
3686 | + def _common_setup(self): |
3687 | + self._init_modules() |
3688 | + self._configure_company() |
3689 | + self._create_partner() |
3690 | + self._create_account() |
3691 | + self._create_products() |
3692 | + |
3693 | + def _init_modules(self): |
3694 | + self.account_obj = self.registry("account.analytic.account") |
3695 | + self.analytic_line_obj = self.registry("account.analytic.line") |
3696 | + self.company_obj = self.registry("res.company") |
3697 | + self.service_obj = self.registry("contract.service") |
3698 | + self.partner_obj = self.registry("res.partner") |
3699 | + self.product_obj = self.registry("product.product") |
3700 | + self.invoice_obj = self.registry("account.invoice") |
3701 | + self.wiz_activate_obj = self.registry("contract.service.activate") |
3702 | + self.wiz_deactivate_obj = self.registry("contract.service.deactivate") |
3703 | + |
3704 | + def _configure_company(self): |
3705 | + self.company = self.company_obj.browse(self.cr, self.uid, 1) |
3706 | + self.company.write({"cutoff_day": "7", "invoice_day": "14"}) |
3707 | + |
3708 | + def _create_partner(self): |
3709 | + self.partner_id = self.partner_obj.name_create( |
3710 | + self.cr, self.uid, |
3711 | + "Test Partner" |
3712 | + )[0] |
3713 | + |
3714 | + def _get_last_invoice(self, query=None, partner_id=None): |
3715 | + domain = [("partner_id", "=", partner_id or self.partner_id)] |
3716 | + if query: |
3717 | + domain.extend(query) |
3718 | + invoice = self.invoice_obj.browse( |
3719 | + self.cr, self.uid, |
3720 | + self.invoice_obj.search( |
3721 | + self.cr, self.uid, |
3722 | + domain, |
3723 | + order="id desc", |
3724 | + limit=1, |
3725 | + )[0] |
3726 | + ) |
3727 | + return invoice |
3728 | + |
3729 | + def _create_products(self): |
3730 | + cr, uid = self.cr, self.uid |
3731 | + self.p_internet = self.product_obj.create(cr, uid, { |
3732 | + "name": "Cable Internet", |
3733 | + "type": "service", |
3734 | + "analytic_line_type": LINE_TYPE_RECURRENT, |
3735 | + "code": "CBL", |
3736 | + "list_price": 56.0, |
3737 | + }) |
3738 | + self.p_inst = self.product_obj.create(cr, uid, { |
3739 | + "name": "Installation", |
3740 | + "type": "service", |
3741 | + "analytic_line_type": LINE_TYPE_ONETIME, |
3742 | + "code": "INST", |
3743 | + "list_price": 50.0, |
3744 | + }) |
3745 | + |
3746 | + def _create_account(self): |
3747 | + wr = self.account_obj.default_get(self.cr, self.uid, |
3748 | + self.account_obj._columns.keys()) |
3749 | + wr.update({ |
3750 | + "partner_id": self.partner_id, |
3751 | + "pricelist_id": 1, |
3752 | + }) |
3753 | + onchange = self.account_obj.on_change_partner_id( |
3754 | + self.cr, self.uid, [], |
3755 | + self.partner_id, False, False, |
3756 | + )["value"] |
3757 | + wr.update(onchange) |
3758 | + |
3759 | + self.account_id = self.account_obj.create(self.cr, self.uid, wr) |
3760 | + |
3761 | + def _create_activate_service(self, product, activation_date, context=None): |
3762 | + context = context or {} |
3763 | + cr, uid = self.cr, self.uid |
3764 | + service = self.service_obj.on_change_product_id( |
3765 | + cr, uid, [], |
3766 | + self.p_internet, |
3767 | + )["value"] |
3768 | + service.update({ |
3769 | + "product_id": self.p_internet, |
3770 | + "account_id": self.account_id, |
3771 | + }) |
3772 | + service_id = self.service_obj.create(cr, uid, service, context=context) |
3773 | + wiz_id = self.wiz_activate_obj.create( |
3774 | + cr, uid, { |
3775 | + "account_id": self.account_id, |
3776 | + "service_id": service_id, |
3777 | + "activation_date": activation_date, |
3778 | + }, |
3779 | + context=context, |
3780 | + ) |
3781 | + self.wiz_activate_obj.activate(cr, uid, [wiz_id], context=context) |
3782 | + return service_id |
3783 | + |
3784 | + def _get_invoice_date_range(self, invoice_id): |
3785 | + # Until we put a bit more common sense into period handling, this |
3786 | + # is our way of knowing the start/end dates of an invoice |
3787 | + cr, uid = self.cr, self.uid |
3788 | + invoice_line = self.analytic_line_obj.browse( |
3789 | + cr, uid, |
3790 | + self.analytic_line_obj.search(cr, uid, [ |
3791 | + ('to_invoice', '!=', False), |
3792 | + ('invoice_id', '=', invoice_id), |
3793 | + ])[0] |
3794 | + ) |
3795 | + date_from = invoice_line.name[-24:-14] |
3796 | + date_to = invoice_line.name[-11:-1] |
3797 | + return date_from, date_to |
3798 | |
3799 | === added file 'contract_isp_invoice/tests/test_deactivate.py' |
3800 | --- contract_isp_invoice/tests/test_deactivate.py 1970-01-01 00:00:00 +0000 |
3801 | +++ contract_isp_invoice/tests/test_deactivate.py 2014-11-24 15:05:14 +0000 |
3802 | @@ -0,0 +1,165 @@ |
3803 | +# -*- coding: utf-8 -*- |
3804 | +############################################################################## |
3805 | +# |
3806 | +# OpenERP, Open Source Management Solution |
3807 | +# Copyright (C) 2014 Savoir-faire Linux (<http://www.savoirfairelinux.com>). |
3808 | +# |
3809 | +# This program is free software: you can redistribute it and/or modify |
3810 | +# it under the terms of the GNU Affero General Public License as |
3811 | +# published by the Free Software Foundation, either version 3 of the |
3812 | +# License, or (at your option) any later version. |
3813 | +# |
3814 | +# This program is distributed in the hope that it will be useful, |
3815 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
3816 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3817 | +# GNU Affero General Public License for more details. |
3818 | +# |
3819 | +# You should have received a copy of the GNU Affero General Public License |
3820 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
3821 | +# |
3822 | +############################################################################## |
3823 | +from __future__ import unicode_literals |
3824 | + |
3825 | +from datetime import date |
3826 | + |
3827 | +from openerp.tests.common import TransactionCase |
3828 | + |
3829 | +from .common import ServiceSetup |
3830 | + |
3831 | + |
3832 | +class test_prorata_deactivate_service(TransactionCase, ServiceSetup): |
3833 | + """ |
3834 | + Tests pro-rata crediting of services at deactivation |
3835 | + """ |
3836 | + def setUp(self): |
3837 | + super(test_prorata_deactivate_service, self).setUp() |
3838 | + self._common_setup() |
3839 | + |
3840 | + def _common_setup(self): |
3841 | + super(test_prorata_deactivate_service, self)._common_setup() |
3842 | + self._create_active_service() |
3843 | + |
3844 | + def _create_active_service(self): |
3845 | + cr, uid = self.cr, self.uid |
3846 | + service = self.service_obj.on_change_product_id( |
3847 | + cr, uid, [], |
3848 | + self.p_internet, |
3849 | + )["value"] |
3850 | + service.update({ |
3851 | + "product_id": self.p_internet, |
3852 | + "account_id": self.account_id, |
3853 | + "state": "active", |
3854 | + }) |
3855 | + self.service_id = self.service_obj.create(cr, uid, service) |
3856 | + |
3857 | + def _deactivate_service(self, deactivation_date, context=None): |
3858 | + context = context or {} |
3859 | + cr, uid = self.cr, self.uid |
3860 | + wiz_id = self.wiz_deactivate_obj.create( |
3861 | + cr, uid, { |
3862 | + "account_id": self.account_id, |
3863 | + "service_id": self.service_id, |
3864 | + "deactivation_date": deactivation_date, |
3865 | + }, |
3866 | + context=context, |
3867 | + ) |
3868 | + self.wiz_deactivate_obj.deactivate(cr, uid, [wiz_id], context=context) |
3869 | + |
3870 | + def test_after_invoice_before_cutoff(self): |
3871 | + self.company.write({"invoice_day": "7", "cutoff_day": "21"}) |
3872 | + self._deactivate_service("2014-02-14", { |
3873 | + "operation_date": date(2014, 2, 17), |
3874 | + }) |
3875 | + invoice = self._get_last_invoice() |
3876 | + date_from, date_to = self._get_invoice_date_range(invoice.id) |
3877 | + self.assertEquals(invoice.date_invoice, "2014-02-07") |
3878 | + self.assertEquals(date_from, "2014-02-14", "Wrong start_date") |
3879 | + self.assertEquals(date_to, "2014-03-31", "Wrong end_date") |
3880 | + self.assertAlmostEquals( |
3881 | + invoice.amount_untaxed, |
3882 | + (1 + self.service_obj._prorata_rate(14, 28)) * 56, |
3883 | + msg="Expect refund for 14-28 feb + march") |
3884 | + self.assertEquals(invoice.type, "out_refund") |
3885 | + |
3886 | + def test_after_invoice_after_cutoff(self): |
3887 | + self.company.write({"invoice_day": "7", "cutoff_day": "21"}) |
3888 | + self._deactivate_service("2014-02-14", { |
3889 | + "operation_date": date(2014, 2, 23), |
3890 | + }) |
3891 | + invoice = self._get_last_invoice() |
3892 | + date_from, date_to = self._get_invoice_date_range(invoice.id) |
3893 | + self.assertEquals(invoice.date_invoice, "2014-03-07") |
3894 | + self.assertEquals(date_from, "2014-02-14", "Wrong start_date") |
3895 | + self.assertEquals(date_to, "2014-03-31", "Wrong end_date") |
3896 | + self.assertAlmostEquals( |
3897 | + invoice.amount_untaxed, |
3898 | + (1 + self.service_obj._prorata_rate(14, 28)) * 56, |
3899 | + msg="Expect refund for 14-28 feb + march") |
3900 | + self.assertEquals(invoice.type, "out_refund") |
3901 | + |
3902 | + def test_before_invoice_past_deactivation_curmonth(self): |
3903 | + self.company.write({"invoice_day": "14", "cutoff_day": "21"}) |
3904 | + self._deactivate_service("2014-02-07", { |
3905 | + "operation_date": date(2014, 2, 8), |
3906 | + }) |
3907 | + invoice = self._get_last_invoice() |
3908 | + date_from, date_to = self._get_invoice_date_range(invoice.id) |
3909 | + self.assertEquals(invoice.date_invoice, "2014-02-14") |
3910 | + self.assertEquals(date_from, "2014-02-07", "Wrong start_date") |
3911 | + self.assertEquals(date_to, "2014-02-28", "Wrong end_date") |
3912 | + self.assertAlmostEquals( |
3913 | + invoice.amount_untaxed, |
3914 | + self.service_obj._prorata_rate(21, 28) * 56, |
3915 | + msg="Expect refund for 7-28 feb") |
3916 | + self.assertEquals(invoice.type, "out_refund") |
3917 | + |
3918 | + def test_before_invoice_past_deactivation_past_month(self): |
3919 | + self.company.write({"invoice_day": "14", "cutoff_day": "21"}) |
3920 | + self._deactivate_service("2014-02-07", { |
3921 | + "operation_date": date(2014, 3, 8), |
3922 | + }) |
3923 | + invoice = self._get_last_invoice() |
3924 | + date_from, date_to = self._get_invoice_date_range(invoice.id) |
3925 | + self.assertEquals(invoice.date_invoice, "2014-03-14") |
3926 | + self.assertEquals(date_from, "2014-02-07", "Wrong start_date") |
3927 | + self.assertEquals(date_to, "2014-03-31", "Wrong end_date") |
3928 | + self.assertAlmostEquals( |
3929 | + invoice.amount_untaxed, |
3930 | + (1 + self.service_obj._prorata_rate(21, 28)) * 56, |
3931 | + msg="Expect refund for 7-28 feb + march") |
3932 | + self.assertEquals(invoice.type, "out_refund") |
3933 | + |
3934 | + def test_before_invoice_day_future_deactivation_same_month(self): |
3935 | + self.company.write({"invoice_day": "14", "cutoff_day": "21"}) |
3936 | + self._deactivate_service("2014-02-14", { |
3937 | + "operation_date": date(2014, 2, 7), |
3938 | + }) |
3939 | + invoice = self._get_last_invoice() |
3940 | + date_from, date_to = self._get_invoice_date_range(invoice.id) |
3941 | + self.assertEquals(invoice.date_invoice, "2014-02-14") |
3942 | + self.assertEquals(date_from, "2014-02-07", "Wrong start_date") |
3943 | + self.assertEquals(date_to, "2014-02-14", "Wrong end_date") |
3944 | + self.assertAlmostEquals( |
3945 | + invoice.amount_untaxed, |
3946 | + self.service_obj._prorata_rate(7, 28) * 56, |
3947 | + msg="Expect invoice for 7-14 feb") |
3948 | + self.assertEquals(invoice.type, "out_invoice") |
3949 | + |
3950 | + def test_before_invoice_day_future_deactivation_future_month(self): |
3951 | + self.company.write({"invoice_day": "14", "cutoff_day": "21"}) |
3952 | + self._deactivate_service("2014-04-16", { |
3953 | + "operation_date": date(2014, 2, 7), |
3954 | + }) |
3955 | + invoice = self._get_last_invoice() |
3956 | + date_from, date_to = self._get_invoice_date_range(invoice.id) |
3957 | + self.assertEquals(invoice.date_invoice, "2014-02-14") |
3958 | + self.assertEquals(date_from, "2014-02-07", "Wrong start_date") |
3959 | + self.assertEquals(date_to, "2014-04-16", "Wrong end_date") |
3960 | + self.assertAlmostEquals( |
3961 | + invoice.amount_untaxed, |
3962 | + 56 * ( |
3963 | + self.service_obj._prorata_rate(21, 28) + |
3964 | + self.service_obj._prorata_rate(16, 30) + |
3965 | + 1), |
3966 | + msg="Expect invoice for 7-28 feb, march, 1-16 apr") |
3967 | + self.assertEquals(invoice.type, "out_invoice") |
3968 | |
3969 | === added file 'contract_isp_invoice/tests/test_prorata.py' |
3970 | --- contract_isp_invoice/tests/test_prorata.py 1970-01-01 00:00:00 +0000 |
3971 | +++ contract_isp_invoice/tests/test_prorata.py 2014-11-24 15:05:14 +0000 |
3972 | @@ -0,0 +1,179 @@ |
3973 | +# -*- coding: utf-8 -*- |
3974 | +############################################################################## |
3975 | +# |
3976 | +# OpenERP, Open Source Management Solution |
3977 | +# Copyright (C) 2014 Savoir-faire Linux (<http://www.savoirfairelinux.com>). |
3978 | +# |
3979 | +# This program is free software: you can redistribute it and/or modify |
3980 | +# it under the terms of the GNU Affero General Public License as |
3981 | +# published by the Free Software Foundation, either version 3 of the |
3982 | +# License, or (at your option) any later version. |
3983 | +# |
3984 | +# This program is distributed in the hope that it will be useful, |
3985 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
3986 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3987 | +# GNU Affero General Public License for more details. |
3988 | +# |
3989 | +# You should have received a copy of the GNU Affero General Public License |
3990 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
3991 | +# |
3992 | +############################################################################## |
3993 | +from __future__ import unicode_literals |
3994 | + |
3995 | +from datetime import date |
3996 | + |
3997 | +from openerp.tests.common import TransactionCase |
3998 | + |
3999 | +from .common import ServiceSetup |
4000 | + |
4001 | + |
4002 | +class test_prorata_activate_service(TransactionCase, ServiceSetup): |
4003 | + """ |
4004 | + Tests pro-rata invoicing of services |
4005 | + """ |
4006 | + |
4007 | + def setUp(self): |
4008 | + super(test_prorata_activate_service, self).setUp() |
4009 | + self._common_setup() |
4010 | + |
4011 | + def test_prorata_after_invoice_before_cutoff_current_month(self): |
4012 | + """ |
4013 | + Test prorata when: |
4014 | + invoice_day < operation_date <= end of month |
4015 | + operation date < cutoff date |
4016 | + """ |
4017 | + cr, uid = self.cr, self.uid |
4018 | + self.company.write({"invoice_day": "7", "cutoff_day": "24"}) |
4019 | + self._create_activate_service(self.p_internet, "2014-01-13", { |
4020 | + "operation_date": date(2014, 1, 14), |
4021 | + }) |
4022 | + |
4023 | + invoice = self.invoice_obj.browse( |
4024 | + cr, uid, |
4025 | + self.invoice_obj.search(cr, uid, |
4026 | + [('partner_id', '=', self.partner_id)])[0] |
4027 | + ) |
4028 | + self.assertEquals(invoice.date_invoice, "2014-01-07") |
4029 | + date_from, date_to = self._get_invoice_date_range(invoice.id) |
4030 | + self.assertEquals(date_from, "2014-02-13", "Wrong start date") |
4031 | + self.assertEquals(date_to, "2014-02-28", "Wrong end date") |
4032 | + self.assertAlmostEquals( |
4033 | + invoice.amount_untaxed, |
4034 | + self.service_obj._prorata_rate(15, 28) * 56, |
4035 | + msg="~Half month, 15/28 of 56", |
4036 | + delta=0.01) |
4037 | + |
4038 | + def test_prorata_after_invoice_before_cutoff_past_month(self): |
4039 | + """ |
4040 | + Test prorata when: |
4041 | + invoice_day < operation_date <= end of month |
4042 | + operation date < cutoff date |
4043 | + """ |
4044 | + cr, uid = self.cr, self.uid |
4045 | + self.company.write({"invoice_day": "7", "cutoff_day": "21"}) |
4046 | + self._create_activate_service(self.p_internet, "2014-08-11", { |
4047 | + "operation_date": date(2014, 9, 10), |
4048 | + }) |
4049 | + |
4050 | + invoice = self.invoice_obj.browse( |
4051 | + cr, uid, |
4052 | + self.invoice_obj.search(cr, uid, |
4053 | + [('partner_id', '=', self.partner_id)])[0] |
4054 | + ) |
4055 | + self.assertEquals(invoice.date_invoice, "2014-09-07") |
4056 | + date_from, date_to = self._get_invoice_date_range(invoice.id) |
4057 | + self.assertEquals(date_from, "2014-09-11", |
4058 | + "Wrong start date, expected activation + 1 month") |
4059 | + self.assertEquals(date_to, "2014-10-31", |
4060 | + "Wrong end date, end of (op) next month") |
4061 | + |
4062 | + self.assertAlmostEquals( |
4063 | + invoice.amount_untaxed, |
4064 | + (1 + self.service_obj._prorata_rate(19, 30)) * 56, |
4065 | + msg="Oct 100%, Sept 11-30", |
4066 | + delta=0.01) |
4067 | + |
4068 | + def test_prorata_after_invoice_after_cutoff(self): |
4069 | + """ |
4070 | + Test prorata when: |
4071 | + invoice_day < operation_date <= end of month |
4072 | + operation date > cutoff date |
4073 | + """ |
4074 | + cr, uid = self.cr, self.uid |
4075 | + self.company.write({"invoice_day": "7", "cutoff_day": "24"}) |
4076 | + self._create_activate_service(self.p_internet, "2014-01-15", { |
4077 | + "operation_date": date(2014, 1, 26), |
4078 | + }) |
4079 | + |
4080 | + invoice = self.invoice_obj.browse( |
4081 | + cr, uid, |
4082 | + self.invoice_obj.search(cr, uid, |
4083 | + [('partner_id', '=', self.partner_id)])[0] |
4084 | + ) |
4085 | + self.assertEquals(invoice.date_invoice, "2014-02-07") |
4086 | + date_from, date_to = self._get_invoice_date_range(invoice.id) |
4087 | + self.assertEquals(date_from, "2014-02-15", "Wrong start date") |
4088 | + self.assertEquals(date_to, "2014-02-28", "Wrong end date") |
4089 | + self.assertAlmostEquals( |
4090 | + invoice.amount_untaxed, |
4091 | + self.service_obj._prorata_rate(13, 28) * 56, |
4092 | + msg="13/28 of 56", |
4093 | + delta=0.01) |
4094 | + |
4095 | + def test_prorata_before_invoice_past_month_activation(self): |
4096 | + """ |
4097 | + Test prorata when: |
4098 | + 1 <= operation_date <= invoice_day |
4099 | + activation is in the past month |
4100 | + |
4101 | + """ |
4102 | + cr, uid = self.cr, self.uid |
4103 | + self.company.write({"invoice_day": "7", "cutoff_day": "21"}) |
4104 | + self._create_activate_service(self.p_internet, "2014-01-27", { |
4105 | + "operation_date": date(2014, 2, 1), |
4106 | + }) |
4107 | + |
4108 | + invoice = self.invoice_obj.browse( |
4109 | + cr, uid, |
4110 | + self.invoice_obj.search(cr, uid, |
4111 | + [('partner_id', '=', self.partner_id)])[0] |
4112 | + ) |
4113 | + self.assertEquals(invoice.date_invoice, "2014-02-07") |
4114 | + date_from, date_to = self._get_invoice_date_range(invoice.id) |
4115 | + self.assertEquals(date_from, "2014-02-27", "Wrong start date") |
4116 | + self.assertEquals(date_to, "2014-02-28", "Wrong end date") |
4117 | + self.assertAlmostEquals( |
4118 | + invoice.amount_untaxed, |
4119 | + self.service_obj._prorata_rate(1, 28) * 56, |
4120 | + msg="1 day in feb", |
4121 | + delta=0.01) |
4122 | + |
4123 | + def test_prorata_before_invoice_current_month_activation(self): |
4124 | + """ |
4125 | + Test prorata when: |
4126 | + 1 <= operation_date <= invoice_day |
4127 | + activation is in the current month and < invoice_day |
4128 | + |
4129 | + """ |
4130 | + cr, uid = self.cr, self.uid |
4131 | + self.company.write({"invoice_day": "21", "cutoff_day": "24"}) |
4132 | + self._create_activate_service(self.p_internet, "2014-02-14", { |
4133 | + "operation_date": date(2014, 2, 10), |
4134 | + }) |
4135 | + |
4136 | + invoice = self.invoice_obj.browse( |
4137 | + cr, uid, |
4138 | + self.invoice_obj.search(cr, uid, |
4139 | + [('partner_id', '=', self.partner_id)])[0] |
4140 | + ) |
4141 | + self.assertEquals(invoice.date_invoice, "2014-02-21") |
4142 | + date_from, date_to = self._get_invoice_date_range(invoice.id) |
4143 | + self.assertEquals(date_from, "2014-03-01", "Wrong start date") |
4144 | + self.assertEquals(date_to, "2014-03-14", "Wrong end date") |
4145 | + self.assertAlmostEquals( |
4146 | + invoice.amount_untaxed, |
4147 | + self.service_obj._prorata_rate(14, 31) * 56, |
4148 | + msg="credit for 1-14 in match", |
4149 | + delta=0.01) |
4150 | + self.assertEquals(invoice.type, "out_refund", |
4151 | + msg="Expected Credit Note") |
4152 | |
4153 | === added file 'contract_isp_invoice/tests/test_reseller.py' |
4154 | --- contract_isp_invoice/tests/test_reseller.py 1970-01-01 00:00:00 +0000 |
4155 | +++ contract_isp_invoice/tests/test_reseller.py 2014-11-24 15:05:14 +0000 |
4156 | @@ -0,0 +1,70 @@ |
4157 | +# -*- coding: utf-8 -*- |
4158 | +############################################################################## |
4159 | +# |
4160 | +# OpenERP, Open Source Management Solution |
4161 | +# Copyright (C) 2014 Savoir-faire Linux (<http://www.savoirfairelinux.com>). |
4162 | +# |
4163 | +# This program is free software: you can redistribute it and/or modify |
4164 | +# it under the terms of the GNU Affero General Public License as |
4165 | +# published by the Free Software Foundation, either version 3 of the |
4166 | +# License, or (at your option) any later version. |
4167 | +# |
4168 | +# This program is distributed in the hope that it will be useful, |
4169 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
4170 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4171 | +# GNU Affero General Public License for more details. |
4172 | +# |
4173 | +# You should have received a copy of the GNU Affero General Public License |
4174 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
4175 | +# |
4176 | +############################################################################## |
4177 | +from __future__ import unicode_literals |
4178 | + |
4179 | +from datetime import date |
4180 | + |
4181 | +from openerp.tests.common import TransactionCase |
4182 | + |
4183 | +from .common import ServiceSetup |
4184 | + |
4185 | + |
4186 | +class test_reseller_invoice(TransactionCase, ServiceSetup): |
4187 | + """ |
4188 | + Tests specific reseller behaviors for invoices |
4189 | + """ |
4190 | + def setUp(self): |
4191 | + super(test_reseller_invoice, self).setUp() |
4192 | + self._common_setup() |
4193 | + |
4194 | + def _create_partner(self): |
4195 | + cr, uid = self.cr, self.uid |
4196 | + p_o = self.partner_obj |
4197 | + self.parent_id = p_o.create(cr, uid, { |
4198 | + "is_company": True, |
4199 | + "is_reseller": True, |
4200 | + "name": "Test Company", |
4201 | + }) |
4202 | + self.partner_id = p_o.create(cr, uid, { |
4203 | + "name": "Test Partner", |
4204 | + "parent_id": self.parent_id, |
4205 | + }) |
4206 | + |
4207 | + def test_prorata_invoice(self): |
4208 | + self._create_activate_service(self.p_internet, "2014-02-08", { |
4209 | + "operation_date": date(2014, 2, 10), |
4210 | + }) |
4211 | + |
4212 | + self.assertEquals( |
4213 | + len(self.invoice_obj.search(self.cr, self.uid, [ |
4214 | + ('partner_id', '=', self.parent_id), |
4215 | + ])), |
4216 | + 1, |
4217 | + "Expected one new invoice on parent" |
4218 | + ) |
4219 | + |
4220 | + self.assertEquals( |
4221 | + len(self.invoice_obj.search(self.cr, self.uid, [ |
4222 | + ('partner_id', '=', self.partner_id), |
4223 | + ])), |
4224 | + 0, |
4225 | + "Expected no new invoice on child" |
4226 | + ) |
4227 | |
4228 | === modified file 'contract_isp_invoice/wizard/activate_contract_service.py' |
4229 | --- contract_isp_invoice/wizard/activate_contract_service.py 2013-10-04 16:19:20 +0000 |
4230 | +++ contract_isp_invoice/wizard/activate_contract_service.py 2014-11-24 15:05:14 +0000 |
4231 | @@ -20,10 +20,8 @@ |
4232 | # |
4233 | ############################################################################## |
4234 | |
4235 | -import time |
4236 | -import datetime |
4237 | -from openerp.osv import orm, fields |
4238 | -from openerp.addons.contract_isp.contract import add_months |
4239 | +from openerp.osv import orm |
4240 | +from ..invoice import PROCESS_PRORATA |
4241 | |
4242 | |
4243 | class contract_service_activate(orm.TransientModel): |
4244 | @@ -33,29 +31,39 @@ |
4245 | if context is None: |
4246 | context = {} |
4247 | |
4248 | - account_invoice_obj = self.pool.get('account.invoice') |
4249 | - account_voucher_obj = self.pool.get('account.voucher') |
4250 | - account_move_obj = self.pool.get('account.move') |
4251 | - res_company_obj = self.pool.get('res.company') |
4252 | wizard = self.browse(cr, uid, ids[0], context) |
4253 | |
4254 | ret = super(contract_service_activate, self).activate(cr, uid, |
4255 | ids, |
4256 | context=context) |
4257 | |
4258 | - contract_service_obj = self.pool.get('contract.service') |
4259 | - account_analytic_account_obj = self.pool.get('account.analytic.account') |
4260 | - account_move_line_obj = self.pool.get('account.move.line') |
4261 | - |
4262 | - query = [ |
4263 | - ('account_id', '=', wizard.account_id.id), |
4264 | - ('state', '=', 'draft') |
4265 | - ] |
4266 | - # Check if all services were activated |
4267 | - if not contract_service_obj.search(cr, uid, query, context=context): |
4268 | - |
4269 | - # jgama - Try to create the prorata invoice |
4270 | - pro_inv = account_analytic_account_obj.create_invoice( |
4271 | - cr, uid, wizard.account_id.id, prorata=True, context=context) |
4272 | + account_analytic_account_obj = self.pool.get('account.analytic.account') |
4273 | + |
4274 | + account_analytic_account_obj.create_invoice( |
4275 | + cr, uid, wizard.account_id.id, |
4276 | + source_process=PROCESS_PRORATA, |
4277 | + context=context) |
4278 | + |
4279 | + return ret |
4280 | + |
4281 | + |
4282 | +class contract_service_deactivate(orm.TransientModel): |
4283 | + _inherit = 'contract.service.deactivate' |
4284 | + |
4285 | + def deactivate(self, cr, uid, ids, context=None): |
4286 | + if context is None: |
4287 | + context = {} |
4288 | + |
4289 | + wizard = self.browse(cr, uid, ids[0], context) |
4290 | + |
4291 | + ret = super(contract_service_deactivate, self).deactivate( |
4292 | + cr, uid, ids, context=context) |
4293 | + |
4294 | + account_analytic_account_obj = self.pool.get('account.analytic.account') |
4295 | + |
4296 | + account_analytic_account_obj.create_invoice( |
4297 | + cr, uid, wizard.account_id.id, |
4298 | + source_process=PROCESS_PRORATA, |
4299 | + context=context) |
4300 | |
4301 | return ret |
4302 | |
4303 | === modified file 'contract_isp_invoice/wizard/close_contract.py' |
4304 | --- contract_isp_invoice/wizard/close_contract.py 2013-09-16 17:59:01 +0000 |
4305 | +++ contract_isp_invoice/wizard/close_contract.py 2014-11-24 15:05:14 +0000 |
4306 | @@ -27,7 +27,7 @@ |
4307 | from openerp.report import report_sxw |
4308 | from openerp.tools import convert |
4309 | from openerp.tools.translate import _ |
4310 | -from openerp.addons.contract_isp.contract import date_interval |
4311 | +from openerp.addons.contract_isp.contract import date_interval, format_interval |
4312 | |
4313 | |
4314 | class contract_isp_close(orm.TransientModel): |
4315 | @@ -71,7 +71,8 @@ |
4316 | last_invoice_id[-1], |
4317 | context=context) |
4318 | if last_invoice.date_invoice > wizard.close_date: |
4319 | - raise orm.except_orm(_('Error!'), _('Close date before last invoice date!')) |
4320 | + raise orm.except_orm(_('Error!'), |
4321 | + _('Close date before last invoice date!')) |
4322 | |
4323 | amount_untaxed = last_invoice.amount_untaxed |
4324 | |
4325 | @@ -81,10 +82,12 @@ |
4326 | used_days = month_days - int(wizard.close_date[8:10]) |
4327 | ptx = (100 * used_days / month_days) / 100.0 |
4328 | amount = amount_untaxed * ptx |
4329 | - interval = date_interval(datetime.date(int(wizard.close_date[:4]), |
4330 | - int(wizard.close_date[5:7]), |
4331 | - int(wizard.close_date[8:10])), |
4332 | - True) |
4333 | + start_date, end_date = date_interval( |
4334 | + datetime.date(int(wizard.close_date[:4]), |
4335 | + int(wizard.close_date[5:7]), |
4336 | + int(wizard.close_date[8:10])), |
4337 | + True) |
4338 | + interval = format_interval(start_date, end_date) |
4339 | |
4340 | line = { |
4341 | 'name': ' '.join([_('Credit refund'), interval]), |
4342 | @@ -111,4 +114,4 @@ |
4343 | mail_message.write({'type': 'email'}) |
4344 | contract.write({'state': 'close'}) |
4345 | return {} |
4346 | - |
4347 | \ No newline at end of file |
4348 | + |
4349 | |
4350 | === modified file 'contract_isp_package_configurator/__init__.py' |
4351 | --- contract_isp_package_configurator/__init__.py 2013-09-16 17:59:01 +0000 |
4352 | +++ contract_isp_package_configurator/__init__.py 2014-11-24 15:05:14 +0000 |
4353 | @@ -20,6 +20,10 @@ |
4354 | # |
4355 | ############################################################################## |
4356 | |
4357 | -import wizard |
4358 | -import workflow |
4359 | -import company |
4360 | +from . import ( |
4361 | + account_analytic, |
4362 | + company, |
4363 | + contract, |
4364 | + wizard, |
4365 | + workflow, |
4366 | +) |
4367 | |
4368 | === modified file 'contract_isp_package_configurator/__openerp__.py' |
4369 | --- contract_isp_package_configurator/__openerp__.py 2013-09-16 17:59:01 +0000 |
4370 | +++ contract_isp_package_configurator/__openerp__.py 2014-11-24 15:05:14 +0000 |
4371 | @@ -35,6 +35,7 @@ |
4372 | 'depends': ['contract_isp', 'product_dependencies', 'stock'], |
4373 | 'data': [ |
4374 | 'security/ir.model.access.csv', |
4375 | + 'security/groups.xml', |
4376 | 'wizard/package_configurator.xml', |
4377 | 'workflow/contract_isp_package_configurator.xml', |
4378 | 'contract_isp_package_configurator_view.xml', |
4379 | |
4380 | === added file 'contract_isp_package_configurator/account_analytic.py' |
4381 | --- contract_isp_package_configurator/account_analytic.py 1970-01-01 00:00:00 +0000 |
4382 | +++ contract_isp_package_configurator/account_analytic.py 2014-11-24 15:05:14 +0000 |
4383 | @@ -0,0 +1,61 @@ |
4384 | +# -*- coding: utf-8 -*- |
4385 | + |
4386 | +############################################################################## |
4387 | +# |
4388 | +# OpenERP, Open Source Management Solution |
4389 | +# Copyright (C) 2014 Savoirfaire-Linux Inc. (<www.savoirfairelinux.com>). |
4390 | +# |
4391 | +# This program is free software: you can redistribute it and/or modify |
4392 | +# it under the terms of the GNU Affero General Public License as |
4393 | +# published by the Free Software Foundation, either version 3 of the |
4394 | +# License, or (at your option) any later version. |
4395 | +# |
4396 | +# This program is distributed in the hope that it will be useful, |
4397 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
4398 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4399 | +# GNU Affero General Public License for more details. |
4400 | +# |
4401 | +# You should have received a copy of the GNU Affero General Public License |
4402 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
4403 | +# |
4404 | +############################################################################## |
4405 | + |
4406 | +from openerp.osv import fields, orm |
4407 | + |
4408 | + |
4409 | +class AccountAnalyticAccount(orm.Model): |
4410 | + _name = 'account.analytic.account' |
4411 | + _inherit = 'account.analytic.account' |
4412 | + |
4413 | + def _get_ui_flags(self, cr, uid, ids, field_names, arg, context): |
4414 | + res = {} |
4415 | + for account in self.browse(cr, uid, ids, context=context): |
4416 | + res[account.id] = cur = { |
4417 | + 'ui_reserve': False, |
4418 | + 'ui_return': False, |
4419 | + } |
4420 | + for service in account.contract_service_ids: |
4421 | + if not service.product_id.type == "product": |
4422 | + continue |
4423 | + if service.prodlot_id: |
4424 | + cur['ui_return'] = True |
4425 | + else: |
4426 | + cur['ui_reserve'] = True |
4427 | + |
4428 | + return res |
4429 | + |
4430 | + _columns = { |
4431 | + 'prodlot_id': fields.many2one( |
4432 | + 'stock.production.lot', |
4433 | + 'Serial Number', |
4434 | + required=False, |
4435 | + ), |
4436 | + 'ui_reserve': fields.function( |
4437 | + _get_ui_flags, |
4438 | + type='boolean', method=True, multi='ui_flags', |
4439 | + ), |
4440 | + 'ui_return': fields.function( |
4441 | + _get_ui_flags, |
4442 | + type='boolean', method=True, multi='ui_flags', |
4443 | + ), |
4444 | + } |
4445 | |
4446 | === added file 'contract_isp_package_configurator/contract.py' |
4447 | --- contract_isp_package_configurator/contract.py 1970-01-01 00:00:00 +0000 |
4448 | +++ contract_isp_package_configurator/contract.py 2014-11-24 15:05:14 +0000 |
4449 | @@ -0,0 +1,35 @@ |
4450 | +# -*- coding: utf-8 -*- |
4451 | + |
4452 | +############################################################################## |
4453 | +# |
4454 | +# OpenERP, Open Source Management Solution |
4455 | +# Copyright (C) 2014 Savoirfaire-Linux Inc. (<www.savoirfairelinux.com>). |
4456 | +# |
4457 | +# This program is free software: you can redistribute it and/or modify |
4458 | +# it under the terms of the GNU Affero General Public License as |
4459 | +# published by the Free Software Foundation, either version 3 of the |
4460 | +# License, or (at your option) any later version. |
4461 | +# |
4462 | +# This program is distributed in the hope that it will be useful, |
4463 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
4464 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4465 | +# GNU Affero General Public License for more details. |
4466 | +# |
4467 | +# You should have received a copy of the GNU Affero General Public License |
4468 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
4469 | +# |
4470 | +############################################################################## |
4471 | + |
4472 | +from openerp.osv import fields, orm |
4473 | + |
4474 | + |
4475 | +class ContractService(orm.Model): |
4476 | + _name = 'contract.service' |
4477 | + _inherit = 'contract.service' |
4478 | + _columns = { |
4479 | + 'prodlot_id': fields.many2one( |
4480 | + 'stock.production.lot', |
4481 | + 'Serial Number', |
4482 | + required=False, |
4483 | + ), |
4484 | + } |
4485 | |
4486 | === modified file 'contract_isp_package_configurator/contract_isp_package_configurator_view.xml' |
4487 | --- contract_isp_package_configurator/contract_isp_package_configurator_view.xml 2013-09-16 17:59:01 +0000 |
4488 | +++ contract_isp_package_configurator/contract_isp_package_configurator_view.xml 2014-11-24 15:05:14 +0000 |
4489 | @@ -1,28 +1,46 @@ |
4490 | <?xml version="1.0" encoding="UTF-8"?> |
4491 | <openerp> |
4492 | <data> |
4493 | - <record id="contract_isp_form_package_configurator_wizard" model="ir.ui.view"> |
4494 | - <field name="name">contract.isp.form.package.configurator.wizard</field> |
4495 | - <field name="model">account.analytic.account</field> |
4496 | - <field name="inherit_id" ref="analytic.view_account_analytic_account_form"/> |
4497 | - <field name="arch" type="xml"> |
4498 | - <xpath expr="//div[@name='buttons']" position='inside'> |
4499 | - <button string="Package Configurator" |
4500 | - name="%(action_contract_isp_package_configurator)d" |
4501 | - type="action" /> |
4502 | - </xpath> |
4503 | - </field> |
4504 | - </record> |
4505 | - <record id="view_company_form_package_configurator" model="ir.ui.view"> |
4506 | - <field name="name">company.form.package.configurator</field> |
4507 | - <field name="model">res.company</field> |
4508 | - <field name="inherit_id" ref="contract_isp.view_company_contract_isp_form"/> |
4509 | - <field name="arch" type="xml"> |
4510 | - <field name="parent_account_id" position="before"> |
4511 | - <field name="default_product_category" /> |
4512 | - </field> |
4513 | - </field> |
4514 | - </record> |
4515 | + <record id="contract_isp_form_package_configurator_wizard" model="ir.ui.view"> |
4516 | + <field name="name">contract.isp.form.package.configurator.wizard</field> |
4517 | + <field name="model">account.analytic.account</field> |
4518 | + <field name="inherit_id" ref="analytic.view_account_analytic_account_form"/> |
4519 | + <field name="arch" type="xml"> |
4520 | + <xpath expr="//div[@name='buttons']" position='inside'> |
4521 | + <field name="ui_reserve" invisible="1" /> |
4522 | + <field name="ui_return" invisible="1" /> |
4523 | + <button string="Package Configurator" |
4524 | + name="%(action_contract_isp_package_configurator)d" |
4525 | + type="action" /> |
4526 | + <button string="Reserve Equipment" |
4527 | + name="%(action_contract_isp_reserve_equipment)d" |
4528 | + attrs="{'invisible': [('ui_reserve', '=', False)]}" |
4529 | + groups="contract_isp_package_configurator.group_isp_add_equipment" |
4530 | + type="action" /> |
4531 | + <button string="Exchange Equipment" |
4532 | + name="%(action_contract_isp_exchange_equipment)d" |
4533 | + attrs="{'invisible': [('ui_return', '=', False)]}" |
4534 | + groups="contract_isp_package_configurator.group_isp_add_equipment" |
4535 | + type="action" /> |
4536 | + <button string="Return Equipment" |
4537 | + name="%(action_contract_isp_return_equipment)d" |
4538 | + attrs="{'invisible': [('ui_return', '=', False)]}" |
4539 | + groups="contract_isp_package_configurator.group_isp_remove_equipment" |
4540 | + type="action" /> |
4541 | + </xpath> |
4542 | + </field> |
4543 | + </record> |
4544 | + |
4545 | + <record id="view_company_form_package_configurator" model="ir.ui.view"> |
4546 | + <field name="name">company.form.package.configurator</field> |
4547 | + <field name="model">res.company</field> |
4548 | + <field name="inherit_id" ref="contract_isp.view_company_contract_isp_form"/> |
4549 | + <field name="arch" type="xml"> |
4550 | + <field name="parent_account_id" position="before"> |
4551 | + <field name="default_product_category" /> |
4552 | + </field> |
4553 | + </field> |
4554 | + </record> |
4555 | |
4556 | </data> |
4557 | </openerp> |
4558 | |
4559 | === modified file 'contract_isp_package_configurator/i18n/contract_isp_package_configurator.pot' |
4560 | --- contract_isp_package_configurator/i18n/contract_isp_package_configurator.pot 2013-09-16 17:59:01 +0000 |
4561 | +++ contract_isp_package_configurator/i18n/contract_isp_package_configurator.pot 2014-11-24 15:05:14 +0000 |
4562 | @@ -0,0 +1,343 @@ |
4563 | +# Translation of OpenERP Server. |
4564 | +# This file contains the translation of the following modules: |
4565 | +# * contract_isp_package_configurator |
4566 | +# |
4567 | +msgid "" |
4568 | +msgstr "" |
4569 | +"Project-Id-Version: OpenERP Server 7.0\n" |
4570 | +"Report-Msgid-Bugs-To: \n" |
4571 | +"POT-Creation-Date: 2014-09-23 00:06+0000\n" |
4572 | +"PO-Revision-Date: 2014-09-23 00:06+0000\n" |
4573 | +"Last-Translator: <>\n" |
4574 | +"Language-Team: \n" |
4575 | +"MIME-Version: 1.0\n" |
4576 | +"Content-Type: text/plain; charset=UTF-8\n" |
4577 | +"Content-Transfer-Encoding: \n" |
4578 | +"Plural-Forms: \n" |
4579 | + |
4580 | +#. module: contract_isp_package_configurator |
4581 | +#: view:contract.service.configurator:0 |
4582 | +msgid "Add" |
4583 | +msgstr "" |
4584 | + |
4585 | +#. module: contract_isp_package_configurator |
4586 | +#: model:res.groups,name:contract_isp_package_configurator.group_isp_add_equipment |
4587 | +msgid "Add Equipment" |
4588 | +msgstr "" |
4589 | + |
4590 | +#. module: contract_isp_package_configurator |
4591 | +#: field:contract.service.configurator,current_product_id:0 |
4592 | +msgid "Add Product" |
4593 | +msgstr "" |
4594 | + |
4595 | +#. module: contract_isp_package_configurator |
4596 | +#: selection:contract.service.configurator.dependency.line,state:0 |
4597 | +#: selection:contract.service.configurator.line,state:0 |
4598 | +msgid "Added" |
4599 | +msgstr "" |
4600 | + |
4601 | +#. module: contract_isp_package_configurator |
4602 | +#: code:_description:0 |
4603 | +#: model:ir.model,name:contract_isp_package_configurator.model_account_analytic_account |
4604 | +#, python-format |
4605 | +msgid "Analytic Account" |
4606 | +msgstr "" |
4607 | + |
4608 | +#. module: contract_isp_package_configurator |
4609 | +#: view:contract.service.configurator:0 |
4610 | +#: view:contract.service.equipment.manage:0 |
4611 | +msgid "Cancel" |
4612 | +msgstr "" |
4613 | + |
4614 | +#. module: contract_isp_package_configurator |
4615 | +#: view:contract.service.configurator:0 |
4616 | +#: field:contract.service.configurator,product_category_id:0 |
4617 | +#: field:contract.service.configurator,root_category_id:0 |
4618 | +msgid "Category" |
4619 | +msgstr "" |
4620 | + |
4621 | +#. module: contract_isp_package_configurator |
4622 | +#: view:contract.service.configurator:0 |
4623 | +msgid "Click on add to view the available components" |
4624 | +msgstr "" |
4625 | + |
4626 | +#. module: contract_isp_package_configurator |
4627 | +#: code:_description:0 |
4628 | +#: model:ir.model,name:contract_isp_package_configurator.model_res_company |
4629 | +#, python-format |
4630 | +msgid "Companies" |
4631 | +msgstr "" |
4632 | + |
4633 | +#. module: contract_isp_package_configurator |
4634 | +#: field:contract.service.configurator,contract_id:0 |
4635 | +#: field:contract.service.equipment.manage,contract_id:0 |
4636 | +msgid "Contract" |
4637 | +msgstr "" |
4638 | + |
4639 | +#. module: contract_isp_package_configurator |
4640 | +#: field:res.company,default_product_category:0 |
4641 | +msgid "Default Product Category" |
4642 | +msgstr "" |
4643 | + |
4644 | +#. module: contract_isp_package_configurator |
4645 | +#: field:contract.service.configurator,dependency_ids:0 |
4646 | +msgid "Dependencies" |
4647 | +msgstr "" |
4648 | + |
4649 | +#. module: contract_isp_package_configurator |
4650 | +#: view:contract.service.configurator:0 |
4651 | +#: selection:contract.service.configurator,state:0 |
4652 | +#: selection:contract.service.configurator.dependency.line,state:0 |
4653 | +#: selection:contract.service.configurator.line,state:0 |
4654 | +msgid "Done" |
4655 | +msgstr "" |
4656 | + |
4657 | +#. module: contract_isp_package_configurator |
4658 | +#: view:contract.service.equipment.manage:0 |
4659 | +msgid "Exchange" |
4660 | +msgstr "" |
4661 | + |
4662 | +#. module: contract_isp_package_configurator |
4663 | +#: view:account.analytic.account:0 |
4664 | +#: model:ir.actions.act_window,name:contract_isp_package_configurator.action_contract_isp_exchange_equipment |
4665 | +msgid "Exchange Equipment" |
4666 | +msgstr "" |
4667 | + |
4668 | +#. module: contract_isp_package_configurator |
4669 | +#: field:contract.service.configurator.dependency.line,handle_dependency:0 |
4670 | +#: field:contract.service.configurator.line,handle_dependency:0 |
4671 | +msgid "Handle dependencies" |
4672 | +msgstr "" |
4673 | + |
4674 | +#. module: contract_isp_package_configurator |
4675 | +#: selection:contract.service.configurator.dependency.line,state:0 |
4676 | +#: selection:contract.service.configurator.line,state:0 |
4677 | +msgid "Information" |
4678 | +msgstr "" |
4679 | + |
4680 | +#. module: contract_isp_package_configurator |
4681 | +#: field:contract.service.configurator,is_level2:0 |
4682 | +msgid "Is level 2" |
4683 | +msgstr "" |
4684 | + |
4685 | +#. module: contract_isp_package_configurator |
4686 | +#: field:contract.service.configurator,line_ids:0 |
4687 | +msgid "Line" |
4688 | +msgstr "" |
4689 | + |
4690 | +#. module: contract_isp_package_configurator |
4691 | +#: field:contract.service.configurator.dependency.line,manager_id:0 |
4692 | +#: field:contract.service.configurator.line,manager_id:0 |
4693 | +msgid "Manage Equipment Wizard" |
4694 | +msgstr "" |
4695 | + |
4696 | +#. module: contract_isp_package_configurator |
4697 | +#: field:contract.service.configurator.dependency.line,message:0 |
4698 | +#: field:contract.service.configurator.line,message:0 |
4699 | +msgid "Message" |
4700 | +msgstr "" |
4701 | + |
4702 | +#. module: contract_isp_package_configurator |
4703 | +#: field:contract.service.configurator.dependency.line,name:0 |
4704 | +#: field:contract.service.configurator.line,name:0 |
4705 | +msgid "Name" |
4706 | +msgstr "" |
4707 | + |
4708 | +#. module: contract_isp_package_configurator |
4709 | +#: view:contract.service.configurator:0 |
4710 | +msgid "Next" |
4711 | +msgstr "" |
4712 | + |
4713 | +#. module: contract_isp_package_configurator |
4714 | +#: selection:contract.service.configurator.dependency.line,state:0 |
4715 | +#: selection:contract.service.configurator.line,state:0 |
4716 | +msgid "No Stock" |
4717 | +msgstr "" |
4718 | + |
4719 | +#. module: contract_isp_package_configurator |
4720 | +#: view:contract.service.configurator.line:0 |
4721 | +msgid "Ok" |
4722 | +msgstr "" |
4723 | + |
4724 | +#. module: contract_isp_package_configurator |
4725 | +#: view:account.analytic.account:0 |
4726 | +#: view:contract.service.configurator:0 |
4727 | +#: field:contract.service.configurator.dependency.line,configurator_id:0 |
4728 | +#: view:contract.service.configurator.line:0 |
4729 | +#: field:contract.service.configurator.line,configurator_id:0 |
4730 | +#: model:ir.actions.act_window,name:contract_isp_package_configurator.action_contract_isp_package_configurator |
4731 | +msgid "Package Configurator" |
4732 | +msgstr "" |
4733 | + |
4734 | +#. module: contract_isp_package_configurator |
4735 | +#: field:contract.service.configurator.dependency.line,parent_id:0 |
4736 | +#: field:contract.service.configurator.line,parent_id:0 |
4737 | +msgid "Parent" |
4738 | +msgstr "" |
4739 | + |
4740 | +#. module: contract_isp_package_configurator |
4741 | +#: view:contract.service.configurator:0 |
4742 | +#: field:contract.service.configurator.dependency.line,product_id:0 |
4743 | +#: field:contract.service.configurator.line,product_id:0 |
4744 | +#: view:contract.service.equipment.manage:0 |
4745 | +msgid "Product" |
4746 | +msgstr "" |
4747 | + |
4748 | +#. module: contract_isp_package_configurator |
4749 | +#: view:contract.service.configurator:0 |
4750 | +#: view:contract.service.configurator.line:0 |
4751 | +msgid "Products" |
4752 | +msgstr "" |
4753 | + |
4754 | +#. module: contract_isp_package_configurator |
4755 | +#: model:res.groups,name:contract_isp_package_configurator.group_isp_remove_equipment |
4756 | +msgid "Remove Equipment" |
4757 | +msgstr "" |
4758 | + |
4759 | +#. module: contract_isp_package_configurator |
4760 | +#: view:contract.service.equipment.manage:0 |
4761 | +msgid "Reserve" |
4762 | +msgstr "" |
4763 | + |
4764 | +#. module: contract_isp_package_configurator |
4765 | +#: view:account.analytic.account:0 |
4766 | +#: view:contract.service.equipment.manage:0 |
4767 | +#: model:ir.actions.act_window,name:contract_isp_package_configurator.action_contract_isp_reserve_equipment |
4768 | +msgid "Reserve Equipment" |
4769 | +msgstr "" |
4770 | + |
4771 | +#. module: contract_isp_package_configurator |
4772 | +#: view:contract.service.equipment.manage:0 |
4773 | +msgid "Return" |
4774 | +msgstr "" |
4775 | + |
4776 | +#. module: contract_isp_package_configurator |
4777 | +#: view:account.analytic.account:0 |
4778 | +#: view:contract.service.equipment.manage:0 |
4779 | +#: model:ir.actions.act_window,name:contract_isp_package_configurator.action_contract_isp_return_equipment |
4780 | +msgid "Return Equipment" |
4781 | +msgstr "" |
4782 | + |
4783 | +#. module: contract_isp_package_configurator |
4784 | +#: selection:contract.service.configurator,state:0 |
4785 | +msgid "Select components" |
4786 | +msgstr "" |
4787 | + |
4788 | +#. module: contract_isp_package_configurator |
4789 | +#: selection:contract.service.configurator,state:0 |
4790 | +msgid "Select product" |
4791 | +msgstr "" |
4792 | + |
4793 | +#. module: contract_isp_package_configurator |
4794 | +#: selection:contract.service.configurator.dependency.line,state:0 |
4795 | +#: selection:contract.service.configurator.line,state:0 |
4796 | +msgid "Select serial number" |
4797 | +msgstr "" |
4798 | + |
4799 | +#. module: contract_isp_package_configurator |
4800 | +#: field:contract.service.equipment.manage,product_id:0 |
4801 | +msgid "Selected Product" |
4802 | +msgstr "" |
4803 | + |
4804 | +#. module: contract_isp_package_configurator |
4805 | +#: view:contract.service.equipment.manage:0 |
4806 | +msgid "Serial" |
4807 | +msgstr "" |
4808 | + |
4809 | +#. module: contract_isp_package_configurator |
4810 | +#: field:account.analytic.account,prodlot_id:0 |
4811 | +#: field:contract.service,prodlot_id:0 |
4812 | +#: field:contract.service.configurator.dependency.line,serial:0 |
4813 | +#: view:contract.service.configurator.line:0 |
4814 | +#: field:contract.service.configurator.line,serial:0 |
4815 | +#: field:contract.service.equipment.manage,prodlot_id:0 |
4816 | +msgid "Serial Number" |
4817 | +msgstr "" |
4818 | + |
4819 | +#. module: contract_isp_package_configurator |
4820 | +#: help:res.company,default_product_category:0 |
4821 | +msgid "Set the default starting point for the package configuration wizard" |
4822 | +msgstr "" |
4823 | + |
4824 | +#. module: contract_isp_package_configurator |
4825 | +#: selection:contract.service.configurator,state:0 |
4826 | +msgid "Start" |
4827 | +msgstr "" |
4828 | + |
4829 | +#. module: contract_isp_package_configurator |
4830 | +#: field:contract.service.configurator,state:0 |
4831 | +#: field:contract.service.configurator.dependency.line,state:0 |
4832 | +#: field:contract.service.configurator.line,state:0 |
4833 | +msgid "State" |
4834 | +msgstr "" |
4835 | + |
4836 | +#. module: contract_isp_package_configurator |
4837 | +#: field:contract.service.configurator.dependency.line,stock_move_id:0 |
4838 | +#: field:contract.service.configurator.line,stock_move_id:0 |
4839 | +msgid "Stock Move" |
4840 | +msgstr "" |
4841 | + |
4842 | +#. module: contract_isp_package_configurator |
4843 | +#: model:res.groups,comment:contract_isp_package_configurator.group_isp_add_equipment |
4844 | +msgid "The users in this group will be able to assign customer equipment" |
4845 | +msgstr "" |
4846 | + |
4847 | +#. module: contract_isp_package_configurator |
4848 | +#: model:res.groups,comment:contract_isp_package_configurator.group_isp_remove_equipment |
4849 | +msgid "The users in this group will be able to unassign customers equipment" |
4850 | +msgstr "" |
4851 | + |
4852 | +#. module: contract_isp_package_configurator |
4853 | +#: view:contract.service.configurator.line:0 |
4854 | +msgid "We don't have this product in stock at the moment!" |
4855 | +msgstr "" |
4856 | + |
4857 | +#. module: contract_isp_package_configurator |
4858 | +#: code:_description:0 |
4859 | +#: model:ir.model,name:contract_isp_package_configurator.model_contract_service |
4860 | +#, python-format |
4861 | +msgid "contract.service" |
4862 | +msgstr "" |
4863 | + |
4864 | +#. module: contract_isp_package_configurator |
4865 | +#: code:_description:0 |
4866 | +#: model:ir.model,name:contract_isp_package_configurator.model_contract_service_configurator |
4867 | +#, python-format |
4868 | +msgid "contract.service.configurator" |
4869 | +msgstr "" |
4870 | + |
4871 | +#. module: contract_isp_package_configurator |
4872 | +#: code:_description:0 |
4873 | +#: model:ir.model,name:contract_isp_package_configurator.model_contract_service_configurator_dependency_line |
4874 | +#, python-format |
4875 | +msgid "contract.service.configurator.dependency.line" |
4876 | +msgstr "" |
4877 | + |
4878 | +#. module: contract_isp_package_configurator |
4879 | +#: code:_description:0 |
4880 | +#: model:ir.model,name:contract_isp_package_configurator.model_contract_service_configurator_line |
4881 | +#, python-format |
4882 | +msgid "contract.service.configurator.line" |
4883 | +msgstr "" |
4884 | + |
4885 | +#. module: contract_isp_package_configurator |
4886 | +#: code:_description:0 |
4887 | +#: model:ir.model,name:contract_isp_package_configurator.model_contract_service_equipment_manage |
4888 | +#, python-format |
4889 | +msgid "contract.service.equipment.manage" |
4890 | +msgstr "" |
4891 | + |
4892 | +#. module: contract_isp_package_configurator |
4893 | +#: view:contract.service.equipment.manage:0 |
4894 | +msgid "or" |
4895 | +msgstr "" |
4896 | + |
4897 | +#. module: contract_isp_package_configurator |
4898 | +#: field:account.analytic.account,ui_reserve:0 |
4899 | +#: field:account.analytic.account,ui_return:0 |
4900 | +#: field:contract.service.equipment.manage,products_all:0 |
4901 | +#: field:contract.service.equipment.manage,products_no_serial:0 |
4902 | +#: field:contract.service.equipment.manage,products_with_serial:0 |
4903 | +msgid "unknown" |
4904 | +msgstr "" |
4905 | + |
4906 | |
4907 | === added file 'contract_isp_package_configurator/i18n/fr.po' |
4908 | --- contract_isp_package_configurator/i18n/fr.po 1970-01-01 00:00:00 +0000 |
4909 | +++ contract_isp_package_configurator/i18n/fr.po 2014-11-24 15:05:14 +0000 |
4910 | @@ -0,0 +1,346 @@ |
4911 | +# Translation of OpenERP Server. |
4912 | +# This file contains the translation of the following modules: |
4913 | +# * contract_isp_package_configurator |
4914 | +# |
4915 | +msgid "" |
4916 | +msgstr "" |
4917 | +"Project-Id-Version: OpenERP Server 7.0\n" |
4918 | +"Report-Msgid-Bugs-To: \n" |
4919 | +"POT-Creation-Date: 2014-09-23 00:06+0000\n" |
4920 | +"PO-Revision-Date: 2014-09-22 20:07-0500\n" |
4921 | +"Last-Translator: Marc Cassuto <marc.cassuto@savoirfairelinux.com>\n" |
4922 | +"Language-Team: \n" |
4923 | +"Language: fr\n" |
4924 | +"MIME-Version: 1.0\n" |
4925 | +"Content-Type: text/plain; charset=UTF-8\n" |
4926 | +"Content-Transfer-Encoding: 8bit\n" |
4927 | +"X-Generator: Poedit 1.5.4\n" |
4928 | + |
4929 | +#. module: contract_isp_package_configurator |
4930 | +#: view:contract.service.configurator:0 |
4931 | +msgid "Add" |
4932 | +msgstr "Ajouter" |
4933 | + |
4934 | +#. module: contract_isp_package_configurator |
4935 | +#: model:res.groups,name:contract_isp_package_configurator.group_isp_add_equipment |
4936 | +msgid "Add Equipment" |
4937 | +msgstr "Ajouter un équipement" |
4938 | + |
4939 | +#. module: contract_isp_package_configurator |
4940 | +#: field:contract.service.configurator,current_product_id:0 |
4941 | +msgid "Add Product" |
4942 | +msgstr "Ajouter un produit" |
4943 | + |
4944 | +#. module: contract_isp_package_configurator |
4945 | +#: selection:contract.service.configurator.dependency.line,state:0 |
4946 | +#: selection:contract.service.configurator.line,state:0 |
4947 | +msgid "Added" |
4948 | +msgstr "Ajouté" |
4949 | + |
4950 | +#. module: contract_isp_package_configurator |
4951 | +#: code:_description:0 |
4952 | +#: model:ir.model,name:contract_isp_package_configurator.model_account_analytic_account |
4953 | +#, python-format |
4954 | +msgid "Analytic Account" |
4955 | +msgstr "Contrat" |
4956 | + |
4957 | +#. module: contract_isp_package_configurator |
4958 | +#: view:contract.service.configurator:0 |
4959 | +#: view:contract.service.equipment.manage:0 |
4960 | +msgid "Cancel" |
4961 | +msgstr "Annuler" |
4962 | + |
4963 | +#. module: contract_isp_package_configurator |
4964 | +#: view:contract.service.configurator:0 |
4965 | +#: field:contract.service.configurator,product_category_id:0 |
4966 | +#: field:contract.service.configurator,root_category_id:0 |
4967 | +msgid "Category" |
4968 | +msgstr "Catégorie" |
4969 | + |
4970 | +#. module: contract_isp_package_configurator |
4971 | +#: view:contract.service.configurator:0 |
4972 | +msgid "Click on add to view the available components" |
4973 | +msgstr "Cliquer sur le bouton 'Ajouter' pour voir les produits disponibles" |
4974 | + |
4975 | +#. module: contract_isp_package_configurator |
4976 | +#: code:_description:0 |
4977 | +#: model:ir.model,name:contract_isp_package_configurator.model_res_company |
4978 | +#, python-format |
4979 | +msgid "Companies" |
4980 | +msgstr "Companies" |
4981 | + |
4982 | +#. module: contract_isp_package_configurator |
4983 | +#: field:contract.service.configurator,contract_id:0 |
4984 | +#: field:contract.service.equipment.manage,contract_id:0 |
4985 | +msgid "Contract" |
4986 | +msgstr "Contrat" |
4987 | + |
4988 | +#. module: contract_isp_package_configurator |
4989 | +#: field:res.company,default_product_category:0 |
4990 | +msgid "Default Product Category" |
4991 | +msgstr "Catégorie de Produit par défault" |
4992 | + |
4993 | +#. module: contract_isp_package_configurator |
4994 | +#: field:contract.service.configurator,dependency_ids:0 |
4995 | +msgid "Dependencies" |
4996 | +msgstr "Dépendances" |
4997 | + |
4998 | +#. module: contract_isp_package_configurator |
4999 | +#: view:contract.service.configurator:0 |
5000 | +#: selection:contract.service.configurator,state:0 |