Browse Source

[MIG] pos_sequence_ref_number

pull/178/head
gilles 7 years ago
committed by Denis Roussel
parent
commit
9b358ed92b
  1. 11
      pos_sequence_ref_number/README.rst
  2. 5
      pos_sequence_ref_number/__init__.py
  3. 13
      pos_sequence_ref_number/__manifest__.py
  4. 2
      pos_sequence_ref_number/i18n/ca.po
  5. 2
      pos_sequence_ref_number/i18n/de.po
  6. 2
      pos_sequence_ref_number/i18n/es.po
  7. 2
      pos_sequence_ref_number/i18n/fr.po
  8. 2
      pos_sequence_ref_number/i18n/gl.po
  9. 2
      pos_sequence_ref_number/i18n/it.po
  10. 2
      pos_sequence_ref_number/i18n/nl_NL.po
  11. 2
      pos_sequence_ref_number/i18n/sl.po
  12. 2
      pos_sequence_ref_number/i18n/zh_CN.po
  13. 5
      pos_sequence_ref_number/models/__init__.py
  14. 26
      pos_sequence_ref_number/models/pos_order.py
  15. 7
      pos_sequence_ref_number/static/lib/moment.js
  16. 138
      pos_sequence_ref_number/static/src/js/main.js
  17. 9
      pos_sequence_ref_number/static/src/xml/pos.xml
  18. 2
      pos_sequence_ref_number/tests/__init__.py
  19. 161
      pos_sequence_ref_number/tests/test_pos_order.py
  20. 31
      pos_sequence_ref_number/views/pos_template.xml

11
pos_sequence_ref_number/README.rst

@ -1,25 +1,27 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:alt: License: AGPL-3
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
=======================
POS Sequence Ref Number
=======================
This module loads the Order Number in the POS, so as to produce and print
a sequential POS order number in the POS Ticket.
Installation
============
Nothing special is needed to install this module.
Usage
=====
The POS number is generated and shown in the printed POS Ticket.
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
:target: https://runbot.odoo-community.org/runbot/184/10.0
Known issues / Roadmap
======================
@ -48,6 +50,7 @@ Contributors
* Rafael Blasco <rblasco@rbnpro.com>
* Ivan Yelizariev <yelizariev@it-projects.info>
* Antonio Espinosa <antonioea@antiun.com>
* Meyomesse Gilles <meyomesse.gilles@gmail.com>
Maintainer

5
pos_sequence_ref_number/__init__.py

@ -1,7 +1,4 @@
# -*- coding: utf-8 -*-
# © 2016 Acsone SA/NV (http://www.acsone.eu)
# © 2016 Eficent Business and IT Consulting Services S.L.
# (http://www.eficent.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import models

13
pos_sequence_ref_number/__openerp__.py → pos_sequence_ref_number/__manifest__.py

@ -1,17 +1,18 @@
# -*- coding: utf-8 -*-
# © 2016 Acsone SA/NV (http://www.acsone.eu)
# © 2016 Eficent Business and IT Consulting Services S.L.
# (http://www.eficent.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
# Copyright 2016-2017 Acsone SA/NV (http://www.acsone.eu) and
# Eficent Business and IT Consulting Services S.L (http://www.eficent.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
'name': 'POS Sequence Ref Number',
'version': '8.0.1.0.0',
'version': '10.0.1.0.0',
'category': 'Point Of Sale',
'sequence': 1,
'author': "Eficent Business and IT Consulting Services,"
"Acsone SA/NV,"
"Odoo Community Association (OCA)",
'summary': 'Sequential Order numbers for Point of sale',
'website': 'https://github.com/OCA/pos',
'license': 'AGPL-3',
'depends': [
"point_of_sale",
],
@ -22,6 +23,4 @@
'static/src/xml/pos.xml'
],
'installable': True,
'application': False,
'auto_install': False,
}

2
pos_sequence_ref_number/i18n/ca.po

@ -6,7 +6,7 @@
# Eric Antones <eantones@users.noreply.github.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-04-29 00:49+0000\n"
"PO-Revision-Date: 2017-04-29 00:49+0000\n"

