deisy пре 5 година
комит
f76968ef0a

+ 2 - 0
__init__.py

@@ -0,0 +1,2 @@
+# -*- coding : utf-8 -*-
+import models


+ 27 - 0
__openerp__.py

@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+{
+    'name': 'Cálculo de Costo de Importación',
+    'version': '8.0.0.1',
+    'category': '',
+    'summary': '',
+    'description' : '',
+    'author': 'Eiru Software',
+    'depends': [
+        'base',
+        'account',
+        'purchase',
+        'product',
+        'expense_menu',
+        'extra_data_dikasa',
+        ],
+    'qweb': [
+        'static/src/xml/*.xml',
+    ],
+    'data': [
+        'data/ir_sequence.xml',
+        'views/import_cost_calculation.xml',
+        'template.xml',
+        ],
+
+    'installable':True,
+}

+ 18 - 0
data/ir_sequence.xml

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<openerp>
+    <data>
+        <record id="import_cost_ir_seq_type" model="ir.sequence.type">
+            <field name="name">Import Cost</field>
+            <field name="code">import.cost</field>
+        </record>
+
+        <record id="import_cost_ir_sequence" model="ir.sequence">
+            <field name="name">Import Cost</field>
+            <field name="code">import.cost</field>
+            <field name="prefix">SCI</field>
+            <field name="padding">5</field>
+            <field name="company_id" eval="False"/>
+        </record>
+
+    </data>
+</openerp>

+ 2 - 0
models/__init__.py

@@ -0,0 +1,2 @@
+# -*- coding : utf-8 -*-
+import import_cost_calculation

BIN
models/__init__.pyc


+ 100 - 0
models/import_cost_calculation.py

