Initial commit of pos_product_catch_weight for 11.0

This commit is contained in:
Jared Kipe
2018-11-23 11:18:33 -08:00
parent 829bb0502f
commit 58bbfbd098
9 changed files with 386 additions and 0 deletions

View File

@@ -0,0 +1 @@
from . import models

View File

@@ -0,0 +1,27 @@
# Copyright 2018 Tecnativa S.L. - David Vidal
# ^^^ For OCA `pos_lot_selection`
# Copyright 2018 Hibou Corp. - Jared Kipe
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
'name': 'POS Catch Weight',
'version': '11.0.1.0.0',
'category': 'Point of Sale',
'author': 'Hibou Corp., '
'Tecnativa,'
'Odoo Community Association (OCA)',
'website': 'https://github.com/OCA/pos',
'license': 'AGPL-3',
'depends': [
'point_of_sale',
'product_catch_weight',
],
'data': [
'templates/assets.xml',
],
'qweb': [
'static/src/xml/pos.xml'
],
'application': False,
'installable': True,
}

View File

@@ -0,0 +1 @@
from . import pos_order

View File

@@ -0,0 +1,57 @@
from odoo import api, fields, models
class PosOrderLine(models.Model):
_inherit = 'pos.order.line'
@api.model
def create(self, values):
quant_model = self.sudo().env['stock.quant']
res = super(PosOrderLine, self).create(values)
if res.pack_lot_ids:
lot_names = res.pack_lot_ids.mapped('lot_name')
product_id = res.product_id.id
quants = quant_model.search([
('product_id', '=', product_id),
('location_id', '=', res.order_id.location_id.id),
('lot_id', '!=', False),
('lot_id.name', 'in', lot_names),
])
for l in res.pack_lot_ids:
named_quants = quants.filtered(lambda q: q.lot_id.name == l.lot_name)
for q in named_quants:
l.lot_id = q.lot_id
return res
@api.depends('price_unit', 'tax_ids', 'qty', 'discount', 'product_id', 'pack_lot_ids.lot_id')
def _compute_amount_line_all(self):
# This is a hard override due to the closed nature of this method.
for line in self:
fpos = line.order_id.fiscal_position_id
tax_ids_after_fiscal_position = fpos.map_tax(line.tax_ids, line.product_id,
line.order_id.partner_id) if fpos else line.tax_ids
price = line.price_unit * (1 - (line.discount or 0.0) / 100.0)
lot_ratio_sum = 0.0
for l in line.pack_lot_ids:
if l.lot_id:
lot_ratio_sum += l.lot_catch_weight_ratio
else:
lot_ratio_sum += 1.0
if lot_ratio_sum != 0.0:
lot_ratio = lot_ratio_sum / line.qty
price = (line.price_unit * lot_ratio) * (1 - (line.discount or 0.0) / 100.0)
taxes = tax_ids_after_fiscal_position.compute_all(price, line.order_id.pricelist_id.currency_id, line.qty,
product=line.product_id, partner=line.order_id.partner_id)
line.update({
'price_subtotal_incl': taxes['total_included'],
'price_subtotal': taxes['total_excluded'],
})
class PosOrderLineLot(models.Model):
_inherit = 'pos.pack.operation.lot'
lot_id = fields.Many2one('stock.production.lot', string='Lot')
lot_catch_weight_ratio = fields.Float(related='lot_id.catch_weight_ratio')

View File

@@ -0,0 +1,30 @@
/* Copyright 2018 Tecnativa - David Vidal
Copyright 2018 Hibou Corp. - Jared Kipe
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
*/
.pos .popup .packlot-select {
border-bottom: solid 1px rgba(60,60,60,0.1);
margin-top: 3px;
}
.pos .popup select {
text-align: left;
padding: 10px;
display: inline-block;
border-radius: 3px;
border: solid 1px #cecbcb;
margin-bottom: 4px;
background: white;
font-family: "Lato","Lucida Grande", Helvetica, Verdana, Arial;
color: #444;
width: 80%;
min-height: 44px;
font-size: 20px;
box-sizing: border-box;
}
.pos .popup select:focus, .pos .popup select:active {
outline: none;
box-shadow: 0px 0px 0px 3px #6EC89B;
}