2
pos_sequence_ref_number/i18n/de.po

@ -6,7 +6,7 @@
# Rudolf Schnapka <rs@techno-flex.de>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-04-29 00:49+0000\n"
"PO-Revision-Date: 2017-04-29 00:49+0000\n"

2
pos_sequence_ref_number/i18n/es.po

@ -6,7 +6,7 @@
# OCA Transbot <transbot@odoo-community.org>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-04-29 00:49+0000\n"
"PO-Revision-Date: 2017-04-29 00:49+0000\n"

2
pos_sequence_ref_number/i18n/fr.po

@ -6,7 +6,7 @@
# OCA Transbot <transbot@odoo-community.org>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-04-29 00:49+0000\n"
"PO-Revision-Date: 2017-04-29 00:49+0000\n"

2
pos_sequence_ref_number/i18n/gl.po

@ -6,7 +6,7 @@
# César Castro Cruz <ulmroan@gmail.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-04-29 00:49+0000\n"
"PO-Revision-Date: 2017-04-29 00:49+0000\n"

2
pos_sequence_ref_number/i18n/it.po

@ -6,7 +6,7 @@
# Paolo Valier <paolo.valier@hotmail.it>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-04-29 00:49+0000\n"
"PO-Revision-Date: 2017-04-29 00:49+0000\n"

2
pos_sequence_ref_number/i18n/nl_NL.po

@ -6,7 +6,7 @@
# OCA Transbot <transbot@odoo-community.org>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-04-29 00:49+0000\n"
"PO-Revision-Date: 2017-04-29 00:49+0000\n"

2
pos_sequence_ref_number/i18n/sl.po

@ -6,7 +6,7 @@
# Matjaž Mozetič <m.mozetic@matmoz.si>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-04-29 00:49+0000\n"
"PO-Revision-Date: 2017-04-29 00:49+0000\n"

2
pos_sequence_ref_number/i18n/zh_CN.po

@ -6,7 +6,7 @@
# liAnGjiA <liangjia@qq.com>, 2017
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 8.0\n"
"Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-04-29 00:49+0000\n"
"PO-Revision-Date: 2017-04-29 00:49+0000\n"

5
pos_sequence_ref_number/models/__init__.py

@ -1,7 +1,4 @@
# -*- coding: utf-8 -*-
# © 2016 Acsone SA/NV (http://www.acsone.eu)
# © 2016 Eficent Business and IT Consulting Services S.L.
# (http://www.eficent.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import pos_order

26
pos_sequence_ref_number/models/pos_order.py

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-
# © 2016 Acsone SA/NV (http://www.acsone.eu)
# © 2016 Eficent Business and IT Consulting Services S.L.
# (http://www.eficent.com)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
# Copyright 2016-2017 Acsone SA/NV (http://www.acsone.eu) and
# Eficent Business and IT Consulting Services S.L. (http://www.eficent.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import api, models
from odoo import api, models
class PosOrder(models.Model):
@ -12,19 +12,19 @@ class PosOrder(models.Model):
@api.model
def sequence_number_sync(self, vals):
next = vals.get('_sequence_ref_number', False)
next = int(next) if next else False
if vals.get('session_id') and next is not False:
next_number = vals.get('sequence_ref_number', False)
next_number = int(next_number) if next_number else False
if vals.get('session_id') and next_number is not False:
session = self.env['pos.session'].sudo().browse(vals['session_id'])
if next != session.config_id.sequence_id.number_next_actual:
session.config_id.sequence_id.number_next_actual = next
if vals.get('_sequence_ref_number') is not None:
del vals['_sequence_ref_number']
if next_number != session.config_id.sequence_id.number_next_actual:
session.config_id.sequence_id.number_next_actual = next_number
if vals.get('sequence_ref_number') is not None:
del vals['sequence_ref_number']
@api.model
def _order_fields(self, ui_order):
vals = super(PosOrder, self)._order_fields(ui_order)
vals['_sequence_ref_number'] = ui_order.get('sequence_ref_number')
vals['sequence_ref_number'] = ui_order.get('sequence_ref_number')
return vals
@api.model

