eiru_utility_tool_sale.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. # -*- coding: utf-8 -*-
  2. from openerp import api, fields, models
  3. from openerp.exceptions import except_orm
  4. from datetime import datetime, timedelta
  5. from openerp.tools import DEFAULT_SERVER_DATE_FORMAT
  6. from dateutil.relativedelta import relativedelta
  7. import math
  8. class saleOrder(models.Model):
  9. _inherit = 'sale.order'
  10. def sale_convert_str_to_datetime(self, date):
  11. return datetime.strptime(date, DEFAULT_SERVER_DATE_FORMAT)
  12. ''' Get Sale Order '''
  13. @api.model
  14. def getSaleOrder(self,idOrder):
  15. return[{
  16. 'id': order.id,
  17. 'amountTotal': order.amount_total,
  18. 'dateOrder': order.date_order.split(" ")[0],
  19. 'currency': {
  20. 'id': order.pricelist_id.currency_id.id,
  21. 'symbol': order.pricelist_id.currency_id.symbol,
  22. 'decimalSeparator': order.pricelist_id.currency_id.decimal_separator,
  23. 'decimalPlaces': order.pricelist_id.currency_id.decimal_places,
  24. 'thousandsSeparator': order.pricelist_id.currency_id.thousands_separator,
  25. }
  26. } for order in self.env['sale.order'].browse(idOrder)]
  27. ''' Get Sale Term '''
  28. @api.model
  29. def getSaleTerm(self, orderId):
  30. return [{
  31. 'saleAmount': term.sale_amount,
  32. 'salePaymentsInit': term.sale_payments_init,
  33. 'saleResidual': term.sale_residual,
  34. 'interestQty': term.interest_qty,
  35. 'amountTotal': term.amount_total,
  36. 'dateInit': term.date_init,
  37. 'termTypeId': term.term_type_id.id,
  38. 'quotaAmount': term.quota_amount,
  39. 'quotaQty': term.quota_qty,
  40. 'interestAmount': term.interest_amount,
  41. 'lines': [{
  42. 'number': line.number,
  43. 'cuotaNumber': line.cuota_number,
  44. 'date': line.date,
  45. 'amount': line.amount,
  46. 'days': line.days,
  47. 'value': line.value,
  48. }for line in term.lines]
  49. }for term in self.env['account.sale.term'].search([('sale_id.id', '=',orderId)])]
  50. ''' Registar entrega Inicial '''
  51. @api.model
  52. def saleTermUpdatePaymentsInitial(self, orderId, amount):
  53. amountPayments = float(amount)
  54. qty = 0
  55. saleOrder = self.env['sale.order'].browse(orderId)
  56. if (not saleOrder):
  57. return {
  58. 'state': False
  59. }
  60. decimalPlaces = saleOrder.pricelist_id.currency_id.decimal_places
  61. if (not decimalPlaces):
  62. decimalPlaces = 0
  63. saleResidual = saleOrder.amount_total - amountPayments
  64. for line in saleOrder.order_line:
  65. line.write({
  66. 'interest_amount': 0,
  67. 'price_unit': round((line.price_unit - line.amount_line_interest), decimalPlaces),
  68. 'amount_line_interest': 0
  69. })
  70. '''Eliminar linia de DESCUENTO '''
  71. lineDiscount = self.env['sale.order.line'].search([('order_id', '=', saleOrder.id), ('is_discount_sale_term', '=', True)])
  72. if (lineDiscount):
  73. lineDiscount.unlink()
  74. term = {
  75. 'sale_amount': round(saleOrder.amount_total, decimalPlaces),
  76. 'sale_payments_init': round(amountPayments, decimalPlaces),
  77. 'sale_residual': round(saleResidual, decimalPlaces),
  78. 'interest_qty': 0,
  79. 'interest_amount': 0,
  80. 'amount_total': round(saleResidual, decimalPlaces),
  81. 'sale_id': saleOrder.id,
  82. }
  83. saleTerm = self.env['account.sale.term'].search([('sale_id', '=', saleOrder.id)])
  84. if (not saleTerm):
  85. saleTerm = saleTerm = self.env['account.sale.term'].create(term)
  86. else:
  87. saleTerm.write(term)
  88. termLines = self.env['account.sale.term.line'].search([('sale_term_id', '=', saleTerm.id),('sale_id', '=', saleOrder.id)])
  89. if(termLines):
  90. termLines.unlink()
  91. return {
  92. 'state': True,
  93. }
  94. ''' Calcular Interes '''
  95. @api.model
  96. def calculateInterestSale(self, orderId, qty, amountPayments,paymentsFormat):
  97. qty = float(qty)
  98. amountPayments= float(amountPayments)
  99. saleOrder = self.env['sale.order'].browse(orderId)
  100. if (not saleOrder):
  101. return {
  102. 'state': False
  103. }
  104. decimalPlaces = saleOrder.pricelist_id.currency_id.decimal_places
  105. if (not decimalPlaces):
  106. decimalPlaces = 0
  107. for line in saleOrder.order_line:
  108. line.write({
  109. 'interest_amount': 0,
  110. 'price_unit': round((line.price_unit - line.amount_line_interest), decimalPlaces),
  111. 'amount_line_interest': 0
  112. })
  113. '''Eliminar linia de DESCUENTO '''
  114. lineDiscount = self.env['sale.order.line'].search([('order_id', '=', saleOrder.id), ('is_discount_sale_term', '=', True)])
  115. if (lineDiscount):
  116. lineDiscount.unlink()
  117. saleResidual = saleOrder.amount_total - amountPayments
  118. amountInterest = round(( saleResidual * (qty / 100)),decimalPlaces)
  119. amountDecimal = saleResidual -int(saleResidual)
  120. newInterest = amountInterest - amountDecimal if (amountInterest < 0 ) else amountInterest
  121. saleTotal = saleResidual + newInterest
  122. term = {
  123. 'sale_amount': round(saleOrder.amount_total,decimalPlaces ),
  124. 'sale_payments_init': round(amountPayments,decimalPlaces),
  125. 'sale_residual': round(saleResidual,decimalPlaces),
  126. 'interest_qty': qty,
  127. 'interest_amount': round(newInterest, decimalPlaces),
  128. 'amount_total': round(saleTotal, decimalPlaces),
  129. 'sale_id': saleOrder.id,
  130. }
  131. saleTerm = self.env['account.sale.term'].search([('sale_id', '=', saleOrder.id)])
  132. if (not saleTerm):
  133. saleTerm = saleTerm = self.env['account.sale.term'].create(term)
  134. else:
  135. saleTerm.write(term)
  136. termLines = self.env['account.sale.term.line'].search([('sale_term_id', '=', saleTerm.id),('sale_id', '=', saleOrder.id)])
  137. if(termLines):
  138. termLines.unlink()
  139. return {
  140. 'state':True,
  141. 'amountInterest': newInterest,
  142. }
  143. ''' Calcular Cuota '''
  144. @api.model
  145. def calculatePaymentTermSaleOrder(self, values):
  146. decimal_precision = self.env['decimal.precision'].precision_get('Account')
  147. order = self.env['sale.order'].browse(values['orderId'])
  148. if (not order):
  149. return False
  150. dateSale = self.sale_convert_str_to_datetime(order.date_order.split(" ")[0])
  151. datefirst = self.sale_convert_str_to_datetime(values['dateInit'])
  152. amountOrder = order.amount_total
  153. termSale = self.env['account.sale.term'].search([('sale_id', '=', values['orderId'])])
  154. if(termSale):
  155. amountOrder += termSale.interest_amount
  156. amountTotal = round(float(amountOrder), decimal_precision)
  157. amountPayments = round(float(values['amountPayments']), decimal_precision)
  158. amountResidual = round(float(amountTotal - amountPayments), decimal_precision)
  159. amountCuota = round(float(values['amountCuota']), decimal_precision)
  160. cuotaCant = values['qtyCuota']
  161. if (values['qtyCuota'] > 0):
  162. amountCuota = round(float(amountResidual /values['qtyCuota']), decimal_precision)
  163. if(values['amountCuota'] > 0):
  164. cuotaCant = (amountResidual /values['amountCuota'])
  165. if (amountPayments > 0):
  166. cuotaCant +=1
  167. termCalculator = []
  168. cuotasCalc = math.modf(round(cuotaCant,decimal_precision))
  169. cuotaTotal = int(cuotasCalc[1])
  170. if (cuotasCalc[0] >= 0.1):
  171. cuotaTotal += 1
  172. termType = self.env['account.payment.term.type'].browse(values['typeTerm'])
  173. if (not termType):
  174. return False
  175. numberCuota = 0
  176. for cuota in xrange(int(cuotaCant)):
  177. numberCuota = cuota+1
  178. amount = amountCuota
  179. adddaysMaturity = datefirst - dateSale
  180. date = datefirst
  181. if (numberCuota == 1 and (amountPayments > 0)):
  182. amount = amountPayments
  183. if (adddaysMaturity.days > 0):
  184. adddaysMaturity = dateSale - dateSale
  185. date = dateSale
  186. if (numberCuota >= cuotaTotal):
  187. amount = amountTotal
  188. amountTotal -= amount
  189. termCalculator.append({
  190. 'number' : numberCuota,
  191. 'cuotaNumber': str(numberCuota)+"/"+str(cuotaTotal),
  192. 'date': date.strftime(DEFAULT_SERVER_DATE_FORMAT),
  193. 'amount': amount,
  194. 'days': adddaysMaturity.days,
  195. 'value': 'fixed' if (numberCuota < cuotaTotal) else 'balance'
  196. })
  197. days = datefirst - dateSale
  198. if(numberCuota == 1 and (amountPayments > 0) and days.days > 0 ):
  199. continue
  200. if (termType.type_calculation == 'month' ):
  201. datefirst += relativedelta(months=termType.qty_add)
  202. else :
  203. datefirst += timedelta(days=termType.qty_add)
  204. if (amountTotal > 0 ):
  205. numberCuota +=1
  206. adddaysMaturity = datefirst - dateSale
  207. termCalculator.append({
  208. 'number' : numberCuota,
  209. 'cuotaNumber': str(numberCuota)+"/"+str(cuotaTotal),
  210. 'date': datefirst.strftime(DEFAULT_SERVER_DATE_FORMAT),
  211. 'amount': amountTotal,
  212. 'days': adddaysMaturity.days,
  213. 'value': 'fixed' if (numberCuota < cuotaTotal) else 'balance'
  214. })
  215. termLines = self.env['account.sale.term.line'].search([('sale_id', '=', values['orderId'])])
  216. if(termLines):
  217. termLines.unlink()
  218. linesTerm= []
  219. for line in termCalculator:
  220. linesTerm.append([0,False,{
  221. 'sale_id': values['orderId'],
  222. 'number': line['number'],
  223. 'cuota_number': line['cuotaNumber'],
  224. 'date': line['date'],
  225. 'amount': line['amount'],
  226. 'days': line['days'],
  227. 'value': line['value'],
  228. }])
  229. if (not termSale):
  230. termSale = self.env['account.sale.term'].create({
  231. 'date_init': values['dateInit'],
  232. 'term_type_id': values['typeTerm'],
  233. 'quota_amount': values['amountCuota'],
  234. 'quota_qty': values['qtyCuota'],
  235. 'lines': linesTerm,
  236. 'sale_id': values['orderId'],
  237. 'sale_amount': order.amount_total,
  238. 'sale_payments_init': 0,
  239. 'sale_residual': order.amount_total,
  240. 'interest_qty': 0,
  241. 'interest_amount': 0,
  242. 'amount_total': order.amount_total,
  243. })
  244. else:
  245. termSale = termSale.write({
  246. 'date_init': values['dateInit'],
  247. 'term_type_id': values['typeTerm'],
  248. 'quota_amount': values['amountCuota'],
  249. 'quota_qty': values['qtyCuota'],
  250. 'lines': linesTerm,
  251. 'sale_id': values['orderId'],
  252. })
  253. return termCalculator
  254. ''' Payments Term '''
  255. @api.model
  256. def accountPaymentTermConfiguratorSale(self, values, orderId):
  257. # import web_pdb; web_pdb.set_trace()
  258. resUser = self.env.user
  259. if (not resUser):
  260. return {
  261. 'state': False,
  262. 'message': 'No fue posible localizar el usuario.'
  263. }
  264. saleOrder = self.env['sale.order'].browse(orderId)
  265. if (not saleOrder):
  266. return {
  267. 'state': False,
  268. 'message': 'No fue posible localizar el numero de orden.'
  269. }
  270. # import web_pdb; web_pdb.set_trace()
  271. saleTerm = self.env['account.sale.term'].search([('sale_id.id', '=', saleOrder.id)])
  272. if (not saleTerm):
  273. return {
  274. 'state': False,
  275. 'message': 'No fue posible localizar Termino de pago configurable.'
  276. }
  277. decimalPlaces = saleOrder.pricelist_id.currency_id.decimal_places
  278. if (not decimalPlaces):
  279. decimalPlaces = 0
  280. ''' Actualizar el interes por item '''
  281. for line in saleOrder.order_line:
  282. line.write({
  283. 'interest_amount': saleTerm.interest_qty,
  284. 'amount_line_interest':round((line.price_unit * (saleTerm.interest_qty / 100)), decimalPlaces),
  285. 'price_unit': round((line.price_unit * (1 + (saleTerm.interest_qty / 100))), decimalPlaces),
  286. })
  287. '''Eliminar linia de DESCUENTO '''
  288. lineDiscount = self.env['sale.order.line'].search([('order_id', '=', saleOrder.id), ('is_discount_sale_term', '=', True)])
  289. if (lineDiscount):
  290. lineDiscount.unlink()
  291. ''' Crear el descuento por la entrega inicial'''
  292. if (saleTerm.interest_qty > 0 and saleTerm.sale_payments_init > 0 ):
  293. interestLine = {
  294. 'order_id': saleOrder.id,
  295. 'name': "Amortización de interés por entrega inicial de %s" %(saleTerm.sale_payments_init),
  296. 'price_unit': -round((saleTerm.sale_payments_init * (saleTerm.interest_qty / 100)), decimalPlaces),
  297. 'price_subtotal': -round((saleTerm.sale_payments_init * (saleTerm.interest_qty / 100)), decimalPlaces),
  298. 'is_discount_sale_term': True,
  299. }
  300. line = self.env['sale.order.line'].create(interestLine)
  301. '''consultar sale term line'''
  302. saleTermLine = self.env['account.sale.term.line'].search([('sale_id', '=', orderId)])
  303. if (not saleTermLine):
  304. return {
  305. 'state': False,
  306. 'message': 'No fue posible localizar la configuracion de las cuota.'
  307. }
  308. '''Eliminar las linea del termino de pago'''
  309. term = self.env['account.payment.term'].search([('config', '=', True),('user_term', '=', resUser.id),('type_operation', '=', 'sale')])
  310. if (term):
  311. term.unlink()
  312. line = []
  313. for configTerm in saleTermLine:
  314. line.append([0,False,{
  315. 'value': configTerm.value,
  316. 'days': configTerm.days,
  317. 'value_amount': configTerm.amount if (configTerm.value == 'fixed') else 0
  318. }])
  319. term = self.env['account.payment.term'].create({
  320. 'name': 'Plazos Configurables %s - %s'%('Ventas', resUser.name),
  321. 'type_operation': 'sale',
  322. 'user_term': resUser.id,
  323. 'config': True,
  324. 'line_ids': line,
  325. })
  326. ''' Actualizar condiciones de pago en la venta '''
  327. saleOrder.write({'payment_term': term.id})
  328. saleTerm.write({'state': 'posted'})
  329. return {
  330. 'state': True,
  331. 'message': 'Condiciones de pago configurado con éxito'
  332. }