From 295cf8b2355a17430370e592b1778c1ce2a3a965 Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Sun, 17 Oct 2010 20:05:28 +0200 Subject: [PATCH] [IMP] Complete rewrite of sale_journal module no need for picking journal anymore, the stock has a journal system by default no need for sale journal anymore, you can use sales team invoice types is kept bzr revid: fp@tinyerp.com-20101017180528-3cmxx06v7wh9a6yi --- addons/sale/sale_installer.py | 7 +- addons/sale/sale_view.xml | 6 +- addons/sale_journal/__init__.py | 3 - addons/sale_journal/__openerp__.py | 7 +- addons/sale_journal/report/__init__.py | 25 -- .../report/picking_journal_report.py | 88 ----- .../report/picking_journal_report_view.xml | 106 ----- .../report/sale_journal_report.py | 75 ---- .../report/sale_journal_report_view.xml | 89 ----- addons/sale_journal/sale_journal.py | 183 +-------- addons/sale_journal/sale_journal_data.xml | 10 +- addons/sale_journal/sale_journal_demo.xml | 20 +- addons/sale_journal/sale_journal_view.xml | 361 +----------------- .../sale_journal/security/ir.model.access.csv | 9 +- addons/sale_journal/test/picking_journal.yml | 87 ----- addons/sale_journal/test/sale_journal.yml | 95 ----- 16 files changed, 51 insertions(+), 1120 deletions(-) delete mode 100644 addons/sale_journal/report/__init__.py delete mode 100644 addons/sale_journal/report/picking_journal_report.py delete mode 100644 addons/sale_journal/report/picking_journal_report_view.xml delete mode 100644 addons/sale_journal/report/sale_journal_report.py delete mode 100644 addons/sale_journal/report/sale_journal_report_view.xml delete mode 100644 addons/sale_journal/test/picking_journal.yml delete mode 100644 addons/sale_journal/test/sale_journal.yml diff --git a/addons/sale/sale_installer.py b/addons/sale/sale_installer.py index 4197c0a370b..a8cc5432020 100644 --- a/addons/sale/sale_installer.py +++ b/addons/sale/sale_installer.py @@ -28,11 +28,8 @@ class sale_installer(osv.osv_memory): _columns = { 'delivery': fields.boolean('Delivery Costs', help="Allows you to compute delivery costs on your quotations."), - 'sale_journal': fields.boolean('Sales and deliveries by journal', - help="Allows you to categorise your " - "sales and deliveries (picking lists) between different journals. " - "This module is very helpful for bigger companies that " - "work by departments."), + 'sale_journal': fields.boolean('Invoicing journals', + help="Allows you to group and invoice your delivery orders according to different invoicing types: daily, weekly, etc."), 'sale_layout': fields.boolean('Sales Order Layout Improvement', help="Provides some features to improve the layout of the Sales Order reports."), 'sale_margin': fields.boolean('Margins in Sales Orders', diff --git a/addons/sale/sale_view.xml b/addons/sale/sale_view.xml index 36ba5e62d81..b9eabcaa02e 100644 --- a/addons/sale/sale_view.xml +++ b/addons/sale/sale_view.xml @@ -49,9 +49,11 @@ If you have more than one shops reselling your company products, you can create and manage them from here. Whenever you will record a new quotation or sale order, it has to be linked to a shop. The shop also defines the warehouse from which the products will be delivered for each particular sale. + + parent="menu_config_sale" sequence="0" /> sale.order.calendar diff --git a/addons/sale_journal/__init__.py b/addons/sale_journal/__init__.py index b41a4be55d1..b05803da6c6 100644 --- a/addons/sale_journal/__init__.py +++ b/addons/sale_journal/__init__.py @@ -20,7 +20,4 @@ ############################################################################## import sale_journal -import report - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale_journal/__openerp__.py b/addons/sale_journal/__openerp__.py index 4fde94fc709..37fc05fd066 100644 --- a/addons/sale_journal/__openerp__.py +++ b/addons/sale_journal/__openerp__.py @@ -53,14 +53,9 @@ 'update_xml': [ 'security/ir.model.access.csv', 'sale_journal_view.xml', - 'report/sale_journal_report_view.xml', - 'report/picking_journal_report_view.xml', ], 'demo_xml': ['sale_journal_demo.xml'], - 'test': [ - 'test/sale_journal.yml', - 'test/picking_journal.yml', - ], + 'test': [ ], 'installable': True, 'active': False, 'certificate': '0077661619085', diff --git a/addons/sale_journal/report/__init__.py b/addons/sale_journal/report/__init__.py deleted file mode 100644 index bfe23eb8cce..00000000000 --- a/addons/sale_journal/report/__init__.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -import sale_journal_report -import picking_journal_report - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/addons/sale_journal/report/picking_journal_report.py b/addons/sale_journal/report/picking_journal_report.py deleted file mode 100644 index 74c00367838..00000000000 --- a/addons/sale_journal/report/picking_journal_report.py +++ /dev/null @@ -1,88 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -from osv import fields, osv -import tools -from decimal_precision import decimal_precision as dp - - -class sale_journal_picking_report(osv.osv): - """ - Picking list by journal and by invoice - """ - _name = "sale.journal.picking.report" - _description = "Picking lists" - _auto = False - _columns = { - 'name': fields.char('Year', size=64, required=False, readonly=True), - 'month': fields.selection([('01', 'January'), ('02', 'February'), ('03', 'March'), ('04', 'April'), ('05', 'May'), ('06', 'June'), - ('07', 'July'), ('08', 'August'), ('09', 'September'), ('10', 'October'), ('11', 'November'), ('12', 'December')], 'Month', readonly=True), - - 'invoice_state':fields.selection([ - ("invoiced", "invoiced"), - ("2binvoiced", "to be invoiced"), - ("none", "None") - ], "Invoice state", readonly=True), - 'state': fields.selection([ - ('draft', 'draft'), - ('auto', 'waiting'), - ('confirmed', 'confirmed'), - ('assigned', 'assigned'), - ('done', 'done'), - ('cancel', 'cancel'), - ], 'State', readonly=True), - 'invoice_type_id': fields.many2one('sale_journal.invoice.type', 'Invoicing method', readonly=True), - 'journal_id': fields.many2one('sale_journal.picking.journal', 'Journal', readonly=True), - 'quantity': fields.float('Quantities', readonly=True), - 'price_total': fields.float('Total Price', readonly=True, digits_compute=dp.get_precision('Sale Price')), - 'price_average': fields.float('Average Price', readonly=True, digits_compute=dp.get_precision('Sale Price')), - 'count': fields.integer('# of Lines', readonly=True), - } - _order = 'journal_id, name desc, price_total desc' - - def init(self, cr): - tools.drop_view_if_exists(cr, 'sale_journal_picking_report') - - cr.execute(""" - create or replace view sale_journal_picking_report as ( - select - min(l.id) as id, - to_char(s.date, 'YYYY') as name, - to_char(s.date, 'MM') as month, - s.state, - s.invoice_state, - s.invoice_type_id, - s.journal_id, - sum(l.product_qty) as quantity, - count(*) as count, - sum(l.product_qty*ol.price_unit*(1.0-ol.discount/100.0)) as price_total, - (sum(l.product_qty*ol.price_unit*(1.0-ol.discount/100.0))/sum(l.product_qty))::decimal(16,2) as price_average - from stock_picking s - right join stock_move l on (s.id=l.picking_id) - left join sale_order_line ol on (l.sale_line_id=ol.id) - group by s.journal_id, s.invoice_type_id, to_char(s.date, 'YYYY'),to_char(s.date, 'MM'),s.state, s.invoice_state - order by s.invoice_type_id, s.invoice_state, s.state - ) - """) - -sale_journal_picking_report() - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale_journal/report/picking_journal_report_view.xml b/addons/sale_journal/report/picking_journal_report_view.xml deleted file mode 100644 index 8c98b6b3928..00000000000 --- a/addons/sale_journal/report/picking_journal_report_view.xml +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - sale.journal.picking.report.tree - sale.journal.picking.report - tree - - - - - - - - - - - - - - - - - - - - sale.journal.picking.report.graph - sale.journal.picking.report - graph - - - - - - - - - - - - - sale.journal.picking.report.search - sale.journal.picking.report - search - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Statistics on picking to invoice - sale.journal.picking.report - ir.actions.act_window - form - tree,form - [('invoice_state','=','2binvoiced'),('invoice_type_id','=',active_id)] - - - - - - Picking Journal - sale.journal.picking.report - ir.actions.act_window - form - tree,graph - - {'search_default_month':1, 'group_by_no_leaf':1,'group_by':[]} - Display your company picking journal and personalize its view by filtering it with specific selection criteria. - - - - - - diff --git a/addons/sale_journal/report/sale_journal_report.py b/addons/sale_journal/report/sale_journal_report.py deleted file mode 100644 index 723a7f88722..00000000000 --- a/addons/sale_journal/report/sale_journal_report.py +++ /dev/null @@ -1,75 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2004-2010 Tiny SPRL (). -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## - -from osv import fields, osv -import tools - -class sale_journal_report(osv.osv): - _name = "sale.journal.report" - _description = "Sales Orders by Journal" - _auto = False - _columns = { - 'name': fields.char('Year', size=64, required=False, readonly=True), - 'month':fields.selection([('01', 'January'), ('02', 'February'), ('03', 'March'), ('04', 'April'), - ('05', 'May'), ('06', 'June'), ('07', 'July'), ('08', 'August'), ('09', 'September'), - ('10', 'October'), ('11', 'November'), ('12', 'December')], 'Month', readonly=True), - 'state': fields.selection([ - ('draft', 'Quotation'), - ('waiting_date', 'Waiting Schedule'), - ('manual', 'Manual in progress'), - ('progress', 'In progress'), - ('shipping_except', 'Shipping Exception'), - ('invoice_except', 'Invoice Exception'), - ('done', 'Done'), - ('cancel', 'Cancel') - ], 'Order State', readonly=True), - 'journal_id': fields.many2one('sale_journal.sale.journal', 'Journal', readonly=True), - 'quantity': fields.float('Quantities', readonly=True), - 'price_total': fields.float('Total Price', readonly=True), - 'price_average': fields.float('Average Price', readonly=True), - 'count': fields.integer('# of Lines', readonly=True), - } - - _order = 'journal_id, name desc,price_total desc' - - def init(self, cr): - tools.drop_view_if_exists(cr, 'sale_journal_report') - cr.execute(""" - create or replace view sale_journal_report as ( - select - min(l.id) as id, - to_char(s.date_order, 'YYYY') as name, - to_char(s.date_order,'MM') as month, - s.state, - s.journal_id, - sum(l.product_uom_qty) as quantity, - count(*), - sum(l.product_uom_qty*l.price_unit) as price_total, - (sum(l.product_uom_qty*l.price_unit)/sum(l.product_uom_qty))::decimal(16,2) as price_average - from sale_order s - right join sale_order_line l on (s.id=l.order_id) - group by s.journal_id , to_char(s.date_order, 'YYYY'),to_char(s.date_order, 'MM'), s.state - ) - """) - -sale_journal_report() - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale_journal/report/sale_journal_report_view.xml b/addons/sale_journal/report/sale_journal_report_view.xml deleted file mode 100644 index e73fdcf9785..00000000000 --- a/addons/sale_journal/report/sale_journal_report_view.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - sale.journal.report.tree - sale.journal.report - tree - - - - - - - - - - - - - - - - - sale.journal.report.graph - sale.journal.report - graph - - - - - - - - - - - - sale.journal.report.search - sale.journal.report - search - - - - - - - - - - - - - - - - - - - - - - - - - - - Sales by Journal - sale.journal.report - ir.actions.act_window - form - tree,graph - - {'search_default_journal': 1,'group_by_no_leaf':1,'group_by':[]} - This view allows you to access your sales orders or quotations by journal. You can create journal in order to group different sales orders by teams and perform automatic actions on a journal (confirm or cancel all sales of a journal). - - - - - - diff --git a/addons/sale_journal/sale_journal.py b/addons/sale_journal/sale_journal.py index 8cb10178f02..09902b21099 100644 --- a/addons/sale_journal/sale_journal.py +++ b/addons/sale_journal/sale_journal.py @@ -39,160 +39,6 @@ class sale_journal_invoice_type(osv.osv): } sale_journal_invoice_type() -class sale_journal(osv.osv): - _name = 'sale_journal.sale.journal' - _description = 'Sale Journal' - _columns = { - 'name': fields.char('Journal', size=64, required=True, states={'close':[('readonly',True)]}), - 'code': fields.char('Code', size=16, required=True, states={'close':[('readonly',True)]}), - 'user_id': fields.many2one('res.users', 'Responsible', required=True, states={'close':[('readonly',True)]}), - 'date': fields.date('Journal date', required=True, states={'close':[('readonly',True)]}), - 'date_created': fields.date('Creation date', readonly=True, required=True), - 'date_close': fields.date('Close date ', readonly=True), - 'sale_stats_ids': fields.one2many("sale.journal.report", "journal_id", 'Sale stats', readonly=True), - 'state': fields.selection([ - ('draft','Draft'), - ('open','Open'), - ('cancel','Cancel'), - ('confirm','Confirm'), - ('close','Close'), - ], 'State', required=True, readonly=True), - 'note': fields.text('Note'), - } - _defaults = { - 'date': time.strftime('%Y-%m-%d'), - 'date_created': time.strftime('%Y-%m-%d'), - 'user_id': lambda self,cr,uid,context: uid, - 'state': lambda self,cr,uid,context: 'draft', - } - - def button_sale_cancel(self, cr, uid, ids, context={}): - self.write(cr, uid, ids, {'state':'cancel'}) - for id in ids: - sale_ids = self.pool.get('sale.order').search(cr, uid, [('journal_id','=',id),('state','=','draft')]) - for saleid in sale_ids: - wf_service = netsvc.LocalService("workflow") - wf_service.trg_validate(uid, 'sale.order', saleid, 'cancel', cr) - return True - - def button_sale_confirm(self, cr, uid, ids, context={}): - self.write(cr, uid, ids, {'state':'confirm'}) - for id in ids: - sale_ids = self.pool.get('sale.order').search(cr, uid, [('journal_id','=',id),('state','=','draft')]) - for saleid in sale_ids: - wf_service = netsvc.LocalService("workflow") - wf_service.trg_validate(uid, 'sale.order', saleid, 'order_confirm', cr) - return True - - def button_open(self, cr, uid, ids, context={}): - self.write(cr, uid, ids, {'state':'open'}) - return True - - def button_draft(self, cr, uid, ids, context={}): - self.write(cr, uid, ids, {'state':'draft'}) - return True - - def button_close(self, cr, uid, ids, context={}): - self.write(cr, uid, ids, {'state':'close', 'date_close':time.strftime('%Y-%m-%d')}) - return True - def button_reset(self, cr, uid, ids, context=None): - self.write(cr, uid, ids, {'state': 'draft'}) - return True - def copy(self, cr, uid, id, default=None, context=None): - """Overrides orm copy method - @param self: The object pointer - @param cr: the current row, from the database cursor, - @param uid: the current user’s ID for security checks, - @param ids: List of case’s IDs - @param context: A standard dictionary for contextual values - """ - if context is None: - context = {} - if default is None: - default = {} - default.update({'sale_stats_ids': []}) - return super(sale_journal, self).copy(cr, uid, id, default=default, context=context) - -sale_journal() - -class picking_journal(osv.osv): - _name = 'sale_journal.picking.journal' - _description = 'Picking Journal' - _columns = { - 'name': fields.char('Journal', size=64, required=True), - 'code': fields.char('Code', size=16, required=True), - 'user_id': fields.many2one('res.users', 'Responsible', required=True), - 'date': fields.date('Journal date', required=True), - 'date_created': fields.date('Creation date', readonly=True, required=True), - 'date_close': fields.date('Close date', readonly=True), - 'picking_stats_ids': fields.one2many("sale.journal.picking.report", "journal_id", 'Journal Stats', readonly=True), - 'state': fields.selection([ - ('draft','Draft'), - ('open','Open'), - ('cancel','Cancel'), - ('close','Close'), - ('confirm','Confirm'), - ], 'Creation date', required=True, readonly=True), - 'note': fields.text('Note'), - } - _defaults = { - 'date': time.strftime('%Y-%m-%d'), - 'date_created': time.strftime('%Y-%m-%d'), - 'user_id': lambda self,cr,uid,context: uid, - 'state': lambda self,cr,uid,context: 'draft', - } - def button_picking_cancel(self, cr, uid, ids, context={}): - self.write(cr, uid, ids, {'state':'cancel'}) - for id in ids: - pick_ids = self.pool.get('stock.picking').search(cr, uid, [('journal_id','=',id)]) - for pickid in pick_ids: - wf_service = netsvc.LocalService("workflow") - wf_service.trg_validate(uid, 'stock.picking', pickid, 'button_cancel', cr) - return True - - def button_open(self, cr, uid, ids, context={}): - self.write(cr, uid, ids, {'state':'open'}) - return True - - def button_draft(self, cr, uid, ids, context={}): - self.write(cr, uid, ids, {'state':'draft'}) - return True - - def button_close(self, cr, uid, ids, context={}): - self.write(cr, uid, ids, {'state':'close', 'date_close':time.strftime('%Y-%m-%d')}) - return True - - def button_reset(self, cr, uid, ids, context=None): - self.write(cr, uid, ids, {'state': 'draft'}) - return True - - def button_picking_confirm(self, cr, uid, ids, context={}): - - self.write(cr, uid, ids, {'state':'confirm'}) - for id in ids: - pick_ids = self.pool.get('stock.picking').search(cr, uid, [('journal_id','=',id)]) - for pickid in pick_ids: - wf_service = netsvc.LocalService("workflow") - wf_service.trg_validate(uid, 'stock.picking', pickid, 'button_confirm', cr) - return True - - def copy(self, cr, uid, id, default=None, context=None): - """Overrides orm copy method - @param self: The object pointer - @param cr: the current row, from the database cursor, - @param uid: the current user’s ID for security checks, - @param ids: List of case’s IDs - @param context: A standard dictionary for contextual values - """ - if context is None: - context = {} - if default is None: - default = {} - default.update({'picking_stats_ids': []}) - return super(picking_journal, self).copy(cr, uid, id, default=default, context=context) - -picking_journal() - #============================================== # sale journal inherit #============================================== @@ -201,22 +47,20 @@ class res_partner(osv.osv): _inherit = 'res.partner' _columns = { 'property_invoice_type': fields.property( - 'sale_journal.invoice.type', - type = 'many2one', - relation = 'sale_journal.invoice.type', - string = "Invoicing Method", - method = True, - view_load = True, - group_name = "Accounting Properties", - help = "The type of journal used for sales and picking."), + 'sale_journal.invoice.type', + type = 'many2one', + relation = 'sale_journal.invoice.type', + string = "Invoicing Method", + method = True, + view_load = True, + group_name = "Accounting Properties", + help = "The type of journal used for sales and picking."), } res_partner() class picking(osv.osv): _inherit = "stock.picking" _columns = { - 'journal_id': fields.many2one('sale_journal.picking.journal', 'Picking Journal', domain=[('state','!=', 'close')],help="Picking Journal"), - 'sale_journal_id': fields.many2one('sale_journal.sale.journal', 'Sale Journal'), 'invoice_type_id': fields.many2one('sale_journal.invoice.type', 'Invoice Type', readonly=True) } picking() @@ -224,7 +68,6 @@ picking() class sale(osv.osv): _inherit = "sale.order" _columns = { - 'journal_id': fields.many2one('sale_journal.sale.journal', 'Journal', domain=[('state','not in', ('done', 'draft''cancel'))]), 'invoice_type_id': fields.many2one('sale_journal.invoice.type', 'Invoice Type') } def action_ship_create(self, cr, uid, ids, *args): @@ -232,18 +75,16 @@ class sale(osv.osv): for order in self.browse(cr, uid, ids, context={}): pids = [ x.id for x in order.picking_ids] self.pool.get('stock.picking').write(cr, uid, pids, { - 'invoice_type_id': order.invoice_type_id.id, - 'sale_journal_id': order.journal_id.id + 'invoice_type_id': order.invoice_type_id and order.invoice_type_id.id or False, }) return result def onchange_partner_id(self, cr, uid, ids, part): result = super(sale, self).onchange_partner_id(cr, uid, ids, part) if part: - itype = self.pool.get('res.partner').browse(cr, uid, part).property_invoice_type.id - result['value']['invoice_type_id'] = itype + itype = self.pool.get('res.partner').browse(cr, uid, part).property_invoice_type + if itype: + result['value']['invoice_type_id'] = itype.id return result sale() - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/sale_journal/sale_journal_data.xml b/addons/sale_journal/sale_journal_data.xml index 3639f945c83..9d305fe9912 100644 --- a/addons/sale_journal/sale_journal_data.xml +++ b/addons/sale_journal/sale_journal_data.xml @@ -2,11 +2,11 @@ - - property_invoice_type - - - + + property_invoice_type + + + diff --git a/addons/sale_journal/sale_journal_demo.xml b/addons/sale_journal/sale_journal_demo.xml index 30606e25145..061a5af8544 100644 --- a/addons/sale_journal/sale_journal_demo.xml +++ b/addons/sale_journal/sale_journal_demo.xml @@ -2,17 +2,17 @@ - - Daily invoicing - - - Monthly invoicing - grouped - + + Daily invoicing + + + Monthly invoicing + grouped + - - - + + + diff --git a/addons/sale_journal/sale_journal_view.xml b/addons/sale_journal/sale_journal_view.xml index 4485769cd62..ad160ec28ae 100644 --- a/addons/sale_journal/sale_journal_view.xml +++ b/addons/sale_journal/sale_journal_view.xml @@ -1,10 +1,5 @@ - - - @@ -14,13 +9,12 @@
- - - + + + - - - + +
@@ -42,113 +36,15 @@ + Invoice Types sale_journal.invoice.type form tree,form - Create specific invoicing types that can be maintained in your sales orders. An invoicing type can, for example, be a time lapse to be observed before billing your sales orders. Example: invoice daily, invoice every Wednesday, at end of month, etc. + Invoice types are used on partners, sales order and delivery orders. You can create journal to group your invoicing according to customer's needs: daily, each wednesday, monthly, etc. - - - - - - sale_journal.sale.journal.form - sale_journal.sale.journal - form - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - -