mirror of
https://gitlab.com/hibou-io/hibou-odoo/suite.git
synced 2025-01-20 12:37:31 +02:00
Initial commit of pos_product_catch_weight for 11.0
This commit is contained in:
1
pos_product_catch_weight/__init__.py
Executable file
1
pos_product_catch_weight/__init__.py
Executable file
@@ -0,0 +1 @@
|
||||
from . import models
|
||||
27
pos_product_catch_weight/__manifest__.py
Executable file
27
pos_product_catch_weight/__manifest__.py
Executable 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,
|
||||
}
|
||||
1
pos_product_catch_weight/models/__init__.py
Normal file
1
pos_product_catch_weight/models/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import pos_order
|
||||
57
pos_product_catch_weight/models/pos_order.py
Normal file
57
pos_product_catch_weight/models/pos_order.py
Normal 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')
|
||||
30
pos_product_catch_weight/static/src/css/pos.css
Executable file
30
pos_product_catch_weight/static/src/css/pos.css
Executable 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;
|
||||
}
|
||||
74
pos_product_catch_weight/static/src/js/chrome.js
Executable file
74
pos_product_catch_weight/static/src/js/chrome.js
Executable 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;
|
||||
},
|
||||
});
|
||||
|
||||
});
|
||||
140
pos_product_catch_weight/static/src/js/models.js
Executable file
140
pos_product_catch_weight/static/src/js/models.js
Executable 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,
|
||||
});
|
||||
},
|
||||
})
|
||||
|
||||
});
|
||||
40
pos_product_catch_weight/static/src/xml/pos.xml
Executable file
40
pos_product_catch_weight/static/src/xml/pos.xml
Executable 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>
|
||||
16
pos_product_catch_weight/templates/assets.xml
Executable file
16
pos_product_catch_weight/templates/assets.xml
Executable 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>
|
||||
Reference in New Issue
Block a user