View File

@@ -0,0 +1,74 @@
/* Copyright 2018 Tecnativa - David Vidal
Copyright 2018 Hibou Corp. - Jared Kipe
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). */
odoo.define("pos_product_catch_weight.chrome", function (require) {
"use strict";
var chrome = require("point_of_sale.chrome");
chrome.Chrome.include({
build_widgets: function () {
var res = this._super.apply(this, arguments);
var packlotline = this.gui.popup_instances.packlotline;
// Add events over instanced popup
var events = {
"change .packlot-line-select": "lot_to_input",
};
packlotline.events = Object.assign(
packlotline.events, events
);
// Add methods over instanced popup
// Write the value in the corresponding input
packlotline.lot_to_input = function (event) {
var $select = $(event.target);
var $option = this.$("select.packlot-line-select option");
var $input = this.$el.find("input");
if ($input.length) {
for (var i = 0; i < $input.length; i++) {
var $i = $input[i];
if (!$i.value || i + 1 == $input.length) {
$i.value = $select[0].value;
$i.blur();
$i.focus();
}
}
}
$option.prop('selected', function () {
return this.defaultSelected;
});
};
packlotline.click_confirm = function(){
var pack_lot_lines = this.options.pack_lot_lines;
this.$('.packlot-line-input').each(function(index, el){
var cid = $(el).attr('cid'),
lot_name = $(el).val();
var pack_line = pack_lot_lines.get({cid: cid});
var quant = null;
for (var i = 0; i < pack_lot_lines.product_quants.length; i++) {
if (pack_lot_lines.product_quants[i].lot_id[1] == lot_name) {
quant = pack_lot_lines.product_quants[i];
break;
}
}
if (quant) {
pack_line.set_quant(quant);
} else {
pack_line.set_lot_name(lot_name);
}
});
pack_lot_lines.remove_empty_model();
pack_lot_lines.set_quantity_by_lot();
this.options.order.save_to_db();
this.options.order_line.trigger('change', this.options.order_line);
this.gui.close_popup();
},
this.gui.popup_instances.packlotline = packlotline;
return res;
},
});
});

View File

