1 /* 2 * Copyright (c) 2003-2018, John Wiegley. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * - Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * - Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * - Neither the name of New Artisans LLC nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /** 33 * @addtogroup data 34 */ 35 36 /** 37 * @file post.h 38 * @author John Wiegley 39 * 40 * @ingroup data 41 */ 42 #ifndef _POST_H 43 #define _POST_H 44 45 #include "item.h" 46 47 namespace ledger { 48 49 class xact_t; 50 class account_t; 51 52 class post_t : public item_t 53 { 54 public: 55 #define POST_VIRTUAL 0x0010 // the account was specified with (parens) 56 #define POST_MUST_BALANCE 0x0020 // posting must balance in the transaction 57 #define POST_CALCULATED 0x0040 // posting's amount was calculated 58 #define POST_COST_CALCULATED 0x0080 // posting's cost was calculated 59 #define POST_COST_IN_FULL 0x0100 // cost specified using @@ 60 #define POST_COST_FIXATED 0x0200 // cost is fixed using = indicator 61 #define POST_COST_VIRTUAL 0x0400 // cost is virtualized: (@) 62 #define POST_ANONYMIZED 0x0800 // a temporary, anonymous posting 63 #define POST_DEFERRED 0x1000 // the account was specified with <angles> 64 65 xact_t * xact; // only set for posts of regular xacts 66 account_t * account; 67 68 amount_t amount; // can be null until finalization 69 optional<expr_t> amount_expr; 70 optional<amount_t> cost; 71 optional<amount_t> given_cost; 72 optional<amount_t> assigned_amount; 73 optional<datetime_t> checkin; 74 optional<datetime_t> checkout; 75 76 post_t(account_t * _account = NULL, 77 flags_t _flags = ITEM_NORMAL) item_t(_flags)78 : item_t(_flags), xact(NULL), account(_account) 79 { 80 TRACE_CTOR(post_t, "account_t *, flags_t"); 81 } 82 post_t(account_t * _account, 83 const amount_t& _amount, 84 flags_t _flags = ITEM_NORMAL, 85 const optional<string>& _note = none) item_t(_flags,_note)86 : item_t(_flags, _note), xact(NULL), account(_account), amount(_amount) 87 { 88 TRACE_CTOR(post_t, "account_t *, amount_t, flags_t, optional<string>"); 89 } post_t(const post_t & post)90 post_t(const post_t& post) 91 : item_t(post), 92 xact(post.xact), 93 account(post.account), 94 amount(post.amount), 95 cost(post.cost), 96 assigned_amount(post.assigned_amount), 97 checkin(post.checkin), 98 checkout(post.checkout), 99 xdata_(post.xdata_) 100 { 101 copy_details(post); 102 TRACE_CTOR(post_t, "copy"); 103 } ~post_t()104 virtual ~post_t() { 105 TRACE_DTOR(post_t); 106 } 107 description()108 virtual string description() { 109 if (pos) { 110 std::ostringstream buf; 111 buf << _f("posting at line %1%") % pos->beg_line; 112 return buf.str(); 113 } else { 114 return string(_("generated posting")); 115 } 116 } 117 118 virtual bool has_tag(const string& tag, 119 bool inherit = true) const; 120 virtual bool has_tag(const mask_t& tag_mask, 121 const optional<mask_t>& value_mask = none, 122 bool inherit = true) const; 123 124 virtual optional<value_t> get_tag(const string& tag, 125 bool inherit = true) const; 126 virtual optional<value_t> get_tag(const mask_t& tag_mask, 127 const optional<mask_t>& value_mask = none, 128 bool inherit = true) const; 129 130 virtual date_t value_date() const; 131 virtual date_t date() const; 132 virtual date_t primary_date() const; 133 virtual optional<date_t> aux_date() const; 134 135 string payee() const; 136 must_balance()137 bool must_balance() const { 138 return ! has_flags(POST_VIRTUAL) || has_flags(POST_MUST_BALANCE); 139 } 140 141 virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind, 142 const string& name); 143 144 amount_t resolve_expr(scope_t& scope, expr_t& expr); 145 146 std::size_t xact_id() const; 147 std::size_t account_id() const; 148 copy_details(const item_t & item)149 virtual void copy_details(const item_t& item) { 150 const post_t& post(dynamic_cast<const post_t&>(item)); 151 xdata_ = post.xdata_; 152 item_t::copy_details(item); 153 } 154 155 bool valid() const; 156 157 struct xdata_t : public supports_flags<uint_least16_t> 158 { 159 #define POST_EXT_RECEIVED 0x0001 160 #define POST_EXT_HANDLED 0x0002 161 #define POST_EXT_DISPLAYED 0x0004 162 #define POST_EXT_DIRECT_AMT 0x0008 163 #define POST_EXT_SORT_CALC 0x0010 164 #define POST_EXT_COMPOUND 0x0020 165 #define POST_EXT_VISITED 0x0040 166 #define POST_EXT_MATCHES 0x0080 167 #define POST_EXT_CONSIDERED 0x0100 168 169 value_t visited_value; 170 value_t compound_value; 171 value_t total; 172 std::size_t count; 173 date_t date; 174 date_t value_date; 175 datetime_t datetime; 176 account_t * account; 177 178 std::list<sort_value_t> sort_values; 179 xdata_txdata_t180 xdata_t() 181 : supports_flags<uint_least16_t>(), count(0), account(NULL) { 182 TRACE_CTOR(post_t::xdata_t, ""); 183 } xdata_txdata_t184 xdata_t(const xdata_t& other) 185 : supports_flags<uint_least16_t>(other.flags()), 186 visited_value(other.visited_value), 187 compound_value(other.compound_value), 188 total(other.total), 189 count(other.count), 190 date(other.date), 191 account(other.account), 192 sort_values(other.sort_values) 193 { 194 TRACE_CTOR(post_t::xdata_t, "copy"); 195 } throwxdata_t196 ~xdata_t() throw() { 197 TRACE_DTOR(post_t::xdata_t); 198 } 199 }; 200 201 // This variable holds optional "extended data" which is usually produced 202 // only during reporting, and only for the posting set being reported. 203 // It's a memory-saving measure to delay allocation until the last possible 204 // moment. 205 mutable optional<xdata_t> xdata_; 206 has_xdata()207 bool has_xdata() const { 208 return static_cast<bool>(xdata_); 209 } clear_xdata()210 void clear_xdata() { 211 xdata_ = none; 212 } xdata()213 xdata_t& xdata() { 214 if (! xdata_) 215 xdata_ = xdata_t(); 216 return *xdata_; 217 } xdata()218 const xdata_t& xdata() const { 219 return const_cast<post_t *>(this)->xdata(); 220 } 221 222 void add_to_value(value_t& value, 223 const optional<expr_t&>& expr = none) const; 224 225 void set_reported_account(account_t * account); 226 reported_account()227 account_t * reported_account() { 228 if (xdata_) 229 if (account_t * acct = xdata_->account) 230 return acct; 231 assert(account); 232 return account; 233 } 234 reported_account()235 const account_t * reported_account() const { 236 return const_cast<post_t *>(this)->reported_account(); 237 } 238 239 friend class xact_t; 240 241 struct compare_by_date_and_sequence 242 { operatorcompare_by_date_and_sequence243 bool operator()(const post_t * left, const post_t * right) const { 244 gregorian::date_duration duration = 245 left->primary_date() - right->primary_date(); 246 if (duration.days() == 0) { 247 return ((left->pos ? left->pos->sequence : 0) < 248 (right->pos ? right->pos->sequence : 0)); 249 } else { 250 return duration.days() < 0; 251 } 252 } 253 }; 254 }; 255 256 class journal_t; 257 void extend_post(post_t& post, journal_t& journal); 258 void put_post(property_tree::ptree& pt, const post_t& post); 259 260 } // namespace ledger 261 262 #endif // _POST_H 263