Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use correct paid_for_type on payment #396 #400

Merged
merged 4 commits into from
Dec 12, 2024

Conversation

beesaferoot
Copy link
Contributor

@beesaferoot beesaferoot commented Dec 8, 2024

  • seed meter tokens table for demo company
  • use appropriate paid_for_type as expected on the frontend

Brief summary of the change made

This PR seeds the meter_tokens table, which ensures the tokens field is correctly returned with values on the api/meters/{meter_id}/ endpoint.

Also on success payment, the payment history paid_for_type is updated to match expected values on the frontend.

Closes: #396
Closes: #83

Are there any other side effects of this change that we should be aware of?

We can now see the tokens on the transaction

Screenshot 2024-12-08 at 8 55 17 PM

Describe how you tested your changes?

Pull Request checklist

Please confirm you have completed any of the necessary steps below.

  • Meaningful Pull Request title and description
  • Changes tested as described above
  • Added appropriate documentation for the change.
  • Created GitHub issues for any relevant followup/future enhancements if appropriate.

@beesaferoot beesaferoot requested a review from dmohns December 9, 2024 07:45
@@ -86,11 +86,11 @@ public function onPaymentSuccess(
$this->applianceRatePaymentHistoryService->assign();
break;
case $paidFor instanceof Asset:
$paymentHistory->paid_for_type = Asset::class;
$paymentHistory->paid_for_type = 'appliance';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a massive change. Probably it's correct, but I'm curious: How did you test this?

Copy link
Contributor Author

@beesaferoot beesaferoot Dec 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked on the frontend, the Meter Transanction list has a condition to display approriate message based on the paid for type.

     <md-table-row v-for="token in transactions.tokens" :key="token.id">
            <md-table-cell
              v-text="token.transaction.original_transaction_type"
            ></md-table-cell>
            <md-table-cell
              v-text="moneyFormat(token.transaction.amount)"
            ></md-table-cell>
            <md-table-cell v-if="token.paid_for_type === 'token'">
              Token {{ token.paid_for.token }}
            </md-table-cell>
            <md-table-cell v-else>
              {{ token.paid_for_type }}
            </md-table-cell>
            <md-table-cell
              v-if="token.paid_for_type === 'token'"
              v-text="readable(token.paid_for.energy) + 'kWh'"
            ></md-table-cell>
            <md-table-cell v-else>-</md-table-cell>
            <md-table-cell
              v-text="timeForTimeZone(token.created_at)"
            ></md-table-cell>
          </md-table-row>

However, on the backend, the string is updated to the internal class name (i.e App\Model\Token), which did not match with what the frontend expected; I found that weird.

Also, while searching for the usecases for paid_for_type field I found this factory. The values seem to tally with the frontend expectation

class PaymentHistoryFactory extends Factory {
  protected $model = PaymentHistory::class;

  /**
   * Define the model's default state.
   *
   * @return array
   */
  public function definition() {
      return [
          'id' => 1,
          'transaction_id' => 1,
          'amount' => $this->faker->randomFloat(2, 0, 100),
          'payment_service' => $this->faker->randomElement(['vodacom_transaction', 'airtel_transaction', 'agent_transaction']),
          'sender' => $this->faker->phoneNumber,
          'payment_type' => $this->faker->randomElement(['appliance', 'energy', 'installment', 'access rate']),
          'paid_for_type' => $this->faker->randomElement(['appliance', 'token', 'loan_rate', 'access_rate']),
          'paid_for_id' => 1,
          'payer_type' => 'person',
          'payer_id' => 1,
      ];
  }
}

With the change, I needed to reseed the demo database with the new format. As shown below, using this format appears to correctly show tokens for transactions that are made for tokens.

Screenshot 2024-12-08 at 8 55 17 PM

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are your thoughts? Do you think we should have a different display for tokens? Right now the frontend also gets the token data we could potentially use for that (from the Meter Token table)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are two questions here. Let me address them individually:

What should be the value for paid_for? App\Model\Token vs token

If I understand correctly paid_for defines a Polymorphic relation ship. I would like to follow the practise that is standard in Laravel. On Database level it I think it should be the class type App\Model\Token as per Laravel convention of defining polymorphic relations (but I'm also not a Laravel expert, maybe I got this wrong), rather than the display name token.

So, I'd suggest we adapt the frontend filter to check for App\Model\Token.

How should token be displayed?

My preferred solution would be to adapt the Frontend to display Token objects like this:

Token (1234-1234-1234) or even Token (123 412 341 234) (this would also resolve #83)

But this should be a pure frontend change. I.e. it should change the tokens in the backend, but just the way they are presented to the user

WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After reading up on how Laravel handles Polymorphic relationship, I now understand your explanations.

I will revert this and make the frontend change as suggested. Thank you @dmohns

Comment on lines 270 to 286
// generate meter_token
$meterTokenData = [
'meter_id' => $randomMeter->id,
'token' => Str::random(30),
'energy' => round(
$transactionData->transaction->amount /
$randomMeter['tariff']['price'],
2
),
'transaction_id' => $transaction->id,
];
$meterToken = $this->meterToken->newQuery()->make(['meter_id' => $meterTokenData['meter_id'],
'token' => $meterTokenData['token'], '' => $meterTokenData['energy'],
'transaction_id' => $meterTokenData['transaction_id']]);
$meterToken->save();
Copy link
Member

@dmohns dmohns Dec 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you manage to understand what is the difference between meterToken and the token from above? It seems very confusing to me. Looks like a place where we could refactor things, to make them more intuitive.

Copy link
Contributor Author

@beesaferoot beesaferoot Dec 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is that they both keep track of tokens associated with meter through the transactions table.

But there are some differences, Meter Token is a much better association because it stores a reference to the meter_id (from Meter table)

Token doesn't need to be for a meter because it has a loose model to the meter table but still is tied to a "transaction"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically, I'm looking at this change: c85f9aa#diff-588c01299a5ad9020a72f27600dc3dfd9cc8c4fbd8afaeb2917d0e9090f71d6d

What I'm wondering is: Is MeterToken deprecated? I.e. was MeterToken replaced by the more generic Token model?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds more plausible since the frontend does expect to get tokens from transactions.

Alright, I will go with this assumption.

@beesaferoot
Copy link
Contributor Author

@dmohns Updated, kindly review.

Copy link
Member

@dmohns dmohns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few small comments, other than that LGTM

Comment on lines 95 to 101
formatToken(token) {
// Ensure token is a string
const tokenStr = String(token)
// Format in the desired pattern
// return tokenStr.match(/.{1,4}/g).join('-'); // For "1234-1234-1234"
return tokenStr.match(/.{1,3}/g).join(" ") // For "123 412 341 234"
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you can move this into a JS mixing, similar to currency and timing where formatting functions like readable (for energy) and timeForTimeZone (for timing) are defined?

@beesaferoot
Copy link
Contributor Author

beesaferoot commented Dec 11, 2024

Made some updates; please have a look @dmohns

Comment on lines +5 to +19
class TokenGenerator {
/**
* Generate a random 12-digit token.
*
* @return string
*/
public static function generate() {
$token = '';
for ($i = 0; $i < 12; ++$i) {
$token .= random_int(0, 9);
}

return $token;
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll leave this for now, but one comment for a later improvement: This should probably be a Factory https://laravel.com/docs/11.x/eloquent-factories

Copy link
Member

@dmohns dmohns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks 🙏

@dmohns
Copy link
Member

dmohns commented Dec 12, 2024

One more non-code related comment: Please use Pull Request keywords to link PR's to corresponding issues.

For example in this PR (in the description) you can do

Closes: #396
Closes: #83

@dmohns dmohns merged commit 74681ba into EnAccess:main Dec 12, 2024
10 checks passed
@beesaferoot
Copy link
Contributor Author

@dmohns Noted your feedbacks with thanks 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature Request]: Display Tokens in the application Token Separation
2 participants