@@ -0,0 +1,100 @@
+# -*- encoding: utf-8 -*-
+from openerp import models, fields, api, _
+from openerp.exceptions import Warning
+from pytz import timezone
+from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT, DEFAULT_SERVER_DATE_FORMAT
+from datetime import datetime,timedelta
+from openerp import http
+
+DATE_FORMAT = '%Y-%m-%d'
+
+class import_purchase_line(models.Model):
+    _name = 'import.purchase.line'
+
+    import_id = fields.Many2one('import.cost', 'Gastos de importación',ondelete='cascade')
+    purchase_id = fields.Many2one('account.invoice', 'Gastos de importación',required=True)
+    purchase_subtotal = fields.Float("Subtotal", related='purchase_id.amount_untaxed', store=True, readonly=True)
+    purchase_taxes = fields.Float("Impuestos", related='purchase_id.amount_tax', store=True, readonly=True)
+    purchase_total = fields.Float("Total", related='purchase_id.amount_total', store=True, readonly=True)
+
+class import_expense_line(models.Model):
+    _name = 'import.expense.line'
+
+    import_id = fields.Many2one('import.cost', 'Gastos de importación',ondelete='cascade')
+    expense_id = fields.Many2one('account.invoice', 'Gastos de importación', required=True)
+    expense_subtotal = fields.Float("Subtotal", related='expense_id.amount_untaxed', store=True, readonly=True)
+    expense_taxes = fields.Float("Impuestos", related='expense_id.amount_tax', store=True, readonly=True)
+    expense_total = fields.Float("Total", related='expense_id.amount_total', store=True, readonly=True)
+
+
+class import_cost(models.Model):
+    _name = 'import.cost'
+
+    name = fields.Char(string='Nombre', readonly=True)
+    date = fields.Datetime('Fecha', default=datetime.now(), required=True)
+    purchases = fields.One2many('import.purchase.line','import_id','Facturas de compra')
+    expenses = fields.One2many('import.expense.line','import_id','Facturas de gasto')
+    factor = fields.Float(string="Factor", readonly=True)
+    state = fields.Selection([
+        ('draft', 'Borrador'),
+        ('approved', 'Aprobado'),
+        ], 'Estado', readonly=True, select=True, default="draft")
+    created_by = fields.Many2one('res.users', 'Creado por', default=lambda self: self.env.user.id, readonly=True)
+    approved_by = fields.Many2one('res.users', 'Aprobado por')
+
+    @api.one
+    def _get_amount(self):
+        suma_purchase_subtotal = 0
+        suma_purchase_taxes = 0
+        suma_purchase_total = 0
+        suma_expense_subtotal = 0
+        suma_expense_taxes = 0
+        suma_expense_total = 0
+
+        invoice1 = self.env['import.purchase.line'].search([('import_id','=',self.id)])
+
+        for each in invoice1:
+            suma_purchase_subtotal = suma_purchase_subtotal + each.purchase_subtotal
+            suma_purchase_taxes = suma_purchase_taxes + each.purchase_taxes
+            suma_purchase_total = suma_purchase_total + each.purchase_total
+
+        invoice2 = self.env['import.expense.line'].search([('import_id','=',self.id)])
+
+        for item in invoice2:
+            suma_expense_subtotal = suma_expense_subtotal + item.expense_subtotal
+            suma_expense_taxes = suma_expense_taxes + item.expense_taxes
+            suma_expense_total = suma_expense_total + item.expense_total
+
+        self.purchases_subtotal = suma_purchase_subtotal
+        self.purchases_taxes = suma_purchase_taxes
+        self.purchases_total = suma_purchase_total
+        self.expenses_subtotal = suma_expense_subtotal
+        self.expenses_taxes = suma_expense_taxes
+        self.expenses_total = suma_expense_total
+
+    purchases_subtotal = fields.Float(string="Subtotal", compute="_get_amount")
+    purchases_taxes = fields.Float(string="Impuestos", compute="_get_amount")
+    purchases_total = fields.Float(string="Total", compute="_get_amount")
+    expenses_subtotal = fields.Float(string="Subtotal", compute="_get_amount")
+    expenses_taxes = fields.Float(string="Impuestos", compute="_get_amount")
+    expenses_total = fields.Float(string="Total", compute="_get_amount")
+
+    @api.model
+    def approve_import_cost(self, value):
+        approved_by = self.env.user.id
+        import_cost = self.env['import.cost'].search([('id','=',value['import_id'])])
+        import_cost.write({'state': 'approved','factor':value['factor'],'approved_by':approved_by})
+
+        for item in value['purchases']:
+            product = self.env['product.product'].search([('id','=',item['product_id'][0])])
+            template = self.env['product.template'].search([('id','=',product.product_tmpl_id.id)])
+
+            if(template.price_change == 'import'):
+                template.write({'standard_price': item['import_cost']})
+        return True
+
+    @api.model
+    def create(self,vals):
+        ctx = dict(self._context or {})
+        vals['name'] = self.env['ir.sequence'].get('import.cost') or '/'
+        return super(import_cost, self.with_context(ctx)).create(vals)

BIN
models/import_cost_calculation.pyc


BIN
static/description/icon.png


+ 17 - 0
static/src/css/style.css

@@ -0,0 +1,17 @@
+.import_table{
+  font-size: 14px;
+  margin-top: 10px;
+}
+
+.import_table,tbody,tr,td{
+  padding: 5px;
+}
+
+.import_table,tbody,tr,th{
+  padding: 5px;
+}
+
+.final_amount{
+  font-size: 16px;
+  font-weight: bold;
+}

+ 220 - 0
static/src/js/import_cost_calculation.js