@@ -0,0 +1,140 @@
/* Copyright 2018 Tecnativa - David Vidal
Copyright 2018 Hibou Corp. - Jared Kipe
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). */
odoo.define("pos_product_catch_weight.models", function (require) {
"use strict";
var models = require("point_of_sale.models");
var session = require("web.session");
var utils = require('web.utils');
var round_pr = utils.round_precision;
models.PosModel = models.PosModel.extend({
get_lot: function (product, location_id) {
var done = new $.Deferred();
session.rpc("/web/dataset/search_read", {
"model": "stock.quant",
"domain": [
["location_id", "=", location_id],
["product_id", "=", product],
["lot_id", "!=", false]],
"fields": [
'lot_id',
'quantity',
'lot_catch_weight',
'lot_catch_weight_ratio',
'lot_catch_weight_uom_id',
]
}, {'async': false}).then(function (result) {
var product_quants = [];
if (result.length) {
product_quants = result.records;
}
done.resolve(product_quants);
});
return done;
},
});
var _orderline_super = models.Orderline.prototype;
models.Orderline = models.Orderline.extend({
compute_lot_lines: function(){
var done = new $.Deferred();
var compute_lot_lines = _orderline_super.compute_lot_lines.apply(this, arguments);
this.pos.get_lot(this.product.id, this.pos.config.stock_location_id[0])
.then(function (product_quants) {
compute_lot_lines.product_quants = product_quants;
done.resolve(compute_lot_lines);
});
return compute_lot_lines;
},
get_base_price: function(){
var rounding = this.pos.currency.rounding;
var valid_product_lot = this.pack_lot_lines.get_valid_lots();
var lot_ratio_sum = 0.0;
for (var i=0; valid_product_lot && i < valid_product_lot.length; i++) {
lot_ratio_sum += valid_product_lot[i].get('lot_catch_weight_ratio');
}
var qty = this.get_quantity();
if (lot_ratio_sum != 0.0) {
qty = lot_ratio_sum;
}
return round_pr(this.get_unit_price() * qty * (1 - this.get_discount()/100), rounding);
},
get_all_prices: function(){
var valid_product_lot = this.pack_lot_lines.get_valid_lots();
var lot_ratio_sum = 0.0;
for (var i=0; valid_product_lot && i < valid_product_lot.length; i++) {
lot_ratio_sum += valid_product_lot[i].get('lot_catch_weight_ratio');
}
var qty = this.get_quantity();
var qty_ratio = 1.0
if (lot_ratio_sum != 0.0) {
qty_ratio = lot_ratio_sum / qty;
}
var price_unit = (this.get_unit_price() * qty_ratio) * (1.0 - (this.get_discount() / 100.0));
var taxtotal = 0;
var product = this.get_product();
var taxes_ids = product.taxes_id;
var taxes = this.pos.taxes;
var taxdetail = {};
var product_taxes = [];
_(taxes_ids).each(function(el){
product_taxes.push(_.detect(taxes, function(t){
return t.id === el;
}));
});
var all_taxes = this.compute_all(product_taxes, price_unit, this.get_quantity(), this.pos.currency.rounding);
_(all_taxes.taxes).each(function(tax) {
taxtotal += tax.amount;
taxdetail[tax.id] = tax.amount;
});
return {
"priceWithTax": all_taxes.total_included,
"priceWithoutTax": all_taxes.total_excluded,
"tax": taxtotal,
"taxDetails": taxdetail,
};
},
});
//var _packlotline_super = models.Packlotline.prototype;
models.Packlotline = models.Packlotline.extend({
defaults: {
lot_name: null,
lot_catch_weight_ratio: 1.0,
lot_catch_weight: 1.0,
lot_catch_weight_uom_id: null,
},
set_quant: function(quant) {
this.set({
lot_name: _.str.trim(quant.lot_id[1]) || null,
lot_catch_weight_ratio: quant.lot_catch_weight_ratio || 1.0,
lot_catch_weight: quant.lot_catch_weight || 1.0,
lot_catch_weight_uom_id: quant.lot_catch_weight_uom_id || null,
});
},
set_lot_name: function(name){
this.set({
lot_name : _.str.trim(name) || null,
lot_catch_weight_ratio : 1.0,
lot_catch_weight : 1.0,
lot_catch_weight_uom_id : null,
});
},
})
});

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2018 Tecnativa - David Vidal
Copyright 2018 Hibou Corp. - Jared Kipe
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). -->
<templates>
<t t-extend="PackLotLinePopupWidget">
<t t-jquery=".title" t-operation="append">
<div class="packlot-select">
<t t-if="widget.options.pack_lot_lines and widget.options.pack_lot_lines.product_quants">
<select class="packlot-line-select">
<option disabled="" selected="" value="">Select a Serial/Lot Number</option>
<t t-foreach="widget.options.pack_lot_lines.product_quants" t-as="q">
<option t-att-value="q.lot_id[1]">
<t t-esc="q.lot_id[1]"/> : <t t-esc="q.lot_catch_weight"/> <t t-esc="q.lot_catch_weight_uom_id[1]"/>
</option>
</t>
</select>
</t>
</div>
</t>
</t>
<t t-extend="Orderline">
<t t-jquery=".info-list" t-operation="append">
<t t-set="lots" t-value="line.pack_lot_lines.get_valid_lots()"/>
<t t-if="lots" t-foreach="lots" t-as="lot">
<li class="info">
-- <t t-esc="lot.get_lot_name()"/>
<t t-if="lot.get('lot_catch_weight_uom_id')">
@ <t t-esc="lot.get('lot_catch_weight')"/>
<t t-esc="lot.get('lot_catch_weight_uom_id')[1]"/>
</t>
</li>
</t>
</t>
</t>
</templates>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2018 Tecnativa - David Vidal
Copyright 2018 Hibou Corp. - Jared Kipe
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). -->
<odoo>
<template id="assets" inherit_id="point_of_sale.assets">
<xpath expr=".">
<script type="text/javascript" src="/pos_product_catch_weight/static/src/js/models.js"/>
<script type="text/javascript" src="/pos_product_catch_weight/static/src/js/chrome.js"/>
<link rel="stylesheet" href="/pos_product_catch_weight/static/src/css/pos.css" />
</xpath>
</template>
</odoo>