invoicing_payments_processing 1.1.8 → 1.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/bufferpaypalnotification.rb +1 -0
- data/lib/extend_client_by_invoicing_payments_processing.rb +105 -2
- data/lib/invoice.rb +90 -45
- data/lib/movement.rb +128 -64
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 079660aadfbd7106fcc74787e3d86002375ec4b2
|
4
|
+
data.tar.gz: 281a650e189be44ed7e91ca2bf439e876f014eb8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 025fd8f5d7060f21b8bdd2e2d1d087ee57d3ac587c32b8c0aaf03f53fba263da0904b21a00d85d5c6d6fe9c220155783e9541bf2ba5dbf8c49aff3c0e58bea82
|
7
|
+
data.tar.gz: 875037f5c24e6702cfcb8c39bca913d22761e2f1a7ca3d8efe6707edc30a8a8ec0c12e24fdc22da2fb4fa7d1517f5c0463d85aed2744429de5ff77ffa5ecda14
|
@@ -10,9 +10,112 @@ module BlackStack
|
|
10
10
|
|
11
11
|
# crea/actualiza un registro en la tabla movment, reduciendo la cantidad de creditos y saldo que tiene el cliente, para el producto indicado en product_code.
|
12
12
|
def consume(product_code, number_of_credits=1, description=nil)
|
13
|
-
|
13
|
+
# create the consumtion
|
14
|
+
total_credits = 0.to_f - BlackStack::Balance.new(self.id, product_code).credits.to_f
|
15
|
+
total_amount = 0.to_f - BlackStack::Balance.new(self.id, product_code).amount.to_f
|
16
|
+
ratio = total_credits == 0 ? 0.to_f : total_amount.to_f / total_credits.to_f
|
17
|
+
amount = number_of_credits.to_f * ratio
|
18
|
+
cons = BlackStack::Movement.new
|
19
|
+
cons.id = guid()
|
20
|
+
cons.id_client = self.id
|
21
|
+
cons.create_time = now()
|
22
|
+
cons.type = BlackStack::Movement::MOVEMENT_TYPE_CANCELATION
|
23
|
+
cons.description = description.nil? ? 'Consumption' : description
|
24
|
+
cons.paypal1_amount = 0
|
25
|
+
cons.bonus_amount = 0
|
26
|
+
cons.amount = amount
|
27
|
+
cons.credits = number_of_credits
|
28
|
+
cons.profits_amount = -amount
|
29
|
+
cons.product_code = product_code
|
30
|
+
cons.expiration_time = nil
|
31
|
+
cons.save
|
32
|
+
# if there is negative credits
|
33
|
+
prod = BlackStack::InvoicingPaymentsProcessing.product_descriptor(product_code)
|
34
|
+
total_credits = 0.to_f - BlackStack::Balance.new(self.id, product_code).credits.to_f
|
35
|
+
total_amount = 0.to_f - BlackStack::Balance.new(self.id, product_code).amount.to_f
|
36
|
+
sleep(2) # delay to ensure the time of the bonus movement will be later than the time of the consumption movement
|
37
|
+
if total_credits < 0
|
38
|
+
self.adjustment(product_code, total_amount, total_credits, 'Adjustment Because Quota Has Been Exceeded.')
|
39
|
+
end
|
40
|
+
# recaculate amounts in both consumptions and expirations - CANCELADO - Se debe hacer offline
|
41
|
+
#self.recalculate(product_code)
|
42
|
+
# return
|
43
|
+
cons
|
14
44
|
end
|
15
|
-
|
45
|
+
|
46
|
+
# crea un registro en la tabla movment, reduciendo la cantidad de creditos con saldo importe 0, para el producto indicado en product_code.
|
47
|
+
def bonus(product_code, expiration, number_of_credits=1, description=nil)
|
48
|
+
bonus_amount = 0 # Los bonos siempre son por un importa igual a 0.
|
49
|
+
|
50
|
+
bonus = BlackStack::Movement.new
|
51
|
+
bonus.id = guid()
|
52
|
+
bonus.id_client = self.id
|
53
|
+
bonus.create_time = now()
|
54
|
+
bonus.type = BlackStack::Movement::MOVEMENT_TYPE_ADD_BONUS
|
55
|
+
bonus.description = description.nil? ? 'Bonus' : description
|
56
|
+
bonus.paypal1_amount = 0
|
57
|
+
bonus.bonus_amount = bonus_amount
|
58
|
+
bonus.amount = -bonus_amount
|
59
|
+
bonus.credits = -number_of_credits
|
60
|
+
bonus.profits_amount = 0
|
61
|
+
bonus.product_code = product_code
|
62
|
+
bonus.expiration_time = expiration
|
63
|
+
bonus.save
|
64
|
+
# recalculate - CANCELADO
|
65
|
+
#bonus.recalculate
|
66
|
+
# return
|
67
|
+
bonus
|
68
|
+
end
|
69
|
+
|
70
|
+
# crea un registro en la tabla movment, reduciendo la cantidad de creditos con saldo importe 0, para el producto indicado en product_code.
|
71
|
+
def adjustment(product_code, adjustment_amount=0, adjustment_credits=0, description=nil, type=BlackStack::Movement::MOVEMENT_TYPE_ADJUSTMENT)
|
72
|
+
adjust = BlackStack::Movement.new
|
73
|
+
adjust.id = guid()
|
74
|
+
adjust.id_client = self.id
|
75
|
+
adjust.create_time = now()
|
76
|
+
adjust.type = type
|
77
|
+
adjust.description = description.nil? ? 'Adjustment' : description
|
78
|
+
adjust.paypal1_amount = 0
|
79
|
+
adjust.bonus_amount = 0
|
80
|
+
adjust.amount = adjustment_amount
|
81
|
+
adjust.credits = adjustment_credits
|
82
|
+
adjust.profits_amount = -adjustment_amount
|
83
|
+
adjust.product_code = product_code
|
84
|
+
adjust.expiration_time = nil
|
85
|
+
adjust.save
|
86
|
+
adjust
|
87
|
+
end
|
88
|
+
|
89
|
+
# recalculate the amount for all the consumptions, expirations, and adjustments
|
90
|
+
def recalculate(product_code)
|
91
|
+
#
|
92
|
+
amount_paid = 0.to_f
|
93
|
+
credits_paid = 0
|
94
|
+
|
95
|
+
#total_credits = 0.to_f - BlackStack::Balance.new(self.id, product_code).credits.to_f
|
96
|
+
#total_amount = 0.to_f - BlackStack::Balance.new(self.id, product_code).amount.to_f
|
97
|
+
|
98
|
+
self.movements.select { |o|
|
99
|
+
o.product_code.upcase == product_code.upcase
|
100
|
+
}.sort_by { |o| o.create_time }.each { |o|
|
101
|
+
#if o.credits.to_f < 0 # payment or bonus
|
102
|
+
# if o.credits.to_f > 0 && ( o.type==BlackStack::Movement::MOVEMENT_TYPE_CANCELATION || o.type==BlackStack::Movement::MOVEMENT_TYPE_EXPIRATION ) # consumption or expiration
|
103
|
+
# consumption or expiration or bonus
|
104
|
+
if (
|
105
|
+
o.type==BlackStack::Movement::MOVEMENT_TYPE_CANCELATION ||
|
106
|
+
o.type==BlackStack::Movement::MOVEMENT_TYPE_EXPIRATION ||
|
107
|
+
o.type==BlackStack::Movement::MOVEMENT_TYPE_ADJUSTMENT
|
108
|
+
)
|
109
|
+
x = credits_paid.to_f == 0 ? 0 : o.credits.to_f * ( amount_paid.to_f / credits_paid.to_f )
|
110
|
+
o.amount = x
|
111
|
+
o.profits_amount = -x
|
112
|
+
o.save
|
113
|
+
end
|
114
|
+
amount_paid += 0.to_f - o.amount.to_f
|
115
|
+
credits_paid += 0.to_i - o.credits.to_i
|
116
|
+
}
|
117
|
+
end
|
118
|
+
|
16
119
|
# TODO: el cliente deberia tener una FK a la tabla division. La relacion no puede ser N-N.
|
17
120
|
# TODO: se debe preguntar a la central
|
18
121
|
def division
|
data/lib/invoice.rb
CHANGED
@@ -11,6 +11,7 @@ module BlackStack
|
|
11
11
|
many_to_one :buffer_paypal_notification, :class=>:'BlackStack::BufferPayPalNotification', :key=>:id_buffer_paypal_notification
|
12
12
|
many_to_one :client, :class=>:'BlackStack::Client', :key=>:id_client
|
13
13
|
many_to_one :paypal_subscription, :class=>:'BlackStack::PayPalSubscription', :key=>:id_paypal_subscription
|
14
|
+
many_to_one :previous, :class=>:'BlackStack::Invoice', :key=>:id_previous_invoice
|
14
15
|
one_to_many :items, :class=>:'BlackStack::InvoiceItem', :key=>:id_invoice
|
15
16
|
|
16
17
|
# compara 2 planes, y retorna TRUE si ambos pueden coexistir en una misma facutra, con un mismo enlace de PayPal
|
@@ -269,24 +270,67 @@ module BlackStack
|
|
269
270
|
self.save()
|
270
271
|
end
|
271
272
|
|
272
|
-
#
|
273
|
-
#
|
274
|
-
#
|
275
|
-
|
273
|
+
# Verifica que el estado de la factura sea NULL o UNPAID.
|
274
|
+
# Cambia el estado de la factura de UNPAID a PAID.
|
275
|
+
# Crea los registros contables por el pago de esta factura: un registro por cada item, y por cada bono del plan en cada item.
|
276
|
+
# Los registros en la table de movimientos se registraran con la fecha del parametro sql_payment_datetime.
|
277
|
+
# Las fechas de expiracion de los movimientos se calculan seguin la fecha del pago.
|
278
|
+
#
|
279
|
+
# sql_payment_datetime: Fecha-hora del pago. Por defecto es la fecha-hora actual.
|
280
|
+
#
|
281
|
+
def getPaid(payment_time=nil)
|
282
|
+
payment_time = Time.now() if payment_time.nil?
|
283
|
+
|
276
284
|
if self.canBePaid? == false
|
277
285
|
raise "Method BlackStack::Invoice::getPaid requires the current status is nil or unpaid."
|
278
286
|
end
|
279
287
|
# marco la factura como pagada
|
280
288
|
self.status = BlackStack::Invoice::STATUS_PAID
|
281
289
|
self.save
|
290
|
+
# expiracion de creditos de la factura anterior
|
291
|
+
i = self.previous
|
292
|
+
if !i.nil?
|
293
|
+
InvoiceItem.where(:id_invoice=>i.id).all { |item|
|
294
|
+
#
|
295
|
+
BlackStack::Movement.where(:id_invoice_item => item.id).all { |mov|
|
296
|
+
#
|
297
|
+
mov.expire if mov.expiration_on_next_payment == true
|
298
|
+
#
|
299
|
+
DB.disconnect
|
300
|
+
GC.start
|
301
|
+
} # BlackStack::Movement.where(:id_invoice_item => item.id).all { |mov|
|
302
|
+
#
|
303
|
+
DB.disconnect
|
304
|
+
GC.start
|
305
|
+
} # InvoiceItem.where(:id_invoice=>i.id).all { |item|
|
306
|
+
end
|
282
307
|
# registro los asientos contables
|
283
|
-
InvoiceItem.where(:id_invoice=>self.id).all { |item|
|
284
|
-
|
308
|
+
InvoiceItem.where(:id_invoice=>self.id).all { |item|
|
309
|
+
# obtengo descriptor del plan
|
310
|
+
plan = BlackStack::InvoicingPaymentsProcessing.plan_descriptor(item.item_number)
|
311
|
+
# obtengo descriptor del producto
|
312
|
+
prod = BlackStack::InvoicingPaymentsProcessing.product_descriptor(plan[:product_code])
|
313
|
+
# registro el pago
|
314
|
+
BlackStack::Movement.new().parse(item, BlackStack::Movement::MOVEMENT_TYPE_ADD_PAYMENT, "Invoice Payment", payment_time, item.id).save()
|
315
|
+
# agrego los bonos de este plan
|
316
|
+
plan[:bonus_plans].each { |h|
|
317
|
+
plan_bonus = BlackStack::InvoicingPaymentsProcessing.plan_descriptor(h[:item_number])
|
318
|
+
raise "bonus plan not found" if plan_bonus.nil?
|
319
|
+
bonus = BlackStack::InvoiceItem.new
|
320
|
+
bonus.id = guid()
|
321
|
+
bonus.id_invoice = self.id
|
322
|
+
bonus.product_code = plan_bonus[:product_code]
|
323
|
+
bonus.unit_price = 0
|
324
|
+
bonus.units = plan_bonus[:credits]
|
325
|
+
bonus.amount = 0
|
326
|
+
bonus.item_number = plan_bonus[:item_number]
|
327
|
+
BlackStack::Movement.new().parse(bonus, BlackStack::Movement::MOVEMENT_TYPE_ADD_BONUS, 'Payment Bonus', payment_time, item.id).save()
|
328
|
+
}
|
285
329
|
#
|
286
330
|
DB.disconnect
|
287
331
|
GC.start
|
288
332
|
}
|
289
|
-
end
|
333
|
+
end # def getPaid
|
290
334
|
|
291
335
|
# Verify if I can add this item_number to this invoice.
|
292
336
|
# Otherwise, it raise an exception.
|
@@ -450,10 +494,10 @@ module BlackStack
|
|
450
494
|
# en este caso la factura se genera antes del pago.
|
451
495
|
# crea uno o mas registros en la tabla invoice_item.
|
452
496
|
def next(i)
|
453
|
-
b = i.buffer_paypal_notification
|
454
|
-
if b == nil
|
455
|
-
raise "Method BlackStack::Invoice::next requires the previous invoice (i) is linked to a record in the table buffer_paypal_notification."
|
456
|
-
end
|
497
|
+
# b = i.buffer_paypal_notification
|
498
|
+
# if b == nil
|
499
|
+
# raise "Method BlackStack::Invoice::next requires the previous invoice (i) is linked to a record in the table buffer_paypal_notification."
|
500
|
+
# end
|
457
501
|
|
458
502
|
id_client = i.id_client
|
459
503
|
c = BlackStack::Client.where(:id=>id_client).first
|
@@ -474,7 +518,8 @@ module BlackStack
|
|
474
518
|
self.create_time = now()
|
475
519
|
self.id_client = c.id
|
476
520
|
self.id_buffer_paypal_notification = nil
|
477
|
-
|
521
|
+
self.id_previous_invoice = i.id
|
522
|
+
self.subscr_id = i.subscr_id
|
478
523
|
self.disabled_for_add_remove_items = true
|
479
524
|
|
480
525
|
i.items.each { |t|
|
@@ -527,17 +572,14 @@ module BlackStack
|
|
527
572
|
# cargo la factura
|
528
573
|
i = BlackStack::Invoice.where(:id=>id_invoice).first
|
529
574
|
raise "Invoice not found (#{id_invoice})" if i.nil?
|
530
|
-
|
531
575
|
# obtengo el total de la factura
|
532
576
|
total = i.total.to_f
|
533
|
-
|
534
577
|
# Si existe un item, y solo uno, con importe igual al reembolso, entonces se aplica todo el reembolso a ese item. Y termina la funcion.
|
535
578
|
# Si existen mas de un item con igual importe que el reembolso, entonces se levanta una excepcion.
|
536
579
|
matched_items = i.items.select { |o| o.amount.to_f == -payment_gross.to_f }
|
537
|
-
|
580
|
+
#
|
538
581
|
if total < -payment_gross
|
539
582
|
raise "The refund is higher than the invoice amount (invoice #{id_invoice}, #{total.to_s}, #{payment_gross.to_s})"
|
540
|
-
|
541
583
|
# Si el monto del reembolso es igual al total de la factura, se hace un reembolso total de todos los items. Y termina la funcion.
|
542
584
|
# Si el monto de la factura es distinto al moneto del reembolso, entonces se levanta una excepcion.
|
543
585
|
elsif total == -payment_gross
|
@@ -555,39 +597,28 @@ module BlackStack
|
|
555
597
|
item1.detail = u.detail.to_s
|
556
598
|
item1.description = u.description.to_s
|
557
599
|
item1.save()
|
558
|
-
BlackStack::Movement.new().parse(item1, BlackStack::Movement::MOVEMENT_TYPE_REFUND_BALANCE).save()
|
600
|
+
BlackStack::Movement.new().parse(item1, BlackStack::Movement::MOVEMENT_TYPE_REFUND_BALANCE, 'Full Refund').save()
|
601
|
+
# si el balance quedo en negativo, entonces aplico otro ajuste
|
602
|
+
net_amount = 0.to_f - BlackStack::Balance.new(self.client.id, u.product_code.to_s).amount.to_f
|
603
|
+
net_credits = 0.to_f - BlackStack::Balance.new(self.client.id, u.product_code.to_s).credits.to_f
|
604
|
+
if net_amount < 0 && net_credits < 0
|
605
|
+
adjust = self.client.adjustment(u.product_code.to_s, net_amount, net_credits, 'Adjustment for Negative Balance after Refund')
|
606
|
+
adjust.id_invoice_item = item1.id
|
607
|
+
adjust.save
|
608
|
+
end # if net_amount < 0
|
559
609
|
# release resources
|
560
610
|
DB.disconnect
|
561
611
|
GC.start
|
562
|
-
}
|
563
|
-
=begin
|
564
|
-
# si existe al menos un item que coincida el total con el monto del reembolso,
|
565
|
-
# entonces selecciono el primero
|
566
|
-
elsif matched_items.size > 0
|
567
|
-
t = matched_items.first
|
568
|
-
h = BlackStack::InvoicingPaymentsProcessing::plans_descriptor.select { |obj| obj[:item_number] == t.item_number }.first
|
569
|
-
raise "Plan not found" if h.nil?
|
570
|
-
item1 = BlackStack::InvoiceItem.new()
|
571
|
-
item1.id = guid()
|
572
|
-
item1.id_invoice = self.id
|
573
|
-
item1.unit_price = t.unit_price.to_f
|
574
|
-
item1.units = -t.units
|
575
|
-
item1.amount = -t.amount.to_f
|
576
|
-
item1.product_code = t.product_code.to_s
|
577
|
-
item1.item_number = t.item_number.to_s
|
578
|
-
item1.detail = t.detail.to_s
|
579
|
-
item1.description = t.description.to_s
|
580
|
-
item1.save()
|
581
|
-
BlackStack::Movement.new().parse(item1, BlackStack::Movement::MOVEMENT_TYPE_REFUND_BALANCE).save()
|
582
|
-
=end
|
612
|
+
} # i.items.each { |u|
|
583
613
|
# reembolso parcial de una factura con un unico item
|
584
614
|
elsif i.items.size == 1
|
585
615
|
t = i.items.first
|
586
|
-
|
616
|
+
#
|
587
617
|
amount = -payment_gross.to_f
|
588
618
|
unit_price = t.amount.to_f / t.units.to_f
|
589
|
-
|
590
|
-
|
619
|
+
float_units = (amount / unit_price.to_f)
|
620
|
+
units = float_units.round.to_i
|
621
|
+
#
|
591
622
|
h = BlackStack::InvoicingPaymentsProcessing::plans_descriptor.select { |obj| obj[:item_number] == t.item_number }.first
|
592
623
|
raise "Plan not found" if h.nil?
|
593
624
|
item1 = BlackStack::InvoiceItem.new()
|
@@ -601,13 +632,27 @@ module BlackStack
|
|
601
632
|
item1.detail = t.detail.to_s
|
602
633
|
item1.description = t.description.to_s
|
603
634
|
item1.save()
|
604
|
-
BlackStack::Movement.new().parse(item1, BlackStack::Movement::MOVEMENT_TYPE_REFUND_BALANCE).save()
|
605
|
-
|
635
|
+
BlackStack::Movement.new().parse(item1, BlackStack::Movement::MOVEMENT_TYPE_REFUND_BALANCE, 'Partial Refund').save()
|
636
|
+
# agrego un ajuste por el redondeo a una cantidad entera de creditos
|
637
|
+
if float_units.to_f != units.to_f
|
638
|
+
adjustment_amount = unit_price.to_f * (units.to_f - float_units.to_f)
|
639
|
+
adjust = self.client.adjustment(t.product_code.to_s, adjustment_amount, 0, 'Adjustment for Partial Refund', BlackStack::Movement::MOVEMENT_TYPE_REFUND_ADJUSTMENT)
|
640
|
+
adjust.id_invoice_item = item1.id
|
641
|
+
adjust.save
|
642
|
+
end
|
643
|
+
# si el balance quedo en negativo, entonces aplico otro ajuste
|
644
|
+
net_amount = 0.to_f - BlackStack::Balance.new(self.client.id, t.product_code.to_s).amount.to_f
|
645
|
+
net_credits = 0.to_f - BlackStack::Balance.new(self.client.id, t.product_code.to_s).credits.to_f
|
646
|
+
if net_amount < 0 && net_credits < 0
|
647
|
+
adjust = self.client.adjustment(t.product_code.to_s, net_amount, net_credits, 'Adjustment for Negative Balance')
|
648
|
+
adjust.id_invoice_item = item1.id
|
649
|
+
adjust.save
|
650
|
+
end # if net_amount < 0
|
651
|
+
# recalculo todos los consumos y expiraciones - CANCELADO - Debe hacerse offline
|
652
|
+
# self.client.recalculate(t.product_code.to_s)
|
606
653
|
else
|
607
654
|
raise "Refund amount is not matching with the invoice total (#{total.to_s}) and the invoice has more than 1 item."
|
608
|
-
|
609
655
|
end
|
610
|
-
|
611
656
|
# release resources
|
612
657
|
DB.disconnect
|
613
658
|
GC.start
|
data/lib/movement.rb
CHANGED
@@ -10,8 +10,10 @@ module BlackStack
|
|
10
10
|
MOVEMENT_TYPE_ADD_BONUS = 1
|
11
11
|
MOVEMENT_TYPE_REASSIGN_BALANCE = 2
|
12
12
|
MOVEMENT_TYPE_REFUND_BALANCE = 3
|
13
|
-
MOVEMENT_TYPE_CANCELATION = 4 # liability with the client is reduced due service delivery
|
14
|
-
MOVEMENT_TYPE_EXPIRATION = 5 # liability with the client is reduced due credits expiration
|
13
|
+
MOVEMENT_TYPE_CANCELATION = 4 # liability with the client is reduced due service delivery. it can be recalculated
|
14
|
+
MOVEMENT_TYPE_EXPIRATION = 5 # liability with the client is reduced due credits expiration. it can be recalculated
|
15
|
+
MOVEMENT_TYPE_ADJUSTMENT = 6 # it can be recalculated
|
16
|
+
MOVEMENT_TYPE_REFUND_ADJUSTMENT = 7 # it cannot be recalculated
|
15
17
|
|
16
18
|
def typeName()
|
17
19
|
if (self.type==MOVEMENT_TYPE_ADD_PAYMENT)
|
@@ -46,17 +48,20 @@ module BlackStack
|
|
46
48
|
end
|
47
49
|
|
48
50
|
# actualiza el registro con los valores del item de una factura
|
49
|
-
# type may be either MOVEMENT_TYPE_ADD_PAYMENT or MOVEMENT_TYPE_ADD_BONUS, but not other value
|
50
|
-
def parse(item, type=MOVEMENT_TYPE_ADD_PAYMENT, description='n/a')
|
51
|
-
|
51
|
+
# type may be either MOVEMENT_TYPE_ADD_PAYMENT or MOVEMENT_TYPE_ADD_BONUS or MOVEMENT_TYPE_REFUND_BALANCE, but not other value
|
52
|
+
def parse(item, type=MOVEMENT_TYPE_ADD_PAYMENT, description='n/a', payment_time=nil, id_item=nil)
|
53
|
+
# the movment must be a payment or a bonus or a refund
|
54
|
+
raise 'Movement must be either a payment or bonus or refund' if type != MOVEMENT_TYPE_ADD_PAYMENT && type != MOVEMENT_TYPE_ADD_BONUS && type != MOVEMENT_TYPE_REFUND_BALANCE
|
55
|
+
#
|
56
|
+
payment_time = Time.now() if payment_time.nil?
|
57
|
+
plan = BlackStack::InvoicingPaymentsProcessing.plan_descriptor(item.item_number)
|
52
58
|
prod = BlackStack::InvoicingPaymentsProcessing.product_descriptor(plan[:product_code])
|
53
|
-
|
54
59
|
if (self.id==nil)
|
55
60
|
self.id=guid()
|
56
61
|
end
|
57
62
|
self.id_client = item.invoice.id_client
|
58
|
-
self.id_invoice_item = item.id
|
59
|
-
self.create_time = item.invoice.billing_period_from
|
63
|
+
self.id_invoice_item = id_item.nil? ? item.id : id_item
|
64
|
+
self.create_time = payment_time #item.invoice.billing_period_from
|
60
65
|
self.type = type
|
61
66
|
if (type != MOVEMENT_TYPE_ADD_BONUS)
|
62
67
|
self.paypal1_amount = item.amount.to_f
|
@@ -70,68 +75,127 @@ module BlackStack
|
|
70
75
|
self.product_code = item.product_code
|
71
76
|
self.profits_amount = 0
|
72
77
|
self.description = description
|
73
|
-
|
78
|
+
if (type == MOVEMENT_TYPE_ADD_BONUS || type == MOVEMENT_TYPE_ADD_PAYMENT)
|
79
|
+
self.expiration_time = DB["SELECT DATEADD(#{prod[:credits_expiration_period].to_s}#{prod[:credits_expiration_period].to_s}, +#{prod[:credits_expiration_units].to_s}, '#{payment_time.to_sql}') AS d"].first[:d].to_s
|
80
|
+
end
|
81
|
+
self.expiration_on_next_payment = plan[:expiration_on_next_payment]
|
82
|
+
self.expiration_lead_period = plan[:expiration_lead_period]
|
83
|
+
self.expiration_lead_units = plan[:expiration_lead_units]
|
84
|
+
#self.give_away_negative_credits = plan[:give_away_negative_credits]
|
74
85
|
self.save()
|
86
|
+
# recalculate - CANCELADO - SE DEBE HACER OFFLINE
|
87
|
+
#self.recalculate
|
88
|
+
#
|
89
|
+
self
|
75
90
|
end
|
76
91
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
if m.expiration_time <= m.create_time
|
98
|
-
raise "Expiration time is lower then creation time."
|
99
|
-
end
|
100
|
-
|
101
|
-
# calculo cuantos creditos tiene este cliente
|
102
|
-
#x = 0.to_f - BlackStack::Balance.new(m.client.id, p[:code]).credits.to_f
|
103
|
-
# calculo los creditos de este movimiento que voy a cancelar
|
104
|
-
x = 0.to_f - m.credits.to_f
|
105
|
-
|
106
|
-
# calculo el credito consumido luego de este movimiento que voy a cancelar
|
107
|
-
y = m.client.movements.select { |o|
|
92
|
+
# Returns the number of credits assigned in the movement that have been consumed.
|
93
|
+
# The movment must be a payment or a bonus
|
94
|
+
def credits_consumed()
|
95
|
+
# the movment must be a payment or a bonus
|
96
|
+
raise 'Movement must be either a payment or a bonus' if self.type != MOVEMENT_TYPE_ADD_PAYMENT && self.type != MOVEMENT_TYPE_ADD_BONUS
|
97
|
+
#puts
|
98
|
+
#puts "product_code:#{self.product_code}:."
|
99
|
+
# itero los pagos y bonos hechos por este mismo producto, desde el primer dia hasta este movimiento.
|
100
|
+
paid = 0
|
101
|
+
self.client.movements.select { |o|
|
102
|
+
(o.type == MOVEMENT_TYPE_ADD_PAYMENT || o.type == MOVEMENT_TYPE_ADD_BONUS) &&
|
103
|
+
o.credits.to_f < 0 &&
|
104
|
+
o.product_code.upcase == self.product_code.upcase
|
105
|
+
}.sort_by { |o| o.create_time }.each { |o|
|
106
|
+
paid += (0.to_f - o.credits.to_f)
|
107
|
+
break if o.id.to_guid == self.id.to_guid
|
108
|
+
}
|
109
|
+
#puts "paid:#{paid.to_s}:."
|
110
|
+
# calculo los credito para este producto, desde el primer dia; incluyendo cosumo, expiraciones, ajustes.
|
111
|
+
consumed = self.client.movements.select { |o|
|
108
112
|
o.credits.to_f > 0 &&
|
109
|
-
o.product_code.upcase ==
|
110
|
-
o.create_time > m.create_time
|
113
|
+
o.product_code.upcase == self.product_code.upcase
|
111
114
|
}.inject(0) { |sum, o| sum.to_f + o.credits.to_f }.to_f
|
115
|
+
#puts "consumed:#{consumed.to_s}:."
|
116
|
+
# calculo los creditos de este movimiento que voy a cancelar
|
117
|
+
credits = 0.to_f - self.credits.to_f
|
118
|
+
#puts "credits:#{credits.to_s}:."
|
119
|
+
#
|
120
|
+
if paid - consumed <= 0 # # se consumio todo
|
121
|
+
#puts "a"
|
122
|
+
return credits
|
123
|
+
else # paid - consumed > 0 # todavia no se consumio todo
|
124
|
+
if paid - consumed > credits # todavia se estan consumiendo creditos de los pagos anteriores
|
125
|
+
#puts "b"
|
126
|
+
return 0
|
127
|
+
else # paid - consumed >= credits # se consumio una parte del credito
|
128
|
+
#puts "c"
|
129
|
+
n = credits >= (paid - consumed) ? credits - (paid - consumed) : credits
|
130
|
+
#puts "n:#{n.to_s}:."
|
131
|
+
return n
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# returns the real expiration based on expiration_time, expiration_lead_period and expiration_lead_units
|
137
|
+
def expiration_lead_time()
|
138
|
+
return nil if self.expiration_time.nil?
|
139
|
+
return self.expiration_time if self.expiration_lead_period.nil? || self.expiration_lead_units.nil?
|
140
|
+
if self.expiration_lead_period == 'H' # hours
|
141
|
+
return self.expiration_time + self.expiration_lead_units.to_i * 60*60
|
142
|
+
elsif self.expiration_lead_period == 'D' # days
|
143
|
+
return self.expiration_time + self.expiration_lead_units.to_i * 24*60*60
|
144
|
+
elsif self.expiration_lead_period == 'W' # weeks
|
145
|
+
return self.expiration_time + self.expiration_lead_units.to_i * 7*24*60*60
|
146
|
+
elsif self.expiration_lead_period == 'M' # months
|
147
|
+
return self.expiration_time + self.expiration_lead_units.to_i * 31*24*60*60
|
148
|
+
elsif self.expiration_lead_period == 'Y' # years
|
149
|
+
return self.expiration_time + self.expiration_lead_units.to_i * 366*24*60*60
|
150
|
+
else
|
151
|
+
return self.expiration_time
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# credits expiration
|
156
|
+
def expire()
|
157
|
+
credits_consumed = self.credits_consumed
|
158
|
+
#
|
159
|
+
self.expiration_start_time = now()
|
160
|
+
self.expiration_tries = self.expiration_tries.to_i + 1
|
161
|
+
self.save
|
162
|
+
#
|
163
|
+
total_credits = 0.to_f - BlackStack::Balance.new(self.client.id, self.product_code).credits.to_f
|
164
|
+
total_amount = 0.to_f - BlackStack::Balance.new(self.client.id, self.product_code).amount.to_f
|
165
|
+
#
|
166
|
+
credits = 0.to_i - self.credits.to_i
|
167
|
+
#
|
168
|
+
credits_to_expire = credits - credits_consumed.to_i #- (0.to_f - self.credits.to_f)).to_i
|
169
|
+
amount_to_expire = total_credits.to_f == 0 ? 0 : credits_to_expire.to_f * ( total_amount.to_f / total_credits.to_f )
|
170
|
+
#
|
171
|
+
exp = BlackStack::Movement.new
|
172
|
+
exp.id = guid()
|
173
|
+
exp.id_client = self.client.id
|
174
|
+
exp.create_time = now()
|
175
|
+
exp.type = BlackStack::Movement::MOVEMENT_TYPE_EXPIRATION
|
176
|
+
exp.id_user_creator = self.id_user_creator
|
177
|
+
exp.description = 'Expiration Because Allocation is Renewed'
|
178
|
+
exp.paypal1_amount = 0
|
179
|
+
exp.bonus_amount = 0
|
180
|
+
exp.amount = amount_to_expire
|
181
|
+
exp.credits = credits_to_expire
|
182
|
+
exp.profits_amount = -amount_to_expire
|
183
|
+
exp.id_invoice_item = self.id_invoice_item
|
184
|
+
exp.product_code = self.product_code
|
185
|
+
exp.save
|
186
|
+
#
|
187
|
+
self.expiration_end_time = now()
|
188
|
+
self.save
|
189
|
+
end # def expire
|
112
190
|
|
113
|
-
|
114
|
-
|
191
|
+
# recalculate the amount for all the consumptions.
|
192
|
+
# The movment must be a payment or a bonus or refund
|
193
|
+
def recalculate()
|
194
|
+
# the movment must be a payment or a bonus or a refund
|
195
|
+
raise 'Movement must be either a payment or bonus or refund' if type != MOVEMENT_TYPE_ADD_PAYMENT && type != MOVEMENT_TYPE_ADD_BONUS && type != MOVEMENT_TYPE_REFUND_BALANCE
|
196
|
+
# recalculate amounts for all the consumptions and expirations
|
197
|
+
self.client.recalculate(self.product_code)
|
198
|
+
end
|
115
199
|
|
116
|
-
# si el monto expirado es positivo, entonces registro
|
117
|
-
# una cancelacion de saldo
|
118
|
-
if z>0
|
119
|
-
amount = ( m.amount.to_f / m.credits.to_f ) * z.to_f
|
120
|
-
m = BlackStack::Movement.new(
|
121
|
-
:id_client => m.client.id,
|
122
|
-
:create_time => now(),
|
123
|
-
:type => BlackStack::Movement::MOVEMENT_TYPE_EXPIRATION,
|
124
|
-
:description => "Expiration of #{m.id.to_guid}",
|
125
|
-
:paypal1_amount => 0,
|
126
|
-
:bonus_amount => 0,
|
127
|
-
:amount => amount,
|
128
|
-
:credits => z,
|
129
|
-
:profits_amount => -amount,
|
130
|
-
:product_code => p[:code],
|
131
|
-
)
|
132
|
-
m.id = guid()
|
133
|
-
m.save
|
134
|
-
end # z>0
|
135
|
-
end # def expire
|
136
200
|
end # class Movement
|
137
201
|
end # module BlackStack
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: invoicing_payments_processing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Leandro Daniel Sardi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-08-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: websocket
|