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.

664 lines
30KB

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