GoodERP
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

670 rindas
31KB

  1. from odoo import fields, models, api
  2. from odoo import _
  3. import datetime
  4. from odoo.exceptions import UserError
  5. from odoo.tools import float_compare, float_is_zero
  6. ISODATEFORMAT = '%Y-%m-%d'
  7. class SellDelivery(models.Model):
  8. _name = 'sell.delivery'
  9. _inherits = {'wh.move': 'sell_move_id'}
  10. _inherit = ['mail.thread', 'barcodes.barcode_events_mixin', 'mail.activity.mixin']
  11. _description = '销售发货单'
  12. _order = 'date desc, id desc'
  13. @api.depends('line_out_ids.subtotal', 'discount_amount', 'partner_cost',
  14. 'receipt', 'partner_id', 'line_in_ids.subtotal')
  15. def _compute_all_amount(selfs):
  16. '''当优惠金额改变时,改变成交金额'''
  17. for self in selfs:
  18. total = 0
  19. if self.line_out_ids:
  20. # 发货时优惠前总金
  21. total = sum(line.subtotal for line in self.line_out_ids)
  22. elif self.line_in_ids:
  23. # 退货时优惠前总金额
  24. total = sum(line.subtotal for line in self.line_in_ids)
  25. self.amount = total - self.discount_amount
  26. @api.depends('is_return', 'invoice_id.reconciled', 'invoice_id.amount')
  27. def _get_sell_money_state(selfs):
  28. '''返回收款状态'''
  29. for self in selfs:
  30. if not self.is_return:
  31. if self.invoice_id.reconciled == 0:
  32. self.money_state = '未收款'
  33. elif self.invoice_id.reconciled < self.invoice_id.amount:
  34. self.money_state = '部分收款'
  35. elif self.invoice_id.reconciled == self.invoice_id.amount:
  36. self.money_state = '全部收款'
  37. # 返回退款状态
  38. if self.is_return:
  39. if self.invoice_id.reconciled == 0:
  40. self.return_state = '未退款'
  41. elif abs(self.invoice_id.reconciled) < abs(self.invoice_id.amount):
  42. self.return_state = '部分退款'
  43. elif self.invoice_id.reconciled == self.invoice_id.amount:
  44. self.return_state = '全部退款'
  45. currency_id = fields.Many2one('res.currency', '外币币别', readonly=True,
  46. help='外币币别')
  47. sell_move_id = fields.Many2one('wh.move', '发货单', required=True,
  48. ondelete='cascade',
  49. help='发货单号')
  50. is_return = fields.Boolean('是否退货', default=lambda self:
  51. self.env.context.get('is_return'),
  52. help='是否为退货类型')
  53. order_id = fields.Many2one('sell.order', '订单号', copy=False,
  54. ondelete='cascade',
  55. help='产生发货单/退货单的销售订单')
  56. invoice_id = fields.Many2one('money.invoice', '发票号',
  57. copy=False, ondelete='set null',
  58. help='产生的发票号')
  59. date_due = fields.Date('到期日期', copy=False,
  60. default=lambda self: fields.Date.context_today(
  61. self),
  62. help='收款截止日期')
  63. discount_rate = fields.Float('优惠率(%)',
  64. help='整单优惠率')
  65. discount_amount = fields.Float('优惠金额',
  66. digits='Amount',
  67. help='整单优惠金额,可由优惠率自动计算得出,也可手动输入')
  68. amount = fields.Float('成交金额', compute=_compute_all_amount,
  69. store=True, readonly=True,
  70. digits='Amount',
  71. help='总金额减去优惠金额')
  72. partner_cost = fields.Float('客户承担费用',
  73. digits='Amount',
  74. help='客户承担费用')
  75. receipt = fields.Float('本次收款',
  76. digits='Amount',
  77. help='本次收款金额')
  78. bank_account_id = fields.Many2one('bank.account',
  79. '结算账户', ondelete='restrict',
  80. help='用来核算和监督企业与其他单位或个人之间的债权债务的结算情况')
  81. cost_line_ids = fields.One2many('cost.line', 'sell_id', '销售费用',
  82. copy=False,
  83. help='销售费用明细行')
  84. money_state = fields.Char('收款状态', compute=_get_sell_money_state,
  85. store=True, default='未收款',
  86. help="销售发货单的收款状态", index=True, copy=False)
  87. return_state = fields.Char('退款状态', compute=_get_sell_money_state,
  88. store=True, default='未退款',
  89. help="销售退货单的退款状态", index=True, copy=False)
  90. contact = fields.Char('联系人',
  91. help='客户方的联系人')
  92. address_id = fields.Many2one('partner.address', '联系人地址',
  93. domain="[('partner_id','=',partner_id)]",
  94. help='联系地址')
  95. mobile = fields.Char('手机',
  96. help='联系手机')
  97. origin_id = fields.Many2one('sell.delivery', '来源单据')
  98. voucher_id = fields.Many2one('voucher', '出库凭证', readonly=True,
  99. help='发货时产生的出库凭证')
  100. money_order_id = fields.Many2one(
  101. 'money.order',
  102. '收款单',
  103. readonly=True,
  104. copy=False,
  105. help='输入本次收款确认时产生的收款单')
  106. project_id = fields.Many2one('project', string='项目')
  107. def set_today(self):
  108. self.date = fields.Date.today()
  109. @api.onchange('address_id')
  110. def onchange_address_id(self):
  111. ''' 选择地址填充 联系人、电话 '''
  112. if self.address_id:
  113. self.contact = self.address_id.contact
  114. self.mobile = self.address_id.mobile
  115. @api.onchange('partner_id')
  116. def onchange_partner_id(self):
  117. '''选择客户带出其默认地址信息'''
  118. if self.partner_id:
  119. self.contact = self.partner_id.contact
  120. self.mobile = self.partner_id.mobile
  121. for child in self.partner_id.child_ids:
  122. if child.is_default_add:
  123. self.address_id = child.id
  124. if self.partner_id.child_ids and not any([child.is_default_add for child in self.partner_id.child_ids]):
  125. partners_add = self.env['partner.address'].search(
  126. [('partner_id', '=', self.partner_id.id)], order='id')
  127. self.address_id = partners_add[0].id
  128. for line in self.line_out_ids:
  129. line.tax_rate = line.goods_id.get_tax_rate(line.goods_id, self.partner_id, 'sell')
  130. address_list = [
  131. child_list.id for child_list in self.partner_id.child_ids]
  132. if address_list:
  133. return {'domain': {'address_id': [('id', 'in', address_list)]}}
  134. else:
  135. self.address_id = False
  136. @api.onchange('discount_rate', 'line_in_ids', 'line_out_ids')
  137. def onchange_discount_rate(self):
  138. '''当优惠率或订单行发生变化时,单据优惠金额发生变化'''
  139. total = 0
  140. if self.line_out_ids:
  141. # 发货时优惠前总金额
  142. total = sum(line.subtotal for line in self.line_out_ids)
  143. elif self.line_in_ids:
  144. # 退货时优惠前总金额
  145. total = sum(line.subtotal for line in self.line_in_ids)
  146. if self.discount_rate:
  147. self.discount_amount = total * self.discount_rate * 0.01
  148. def get_move_origin(self, vals):
  149. return self._name + (self.env.context.get('is_return') and '.return'
  150. or '.sell')
  151. @api.model_create_multi
  152. def create(self, vals_list):
  153. '''创建销售发货单时生成有序编号'''
  154. if not self.env.context.get('is_return'):
  155. name = self._name
  156. else:
  157. name = 'sell.return'
  158. for vals in vals_list:
  159. if vals.get('name', '/') == '/':
  160. vals['name'] = self.env['ir.sequence'].next_by_code(name) or '/'
  161. vals.update({
  162. 'origin': self.get_move_origin(vals),
  163. 'finance_category_id': self.env.ref('finance.categ_sell_goods').id,
  164. })
  165. return super(SellDelivery, self).create(vals_list)
  166. def unlink(self):
  167. for delivery in self:
  168. return delivery.sell_move_id.unlink()
  169. def goods_inventory(self, vals):
  170. """
  171. 审核时若仓库中商品不足,则产生补货向导生成其他入库单并审核。
  172. :param vals: 创建其他入库单需要的字段及取值信息构成的字典
  173. :return:
  174. """
  175. auto_in = self.env['wh.in'].create(vals)
  176. line_ids = [line.id for line in auto_in.line_in_ids]
  177. self.with_context({'wh_in_line_ids': line_ids}).sell_delivery_done()
  178. return True
  179. def _wrong_delivery_done(self):
  180. self.ensure_one()
  181. '''审核时不合法的给出报错'''
  182. if self.state == 'done':
  183. raise UserError('请不要重复发货')
  184. for line in self.line_in_ids:
  185. if line.goods_qty <= 0 or line.price_taxed < 0:
  186. raise UserError(_('商品 %s 的数量和商品含税单价不能小于0!') % line.goods_id.name)
  187. if not self.bank_account_id and self.receipt:
  188. raise UserError('收款额不为空时,请选择结算账户!')
  189. decimal_amount = self.env.ref('core.decimal_amount')
  190. if float_compare(self.receipt, self.amount + self.partner_cost, precision_digits=decimal_amount.digits) == 1:
  191. raise UserError('本次收款金额不能大于成交金额!\n本次收款金额:%s 成交金额:%s' %
  192. (self.receipt, self.amount + self.partner_cost))
  193. # TODO:客户有自己的发货时检查信用额度的逻辑,这里暂时去掉gooderp原生的检查
  194. return
  195. # 发库单/退货单 计算客户的 本次发货金额+客户应收余额 是否小于客户信用额度, 否则报错
  196. if not self.is_return:
  197. amount = self.amount + self.partner_cost
  198. if self.partner_id.credit_limit != 0:
  199. if float_compare(amount - self.receipt + self.partner_id.receivable, self.partner_id.credit_limit,
  200. precision_digits=decimal_amount.digits) == 1:
  201. raise UserError('本次发货金额 + 客户应收余额 - 本次收款金额 不能大于客户信用额度!\n\
  202. 本次发货金额:%s\n 客户应收余额:%s\n 本次收款金额:%s\n客户信用额度:%s' % (
  203. amount, self.partner_id.receivable, self.receipt, self.partner_id.credit_limit))
  204. def _line_qty_write(self):
  205. if self.order_id:
  206. for line in self.line_in_ids:
  207. if self.order_id.type == 'return':
  208. line.sell_line_id.quantity_out += line.goods_qty
  209. else:
  210. line.sell_line_id.quantity_out -= line.goods_qty
  211. for line in self.line_out_ids:
  212. decimal_quantity = self.env.ref('core.decimal_quantity')
  213. if float_compare(
  214. line.sell_line_id.quantity_out + line.goods_qty,
  215. line.sell_line_id.quantity,
  216. decimal_quantity.digits) == 1:
  217. if not line.goods_id.excess:
  218. raise UserError('%s发货数量大于订单数量' % line.goods_id.name)
  219. line.sell_line_id.write({'quantity_out':line.sell_line_id.quantity_out + line.goods_qty})
  220. return
  221. def _get_invoice_vals(self, partner_id, category_id, date, amount, tax_amount):
  222. '''返回创建 money_invoice 时所需数据'''
  223. return {
  224. 'move_id': self.sell_move_id.id,
  225. 'name': self.name,
  226. 'partner_id': partner_id.id,
  227. 'pay_method': self.order_id.pay_method.id,
  228. 'category_id': category_id.id,
  229. 'date': date,
  230. 'amount': amount,
  231. 'reconciled': 0,
  232. 'to_reconcile': amount,
  233. 'tax_amount': tax_amount,
  234. 'date_due': self.date_due,
  235. 'state': 'draft',
  236. 'currency_id': self.currency_id.id,
  237. }
  238. def _delivery_make_invoice(self):
  239. '''发货单/退货单 生成结算单'''
  240. if not self.is_return:
  241. amount = self.amount + self.partner_cost
  242. tax_amount = sum(line.tax_amount for line in self.line_out_ids)
  243. else:
  244. amount = -(self.amount + self.partner_cost)
  245. tax_amount = - sum(line.tax_amount for line in self.line_in_ids)
  246. category = self.env.ref('money.core_category_sale')
  247. invoice_id = False
  248. if not float_is_zero(amount, 2):
  249. invoice_id = self.env['money.invoice'].create(
  250. self._get_invoice_vals(
  251. self.partner_id, category, self.date, amount, tax_amount)
  252. )
  253. return invoice_id
  254. def _sell_amount_to_invoice(self):
  255. '''销售费用产生结算单'''
  256. invoice_id = False
  257. if sum(cost_line.amount for cost_line in self.cost_line_ids) > 0:
  258. for line in self.cost_line_ids:
  259. if not float_is_zero(line.amount, 2):
  260. invoice_id = self.env['money.invoice'].create(
  261. self._get_invoice_vals(
  262. line.partner_id, line.category_id, self.date, line.amount + line.tax, line.tax)
  263. )
  264. return invoice_id
  265. def _make_money_order(self, invoice_id, amount, this_reconcile):
  266. '''生成收款单'''
  267. categ = self.env.ref('money.core_category_sale')
  268. money_lines = [{
  269. 'bank_id': self.bank_account_id.id,
  270. 'amount': this_reconcile,
  271. }]
  272. source_lines = [{
  273. 'name': invoice_id and invoice_id.id,
  274. 'category_id': categ.id,
  275. 'date': invoice_id and invoice_id.date,
  276. 'amount': amount,
  277. 'reconciled': 0.0,
  278. 'to_reconcile': amount,
  279. 'this_reconcile': this_reconcile,
  280. }]
  281. rec = self.with_context(type='get')
  282. money_order = rec.env['money.order'].create({
  283. 'partner_id': self.partner_id.id,
  284. 'date': self.date,
  285. 'line_ids': [(0, 0, line) for line in money_lines],
  286. 'source_ids': [(0, 0, line) for line in source_lines] if invoice_id.state == 'done' else False,
  287. 'amount': amount,
  288. 'reconciled': this_reconcile,
  289. 'to_reconcile': amount,
  290. 'state': 'draft',
  291. 'origin_name': self.name,
  292. 'sell_id': self.order_id.id,
  293. })
  294. return money_order
  295. def _create_voucher_line(self, account_id, debit, credit, voucher, goods_id, goods_qty):
  296. """
  297. 创建凭证明细行
  298. :param account_id: 科目
  299. :param debit: 借方
  300. :param credit: 贷方
  301. :param voucher: 凭证
  302. :param goods_id: 商品
  303. :return:
  304. """
  305. voucher_line = self.env['voucher.line'].create({
  306. 'name': '%s ' % (self.name),
  307. 'account_id': account_id and account_id.id,
  308. 'partner_id': not goods_id and self.partner_id.id,
  309. 'debit': debit,
  310. 'credit': credit,
  311. 'voucher_id': voucher and voucher.id,
  312. 'goods_qty': goods_qty,
  313. 'goods_id': goods_id and goods_id.id,
  314. 'auxiliary_id': self.project_id.auxiliary_id.id if self.project_id else False,
  315. })
  316. return voucher_line
  317. def create_voucher(self):
  318. '''
  319. 销售发货单、退货单审核时生成会计凭证
  320. 借:主营业务成本(核算分类上会计科目)
  321. 贷:库存商品(商品分类上会计科目)
  322. 当一张发货单有多个商品的时候,按对应科目汇总生成多个贷方凭证行。
  323. 退货单生成的金额为负
  324. '''
  325. self.ensure_one()
  326. voucher = self.env['voucher'].create({'date': self.date, 'ref': '%s,%s' % (self._name, self.id)})
  327. sum_amount = 0
  328. line_ids = self.is_return and self.line_in_ids or self.line_out_ids
  329. for line in line_ids: # 发货单/退货单明细
  330. cost = self.is_return and -line.cost or line.cost
  331. if not cost:
  332. continue # 缺货审核发货单时不产生出库凭证
  333. else: # 贷方明细
  334. sum_amount += cost
  335. self._create_voucher_line(line.goods_id.category_id.account_id,
  336. 0, cost, voucher, line.goods_id, line.goods_qty)
  337. if sum_amount: # 借方明细
  338. self._create_voucher_line(self.sell_move_id.finance_category_id.account_id,
  339. sum_amount, 0, voucher, False, 0)
  340. if len(voucher.line_ids) > 0:
  341. voucher.voucher_done()
  342. return voucher
  343. else:
  344. voucher.unlink()
  345. def auto_reconcile_sell_order(self):
  346. ''' 预收款与结算单自动核销 '''
  347. self.ensure_one()
  348. all_delivery_amount = 0
  349. for delivery in self.order_id.delivery_ids:
  350. all_delivery_amount += delivery.amount
  351. if (self.order_id.received_amount and self.order_id.received_amount == all_delivery_amount and
  352. not self.env.user.company_id.draft_invoice): #根据发票确认应收应付勾选时不自动核销
  353. adv_pay_result = []
  354. receive_source_result = []
  355. # 预收款
  356. adv_pay_orders = self.env['money.order'].search([('partner_id', '=', self.partner_id.id),
  357. ('type', '=', 'get'),
  358. ('state', '=', 'done'),
  359. ('to_reconcile',
  360. '!=', 0),
  361. ('sell_id', '=', self.order_id.id)])
  362. for order in adv_pay_orders:
  363. adv_pay_result.append((0, 0, {'name': order.id,
  364. 'amount': order.amount,
  365. 'date': order.date,
  366. 'reconciled': order.reconciled,
  367. 'to_reconcile': order.to_reconcile,
  368. 'this_reconcile': order.to_reconcile,
  369. }))
  370. # 结算单
  371. receive_source_name = [
  372. delivery.name for delivery in self.order_id.delivery_ids]
  373. receive_source_orders = self.env['money.invoice'].search([('category_id.type', '=', 'income'),
  374. ('partner_id', '=',
  375. self.partner_id.id),
  376. ('to_reconcile',
  377. '!=', 0),
  378. ('name', 'in', receive_source_name)])
  379. for invoice in receive_source_orders:
  380. receive_source_result.append((0, 0, {
  381. 'name': invoice.id,
  382. 'category_id': invoice.category_id.id,
  383. 'amount': invoice.amount,
  384. 'date': invoice.date,
  385. 'reconciled': invoice.reconciled,
  386. 'to_reconcile': invoice.to_reconcile,
  387. 'date_due': invoice.date_due,
  388. 'this_reconcile': invoice.to_reconcile,
  389. }))
  390. # 创建核销单
  391. reconcile_order = self.env['reconcile.order'].create({
  392. 'partner_id': self.partner_id.id,
  393. 'business_type': 'adv_pay_to_get',
  394. 'advance_payment_ids': adv_pay_result,
  395. 'receivable_source_ids': receive_source_result,
  396. 'note': '自动核销',
  397. })
  398. reconcile_order.reconcile_order_done() # 自动审核
  399. def sell_delivery_done(self):
  400. '''审核销售发货单/退货单,更新本单的收款状态/退款状态,并生成结算单和收款单'''
  401. for record in self:
  402. record._wrong_delivery_done()
  403. # 库存不足 生成零的
  404. if self.env.user.company_id.is_enable_negative_stock:
  405. result_vals = self.env['wh.move'].create_zero_wh_in(
  406. record, record._name)
  407. if result_vals:
  408. return result_vals
  409. # 调用wh.move中审核方法,更新审核人和审核状态
  410. record.sell_move_id.approve_order()
  411. # 将发货/退货数量写入销售订单行
  412. if record.order_id:
  413. record._line_qty_write()
  414. voucher = False
  415. # 创建出库的会计凭证,生成盘盈的入库单的不产生出库凭证
  416. if not self.env.user.company_id.endmonth_generation_cost:
  417. voucher = record.create_voucher()
  418. # 发货单/退货单 生成结算单
  419. invoice_id = record._delivery_make_invoice()
  420. # 销售费用产生结算单
  421. record._sell_amount_to_invoice()
  422. # 生成收款单,并审核
  423. money_order = False
  424. if record.receipt:
  425. flag = not record.is_return and 1 or -1
  426. amount = flag * (record.amount + record.partner_cost)
  427. this_reconcile = flag * record.receipt
  428. money_order = record._make_money_order(
  429. invoice_id, amount, this_reconcile)
  430. money_order.money_order_done()
  431. record.write({
  432. 'voucher_id': voucher and voucher.id,
  433. 'invoice_id': invoice_id and invoice_id.id,
  434. 'money_order_id': money_order and money_order.id,
  435. 'state': 'done', # 为保证审批流程顺畅,否则,未审批就可审核
  436. })
  437. # 先收款后发货订单自动核销
  438. self.auto_reconcile_sell_order()
  439. if record.order_id:
  440. # 如果已退货也已退款,不生成新的分单
  441. if record.is_return and record.receipt:
  442. return True
  443. #产生新的销售发货单时,如果已经存在草稿的销售发货单时,先将已经存在的草稿发货单进行删除
  444. self.env['sell.delivery'].search(['&',('state', '=', 'draft'),'&',('order_id','=', record.order_id.id),('is_return', '=', False)]).unlink()
  445. return record.order_id.sell_generate_delivery()
  446. def sell_delivery_draft(self):
  447. '''反审核销售发货单/退货单,更新本单的收款状态/退款状态,并删除生成的结算单、收款单及凭证'''
  448. self.ensure_one()
  449. if self.state == 'draft':
  450. raise UserError('请不要重复撤销 %s' % self._description)
  451. # 查找产生的结算单(除了开给客户的发票还有可能是采购费用发票)
  452. invoice_ids = self.env['money.invoice'].search([('name', '=', self.name)])
  453. for invoice in invoice_ids:
  454. # 不能反审核已核销的发货单
  455. if invoice.reconciled != 0:
  456. raise UserError('发票已核销,不能撤销发货!')
  457. if invoice.state == 'done':
  458. if self.env.company.draft_invoice:
  459. raise UserError('发票已开不可撤销发货')
  460. invoice.money_invoice_draft()
  461. invoice.unlink()
  462. # 删除产生的出库凭证
  463. voucher = self.voucher_id
  464. if voucher and voucher.state == 'done':
  465. voucher.voucher_draft()
  466. voucher.unlink()
  467. self.write({
  468. 'state': 'draft',
  469. })
  470. # 将原始订单中已执行数量清零
  471. if self.order_id:
  472. for line in self.line_out_ids:
  473. line.sell_line_id.quantity_out -= line.goods_qty
  474. for line in self.line_in_ids:
  475. if self.order_id.type == 'return':
  476. line.sell_line_id.quantity_out -= line.goods_qty
  477. else:
  478. line.sell_line_id.quantity_out += line.goods_qty
  479. # 调用wh.move中反审核方法,更新审核人和审核状态
  480. self.sell_move_id.cancel_approved_order()
  481. return True
  482. def sell_to_return(self):
  483. '''销售发货单转化为销售退货单'''
  484. return_goods = {}
  485. return_order_draft = self.search([
  486. ('is_return', '=', True),
  487. ('origin_id', '=', self.id),
  488. ('state', '=', 'draft')
  489. ])
  490. if return_order_draft:
  491. raise UserError('销售发货单存在草稿状态的退货单!')
  492. return_order = self.search([
  493. ('is_return', '=', True),
  494. ('origin_id', '=', self.id),
  495. ('state', '=', 'done')
  496. ])
  497. for order in return_order:
  498. for return_line in order.line_in_ids:
  499. # 用产品、属性、批次做key记录已退货数量
  500. t_key = (return_line.goods_id.id,
  501. return_line.attribute_id.id, return_line.lot)
  502. if return_goods.get(t_key):
  503. return_goods[t_key] += return_line.goods_qty
  504. else:
  505. return_goods[t_key] = return_line.goods_qty
  506. receipt_line = []
  507. for line in self.line_out_ids:
  508. qty = line.goods_qty
  509. l_key = (line.goods_id.id, line.attribute_id.id, line.lot_id.lot)
  510. if return_goods.get(l_key):
  511. qty = qty - return_goods[l_key]
  512. if qty > 0:
  513. dic = {
  514. 'goods_id': line.goods_id.id,
  515. 'attribute_id': line.attribute_id.id,
  516. 'uom_id': line.uom_id.id,
  517. 'warehouse_id': line.warehouse_dest_id.id,
  518. 'warehouse_dest_id': line.warehouse_id.id,
  519. 'goods_qty': qty,
  520. 'sell_line_id': line.sell_line_id.id,
  521. 'price_taxed': line.price_taxed,
  522. 'price': line.price,
  523. 'tax_rate':line.tax_rate,
  524. 'cost_unit': line.cost_unit,
  525. 'cost': line.cost,#退货取不到成本
  526. 'discount_rate': line.discount_rate,
  527. 'discount_amount': line.discount_amount,
  528. 'type': 'in',
  529. }
  530. if line.goods_id.using_batch:
  531. dic.update({'lot': line.lot_id.lot})
  532. receipt_line.append(dic)
  533. if len(receipt_line) == 0:
  534. raise UserError('该订单已全部退货!')
  535. vals = {'partner_id': self.partner_id.id,
  536. 'is_return': True,
  537. 'order_id': self.order_id.id,
  538. 'user_id': self.user_id.id,
  539. 'origin_id': self.id,
  540. 'origin': 'sell.delivery.return',
  541. 'warehouse_dest_id': self.warehouse_id.id,
  542. 'warehouse_id': self.warehouse_dest_id.id,
  543. 'bank_account_id': self.bank_account_id.id,
  544. 'date_due': (datetime.datetime.now()).strftime(ISODATEFORMAT),
  545. 'date': (datetime.datetime.now()).strftime(ISODATEFORMAT),
  546. 'line_in_ids': [(0, 0, line) for line in receipt_line],
  547. 'discount_amount': self.discount_amount,
  548. }
  549. delivery_return = self.with_context(is_return=True).create(vals)
  550. view_id = self.env.ref('sell.sell_return_form').id
  551. name = '销售退货单'
  552. return {
  553. 'name': name,
  554. 'view_mode': 'form',
  555. 'view_id': False,
  556. 'views': [(view_id, 'form')],
  557. 'res_model': 'sell.delivery',
  558. 'type': 'ir.actions.act_window',
  559. 'res_id': delivery_return.id,
  560. 'target': 'current'
  561. }
  562. class WhMoveLine(models.Model):
  563. _inherit = 'wh.move.line'
  564. sell_line_id = fields.Many2one('sell.order.line', '销售单行',
  565. ondelete='cascade',
  566. help='对应的销售订单行')
  567. @api.onchange('warehouse_id', 'goods_id')
  568. def onchange_warehouse_id(self):
  569. '''当订单行的仓库变化时,带出定价策略中的折扣率'''
  570. if self.warehouse_id and self.goods_id:
  571. partner_id = self.env.context.get('default_partner')
  572. partner = self.env['partner'].browse(
  573. partner_id) or self.move_id.partner_id
  574. warehouse = self.warehouse_id
  575. goods = self.goods_id
  576. date = self.env.context.get('default_date') or self.move_id.date
  577. if self.env.context.get('warehouse_type') == 'customer' or \
  578. self.env.context.get('warehouse_dest_type') == 'customer':
  579. pricing = self.env['pricing'].get_pricing_id(
  580. partner, warehouse, goods, date)
  581. if pricing:
  582. self.discount_rate = pricing.discount_rate
  583. else:
  584. self.discount_rate = 0
  585. def _delivery_get_price_and_tax(self):
  586. self.tax_rate = self.env.user.company_id.output_tax_rate
  587. self.price_taxed = self.goods_id.price
  588. if self.env.context.get('order_id'):
  589. line = self.env['sell.order.line'].search([
  590. ('order_id', '=', self.env.context.get('order_id')),
  591. ('goods_id', '=', self.goods_id.id)
  592. ], limit=1)
  593. if line:
  594. self.sell_line_id = line.id
  595. self.uos_id = line.goods_id.uos_id.id
  596. self.uom_id = line.uom_id.id
  597. self.price = line.price
  598. self.price_taxed = line.price_taxed
  599. self.discount_rate = line.discount_rate
  600. self.tax_rate = line.tax_rate
  601. self.plan_date = line.order_id.delivery_date
  602. else:
  603. raise UserError(_('无此商品的订单行'))
  604. @api.onchange('goods_id')
  605. def onchange_goods_id(self):
  606. '''当订单行的商品变化时,带出商品上的零售价,以及公司的销项税'''
  607. self.ensure_one()
  608. is_return = self.env.context.get('default_is_return')
  609. if self.goods_id:
  610. # 如果是销售发货单行 或 销售退货单行
  611. if is_return is not None and \
  612. ((self.type == 'out' and not is_return) or (self.type == 'in' and is_return)):
  613. self._delivery_get_price_and_tax()
  614. return super(WhMoveLine, self).onchange_goods_id()
上海开阖软件有限公司 沪ICP备12045867号-1