GoodERP
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.

259 line
13KB

  1. # -*- coding: utf-8 -*-
  2. # Copyright 2016 上海开阖软件有限公司 (http://www.osbzr.com)
  3. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
  4. from odoo import _
  5. from odoo import models, fields, api
  6. from odoo.exceptions import UserError
  7. class MoneyInvoice(models.Model):
  8. _inherit = 'money.invoice'
  9. voucher_id = fields.Many2one(
  10. 'voucher',
  11. '对应凭证',
  12. readonly=True,
  13. ondelete='restrict',
  14. copy=False,
  15. help='结算单确认时生成的对应凭证')
  16. cogs_voucher_id = fields.Many2one(
  17. 'voucher',
  18. '成本凭证',
  19. readonly=True,
  20. ondelete='set null',
  21. copy=False,
  22. help='结算单确认时生成的成本凭证')
  23. def money_invoice_draft(self):
  24. """
  25. 撤销确认结算单时,撤销确认凭证
  26. """
  27. res = super(MoneyInvoice, self).money_invoice_draft()
  28. for invoice in self:
  29. voucher, invoice.voucher_id = invoice.voucher_id, False
  30. if voucher.state == 'done':
  31. voucher.voucher_draft()
  32. # 始初化单反审核只删除明细行:生成初始化凭证时,不生成往来单位对方的科目,所以要删除相关明细行
  33. if invoice.is_init:
  34. vouch_obj = self.env['voucher'].search(
  35. [('id', '=', voucher.id)])
  36. vouch_obj_lines = self.env['voucher.line'].search([
  37. ('voucher_id', '=', vouch_obj.id),
  38. ('partner_id', '=', invoice.partner_id.id),
  39. ('init_obj', '=', 'money_invoice'), ])
  40. for vouch_obj_line in vouch_obj_lines:
  41. vouch_obj_line.unlink()
  42. else: # 非初始化单反审核时删除凭证
  43. voucher.unlink()
  44. # 删除发出成本凭证
  45. cogs_voucher = self.env['voucher'].search(
  46. [('ref', '=', '%s,%s' % (self._name, invoice.id))])
  47. if cogs_voucher:
  48. if cogs_voucher.state == 'done':
  49. cogs_voucher.voucher_draft()
  50. cogs_voucher.unlink()
  51. return res
  52. def money_invoice_done(self):
  53. """
  54. 确认结算单时,创建凭证并确认
  55. """
  56. res = super(MoneyInvoice, self).money_invoice_done()
  57. vals = {}
  58. # 初始化单的话,先找是否有初始化凭证,没有则新建一个
  59. for invoice in self:
  60. if invoice.is_init:
  61. vouch_obj = self.env['voucher'].search(
  62. [('is_init', '=', True)])
  63. if not vouch_obj:
  64. vouch_obj = self.env['voucher'].create(
  65. {'date': invoice.date,
  66. 'is_init': True,
  67. 'ref': '%s,%s' % (self._name, self.id)})
  68. invoice.write({'voucher_id': vouch_obj.id})
  69. else:
  70. vouch_obj = self.env['voucher'].create({
  71. 'date': invoice.invoice_date or
  72. fields.Date.context_today(self),
  73. 'ref': '%s,%s' % (self._name, self.id)})
  74. invoice.write({'voucher_id': vouch_obj.id})
  75. if not invoice.category_id.account_id:
  76. raise UserError(f'请配置采购类型的[{invoice.category_id.name}]的会计科目')
  77. partner_cat = invoice.category_id.type == 'income' \
  78. and invoice.partner_id.c_category_id \
  79. or invoice.partner_id.s_category_id
  80. partner_type_name = invoice.category_id.type == 'income' and '客户类别' or '供应商类别'
  81. partner_account_id = partner_cat.account_id.id
  82. if not partner_account_id:
  83. raise UserError(f'请配置{partner_type_name}[{partner_cat.name}]的会计科目')
  84. if invoice.category_id.type == 'income':
  85. vals.update({
  86. 'vouch_obj_id': vouch_obj.id,
  87. 'partner_credit': invoice.partner_id.id,
  88. 'name': invoice.name,
  89. 'string': invoice.note or '',
  90. 'amount': invoice.amount,
  91. 'credit_account_id': invoice.category_id.account_id.id,
  92. 'partner_debit': invoice.partner_id.id,
  93. 'debit_account_id': partner_account_id,
  94. 'sell_tax_amount': invoice.tax_amount or 0,
  95. 'credit_auxiliary_id': invoice.auxiliary_id.id,
  96. 'currency_id': invoice.currency_id.id or '',
  97. 'rate_silent': self.env['res.currency'].get_rate_silent(
  98. self.date, invoice.currency_id.id) or 0,
  99. })
  100. # 找到发票对应发货单的凭证,复制修改, 结转主营业务成本
  101. send_voucher = False
  102. if self.env['ir.module.module'].sudo().search(
  103. [('name', '=', 'sell'), ('state', '=', 'installed')]):
  104. delivery = self.env['sell.delivery'].search(
  105. [('name', '=', invoice.name)])
  106. send_voucher = delivery.voucher_id
  107. # 该公司不是月末一次性结转发出成本
  108. if send_voucher:
  109. cost_voucher_data = send_voucher.copy_data()
  110. out_account_id = self.env.ref(
  111. 'finance.categ_sell_goods').account_id.id
  112. cogs_account_id = self.env.company.cogs_account.id
  113. # 如果发货单没有直接结转成本
  114. if out_account_id != cogs_account_id:
  115. for vl in cost_voucher_data[0]['line_ids']:
  116. if vl[2]['account_id'] != out_account_id:
  117. vl[2].update({'account_id': cogs_account_id})
  118. vl[2].update({
  119. 'debit': vl[2]['credit'],
  120. 'credit': vl[2]['debit'],
  121. 'voucher_id': False})
  122. cost_voucher_data[0].update(
  123. {'ref': '%s,%s' % (self._name, self.id)})
  124. if invoice.invoice_date:
  125. cost_voucher_data[0].update(
  126. {'date': invoice.invoice_date})
  127. cogs_voucher = self.env['voucher'].create(
  128. cost_voucher_data)
  129. cogs_voucher.voucher_done()
  130. invoice.cogs_voucher_id = cogs_voucher.id
  131. else:
  132. vals.update({
  133. 'vouch_obj_id': vouch_obj.id,
  134. 'name': invoice.name,
  135. 'string': invoice.note or '',
  136. 'amount': invoice.amount,
  137. 'credit_account_id': partner_account_id,
  138. 'debit_account_id': invoice.category_id.account_id.id,
  139. 'partner_debit': invoice.partner_id.id,
  140. 'partner_credit': invoice.partner_id.id,
  141. 'buy_tax_amount': invoice.tax_amount or 0,
  142. 'debit_auxiliary_id': invoice.auxiliary_id.id,
  143. 'currency_id': invoice.currency_id.id or '',
  144. 'rate_silent': self.env['res.currency'].get_rate_silent(
  145. self.date, invoice.currency_id.id) or 0,
  146. })
  147. if invoice.is_init:
  148. vals.update({'init_obj': 'money_invoice', })
  149. invoice.create_voucher_line(vals)
  150. # 删除初始非需要的凭证明细行,不确认凭证
  151. if invoice.is_init:
  152. vouch_line_ids = self.env['voucher.line'].search([
  153. ('account_id', '=', invoice.category_id.account_id.id),
  154. ('init_obj', '=', 'money_invoice')])
  155. # 删除凭证明细行之前先确保凭证是草稿状态
  156. if invoice.voucher_id.state == 'done':
  157. invoice.voucher_id.voucher_draft()
  158. for vouch_line_id in vouch_line_ids:
  159. vouch_line_id.unlink()
  160. else:
  161. vouch_obj.voucher_done()
  162. return res
  163. def create_voucher_line(self, vals):
  164. if vals.get('currency_id') == self.env.user.company_id.currency_id.id \
  165. or not vals.get('rate_silent'):
  166. debit = credit = vals.get('amount')
  167. sell_tax_amount = vals.get('sell_tax_amount')
  168. else:
  169. # 外币免税
  170. debit = credit = vals.get('amount') * vals.get('rate_silent')
  171. # 把税从金额中减去
  172. if vals.get('buy_tax_amount'): # 如果传入了进项税
  173. debit = vals.get('amount') - vals.get('buy_tax_amount')
  174. if vals.get('sell_tax_amount'): # 如果传入了销项税
  175. credit = vals.get('amount') - sell_tax_amount
  176. # 借方行
  177. currency_id = vals.get(
  178. 'currency_id') or self.env.user.company_id.currency_id.id
  179. if currency_id != self.env.user.company_id.currency_id.id: # 结算单上是外币
  180. self.env['voucher.line'].create({
  181. 'name': "%s %s" % (vals.get('name'), vals.get('string')),
  182. 'account_id': vals.get('debit_account_id'),
  183. 'debit': debit,
  184. 'voucher_id': vals.get('vouch_obj_id'),
  185. 'partner_id': vals.get('partner_debit', ''),
  186. 'auxiliary_id': vals.get('debit_auxiliary_id', False),
  187. 'currency_id': vals.get('currency_id'),
  188. 'currency_amount': vals.get('amount'),
  189. 'rate_silent': vals.get('rate_silent'),
  190. 'init_obj': vals.get('init_obj', False),
  191. })
  192. else: # 结算单上是本位币
  193. self.env['voucher.line'].create({
  194. 'name': "%s %s" % (vals.get('name'), vals.get('string')),
  195. 'account_id': vals.get('debit_account_id'),
  196. 'debit': debit,
  197. 'voucher_id': vals.get('vouch_obj_id'),
  198. 'partner_id': vals.get('partner_debit', ''),
  199. 'auxiliary_id': vals.get('debit_auxiliary_id', False),
  200. 'init_obj': vals.get('init_obj', False),
  201. })
  202. # 进项税行
  203. if vals.get('buy_tax_amount'):
  204. if not self.env.user.company_id.import_tax_account:
  205. raise UserError(_('请通过"配置-->高级配置-->公司"菜单来设置进项税科目'))
  206. self.env['voucher.line'].create({
  207. 'name': "%s %s" % (vals.get('name'), vals.get('string')),
  208. 'account_id': self.env.user.company_id.import_tax_account.id,
  209. 'debit': vals.get('buy_tax_amount'),
  210. 'voucher_id': vals.get('vouch_obj_id'),
  211. })
  212. # 贷方行
  213. currency_id = vals.get(
  214. 'currency_id') or self.env.user.company_id.currency_id.id
  215. if currency_id != self.env.user.company_id.currency_id.id:
  216. self.env['voucher.line'].create({
  217. 'name': "%s %s" % (vals.get('name'), vals.get('string')),
  218. 'partner_id': vals.get('partner_credit', ''),
  219. 'account_id': vals.get('credit_account_id'),
  220. 'credit': credit,
  221. 'voucher_id': vals.get('vouch_obj_id'),
  222. 'auxiliary_id': vals.get('credit_auxiliary_id', False),
  223. 'currency_amount': vals.get('amount'),
  224. 'rate_silent': vals.get('rate_silent'),
  225. 'currency_id': vals.get('currency_id'),
  226. 'init_obj': vals.get('init_obj', False),
  227. })
  228. else:
  229. self.env['voucher.line'].create({
  230. 'name': "%s %s" % (vals.get('name'), vals.get('string')),
  231. 'partner_id': vals.get('partner_credit', ''),
  232. 'account_id': vals.get('credit_account_id'),
  233. 'credit': credit,
  234. 'voucher_id': vals.get('vouch_obj_id'),
  235. 'auxiliary_id': vals.get('credit_auxiliary_id', False),
  236. 'init_obj': vals.get('init_obj', False),
  237. })
  238. # 销项税行
  239. if vals.get('sell_tax_amount'):
  240. if not self.env.user.company_id.output_tax_account:
  241. raise UserError(
  242. _('您还没有配置公司的销项税科目。\n请通过"配置-->高级配置-->公司"菜单来设置销项税科目!'))
  243. self.env['voucher.line'].create({
  244. 'name': "%s %s" % (vals.get('name'), vals.get('string')),
  245. 'account_id': self.env.user.company_id.output_tax_account.id,
  246. 'credit': sell_tax_amount,
  247. 'voucher_id': vals.get('vouch_obj_id'),
  248. })
  249. return True
上海开阖软件有限公司 沪ICP备12045867号-1