You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

697 lines
33 KiB

6 years ago
6 years ago
6 years ago
6 years ago
  1. # -*- coding: utf-8 -*-
  2. from datetime import datetime
  3. from openerp import api, fields, models, _
  4. from openerp.addons.base_iban import base_iban
  5. from openerp.exceptions import UserError, ValidationError
  6. _REQUIRED = ['email',
  7. 'firstname',
  8. 'lastname',
  9. 'birthdate',
  10. 'address',
  11. 'share_product_id',
  12. 'ordered_parts',
  13. 'zip_code',
  14. 'city',
  15. 'iban',
  16. 'gender'] # Could be improved including required from model
  17. @api.model
  18. def _lang_get(self):
  19. languages = self.env['res.lang'].search([])
  20. return [(language.code, language.name) for language in languages]
  21. class subscription_request(models.Model):
  22. _name = 'subscription.request'
  23. _description = 'Subscription Request'
  24. def get_required_field(self):
  25. required_fields = _REQUIRED
  26. company = self.env['res.company']._company_default_get()
  27. if company.internal_rules_approval_required:
  28. required_fields.append('internal_rules_approved')
  29. if company.data_policy_approval_required:
  30. required_fields.append('data_policy_approved')
  31. if company.financial_risk_approval_required:
  32. required_fields.append('financial_risk_approved')
  33. return required_fields
  34. @api.model
  35. def create(self, vals):
  36. partner_obj = self.env['res.partner']
  37. if not vals.get('partner_id'):
  38. cooperator = False
  39. if vals.get('email'):
  40. cooperator = partner_obj.get_cooperator_from_email(
  41. vals.get('email'))
  42. if cooperator:
  43. # TODO remove the following line of code once it has
  44. # been found a way to avoid double entry
  45. cooperator = cooperator[0]
  46. if cooperator.member:
  47. vals['type'] = 'increase'
  48. vals['already_cooperator'] = True
  49. else:
  50. vals['type'] = 'subscription'
  51. vals['partner_id'] = cooperator.id
  52. if not cooperator.cooperator:
  53. cooperator.write({'cooperator': True})
  54. else:
  55. cooperator_id = vals.get('partner_id')
  56. cooperator = partner_obj.browse(cooperator_id)
  57. if cooperator.member:
  58. vals['type'] = 'increase'
  59. vals['already_cooperator'] = True
  60. subscr_request = super(subscription_request, self).create(vals)
  61. confirmation_mail_template = self.env.ref('easy_my_coop.email_template_confirmation', False)
  62. confirmation_mail_template.send_mail(subscr_request.id)
  63. return subscr_request
  64. @api.model
  65. def create_comp_sub_req(self, vals):
  66. vals["name"] = vals['company_name']
  67. if not vals.get('partner_id'):
  68. cooperator = self.env['res.partner'].get_cooperator_from_crn(vals.get('company_register_number'))
  69. if cooperator:
  70. vals['partner_id'] = cooperator.id
  71. vals['type'] = 'increase'
  72. vals['already_cooperator'] = True
  73. subscr_request = super(subscription_request, self).create(vals)
  74. confirmation_mail_template = self.env.ref('easy_my_coop.email_template_confirmation_company', False)
  75. confirmation_mail_template.send_mail(subscr_request.id, True)
  76. return subscr_request
  77. def check_empty_string(self, value):
  78. if value is None or value is False or value == '':
  79. return False
  80. return True
  81. def check_iban(self, iban):
  82. validated = True
  83. try:
  84. base_iban.validate_iban(iban)
  85. except ValidationError:
  86. validated = False
  87. return validated
  88. @api.multi
  89. @api.depends('iban', 'skip_control_ng', 'is_company')
  90. def _validated_lines(self):
  91. for sub_request in self:
  92. validated = (self.check_iban(sub_request.iban)
  93. or sub_request.skip_control_ng
  94. )
  95. sub_request.validated = validated
  96. @api.multi
  97. @api.depends('share_product_id',
  98. 'share_product_id.list_price',
  99. 'ordered_parts')
  100. def _compute_subscription_amount(self):
  101. for sub_request in self:
  102. sub_request.subscription_amount = (sub_request.share_product_id.
  103. list_price *
  104. sub_request.ordered_parts)
  105. already_cooperator = fields.Boolean(string="I'm already cooperator",
  106. readonly=True,
  107. states={'draft': [('readonly', False)]}
  108. )
  109. name = fields.Char(string='Name',
  110. required=True,
  111. readonly=True,
  112. states={'draft': [('readonly', False)]})
  113. firstname = fields.Char(string='Firstname',
  114. readonly=True,
  115. states={'draft': [('readonly', False)]})
  116. lastname = fields.Char(string='Lastname',
  117. readonly=True,
  118. states={'draft': [('readonly', False)]})
  119. birthdate = fields.Date(string="Birthdate",
  120. readonly=True,
  121. states={'draft': [('readonly', False)]})
  122. gender = fields.Selection([('male', _('Male')),
  123. ('female', _('Female')),
  124. ('other', _('Other'))],
  125. string='Gender',
  126. readonly=True,
  127. states={'draft': [('readonly', False)]})
  128. type = fields.Selection([('new', 'New Cooperator'),
  129. ('subscription', 'Subscription'),
  130. ('increase', 'Increase number of share')],
  131. string='Type', default="new",
  132. readonly=True,
  133. states={'draft': [('readonly', False)]})
  134. state = fields.Selection([('draft', 'Draft'),
  135. ('block', 'Blocked'),
  136. ('done', 'Done'),
  137. ('waiting', 'Waiting'),
  138. ('transfer', 'Transfer'),
  139. ('cancelled', 'Cancelled'),
  140. ('paid', 'paid')],
  141. string='State', required=True, default="draft")
  142. email = fields.Char(string='Email',
  143. required=True,
  144. readonly=True,
  145. states={'draft': [('readonly', False)]})
  146. iban = fields.Char(string='Account Number',
  147. readonly=True,
  148. states={'draft': [('readonly', False)]})
  149. partner_id = fields.Many2one('res.partner',
  150. string='Cooperator',
  151. readonly=True,
  152. states={'draft': [('readonly', False)]})
  153. share_product_id = fields.Many2one('product.product',
  154. string='Share type',
  155. domain=[('is_share', '=', True)],
  156. required=True,
  157. readonly=True,
  158. states={'draft': [('readonly', False)]})
  159. share_short_name = fields.Char(related='share_product_id.short_name',
  160. string='Share type name',
  161. readonly=True,
  162. states={'draft': [('readonly', False)]})
  163. share_unit_price = fields.Float(related='share_product_id.list_price',
  164. string='Share price',
  165. readonly=True,
  166. states={'draft': [('readonly', False)]})
  167. subscription_amount = fields.Float(compute='_compute_subscription_amount',
  168. string='Subscription amount',
  169. readonly=True,
  170. states={'draft': [('readonly', False)]})
  171. ordered_parts = fields.Integer(string='Number of Share',
  172. required=True,
  173. readonly=True,
  174. default=1,
  175. states={'draft': [('readonly', False)]})
  176. address = fields.Char(string='Address',
  177. required=True,
  178. readonly=True,
  179. states={'draft': [('readonly', False)]})
  180. city = fields.Char(string='City',
  181. required=True,
  182. readonly=True,
  183. states={'draft': [('readonly', False)]})
  184. zip_code = fields.Char(string='Zip Code',
  185. required=True,
  186. readonly=True,
  187. states={'draft': [('readonly', False)]})
  188. country_id = fields.Many2one('res.country',
  189. string='Country',
  190. ondelete='restrict',
  191. required=True,
  192. readonly=True,
  193. states={'draft': [('readonly', False)]})
  194. phone = fields.Char(string='Phone',
  195. readonly=True,
  196. states={'draft': [('readonly', False)]})
  197. user_id = fields.Many2one('res.users',
  198. string='Responsible',
  199. readonly=True)
  200. validated = fields.Boolean(compute='_validated_lines',
  201. string='Valid Line?',
  202. readonly=True)
  203. skip_control_ng = fields.Boolean(string="Skip control",
  204. help="if this field is checked then no"
  205. " control will be done on the national"
  206. " register number and on the iban bank"
  207. " account. To be done in case of the id"
  208. " card is from abroad or in case of"
  209. " a passport")
  210. lang = fields.Selection(_lang_get,
  211. string='Language',
  212. required=True,
  213. readonly=True,
  214. states={'draft': [('readonly', False)]},
  215. default=lambda self: self.env['res.company']._company_default_get().default_lang_id.code)
  216. date = fields.Date(string='Subscription date request',
  217. required=True,
  218. readonly=True,
  219. states={'draft': [('readonly', False)]},
  220. default=lambda self: datetime.strftime(datetime.now(),
  221. '%Y-%m-%d'))
  222. company_id = fields.Many2one('res.company',
  223. string='Company',
  224. required=True,
  225. change_default=True,
  226. readonly=True,
  227. default=lambda self: self.env['res.company']._company_default_get())
  228. is_company = fields.Boolean(string='Is a company',
  229. readonly=True,
  230. states={'draft': [('readonly', False)]})
  231. is_operation = fields.Boolean(string='Is an operation',
  232. readonly=True,
  233. states={'draft': [('readonly', False)]})
  234. company_name = fields.Char(string="Company name",
  235. readonly=True,
  236. states={'draft': [('readonly', False)]})
  237. company_email = fields.Char(string="Company email",
  238. readonly=True,
  239. states={'draft': [('readonly', False)]})
  240. company_register_number = fields.Char(string='Company register number',
  241. readonly=True,
  242. states={'draft': [('readonly', False)]})
  243. company_type = fields.Selection([('', '')],
  244. string="Company type",
  245. readonly=True,
  246. states={'draft': [('readonly', False)]})
  247. same_address = fields.Boolean(string='Same address',
  248. readonly=True,
  249. states={'draft': [('readonly', False)]})
  250. activities_address = fields.Char(string='Activities address',
  251. readonly=True,
  252. states={'draft': [('readonly', False)]})
  253. activities_city = fields.Char(string='Activities city',
  254. readonly=True,
  255. states={'draft': [('readonly', False)]})
  256. activities_zip_code = fields.Char(string='Activities zip Code',
  257. readonly=True,
  258. states={'draft': [('readonly', False)]})
  259. activities_country_id = fields.Many2one('res.country',
  260. string='Activities country',
  261. ondelete='restrict',
  262. readonly=True,
  263. states={'draft': [('readonly', False)]})
  264. contact_person_function = fields.Char(string='Function',
  265. readonly=True,
  266. states={'draft': [('readonly', False)]})
  267. operation_request_id = fields.Many2one('operation.request',
  268. string="Operation Request",
  269. readonly=True,
  270. states={'draft': [('readonly', False)]})
  271. capital_release_request = fields.One2many('account.invoice',
  272. 'subscription_request',
  273. string='Capital release request',
  274. readonly=True,
  275. states={'draft': [('readonly', False)]})
  276. capital_release_request_date = fields.Date(string="Force the capital "
  277. "release request date",
  278. help="Keep empty to use the "
  279. "current date",
  280. copy=False,
  281. readonly=True,
  282. states={'draft': [('readonly', False)]})
  283. source = fields.Selection([('website', 'Website'),
  284. ('crm', 'CRM'),
  285. ('manual', 'Manual'),
  286. ('operation', 'Operation')],
  287. string="Source",
  288. default="website",
  289. readonly=True,
  290. states={'draft': [('readonly', False)]})
  291. internal_rules_approved = fields.Boolean(
  292. string='Internal Rules Approved ',
  293. default=False,
  294. )
  295. data_policy_approved = fields.Boolean(
  296. string='Data Policy Approved',
  297. default=False,
  298. )
  299. financial_risk_approved = fields.Boolean(
  300. string='Financial Risk Approved',
  301. default=False,
  302. )
  303. _order = "id desc"
  304. def get_person_info(self, partner):
  305. self.firstname = partner.firstname
  306. self.name = partner.name
  307. self.lastname = partner.lastname
  308. self.email = partner.email
  309. self.birthdate = partner.birthdate_date
  310. self.gender = partner.gender
  311. self.address = partner.street
  312. self.city = partner.city
  313. self.zip_code = partner.zip
  314. self.country_id = partner.country_id
  315. self.phone = partner.phone
  316. self.lang = partner.lang
  317. @api.onchange('partner_id')
  318. def onchange_partner(self):
  319. partner = self.partner_id
  320. if partner:
  321. self.is_company = partner.is_company
  322. self.already_cooperator = partner.member
  323. if partner.bank_ids:
  324. self.iban = partner.bank_ids[0].acc_number
  325. if partner.member:
  326. self.type = 'increase'
  327. if partner.is_company:
  328. self.company_name = partner.name
  329. self.company_email = partner.email
  330. self.company_register_number = partner.company_register_number
  331. representative = partner.get_representative()
  332. self.get_person_info(representative)
  333. self.contact_person_function = representative.function
  334. else:
  335. self.get_person_info(partner)
  336. # declare this function in order to be overriden
  337. def get_eater_vals(self, partner, share_product_id): #noqa
  338. return {}
  339. def _prepare_invoice_line(self, product, partner, qty):
  340. self.ensure_one()
  341. account = product.property_account_income_id \
  342. or product.categ_id.property_account_income_categ_id
  343. if not account:
  344. raise UserError(_('Please define income account for this product:'
  345. ' "%s" (id:%d) - or for its category: "%s".') %
  346. (product.name, product.id, product.categ_id.name))
  347. fpos = partner.property_account_position_id
  348. if fpos:
  349. account = fpos.map_account(account)
  350. res = {
  351. 'name': product.name,
  352. 'account_id': account.id,
  353. 'price_unit': product.lst_price,
  354. 'quantity': qty,
  355. 'uom_id': product.uom_id.id,
  356. 'product_id': product.id or False,
  357. }
  358. return res
  359. def send_capital_release_request(self, invoice):
  360. invoice_email_template = self.env.ref('easy_my_coop.email_template_release_capital', False)
  361. # we send the email with the capital release request in attachment
  362. invoice_email_template.send_mail(invoice.id, True)
  363. invoice.sent = True
  364. def create_invoice(self, partner):
  365. # get subscription journal
  366. journal = self.env['account.journal'].search([('code', '=', 'SUBJ')])[0]
  367. # get the account for associate
  368. # TODO this should be defined in configuration
  369. if self.company_id.property_cooperator_account:
  370. account = self.company_id.property_cooperator_account
  371. else:
  372. account = self.env['account.account'].search([('code', '=', '416000')])[0]
  373. # creating invoice and invoice lines
  374. invoice_vals = {'partner_id': partner.id,
  375. 'journal_id': journal.id,
  376. 'account_id': account.id,
  377. 'type': 'out_invoice',
  378. 'release_capital_request': True,
  379. 'subscription_request': self.id}
  380. if self.capital_release_request_date:
  381. invoice_vals['date_invoice'] = self.capital_release_request_date
  382. invoice = self.env['account.invoice'].create(invoice_vals)
  383. vals = self._prepare_invoice_line(self.share_product_id, partner,
  384. self.ordered_parts)
  385. vals['invoice_id'] = invoice.id
  386. self.env['account.invoice.line'].create(vals)
  387. # validate the capital release request
  388. invoice.signal_workflow('invoice_open')
  389. self.send_capital_release_request(invoice)
  390. return invoice
  391. def get_partner_company_vals(self):
  392. partner_vals = {'name': self.company_name,
  393. 'last_name': self.company_name,
  394. 'is_company': self.is_company,
  395. 'legal_form': self.company_type,
  396. 'company_register_number': self.company_register_number, #noqa
  397. 'cooperator': True,
  398. 'street': self.address, 'zip': self.zip_code,
  399. 'city': self.city, 'email': self.company_email,
  400. 'out_inv_comm_type': 'bba',
  401. 'customer': self.share_product_id.customer,
  402. 'out_inv_comm_algorithm': 'random',
  403. 'country_id': self.country_id.id,
  404. 'lang': self.lang,
  405. 'internal_rules_approved': self.internal_rules_approved,
  406. 'data_policy_approved': self.data_policy_approved,
  407. 'financial_risk_approved': self.financial_risk_approved
  408. }
  409. return partner_vals
  410. def get_partner_vals(self):
  411. partner_vals = {'name': self.name, 'firstname': self.firstname,
  412. 'lastname': self.lastname, 'street': self.address,
  413. 'zip': self.zip_code, 'email': self.email,
  414. 'gender': self.gender, 'cooperator': True,
  415. 'city': self.city, 'phone': self.phone,
  416. 'out_inv_comm_type': 'bba',
  417. 'out_inv_comm_algorithm': 'random',
  418. 'country_id': self.country_id.id, 'lang': self.lang,
  419. 'birthdate_date': self.birthdate,
  420. 'customer': self.share_product_id.customer,
  421. 'internal_rules_approved': self.internal_rules_approved,
  422. 'data_policy_approved': self.data_policy_approved,
  423. 'financial_risk_approved': self.financial_risk_approved
  424. }
  425. return partner_vals
  426. def create_coop_partner(self):
  427. partner_obj = self.env['res.partner']
  428. if self.is_company:
  429. partner_vals = self.get_partner_company_vals()
  430. else:
  431. partner_vals = self.get_partner_vals()
  432. partner = partner_obj.create(partner_vals)
  433. if self.iban:
  434. self.env['res.partner.bank'].create({
  435. 'partner_id': partner.id,
  436. 'acc_number': self.iban
  437. })
  438. return partner
  439. @api.one
  440. def validate_subscription_request(self):
  441. partner_obj = self.env['res.partner']
  442. if self.ordered_parts <= 0:
  443. raise UserError(_('Number of share must be greater than 0.'))
  444. if self.partner_id:
  445. partner = self.partner_id
  446. else:
  447. partner = None
  448. domain = []
  449. if self.already_cooperator:
  450. raise UserError(_('The checkbox already cooperator is'
  451. ' checked please select a cooperator.'))
  452. elif self.is_company and self.company_register_number:
  453. domain = [('company_register_number', '=', self.company_register_number)] #noqa
  454. elif not self.is_company and self.email:
  455. domain = [('email', '=', self.email)]
  456. if domain:
  457. partner = partner_obj.search(domain)
  458. if not partner:
  459. partner = self.create_coop_partner()
  460. else:
  461. partner = partner[0]
  462. partner.write({
  463. "cooperator": True,
  464. "customer": self.share_product_id.customer
  465. })
  466. if self.is_company and not partner.has_representative():
  467. contact = False
  468. if self.email:
  469. domain = [('email', '=', self.email)]
  470. contact = partner_obj.search(domain)
  471. if contact:
  472. contact.type = 'representative'
  473. if not contact:
  474. contact_vals = {'name': self.name,
  475. 'firstname': self.firstname,
  476. 'lastname': self.lastname, 'customer': False,
  477. 'is_company': False, 'cooperator': True,
  478. 'street': self.address, 'gender': self.gender,
  479. 'zip': self.zip_code, 'city': self.city,
  480. 'phone': self.phone, 'email': self.email,
  481. 'country_id': self.country_id.id,
  482. 'out_inv_comm_type': 'bba',
  483. 'out_inv_comm_algorithm': 'random',
  484. 'lang': self.lang,
  485. 'birthdate_date': self.birthdate,
  486. 'parent_id': partner.id,
  487. 'representative': True,
  488. 'function': self.contact_person_function,
  489. 'type': 'representative',
  490. 'internal_rules_approved': self.internal_rules_approved,
  491. 'data_policy_approved': self.data_policy_approved,
  492. 'financial_risk_approved': self.financial_risk_approved
  493. }
  494. contact = partner_obj.create(contact_vals)
  495. else:
  496. if len(contact) > 1:
  497. raise UserError(_('There is two different persons with the'
  498. ' same national register number. Please'
  499. ' proceed to a merge before to continue')
  500. )
  501. if contact.parent_id and contact.parent_id.id != partner.id:
  502. raise UserError(_('This contact person is already defined'
  503. ' for another company. Please select'
  504. ' another contact'))
  505. else:
  506. contact.write({'parent_id': partner.id,
  507. 'representative': True})
  508. invoice = self.create_invoice(partner)
  509. self.write({'partner_id': partner.id, 'state': 'done'})
  510. return invoice
  511. @api.one
  512. def block_subscription_request(self):
  513. self.write({'state': 'block'})
  514. @api.one
  515. def unblock_subscription_request(self):
  516. self.write({'state': 'draft'})
  517. @api.one
  518. def cancel_subscription_request(self):
  519. self.write({'state': 'cancelled'})
  520. @api.one
  521. def put_on_waiting_list(self):
  522. waiting_list_mail_template = self.env.ref('easy_my_coop.email_template_waiting_list', False)
  523. waiting_list_mail_template.send_mail(self.id, True)
  524. self.write({'state': 'waiting'})
  525. class share_line(models.Model):
  526. _name = 'share.line'
  527. @api.multi
  528. def _compute_total_line(self):
  529. res = {}
  530. for line in self:
  531. line.total_amount_line = line.share_unit_price * line.share_number
  532. return res
  533. share_product_id = fields.Many2one('product.product',
  534. string='Share type',
  535. required=True,
  536. readonly=True)
  537. share_number = fields.Integer(string='Number of Share',
  538. required=True,
  539. readonly=True)
  540. share_short_name = fields.Char(related='share_product_id.short_name',
  541. string='Share type name',
  542. readonly=True)
  543. share_unit_price = fields.Float(string='Share price',
  544. readonly=True)
  545. effective_date = fields.Date(string='Effective Date',
  546. readonly=True)
  547. partner_id = fields.Many2one('res.partner',
  548. string='Cooperator',
  549. required=True,
  550. ondelete='cascade',
  551. readonly=True)
  552. total_amount_line = fields.Float(compute='_compute_total_line',
  553. string='Total amount line')
  554. class subscription_register(models.Model):
  555. _name = 'subscription.register'
  556. @api.multi
  557. def _compute_total_line(self):
  558. for register_line in self:
  559. register_line.total_amount_line = register_line.share_unit_price * register_line.quantity
  560. name = fields.Char(string='Register Number Operation',
  561. required=True,
  562. readonly=True)
  563. register_number_operation = fields.Integer(string='Register Number Operation',
  564. required=True,
  565. readonly=True)
  566. partner_id = fields.Many2one('res.partner',
  567. string='Cooperator',
  568. required=True,
  569. readonly=True)
  570. partner_id_to = fields.Many2one('res.partner',
  571. string='Transfered to',
  572. readonly=True)
  573. date = fields.Date(string='Subscription Date',
  574. required=True,
  575. readonly=True)
  576. quantity = fields.Integer(string='Number of share',
  577. readonly=True)
  578. share_unit_price = fields.Float(string='Share price',
  579. readonly=True)
  580. total_amount_line = fields.Float(compute='_compute_total_line',
  581. string='Total amount line')
  582. share_product_id = fields.Many2one('product.product',
  583. string='Share type',
  584. required=True,
  585. readonly=True,
  586. domain=[('is_share', '=', True)])
  587. share_short_name = fields.Char(related='share_product_id.short_name',
  588. string='Share type name',
  589. readonly=True)
  590. share_to_product_id = fields.Many2one('product.product',
  591. string='Share to type',
  592. readonly=True,
  593. domain=[('is_share', '=', True)])
  594. share_to_short_name = fields.Char(related='share_to_product_id.short_name',
  595. string='Share to type name',
  596. readonly=True)
  597. quantity_to = fields.Integer(string='Number of share to',
  598. readonly=True)
  599. share_to_unit_price = fields.Float(string='Share to price',
  600. readonly=True)
  601. type = fields.Selection([('subscription', 'Subscription'),
  602. ('transfer', 'Transfer'),
  603. ('sell_back', 'Sell Back'),
  604. ('convert', 'Conversion')],
  605. string='Operation Type', readonly=True)
  606. company_id = fields.Many2one('res.company', string='Company',
  607. required=True,
  608. change_default=True, readonly=True,
  609. default=lambda self: self.env['res.company']._company_default_get())
  610. user_id = fields.Many2one('res.users',
  611. string='Responsible',
  612. readonly=True,
  613. default=lambda self: self.env.user)
  614. _order = "register_number_operation asc"
  615. @api.model
  616. def read_group(self, domain, fields, groupby, offset=0, limit=None,
  617. orderby=False,
  618. lazy=True):
  619. if 'share_unit_price' in fields:
  620. fields.remove('share_unit_price')
  621. if 'register_number_operation' in fields:
  622. fields.remove('register_number_operation')
  623. res = super(subscription_register, self).read_group(domain, fields,
  624. groupby,
  625. offset=offset,
  626. limit=limit,
  627. orderby=orderby,
  628. lazy=lazy)
  629. if 'total_amount_line' in fields:
  630. for line in res:
  631. if '__domain' in line:
  632. lines = self.search(line['__domain'])
  633. inv_value = 0.0
  634. for line2 in lines:
  635. inv_value += line2.total_amount_line
  636. line['total_amount_line'] = inv_value
  637. return res