@@ -0,0 +1,220 @@
+openerp.import_cost_calculation = function(instance) {
+
+  instance.widgetInstance = null;
+  instance.parentInstance = {};
+  var QWeb = openerp.web.qweb;
+
+  instance.ImportCostWidget = instance.Widget.extend({
+    template: "import_cost_calculation.CalculateButton",
+
+    init:function(parent){
+      this._super(parent);
+    },
+
+    updateId : function(record){
+      var self = this;
+      self.record=record;
+    },
+
+    start: function () {
+      var self = this;
+      this.$el.click(function (e) {
+        var validation = self.checkValidation();
+        if (validation == true){
+          self.fecthInitial();
+        }else{
+          alert("Necesita cargar al menos una factura de compra y otra de gasto para poder realizar el cálculo!");
+        }
+      });
+    },
+
+    checkValidation: function(){
+      var self = this;
+      if(!self.record.id){
+        return alert("Antes de realizar el cálculo, guarde el documento!");
+      }
+      if(self.record.expenses.length == 0 || self.record.purchases.length == 0){
+        return false;
+      }else {
+        return true
+      }
+    },
+
+    fecthInitial: function(){
+      var self = this;
+
+      self.fetchImportPurchaseLine(self.record.id).then(function(ImportPurchaseLine) {
+        return ImportPurchaseLine;
+      }).then(function(ImportPurchaseLine) {
+        self.ImportPurchaseLine = ImportPurchaseLine;
+        return self.fetchImportExpenseLine(self.record.id)
+      }).then(function(ImportExpenseLine) {
+        self.ImportExpenseLine = ImportExpenseLine;
+        return self.fetchAccountInvoiceLine();
+      }).then(function(AccountInvoiceLine){
+        self.AccountInvoiceLine = AccountInvoiceLine;
+        return self.renderModal(self.record);
+      });
+    },
+
+    fetchImportPurchaseLine: function(import_id) {
+      var ImportPurchaseLine = new openerp.web.Model('import.purchase.line');
+      var fields = ['id', 'import_id', 'purchase_id', 'purchase_subtotal','purchase_taxes','purchase_total'];
+      var domain = [['import_id', '=', parseInt(import_id)]];
+      return ImportPurchaseLine.query(fields).filter(domain).all();
+    },
+
+    fetchImportExpenseLine: function(import_id) {
+      var ImportExpenseLine = new openerp.web.Model('import.expense.line');
+      var fields = ['id', 'import_id', 'expense_id', 'expense_subtotal','expense_taxes','expense_total'];
+      var domain = [['import_id', '=', parseInt(import_id)]];
+      return ImportExpenseLine.query(fields).filter(domain).all();
+    },
+
+
+    fetchAccountInvoiceLine: function() {
+      var AccountInvoiceLine = new openerp.web.Model('account.invoice.line');
+      var fields = ['id', 'name', 'invoice_id', 'product_id', 'price_unit','quantity', 'price_subtotal'];
+      return AccountInvoiceLine.query(fields).filter().all();
+    },
+
+    getAccountInvoiceLine: function (id) {
+      var self = this;
+      return _.filter(self.AccountInvoiceLine,function (item) {
+        return item.invoice_id[0] == id;
+      })
+    },
+
+    renderModal: function (record){
+      var self = this;
+      var purchases = [];
+      var expenses = [];
+      var params = [];
+      var expenses_subtotal = 0;
+      var expenses_taxes = 0;
+      var expenses_total = 0;
+      var purchases_subtotal = 0;
+      var purchases_taxes = 0;
+      var purchases_total = 0;
+      var total = 0;
+      var factor = 0;
+      var purchase_lines = self.ImportPurchaseLine;
+      var expenses_lines = self.ImportExpenseLine;
+
+      _.each(expenses_lines, function(item){
+        expenses_subtotal = expenses_subtotal + item.expense_subtotal;
+        expenses_taxes = expenses_taxes + item.expense_taxes;
+        expenses_total = expenses_total + item.expense_total;
+        var invoice_line = self.getAccountInvoiceLine(item.expense_id[0]);
+        _.each(invoice_line, function(product) {
+          product['price_unit'] = accounting.formatMoney(product.price_unit, '',0, '.', ',');
+          product['price_subtotal'] = accounting.formatMoney(product.price_subtotal, '',0, '.', ',');
+          expenses.push(product);
+        });
+     });
+
+      _.each(purchase_lines, function(item){
+        purchases_subtotal = purchases_subtotal + item.purchase_subtotal;
+        purchases_taxes = purchases_taxes + item.purchase_taxes;
+        purchases_total = purchases_total + item.purchase_total;
+     });
+
+     total = purchases_total + expenses_total;
+     factor = total/purchases_total;
+     factor = parseFloat(factor.toFixed(6));
+
+     _.each(purchase_lines, function(item){
+       var invoice_line = self.getAccountInvoiceLine(item.purchase_id[0]);
+       _.each(invoice_line, function(product) {
+         product['import_cost'] = parseFloat((product.price_unit * factor).toFixed(0));
+         product['import_cost_formated'] = accounting.formatMoney((product.price_unit * factor), '',0, '.', ',');
+         product['price_unit'] = accounting.formatMoney(product.price_unit, '',0, '.', ',');
+         product['price_subtotal'] = accounting.formatMoney(product.price_subtotal, '',0, '.', ',');
+         purchases.push(product);
+       });
+    });
+
+   params={
+     title:'Resumen de cálculo de importación',
+     name: record.name,
+     date: record.date,
+     state: record.state,
+     purchases : purchases,
+     purchase_subtotal: accounting.formatMoney(purchases_subtotal, '',0, '.', ','),
+     purchase_taxes: accounting.formatMoney(purchases_taxes, '',0, '.', ','),
+     purchase_total:accounting.formatMoney(purchases_total, '',0, '.', ','),
+     expenses: expenses,
+     expenses_subtotal: accounting.formatMoney(expenses_subtotal, '',0, '.', ','),
+     expenses_taxes: accounting.formatMoney(expenses_taxes, '',0, '.', ','),
+     expenses_total: accounting.formatMoney(expenses_total, '',0, '.', ','),
+     factor:factor,
+   }
+
+    $("body").append(QWeb.render("import_cost_modal", params));
+    $('#myModal').modal('show');
+
+    $('#myModal').on('shown.bs.modal', function (e) {
+      if(record.state === 'approved'){
+   $('#approveImportButton').button("disable");
+}
+      $('#approveImportButton').click(function() {
+        var saveParams= {
+          import_id: record.id,
+          purchases: purchases,
+          factor: factor,
+        }
+
+        self.approveImport(saveParams).then(function(results) {
+          return results;
+        }).then(function(results) {
+          self.reloadPage();
+          self.closeModal();
+        });
+      });
+    });
+
+    $('#myModal').on('hidden.bs.modal', function(e) {
+      self.closeModal(e);
+    });
+ },
+
+ approveImport:function(saveParams){
+   var self = this;
+   var saveImport = new openerp.web.Model('import.cost');
+   return saveImport.call('approve_import_cost',[saveParams], {
+     context: new openerp.web.CompoundContext()
+   });
+ },
+
+ closeModal: function(){
+   $('#myModal').remove();
+   $('.modal-backdrop').remove();
+ },
+
+ reloadPage: function() {
+   instance.parentInstance.reload();
+ },
+  });
+
+   if (instance.web && instance.web.FormView) {
+    instance.web.FormView.include({
+      load_record: function (record) {
+        this._super.apply(this, arguments);
+        if (this.model !== 'import.cost') return;
+        instance.parentInstance = this;
+
+        if (instance.widgetInstance) {
+          instance.widgetInstance.updateId(record);
+          return;
+        }
+
+        instance.widgetInstance = new instance.ImportCostWidget(this);
+
+        var elemento =  this.$el.find('.import_cost_button');
+
+        instance.widgetInstance.appendTo(elemento[0]);
+        instance.widgetInstance.updateId(record);
+      }
+    });
+   }
+};

