source: rattail/rattail/db/model/batch/purchase.py @ 180c931

Last change on this file since 180c931 was 180c931, checked in by Lance Edgar <lance@…>, 3 years ago

Switch license to GPL v3 (no longer Affero)

refs #2

  • Property mode set to 100644
File size: 5.8 KB
Line 
1# -*- coding: utf-8 -*-
2################################################################################
3#
4#  Rattail -- Retail Software Framework
5#  Copyright © 2010-2017 Lance Edgar
6#
7#  This file is part of Rattail.
8#
9#  Rattail is free software: you can redistribute it and/or modify it under the
10#  terms of the GNU General Public License as published by the Free Software
11#  Foundation, either version 3 of the License, or (at your option) any later
12#  version.
13#
14#  Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
15#  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16#  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
17#  details.
18#
19#  You should have received a copy of the GNU General Public License along with
20#  Rattail.  If not, see <http://www.gnu.org/licenses/>.
21#
22################################################################################
23"""
24Models for purchase order batches
25"""
26
27from __future__ import unicode_literals, absolute_import
28
29import sqlalchemy as sa
30from sqlalchemy import orm
31from sqlalchemy.ext.declarative import declared_attr
32
33from rattail.db.model import (Base, uuid_column, BatchMixin, BatchRowMixin,
34                              PurchaseBase, PurchaseItemBase, PurchaseCreditBase,
35                              Purchase, PurchaseItem)
36from rattail.util import pretty_quantity
37
38
39class PurchaseBatch(BatchMixin, PurchaseBase, Base):
40    """
41    Hopefully generic batch used for entering new purchases into the system, etc.?
42    """
43    batch_key = 'purchase'
44    __tablename__ = 'purchase_batch'
45    __batchrow_class__ = 'PurchaseBatchRow'
46    model_title = "Purchasing Batch"
47    model_title_plural = "Purchasing Batches"
48
49    @declared_attr
50    def __table_args__(cls):
51        return cls.__batch_table_args__() + cls.__purchase_table_args__() + (
52            sa.ForeignKeyConstraint(['purchase_uuid'], ['purchase.uuid'], name='purchase_batch_fk_purchase'),
53        )
54
55    purchase_uuid = sa.Column(sa.String(length=32), nullable=True)
56
57    purchase = orm.relationship(
58        Purchase,
59        doc="""
60        Reference to the purchase with which the batch is associated.  May be
61        null, e.g. in the case of a "new purchase" batch.
62        """,
63        backref=orm.backref(
64            'batches',
65            order_by='PurchaseBatch.id',
66            doc="""
67            List of batches associated with the purchase.
68            """))
69
70    mode = sa.Column(sa.Integer(), nullable=False, doc="""
71    Numeric "mode" for the purchase batch, to indicate new/receiving etc.
72    """)
73
74    complete = sa.Column(sa.Boolean(), nullable=True, doc="""
75    Flag to indicate whether the batch is complete.  This may be used to assist
76    with workflow when entering/executing new purchases.
77    """)
78
79
80class PurchaseBatchRow(BatchRowMixin, PurchaseItemBase, Base):
81    """
82    Row of data within a purchase batch.
83    """
84    __tablename__ = 'purchase_batch_row'
85    __batch_class__ = PurchaseBatch
86
87    @declared_attr
88    def __table_args__(cls):
89        return cls.__batchrow_table_args__() + cls.__purchaseitem_table_args__() + (
90            sa.ForeignKeyConstraint(['item_uuid'], ['purchase_item.uuid'], name='purchase_batch_row_fk_item'),
91        )
92
93    STATUS_OK                           = 1
94    STATUS_PRODUCT_NOT_FOUND            = 2
95    STATUS_COST_NOT_FOUND               = 3
96    STATUS_CASE_QUANTITY_UNKNOWN        = 4
97    STATUS_INCOMPLETE                   = 5
98    STATUS_ORDERED_RECEIVED_DIFFER      = 6
99
100    STATUS = {
101        STATUS_OK                       : "ok",
102        STATUS_PRODUCT_NOT_FOUND        : "product not found",
103        STATUS_COST_NOT_FOUND           : "product found but not cost",
104        STATUS_CASE_QUANTITY_UNKNOWN    : "case quantity not known",
105        STATUS_INCOMPLETE               : "incomplete",
106        STATUS_ORDERED_RECEIVED_DIFFER  : "ordered / received differ",
107    }
108
109    item_uuid = sa.Column(sa.String(length=32), nullable=True)
110
111    item = orm.relationship(
112        PurchaseItem,
113        doc="""
114        Reference to the purchase item with which the batch row is associated.
115        May be null, e.g. in the case of a "new purchase" batch.
116        """)
117
118
119class PurchaseBatchCredit(PurchaseCreditBase, Base):
120    """
121    Represents a working copy of purchase credit tied to a batch row.
122    """
123    __tablename__ = 'purchase_batch_credit'
124
125    @declared_attr
126    def __table_args__(cls):
127        return cls.__purchasecredit_table_args__() + (
128            sa.ForeignKeyConstraint(['row_uuid'], ['purchase_batch_row.uuid'], name='purchase_batch_credit_fk_row'),
129        )
130
131    uuid = uuid_column()
132
133    row_uuid = sa.Column(sa.String(length=32), nullable=True)
134
135    row = orm.relationship(
136        PurchaseBatchRow,
137        doc="""
138        Reference to the batch row with which the credit is associated.
139        """,
140        backref=orm.backref(
141            'credits',
142            doc="""
143            List of :class:`PurchaseBatchCredit` instances for the row.
144            """))
145
146    def __unicode__(self):
147        if self.cases_shorted is not None and self.units_shorted is not None:
148            qty = "{} cases, {} units".format(
149                pretty_quantity(self.cases_shorted),
150                pretty_quantity(self.units_shorted))
151        elif self.cases_shorted is not None:
152            qty = "{} cases".format(pretty_quantity(self.cases_shorted))
153        elif self.units_shorted is not None:
154            qty = "{} units".format(pretty_quantity(self.units_shorted))
155        else:
156            qty = "??"
157        qty += " {}".format(self.credit_type)
158        if self.credit_type == 'expired' and self.expiration_date:
159            qty += " ({})".format(self.expiration_date)
160        if self.credit_type == 'mispick' and self.mispick_product:
161            qty += " ({})".format(self.mispick_product)
162        if self.invoice_total:
163            return "{} = ${:0.2f}".format(qty, self.invoice_total)
164        return qty
Note: See TracBrowser for help on using the repository browser.