[POS-commit] r7083 - in stoqlib/trunk: data/glade stoqlib/domain
stoqlib/domain/test stoqlib/gui/dialogs stoqlib/gui/search
Johan Dahlin
jdahlin at async.com.br
Fri Aug 3 14:08:40 BRT 2007
Author: jdahlin
Date: Fri Aug 3 14:08:40 2007
New Revision: 7083
Added:
stoqlib/trunk/data/glade/SupplierDetailsDialog.glade
stoqlib/trunk/stoqlib/gui/dialogs/supplierdetails.py
Modified:
stoqlib/trunk/stoqlib/domain/person.py
stoqlib/trunk/stoqlib/domain/purchase.py
stoqlib/trunk/stoqlib/domain/test/test_person.py
stoqlib/trunk/stoqlib/gui/search/personsearch.py
Log:
#3507: Add a supplier details dialog
Added: stoqlib/trunk/data/glade/SupplierDetailsDialog.glade
==============================================================================
--- (empty file)
+++ stoqlib/trunk/data/glade/SupplierDetailsDialog.glade Fri Aug 3 14:08:40 2007
@@ -0,0 +1,181 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://gazpacho.sicem.biz/gazpacho-0.1.dtd">
+<glade-interface domain="stoqlib">
+ <widget class="GtkWindow" id="SupplierDetailsDialog">
+ <property name="border_width">6</property>
+ <property name="default_height">250</property>
+ <property name="default_width">440</property>
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkTable" id="table1">
+ <property name="column_spacing">6</property>
+ <property name="n_columns">4</property>
+ <property name="n_rows">2</property>
+ <property name="row_spacing">6</property>
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkLabel" id="label1">
+ <property name="label" context="yes" translatable="yes">Supplier:</property>
+ <property name="visible">True</property>
+ <property name="xalign">1.0</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label2">
+ <property name="label" context="yes" translatable="yes">Last Purchase Date:</property>
+ <property name="visible">True</property>
+ <property name="xalign">1.0</property>
+ </widget>
+ <packing>
+ <property name="bottom_attach">2</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="ProxyLabel" id="supplier">
+ <property name="data_type">unicode</property>
+ <property name="model_attribute">name</property>
+ <property name="visible">True</property>
+ <property name="xalign">0.0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="ProxyLabel" id="last_purchase_date">
+ <property name="data_type">date</property>
+ <property name="model_attribute">last_purchase_date</property>
+ <property name="visible">True</property>
+ <property name="xalign">0.0</property>
+ </widget>
+ <packing>
+ <property name="bottom_attach">2</property>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label3">
+ <property name="label" context="yes" translatable="yes">Status:</property>
+ <property name="visible">True</property>
+ <property name="xalign">1.0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="ProxyLabel" id="status">
+ <property name="data_type">str</property>
+ <property name="model_attribute">status_string</property>
+ <property name="visible">True</property>
+ <property name="xalign">0.0</property>
+ </widget>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="right_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox1">
+ <property name="visible">True</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkButton" id="further_details_button">
+ <property name="is_focus">True</property>
+ <property name="label" context="yes" translatable="yes">Further Details</property>
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="bottom_attach">2</property>
+ <property name="left_attach">3</property>
+ <property name="right_attach">4</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkNotebook" id="notebook1">
+ <property name="is_focus">True</property>
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkVBox" id="purchases_vbox">
+ <property name="visible">True</property>
+ <child>
+ <widget class="ObjectList" id="purchases_list">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+ <child>
+ <placeholder/>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="tab_label" context="yes" translatable="yes">Purchases</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="ObjectList" id="product_list">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_label" context="yes" translatable="yes">Products</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="ObjectList" id="payments_list">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="position">2</property>
+ <property name="tab_label" context="yes" translatable="yes">Payments</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+</glade-interface>
Modified: stoqlib/trunk/stoqlib/domain/person.py
==============================================================================
--- stoqlib/trunk/stoqlib/domain/person.py (original)
+++ stoqlib/trunk/stoqlib/domain/person.py Fri Aug 3 14:08:40 2007
@@ -587,6 +587,19 @@
query = cls.q.status == cls.STATUS_ACTIVE
return cls.select(query, connection=conn)
+ def get_supplier_purchases(self):
+ """
+ @returns: a list of PurchaseOrderViews representing all purchases
+ done from this supplier.
+ """
+ from stoqlib.domain.purchase import PurchaseOrderView
+ return PurchaseOrderView.select(
+ # FIXME: should of course use id, fix this
+ # when migrating PurchaseOrderView from views.sql
+ PurchaseOrderView.q.supplier_name == self.person.name,
+ connection=self.get_connection(),
+ orderBy=PurchaseOrderView.q.open_date)
+
Person.registerFacet(PersonAdaptToSupplier, ISupplier)
class PersonAdaptToEmployee(PersonAdapter):
Modified: stoqlib/trunk/stoqlib/domain/purchase.py
==============================================================================
--- stoqlib/trunk/stoqlib/domain/purchase.py (original)
+++ stoqlib/trunk/stoqlib/domain/purchase.py Fri Aug 3 14:08:40 2007
@@ -571,3 +571,6 @@
@property
def purchase(self):
return PurchaseOrder.get(self.id)
+
+ def get_status_name(self):
+ return self.purchase.translate_status(self.status)
Modified: stoqlib/trunk/stoqlib/domain/test/test_person.py
==============================================================================
--- stoqlib/trunk/stoqlib/domain/test/test_person.py (original)
+++ stoqlib/trunk/stoqlib/domain/test/test_person.py Fri Aug 3 14:08:40 2007
@@ -55,6 +55,7 @@
PersonAdaptToTransporter)
from stoqlib.domain.product import Product
from stoqlib.domain.profile import UserProfile
+from stoqlib.domain.purchase import PurchaseOrder
from stoqlib.domain.sale import Sale
from stoqlib.domain.test.domaintest import DomainTest
from stoqlib.lib.translation import stoqlib_gettext
@@ -64,14 +65,15 @@
class TestEmployeeRoleHistory(DomainTest):
- def testCreate(self):
- EmployeeRole(connection=self.trans, name='ajudante')
+ def testCreate(self):
+ EmployeeRole(connection=self.trans, name='ajudante')
+
+ def testHasRole(self):
+ role = EmployeeRole(connection=self.trans, name='role')
+ self.failIf(role.has_other_role('Role'))
+ role = EmployeeRole(connection=self.trans, name='Role')
+ self.failUnless(role.has_other_role('role'))
- def testHasRole(self):
- role = EmployeeRole(connection=self.trans, name='role')
- self.failIf(role.has_other_role('Role'))
- role = EmployeeRole(connection=self.trans, name='Role')
- self.failUnless(role.has_other_role('role'))
class TestEmployeeRole(DomainTest):
def test_get_description(self):
@@ -79,6 +81,7 @@
role.name = 'manager'
self.assertEquals(role.name, role.get_description())
+
class TestPerson(DomainTest):
def testGetMainAddress(self):
@@ -365,9 +368,9 @@
facet = PersonAdaptToSupplier
def testGetActiveSuppliers(self):
- for supplier in PersonAdaptToSupplier.get_active_suppliers(self.trans):
- self.assertEquals(supplier.status,
- PersonAdaptToSupplier.STATUS_ACTIVE)
+ for supplier in PersonAdaptToSupplier.get_active_suppliers(self.trans):
+ self.assertEquals(supplier.status,
+ PersonAdaptToSupplier.STATUS_ACTIVE)
def testGetAllSuppliers(self):
query = AND(Person.q.name == "test",
@@ -382,6 +385,23 @@
suppliers = Person.select(query, connection=self.trans)
self.assertEqual(suppliers.count(), 1)
+ def testGetSupplierPurchase(self):
+ supplier = self.create_supplier()
+
+ self.failIf(supplier.get_supplier_purchases())
+
+ order = self.create_receiving_order()
+ order.purchase.supplier = supplier
+ order_item = self.create_receiving_order_item(order)
+ order.purchase.status = PurchaseOrder.ORDER_PENDING
+ order.purchase.confirm()
+ order.confirm()
+ order.set_valid()
+ order.purchase.set_valid()
+
+ self.failUnless(supplier.get_supplier_purchases())
+
+
class TestEmployee(_PersonFacetTest, DomainTest):
facet = PersonAdaptToEmployee
Added: stoqlib/trunk/stoqlib/gui/dialogs/supplierdetails.py
==============================================================================
--- (empty file)
+++ stoqlib/trunk/stoqlib/gui/dialogs/supplierdetails.py Fri Aug 3 14:08:40 2007
@@ -0,0 +1,176 @@
+# -*- coding: utf-8 -*-
+# vi:si:et:sw=4:sts=4:ts=4
+
+##
+## Copyright (C) 2006-2007 Async Open Source <http://www.async.com.br>
+## All rights reserved
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU Lesser General Public License as published by
+## the Free Software Foundation; either version 2 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 Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., or visit: http://www.gnu.org/.
+##
+## Author(s): Lincoln Molica <lincolnn at gmail.com>
+## Ariqueli Tejada Fonseca <ariqtf at yahoo.com.br>
+## Evandro Vale Miquelito <evandro at async.com.br>
+## Johan Dahlin <jdahlin at async.com.br>
+##
+##
+""" Classes for supplier details """
+
+import datetime
+
+import gtk
+from kiwi.python import Settable
+from kiwi.ui.objectlist import Column, ColoredColumn
+from kiwi.datatypes import currency
+from kiwi.ui.widgets.list import SummaryLabel
+
+from stoqlib.domain.interfaces import ISupplier, IPaymentGroup
+from stoqlib.domain.purchase import PurchaseOrder
+from stoqlib.gui.editors.baseeditor import BaseEditor
+from stoqlib.gui.editors.personeditor import SupplierEditor
+from stoqlib.gui.wizards.personwizard import run_person_role_dialog
+from stoqlib.lib.translation import stoqlib_gettext
+from stoqlib.lib.defaults import payment_value_colorize
+
+
+_ = stoqlib_gettext
+
+class SupplierDetailsDialog(BaseEditor):
+ """This dialog shows some important details about suppliers like:
+ - history of purchases
+ - all products tied with purchases
+ - all payments already created
+ """
+ title = _(u"Supplier Details")
+ hide_footer = True
+ size = (780, 400)
+ model_iface = ISupplier
+ gladefile = "SupplierDetailsDialog"
+ proxy_widgets = ('supplier',
+ 'last_purchase_date',
+ 'status')
+
+ def __init__(self, conn, model):
+ BaseEditor.__init__(self, conn, model)
+ self._setup_widgets()
+
+ def _build_data(self, purchases):
+ self.payments = []
+ product_dict = {}
+ for purchase_view in purchases:
+ purchase = PurchaseOrder.get(purchase_view.id, connection=self.conn)
+ group = IPaymentGroup(purchase)
+ self.payments.extend(group.get_items())
+ for purchase_item in purchase.get_items():
+ qty = purchase_item.quantity
+ cost = purchase_item.cost
+ total_value = cost * qty
+ unit = purchase_item.sellable.get_unit_description()
+ qty_str = '%s %s' % (qty, unit)
+ product_codes = [item.code for item in product_dict.values()]
+ sellable = purchase_item.sellable
+ if not sellable.id in product_codes:
+ desc = sellable.base_sellable_info.description
+ obj = Settable(code=sellable.id, description=desc,
+ _total_qty=qty, total_value=total_value,
+ qty_str=qty_str, unit=unit, cost=cost)
+ product_dict[sellable] = obj
+ else:
+ product_dict[sellable]._total_qty += qty
+ table = product_dict[sellable]
+ table.qty_str = '%s %s' % (table._total_qty, table.unit)
+ table.total_value = table._total_qty * table.cost
+ self.products = product_dict.values()
+
+ def _setup_widgets(self):
+ self.purchases_list.set_columns(self._get_purchase_columns())
+ self.product_list.set_columns(self._get_product_columns())
+ self.payments_list.set_columns(self._get_payments_columns())
+
+ purchases = self.model.get_supplier_purchases()
+ self.purchases_list.add_list(purchases)
+
+ self._build_data(purchases)
+ self.product_list.add_list(self.products)
+ self.payments_list.add_list(self.payments)
+
+ value_format = '<b>%s</b>'
+ total_label = "<b>%s</b>" % _("Total:")
+ purchases_summary_label = SummaryLabel(klist=self.purchases_list,
+ column='total',
+ label=total_label,
+ value_format=value_format)
+
+ purchases_summary_label.show()
+ self.purchases_vbox.pack_start(purchases_summary_label, False)
+
+ def _get_purchase_columns(self):
+ return [Column("id", title=_("#"),
+ data_type=int, justify=gtk.JUSTIFY_RIGHT,
+ format='%04d', width=90, sorted=True),
+ Column("open_date", title=_("Date"), data_type=datetime.date,
+ justify=gtk.JUSTIFY_RIGHT, width=80),
+ Column("status_name", title=_("Status"), width=80,
+ data_type=str),
+ Column("total", title=_("Total"), justify=gtk.JUSTIFY_RIGHT,
+ data_type=currency, width=100)]
+
+ def _get_product_columns(self):
+ return [Column("code", title=_("Code"), data_type=int,
+ format='%04d', justify=gtk.JUSTIFY_RIGHT,
+ width=90, sorted=True),
+ Column("description", title=_("Description"), data_type=str,
+ expand=True, searchable=True),
+ Column("qty_str", title=_("Total Quantity"),
+ data_type=str, width=120, justify=gtk.JUSTIFY_RIGHT),
+ Column("total_value", title=_("Total Value"), width=80,
+ data_type=currency, justify=gtk.JUSTIFY_RIGHT,)]
+
+ def _get_payments_columns(self):
+ return [Column("id", title=_("#"),
+ data_type=int, justify=gtk.JUSTIFY_RIGHT,
+ format='%04d', width=50),
+ Column("method.description", title=_("Type"),
+ data_type=str, width=90),
+ Column("description", title=_("Description"),
+ data_type=str, searchable=True, width=190,
+ expand=True),
+ Column("due_date", title=_("Due Date"), width=110,
+ data_type=datetime.date, sorted=True),
+ Column("status_str", title=_("Status"), width=80,
+ data_type=str),
+ ColoredColumn("base_value", title=_("Value"),
+ justify=gtk.JUSTIFY_RIGHT, data_type=currency,
+ color='red', width=100,
+ data_func=payment_value_colorize),
+ Column("days_late", title=_("Days Late"), width=110,
+ format_func=(lambda days_late: days_late and
+ str(days_late) or u""),
+ justify=gtk.JUSTIFY_RIGHT, data_type=str)]
+
+ #
+ # BaseEditor Hooks
+ #
+
+ def setup_proxies(self):
+ self.add_proxy(self.model, self.proxy_widgets)
+
+ #
+ # Callbacks
+ #
+
+ def on_further_details_button__clicked(self, *args):
+ run_person_role_dialog(SupplierEditor, self, self.conn,
+ self.model, visual_mode=True)
+
Modified: stoqlib/trunk/stoqlib/gui/search/personsearch.py
==============================================================================
--- stoqlib/trunk/stoqlib/gui/search/personsearch.py (original)
+++ stoqlib/trunk/stoqlib/gui/search/personsearch.py Fri Aug 3 14:08:40 2007
@@ -42,6 +42,7 @@
from stoqlib.gui.base.search import SearchEditor
from stoqlib.gui.base.dialogs import run_dialog
from stoqlib.gui.dialogs.clientdetails import ClientDetailsDialog
+from stoqlib.gui.dialogs.supplierdetails import SupplierDetailsDialog
from stoqlib.domain.person import (EmployeeRole,
PersonAdaptToBranch, BranchView,
PersonAdaptToClient, ClientView,
@@ -133,6 +134,15 @@
width=180),
Column('cnpj', _('CNPJ'), str, width=140)]
+ def on_details_button_clicked(self, *args):
+ selected = self.results.get_selected()
+ run_dialog(SupplierDetailsDialog, self, self.conn, selected.supplier)
+
+ def update_widgets(self, *args):
+ supplier_view = self.results.get_selected()
+ self.set_details_button_sensitive(supplier_view is not None)
+ self.set_edit_button_sensitive(supplier_view is not None)
+
def get_editor_model(self, supplier_view):
return supplier_view.supplier
More information about the POS-commit
mailing list