7
pos_sequence_ref_number/static/lib/moment.js

@ -1,8 +1,5 @@
//! moment.js
//! version : 2.8.1
//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
//! license : MIT
//! momentjs.com
/* Copyright 2017 Tim Wood, Iskren Chernev, Moment.js contributors
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */
(function (undefined) {
/************************************

138
pos_sequence_ref_number/static/src/js/main.js

@ -1,82 +1,76 @@
/**
* # -*- coding: utf-8 -*-
* # See README.rst file on addon root folder for license details
*/
odoo.define('pos_sequence_ref_number.pos_sequence_ref_number_assets_backend', function(require) {
"use strict";
+function ($) {
'use strict';
var models = require('point_of_sale.models');
openerp.pos_sequence_ref_number = function (instance) {
var _t = instance.web._t,
_lt = instance.web._lt;
var QWeb = instance.web.qweb;
var module = instance.point_of_sale;
var _sequence_next = function(seq){
var idict = {
'year': moment().format('YYYY'),
'month': moment().format('MM'),
'day': moment().format('DD'),
'y': moment().format('YY')
};
var format = function(s, dict){
s = s || '';
$.each(dict, function(k, v){
s = s.replace('%(' + k + ')s', v);
});
return s;
};
function pad(n, width, z) {
z = z || '0';
n = n + '';
if (n.length < width) {
n = new Array(width - n.length + 1).join(z) + n;
}
return n;
var PosModelSuper = models.PosModel;
var posmodel_super = models.PosModel.prototype;
var _super_order = models.Order.prototype;
var sequence_next = function(seq){
var idict = {
'year': moment().format('YYYY'),
'month': moment().format('MM'),
'day': moment().format('DD'),
'y': moment().format('YY')
};
var format = function(s, dict){
s = s || '';
$.each(dict, function(k, v){
s = s.replace('%(' + k + ')s', v);
});
return s;
};
function pad(n, width, z) {
z = z || '0';
n = n + '';
if (n.length < width) {
n = new Array(width - n.length + 1).join(z) + n;
}
var num = seq.number_next_actual;
var prefix = format(seq.prefix, idict);
var suffix = format(seq.suffix, idict);
seq.number_next_actual += seq.number_increment;
return n;
}
var num = seq.number_next_actual;
var prefix = format(seq.prefix, idict);
var suffix = format(seq.suffix, idict);
seq.number_next_actual += seq.number_increment;
return prefix + pad(num, seq.padding) + suffix;
return prefix + pad(num, seq.padding) + suffix;
};
var PosModelParent = module.PosModel;
module.PosModel = module.PosModel.extend({
load_server_data: function(){
var self = this;
// Load POS sequence object
self.models.push({
model: 'ir.sequence',
fields: [],
ids: function(self){ return [self.config.sequence_id[0]]; },
loaded: function(self, sequence){ self.pos_order_sequence = sequence[0]; },
});
return PosModelParent.prototype.load_server_data.apply(this, arguments);
},
push_order: function(order) {
if (order !== undefined) {
models.PosModel = models.PosModel.extend({
load_server_data: function () {
var self = this;
// Load POS sequence object
self.models.push({
model: 'ir.sequence',
fields: [],
ids: function(self){ return [self.config.sequence_id[0]]; },
loaded: function(self, sequence){ self.pos_order_sequence = sequence[0]; },
});
return posmodel_super.load_server_data.apply(this, arguments);
},
push_order: function(order){
if (order !== undefined) {
order.set({'sequence_ref_number': this.pos_order_sequence.number_next_actual});
order.set({'sequence_ref': _sequence_next(this.pos_order_sequence)});
order.set({'sequence_ref': sequence_next(this.pos_order_sequence)});
}
return PosModelParent.prototype.push_order.call(this, order);
}
});
return PosModelSuper.prototype.push_order.call(this, order);
},
});
var OrderParent = module.Order;
module.Order = module.Order.extend({
export_for_printing: function(attributes){
var order = OrderParent.prototype.export_for_printing.apply(this, arguments);
order['sequence_ref_number'] = this.get('sequence_ref_number');
return order;
},
export_as_JSON: function() {
var order = OrderParent.prototype.export_as_JSON.apply(this, arguments);
order['sequence_ref'] = this.get('sequence_ref');
order['sequence_ref_number'] = this.get('sequence_ref_number');
return order;
},
});
};
models.Order = models.Order.extend({
export_as_JSON: function() {
var json = _super_order.export_as_JSON.apply(this,arguments);
json['sequence_ref'] = this.get('sequence_number');
json['sequence_ref_number'] = this.get('sequence_ref_number');
return json;
},
export_for_printing: function() {
var json = _super_order.export_for_printing.apply(this,arguments);
json['sequence_ref_number'] = this.get('sequence_number');
return json;
},
});
}(jQuery);
});

9
pos_sequence_ref_number/static/src/xml/pos.xml

@ -1,19 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2017 Jordi Ballester, Rafael Blasco, Ivan Yelizariev, Antonio Espinosa, Meyomesse Gilles
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<templates id="template" xml:space="preserve">
<t t-extend="PosTicket">
<t t-jquery=".pos-center-align t:first" t-operation="after">
<br/>
<t t-esc="order.get('sequence_ref')"/>
<!-- sequence_number -->
<br/>
</t>
</t>
<t t-extend="XmlReceipt">
<t t-extend="XmlReceipt">
<t t-jquery="[t-if='!receipt.company.logo']" t-operation="after">
<br/>
<t t-esc="receipt.sequence_ref"/>
<br/>
</t>
</t>
</t>
</templates>
</templates>

2
pos_sequence_ref_number/tests/__init__.py

@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-
from . import test_pos_order

161
pos_sequence_ref_number/tests/test_pos_order.py

@ -0,0 +1,161 @@
# -*- coding: utf-8 -*-
# Copyright 2017 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields
from odoo.tests.common import SavepointCase
class TestSequenceNumberSync(SavepointCase):
@classmethod
def setUpClass(cls):
"""
Simulation of sales coming from the interface
"""
super(TestSequenceNumberSync, cls).setUpClass()
# ENVIRONEMENTS
cls.pos_obj = cls.env['pos.order']
cls.partner_obj = cls.env['res.partner']
# INSTANCES
cls.partner = cls.partner_obj.create({'name': 'test_partner_A'})
cls.product = cls.env.ref(
'product.product_order_01')
cls.pos_config = cls.env.ref('point_of_sale.pos_config_main')
# USING VARIABLE
cls.sequence_ref_number = 10
cls.sequence_number = 2
# USER PARTNER
cls.user_partner = cls.env.user.partner_id
def get_data(self, session, sequence_number):
return '000' + str(session.id) + '-001-000' + str(sequence_number)
def ui_order_data(self, sequence_ref_number, sequence_number,
current_session):
values = {
'data': {
'creation_date': fields.Datetime.now(),
'fiscal_position_id': False,
'amount_return': 0,
'sequence_ref_number': sequence_ref_number,
'lines': [[0, 0, {'product_id': self.product.id,
'qty': 1}]],
'name': 'Order ' + self.get_data(
current_session, sequence_number),
'partner_id': False,
'pos_session_id': current_session.id,
'sequence_number': sequence_number,
'statement_ids': [[0, 0, {
'account_id':
self.user_partner.property_account_receivable_id.id,
'amount': 0.9,
'journal_id': self.pos_config.journal_ids[0].id,
'name': fields.Datetime.now(),
'statement_id':current_session.statement_ids[0].id}]],
'user_id': self.env.uid
},
'to_invoice': False
}
# because travis install (pos_loyalty)
# may be an edge effect
if 'loyalty_points' in self.pos_obj._fields:
values['data']['loyalty_points'] = 0
return values
def test_check_sequence_number_sync_00(self):
"""
case 1 :
1 - create order from ui
2 - close session
3 - create new order from ui,
4 - close session
5 - validate closing & post entries
sequence result : 000session_id-001-000sequence_number
and 000new_session_id+1-001-000sequence_number
order name result : Main/00sequence_ref_number
"""
# click on create a new session button
self.pos_config.open_session_cb()
# session
current_session = self.pos_config.current_session_id
# data
ui_order = self.ui_order_data(self.sequence_ref_number,
self.sequence_number, current_session)
# I create an order on an open session
pos_order_id = self.pos_obj.create_from_ui([ui_order])
pos_order = self.env['pos.order'].browse(pos_order_id)
self.assertEqual(pos_order.name,
'Main/00' + str(self.sequence_ref_number))
self.assertEqual(pos_order.pos_reference,
'Order 000' + str(current_session.id)+'-001-0002')
# close the session
self.pos_config.current_session_id.action_pos_session_closing_control()
# create an open new session
self.pos_config.open_session_cb()
new_current_session = self.pos_config.current_session_id
ui_order['data']['pos_session_id'] = new_current_session.id
ui_order['data']['name'] = self.get_data(
new_current_session, self.sequence_number)
# create an order on an open session
pos_order_id = self.pos_obj.create_from_ui([ui_order])
pos_order = self.env['pos.order'].browse(pos_order_id)
self.assertEqual(pos_order.name,
'Main/00' + str(self.sequence_ref_number))
self.assertEqual(pos_order.pos_reference,
'000' + str(new_current_session.id)+'-001-0002')
def test_check_sequence_number_sync_01(self):
"""
case 2 :
1 - create order from ui,
2 - create new order from ui
3 - validate closing & post entries
sequence result : 000session_id-001-000sequence_number
and 000session_id-001-000new_sequence_number
order name result : Main/00sequence_ref_number
"""
# create a new session button
self.pos_config.open_session_cb()
# session
current_session = self.pos_config.current_session_id
# data
ui_order = self.ui_order_data(self.sequence_ref_number,
self.sequence_number, current_session)
# create an order on an open session
pos_order_id = self.pos_obj.create_from_ui([ui_order])
pos_order = self.env['pos.order'].browse(pos_order_id)
self.assertEqual(pos_order.name,
'Main/00' + str(self.sequence_ref_number))
self.assertEqual(pos_order.pos_reference,
'Order 000' + str(current_session.id) + '-001-0002')
self.sequence_number = self.sequence_number+1
ui_order = self.ui_order_data(self.sequence_ref_number,
self.sequence_number, current_session)
pos_order_id = self.pos_obj.create_from_ui([ui_order])
pos_order = self.env['pos.order'].browse(pos_order_id)
self.assertEqual(pos_order.name,
'Main/00' + str(self.sequence_ref_number))
self.assertEqual(pos_order.pos_reference,
'Order 000' + str(current_session.id) + '-001-0003')
# close the session
self.pos_config.current_session_id.action_pos_session_closing_control()

31
pos_sequence_ref_number/views/pos_template.xml

@ -1,16 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<template id="pos_sequence_ref_number_assets_backend"
name="pos_sequence_ref_number_assets_backend"
inherit_id="point_of_sale.assets_backend">
<xpath expr="." position="inside">
<script src="/pos_sequence_ref_number/static/src/js/main.js"
type="text/javascript"/>
<script type="text/javascript"
src="/pos_sequence_ref_number/static/lib/moment.js"/>
</xpath>
</template>
</data>
</openerp>
<!-- Copyright 2017 Jordi Ballester, Rafael Blasco, Ivan Yelizariev, Antonio Espinosa, Meyomesse Gilles
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<data>
<template id="pos_sequence_ref_number_assets_backend"
name="pos_sequence_ref_number_assets_backend"
inherit_id="point_of_sale.assets">
<xpath expr="." position="inside">
<script src="/pos_sequence_ref_number/static/src/js/main.js"
type="text/javascript"/>
<script type="text/javascript"
src="/pos_sequence_ref_number/static/lib/moment.js"/>
</xpath>
</template>
</data>
</odoo>
Loading…
Cancel
Save