source: rattail/rattail/db/model/batch/pricing.py @ 72d1b07

Last change on this file since 72d1b07 was 72d1b07, checked in by Lance Edgar <lance@…>, 8 months ago

Add basic start date support for "future" pricing batch

  • Property mode set to 100644
File size: 8.1 KB
Line 
1# -*- coding: utf-8; -*-
2################################################################################
3#
4#  Rattail -- Retail Software Framework
5#  Copyright © 2010-2022 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"""
24Data model for pricing 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, BatchMixin, ProductBatchRowMixin, Vendor
34from rattail.db.core import filename_column
35
36
37class PricingBatch(BatchMixin, Base):
38    """
39    Primary data model for pricing batches.
40    """
41    __tablename__ = 'batch_pricing'
42    __batchrow_class__ = 'PricingBatchRow'
43    batch_key = 'pricing'
44    model_title = "Pricing Batch"
45
46    min_diff_threshold = sa.Column(sa.Numeric(precision=6, scale=2), nullable=True, doc="""
47    Threshold amount in currency units (i.e. dollars), to which the new *price
48    change* is compared, to determine whether the price change is "minor".
49    """)
50
51    min_diff_percent = sa.Column(sa.Numeric(precision=5, scale=2), nullable=True, doc="""
52    Percentage to which the new price *margin change* is to be compared, to
53    determine whether the price change is "minor".
54    """)
55
56    calculate_for_manual = sa.Column(sa.Boolean(), nullable=True, default=False, doc="""
57    Flag indicating whether prices should be calculated for products which are
58    manually priced under normal circumstances.
59    """)
60
61    start_date = sa.Column(sa.Date(), nullable=True, doc="""
62    Start date for prices within the batch.
63    """)
64
65    input_filename = filename_column(nullable=True, doc="""
66    Base name of the input data file, if applicable.
67    """)
68
69    shelved = sa.Column(sa.Boolean(), nullable=False, default=False, doc="""
70    Flag to indicate whether the batch is "shelved" for later processing.  This
71    may be used to assist with workflow when entering/executing new batches.
72    """)
73
74
75class PricingBatchRow(ProductBatchRowMixin, Base):
76    """
77    Row of data within a pricing batch.
78    """
79    __tablename__ = 'batch_pricing_row'
80    __batch_class__ = PricingBatch
81
82    @declared_attr
83    def __table_args__(cls):
84        return cls.__default_table_args__() + (
85            sa.ForeignKeyConstraint(['vendor_uuid'], ['vendor.uuid'],
86                                    name='batch_pricing_row_fk_vendor'),
87        )
88
89    STATUS_PRICE_UNCHANGED              = 1
90    STATUS_PRICE_INCREASE               = 2
91    STATUS_PRICE_DECREASE               = 3
92    STATUS_PRODUCT_NOT_FOUND            = 4
93    STATUS_PRODUCT_MANUALLY_PRICED      = 5
94    STATUS_CANNOT_CALCULATE_PRICE       = 6
95    STATUS_PRICE_INCREASE_MINOR         = 7
96    STATUS_PRICE_DECREASE_MINOR         = 8
97    STATUS_PRICE_BREACHES_SRP           = 9
98
99    STATUS = {
100        STATUS_PRICE_UNCHANGED          : "price not changed",
101        STATUS_PRICE_INCREASE           : "price increase",
102        STATUS_PRICE_INCREASE_MINOR     : "price increase (minor)",
103        STATUS_PRICE_DECREASE           : "price drop",
104        STATUS_PRICE_DECREASE_MINOR     : "price drop (minor)",
105        STATUS_PRICE_BREACHES_SRP       : "price goes over SRP",
106        STATUS_PRODUCT_NOT_FOUND        : "product not found",
107        STATUS_PRODUCT_MANUALLY_PRICED  : "product is priced manually",
108        STATUS_CANNOT_CALCULATE_PRICE   : "cannot calculate price",
109    }
110
111    vendor_uuid = sa.Column(sa.String(length=32), nullable=True)
112    vendor = orm.relationship(Vendor)
113
114    vendor_item_code = sa.Column(sa.String(length=20), nullable=True, doc="""
115    Vendor-specific code (SKU) for the item.
116    """)
117
118    family_code = sa.Column(sa.Integer(), nullable=True, doc="""
119    Family code for the item.
120    """)
121
122    report_code = sa.Column(sa.Integer(), nullable=True, doc="""
123    Report code for the item.
124    """)
125
126    alternate_code = sa.Column(sa.String(length=20), nullable=True, doc="""
127    Alternate code (UPC, PLU etc.) for the item.
128    """)
129
130    regular_unit_cost = sa.Column(sa.Numeric(precision=9, scale=5), nullable=True, doc="""
131    The "normal" base unit cost for the item, i.e. with no discounts applied.
132    """)
133
134    true_unit_cost = sa.Column(sa.Numeric(precision=9, scale=5), nullable=True, doc="""
135    The "true" base unit cost for the item.  Note that this may vary over time
136    based on allowances etc.
137    """)
138
139    old_true_margin = sa.Column(sa.Numeric(precision=8, scale=3), nullable=True, doc="""
140    Profit margin for the "old" price vs. the "true" unit cost
141    (:attr:`true_unit_cost`).
142    """)
143
144    true_margin = sa.Column(sa.Numeric(precision=8, scale=3), nullable=True, doc="""
145    Profit margin for the "new" price vs. the "true" unit cost
146    (:attr:`true_unit_cost`).
147    """)
148
149    discounted_unit_cost = sa.Column(sa.Numeric(precision=9, scale=5), nullable=True, doc="""
150    The "discounted" base unit cost for the item.  This is meant to be the
151    "effective" unit cost which is used as the basis for the price calculation.
152    """)
153
154    suggested_price = sa.Column(sa.Numeric(precision=8, scale=3), nullable=True, doc="""
155    The "suggested" retail price for the item.  This is assumed to be defined
156    by some external source, i.e. traditional MSRP as opposed to the price
157    being actually suggested by the batch logic.
158    """)
159
160    current_price = sa.Column(sa.Numeric(precision=8, scale=3), nullable=True, doc="""
161    The "current" price for the item (i.e. which overrides the "regular"
162    price), if there is one at time of batch creation/refresh.
163    """)
164
165    current_price_type = sa.Column(sa.Integer(), nullable=True, doc="""
166    The "type" code for :attr:`current_price`, if applicable.  Distinguishes
167    e.g. Sale price from TPR.
168    """)
169
170    current_price_starts = sa.Column(sa.DateTime(), nullable=True, doc="""
171    Start date/time for the :attr:`current_price`, if applicable.
172    """)
173
174    current_price_ends = sa.Column(sa.DateTime(), nullable=True, doc="""
175    End date/time for the :attr:`current_price`, if applicable.
176    """)
177
178    old_price = sa.Column(sa.Numeric(precision=8, scale=3), nullable=True, doc="""
179    The "old" price for the item.  This is assumed to be the "regular" price as
180    of batch creation.
181    """)
182
183    old_price_margin = sa.Column(sa.Numeric(precision=8, scale=3), nullable=True, doc="""
184    Profit margin for the "old" price vs. the "effective" unit cost
185    (:attr:`discounted_unit_cost`).
186    """)
187
188    price_markup = sa.Column(sa.Numeric(precision=5, scale=3), nullable=True, doc="""
189    Markup used to calculate new price, if applicable.
190    """)
191
192    new_price = sa.Column(sa.Numeric(precision=8, scale=3), nullable=True, doc="""
193    The "new" price for the item, as calculated by the batch handler logic.
194    """)
195
196    price_margin = sa.Column(sa.Numeric(precision=8, scale=3), nullable=True, doc="""
197    Profit margin for the "new" price vs. the "effective" unit cost
198    (:attr:`discounted_unit_cost`).
199    """)
200
201    price_diff = sa.Column(sa.Numeric(precision=8, scale=3), nullable=True, doc="""
202    Difference in dollars, between the new and old price amounts.
203    """)
204
205    price_diff_percent = sa.Column(sa.Numeric(precision=8, scale=3), nullable=True, doc="""
206    Difference in percentage, between the new and old price amounts.
207    """)
208
209    margin_diff = sa.Column(sa.Numeric(precision=8, scale=3), nullable=True, doc="""
210    Difference in margin, between the new and old price margins.
211    """)
212
213    manually_priced = sa.Column(sa.Boolean(), nullable=True, doc="""
214    Optional flag to indicate whether the product is manually priced, under
215    normal circumstances.
216    """)
Note: See TracBrowser for help on using the repository browser.