+ 119 - 0
static/src/xml/import_cost_wizard.xml

@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<template xml:space="preserve">
+  <t t-name="import_cost_calculation.CalculateButton">
+    <button type="button" class="oe_form_button" style="font-size: 14px;background: #0288d1 !important;color: white !important;">Calcular Coste</button>
+  </t>
+
+  <div t-name="import_cost_modal" class="modal fade" id="myModal" role="dialog">
+    <div class="modal-dialog">
+      <div class="modal-content">
+        <div class="modal-header">
+          <button type="button" class="close" data-dismiss="modal">
+            x
+          </button>
+          <h4 class="modal-title"><t t-esc="title"/></h4>
+        </div>
+
+        <div class="modal-body">
+          <h2>
+            <span>Importación</span>
+            <t t-esc="name" class="oe_inline"/>
+          </h2>
+          <div style="font-size:16px;"> Fecha: <t t-esc="date"/></div>
+          <h4 style="text-align: center;text-shadow: 2px 0 lightgrey;font-weight: bold;">Detalles de las compras</h4>
+          <table class="table-bordered table-striped import_table">
+            <thead >
+              <tr class="oe_list_header_columns">
+                <th style="text-align:left;">Producto</th>
+                <th style="text-align:center;">Cantidad</th>
+                <th style="text-align:right;">Precio Unitario</th>
+                <th style="text-align:right;">Subtotal</th>
+                <th style="text-align:center;">Factor</th>
+                <th style="text-align:right;">Costo Importación</th>
+              </tr>
+            </thead>
+            <tbody>
+              <tr t-foreach="purchases" t-as="line">
+                <td style="text-align:left;"><t t-esc="line.name" /></td>
+                <td style="text-align:center;"><t t-esc="line.quantity"/></td>
+                <td style="text-align:right;"><t t-esc="line.price_unit"/></td>
+                <td style="text-align:right;"><t t-esc="line.price_subtotal" /></td>
+                <td style="text-align:center;"><t t-esc="factor"/></td>
+                <td style="text-align:right;"><t t-esc="line.import_cost_formated"/></td>
+              </tr>
+            </tbody>
+            <tfoot>
+              <tr>
+                <th></th>
+                <th></th>
+                <th style="text-align:right;">Subtotal:</th>
+                <th style="text-align:right;"><t t-esc="purchase_subtotal"/></th>
+              </tr>
+              <tr>
+                <th></th>
+                <th></th>
+                <th style="text-align:right;">Impuestos:</th>
+                <th style="text-align:right;"><t t-esc="purchase_taxes"/></th>
+              </tr>
+              <tr>
+                <th></th>
+                <th></th>
+                <th style="text-align:right;">Total:</th>
+                <th style="text-align:right;"><t t-esc="purchase_total"/></th>
+              </tr>
+            </tfoot>
+          </table>
+
+          <h4 style="text-align: center;text-shadow: 2px 0 lightgrey;font-weight: bold;">Detalles de los gastos</h4>
+
+          <table class="table-bordered table-striped import_table">
+            <thead >
+              <tr class="oe_list_header_columns">
+                <th style="text-align:left;">Gastos</th>
+                <th style="text-align:right;">Cantidad</th>
+                <th style="text-align:right;">Precio Unitario</th>
+                <th style="text-align:right;">Subtotal</th>
+              </tr>
+            </thead>
+            <tbody>
+              <tr t-foreach="expenses" t-as="line">
+                <td style="text-align:left;"><t t-esc="line.name" /></td>
+                <td style="text-align:center;"><t t-esc="line.quantity"/></td>
+                <td style="text-align:right;"><t t-esc="line.price_unit" /></td>
+                <td style="text-align:right;"><t t-esc="line.price_subtotal" /></td>
+              </tr>
+            </tbody>
+            <tfoot>
+              <tr>
+                <th></th>
+                <th></th>
+                <th style="text-align:right;">Subtotal:</th>
+                <th style="text-align:right;"><t t-esc="expenses_subtotal"/></th>
+              </tr>
+              <tr>
+                <th></th>
+                <th></th>
+                <th style="text-align:right;">Impuestos:</th>
+                <th style="text-align:right;"><t t-esc="expenses_taxes"/></th>
+              </tr>
+              <tr>
+                <th></th>
+                <th></th>
+                <th style="text-align:right;">Total:</th>
+                <th style="text-align:right;"><t t-esc="expenses_total"/></th>
+              </tr>
+            </tfoot>
+          </table>
+
+        </div>
+
+        <div class="modal-footer">
+          <t t-if="state=='draft'">
+            <button type="button" class="btn btn-success" id="approveImportButton">Aprobar</button>
+          </t>
+          <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>

