[598-50][@ant] fix: убрать авто-конвертацию паевого в signiss2 — доплата/довзнос по факту только с членского
Ветка signiss2 «факт больше заказа» конвертировала паевой в членский (o.mkt.conv) и добирала довзнос с паевого (o.mkt.fee) автоматически, без Заявления о конвертации. Это нарушало инвариант «паевой→членский только по заявлению»: на выдаче паевой трогать нельзя нигде. Теперь доплата тела (o.mkt.lockm) и довзнос (o.mkt.lockmf) берутся ТОЛЬКО с w.mkt.member; при нехватке — отказ с просьбой сконвертировать заранее. Backend покажет пайщику разложение (с членского / с паевого по заявлению) до подписи. Зачем: деньги пайщика на паевом не должны списываться помимо его явного волеизъявления — конвертация всегда отдельный подписанный документ.
This commit is contained in:
@@ -86,7 +86,7 @@ namespace operations {
|
||||
// marketplace — членская модель «Стола заказов».
|
||||
namespace marketplace {
|
||||
inline constexpr eosio::name LOCK_ORDER = "o.mkt.lock"_n; ///< Резервирование средств заказчика под конкретный Order (TRANSFER w.wal.share → w.mkt.order, Dr 80 / Cr 86 — паевой переходит в целевое финансирование на резерв-кошелёк). Единственный обязательный шаг ledger2 при createorder.
|
||||
inline constexpr eosio::name CONVERT_TO_MKT_MEMBER = "o.mkt.conv"_n; ///< Конвертация паевого взноса в членский кошелёк «Стола заказов» (TRANSFER w.wal.share → w.mkt.member, Dr 80 / Cr 86). Доплата по факту (signiss2, actual > ordered) идёт ИМЕННО с членского программы — паевой сперва конвертируется сюда, напрямую с паевого не списываем.
|
||||
inline constexpr eosio::name CONVERT_TO_MKT_MEMBER = "o.mkt.conv"_n; ///< Конвертация паевого взноса в членский кошелёк «Стола заказов» (TRANSFER w.wal.share → w.mkt.member, Dr 80 / Cr 86). ЕДИНСТВЕННЫЙ путь паевой→членский — только по Заявлению о конвертации (action convert). Автоматической конвертации на выдаче (signiss2) НЕТ: доплата/довзнос по факту берутся с уже внесённого членского (o.mkt.lockm/o.mkt.lockmf), при нехватке — отказ.
|
||||
inline constexpr eosio::name LOCK_FROM_MEMBER = "o.mkt.lockm"_n; ///< Добор резерва заказа с членского «Стола заказов» (TRANSFER w.mkt.member → w.mkt.order, без Dr/Cr — оба кошелька на 86). Парный к o.mkt.conv шаг доплаты по факту: после конвертации добирает резерв под этот же Order.
|
||||
inline constexpr eosio::name UNLOCK_ORDER = "o.mkt.unlock"_n; ///< Снятие резерва при отмене Order'а или недовыдаче (TRANSFER w.mkt.order → w.mkt.member, без Dr/Cr — оба кошелька на 86). Средства возвращаются на членский «Стола заказов» (не на универсальный членский) — остаются в программе и могут быть потрачены на следующие заказы.
|
||||
inline constexpr eosio::name PURCHASE_FROM_SUPPLIER = "o.mkt.purch"_n; ///< Приёмка имущества кооперативом по АПП приёмки от поставщика (Dr 10 / Cr 86, NONE — только бухпроводка, кошельки не двигаются; имущество — аналитика по 10). Атомарно с PAY_SUPPLIER на закрывающей подписи председателя.
|
||||
|
||||
@@ -13,14 +13,15 @@
|
||||
* w.mkt.member на разницу (остаток резерва на членский «Стола заказов»).
|
||||
* затем — consum на fact_cost.
|
||||
*
|
||||
* 3) actual > ordered (доплата по факту — НЕ списываем с паевого напрямую):
|
||||
* 3) actual > ordered (доплата по факту — ТОЛЬКО с членского, паевой не трогаем):
|
||||
* diff = fact_cost - ordered_cost
|
||||
* проверка достаточности средств для diff на w.wal.share (источник конвертации).
|
||||
* o.mkt.conv(diff) — TRANSFER w.wal.share → w.mkt.member, Дт 80 / Кт 86 —
|
||||
* дополнительный паевой взнос конвертируется в членский «Стола заказов».
|
||||
* проверка достаточности diff на w.mkt.member (членский «Стола заказов»).
|
||||
* o.mkt.lockm(diff) — TRANSFER w.mkt.member → w.mkt.order (без проводки) —
|
||||
* добор резерва на этот же Order ИМЕННО с членского программы.
|
||||
* добор резерва на этот же Order с членского программы.
|
||||
* Затем — consum на fact_cost.
|
||||
* Недостающее на членском пайщик переводит ЗАРАНЕЕ отдельным Заявлением о
|
||||
* конвертации (action convert, o.mkt.conv) — авто-конвертации паевого на
|
||||
* выдаче нет НИГДЕ; при нехватке членского транзакция фейлится.
|
||||
*
|
||||
* Status: ready_to_receive → received. actual_quantity, fact_cost,
|
||||
* issue_act_signiss2, warranty_until заполняются.
|
||||
@@ -85,25 +86,20 @@ void marketplace::signiss2(eosio::name coopname,
|
||||
Marketplace::Memo::get_signiss2_correction_less_memo(o.id));
|
||||
|
||||
} else if (fact_cost > o.total_cost) {
|
||||
// actual > ordered: доплату НЕ списываем с паевого напрямую. Дополнительный
|
||||
// паевой взнос конвертируется в членский «Стола заказов» (o.mkt.conv), и уже
|
||||
// с членского программы добирается резерв этого же заказа (o.mkt.lockm).
|
||||
// actual > ordered: доплата по факту — ТОЛЬКО с членского «Стола заказов».
|
||||
// Паевой на выдаче не трогаем НИКОГДА: недостающее пайщик переводит в членский
|
||||
// ЗАРАНЕЕ отдельным Заявлением о конвертации (action convert, o.mkt.conv).
|
||||
// Здесь — проверка членского и добор резерва этого же заказа из него (o.mkt.lockm).
|
||||
const eosio::asset diff = fact_cost - o.total_cost;
|
||||
|
||||
// Проверка доступности diff на паевом заказчика — источнике конвертации.
|
||||
auto bal_share = Marketplace::get_user_wallet_balance(
|
||||
coopname, ledger2_wallets::SHARE_FUND_PAY, orderer);
|
||||
eosio::check(bal_share.available >= diff,
|
||||
std::string{"Недостаточно средств для дооплаты по факту: требуется "} +
|
||||
diff.to_string() + ", доступно " + bal_share.available.to_string());
|
||||
auto bal_member = Marketplace::get_user_wallet_balance(
|
||||
coopname, ledger2_wallets::MARKETPLACE_MEMBER_FUND, orderer);
|
||||
eosio::check(bal_member.available >= diff,
|
||||
std::string{"Недостаточно членских средств «Стола заказов» для дооплаты по факту: требуется "} +
|
||||
diff.to_string() + ", доступно " + bal_member.available.to_string() +
|
||||
". Сперва переведите паевой в членский (Заявление о конвертации).");
|
||||
|
||||
// 1) Конвертация паевой → членский «Стола заказов» (Дт 80 / Кт 86).
|
||||
Ledger2::apply(_marketplace, coopname,
|
||||
operations::marketplace::CONVERT_TO_MKT_MEMBER,
|
||||
diff, orderer, o.hash,
|
||||
Marketplace::Memo::get_signiss2_correction_more_convert_memo(o.id));
|
||||
|
||||
// 2) Добор резерва заказа с членского «Стола заказов» (без проводки, оба на 86).
|
||||
// Добор резерва заказа с членского «Стола заказов» (без проводки, оба на 86).
|
||||
Ledger2::apply(_marketplace, coopname,
|
||||
operations::marketplace::LOCK_FROM_MEMBER,
|
||||
diff, orderer, o.hash,
|
||||
@@ -139,12 +135,19 @@ void marketplace::signiss2(eosio::name coopname,
|
||||
locked_fee - fact_fee, orderer, o.hash,
|
||||
Marketplace::Memo::get_membership_fee_refund_memo(o.id));
|
||||
} else if (fact_fee > locked_fee) {
|
||||
// Факт больше заказа: взнос дособирается с паевого по той же ставке.
|
||||
// Достаточность проверена выше вместе с доплатой стоимости — при
|
||||
// нехватке упадёт walletop с человекочитаемым сообщением.
|
||||
// Факт больше заказа: довзнос дособирается ТОЖЕ с членского «Стола заказов»
|
||||
// (o.mkt.lockmf: w.mkt.member → w.mkt.fee, без проводки), не с паевого.
|
||||
// Недостающее — заранее через Заявление о конвертации; здесь проверка членского.
|
||||
const eosio::asset fee_diff = fact_fee - locked_fee;
|
||||
auto bal_member_fee = Marketplace::get_user_wallet_balance(
|
||||
coopname, ledger2_wallets::MARKETPLACE_MEMBER_FUND, orderer);
|
||||
eosio::check(bal_member_fee.available >= fee_diff,
|
||||
std::string{"Недостаточно членских средств «Стола заказов» для довзноса по факту: требуется "} +
|
||||
fee_diff.to_string() + ", доступно " + bal_member_fee.available.to_string() +
|
||||
". Сперва переведите паевой в членский (Заявление о конвертации).");
|
||||
Ledger2::apply(_marketplace, coopname,
|
||||
operations::marketplace::MEMBERSHIP_FEE_LOCK,
|
||||
fact_fee - locked_fee, orderer, o.hash,
|
||||
operations::marketplace::LOCK_FEE_FROM_MEMBER,
|
||||
fee_diff, orderer, o.hash,
|
||||
Marketplace::Memo::get_membership_fee_topup_memo(o.id));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user