+ 10 - 0
template.xml

@@ -0,0 +1,10 @@
+<openerp>
+    <data>
+        <template id="import_cost_calculation.eiru_assets" name="import_cost_calculation_eiru_assets" inherit_id="eiru_assets.assets">
+            <xpath expr="." position="inside">
+                <link rel="stylesheet" href="/import_cost_calculation/static/src/css/style.css"/>
+                <script type="text/javascript" src="/import_cost_calculation/static/src/js/import_cost_calculation.js"/>
+            </xpath>
+        </template>
+    </data>
+</openerp>

+ 97 - 0
views/import_cost_calculation.xml

@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+  <data>
+    <record model="ir.ui.view" id="import_cost_form">
+      <field name="name">import_cost_form</field>
+      <field name="model">import.cost</field>
+      <field name="arch" type="xml">
+        <form string="Import">
+          <header>
+            <div class="import_cost_button" style="position:absolute"></div>
+            <field name="state" widget="statusbar" statusbar_visible="draft,approved" statusbar_colors='{"draft":"red","approved":"blue"}'/>
+          </header>
+
+          <sheet>
+            <h1>
+              <label string="Importación "/>
+              <field name="name" class="oe_inline" readonly="1"/>
+            </h1>
+            <group>
+              <field name="date"/>
+              <field name="created_by" readonly="1"/>
+              <field name="approved_by" readonly="1"/>
+            </group>
+
+
+            <group string="Facturas de compras"></group>
+            <group>
+              <field name="purchases"  nolabel="1" attrs="{'readonly': [('state','=', 'approved')]}">
+                <tree string="Detalles" editable="bottom" >
+                  <field name="purchase_id" domain="[('type', '=', 'in_invoice')]"/>
+                  <field name="purchase_subtotal"/>
+                  <field name="purchase_taxes"/>
+                  <field name="purchase_total"/>
+                </tree>
+              </field>
+            </group>
+            <group class="oe_subtotal_footer" colspan="2" style="float:right; margin-right:10px !important">
+              <field name="purchases_subtotal" widget='monetary'/>
+              <field name="purchases_taxes" widget='monetary'/>
+              <div class="oe_subtotal_footer_separator oe_inline">
+                <label for="purchases_total"/>
+              </div>
+              <field name="purchases_total" nolabel="1" class="oe_subtotal_footer_separator" widget='monetary'/>
+            </group>
+
+            <group string="Facturas de gastos"></group>
+            <group>
+              <field name="expenses" nolabel="1" attrs="{'readonly': [('state','=', 'approved')]}">
+                <tree string="Detalles" editable="bottom" >
+                  <field name="expense_id" domain="[('type', '=', 'in_invoice')]"/>
+                  <field name="expense_subtotal"/>
+                  <field name="expense_taxes"/>
+                  <field name="expense_total"/>
+                </tree>
+              </field>
+            </group>
+            <group class="oe_subtotal_footer" colspan="2" style="float:right; margin-right:10px !important">
+              <field name="expenses_subtotal" widget='monetary' />
+              <field name="expenses_taxes" widget='monetary' />
+              <div class="oe_subtotal_footer_separator oe_inline">
+                <label for="expenses_total"/>
+              </div>
+              <field name="expenses_total" nolabel="1" class="oe_subtotal_footer_separator" widget='monetary'/>
+            </group>
+          </sheet>
+        </form>
+      </field>
+    </record>
+
+    <record model="ir.ui.view" id="import_cost_tree">
+        <field name="name">import_cost_tree</field>
+        <field name="model">import.cost</field>
+        <field name="arch" type="xml">
+            <tree string="Import Cost Tree" colors="grey:state=='draft';blue:state=='approved'">
+                <field name="name" />
+                <field name="date" />
+                <field name="purchases_total" string="Total compra"/>
+                <field name="expenses_total" string="Total gasto"/>
+                <field name="factor" />
+                <field name="state" />
+            </tree>
+        </field>
+    </record>
+
+    <record model="ir.actions.act_window" id="action_import_cost">
+      <field name="name">Gastos de Importación</field>
+      <field name="type">ir.actions.act_window</field>
+      <field name="res_model">import.cost</field>
+      <field name="view_type">form</field>
+      <field name="view_mode">tree,form</field>
+    </record>
+
+    <menuitem name="Importación" id="import_main_menu" parent="expense_menu.expense_main_menu" sequence="20" />
+    <menuitem name="Gastos de Importación" id="import_submenu_1" parent="import_main_menu" action="action_import_cost" />
+
+  </data>
+</openerp>