Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Subract sums of two queries from each other to get subtotal

Contributor ,
Oct 29, 2008 Oct 29, 2008
Once again, I'm in over my head - help help!
I have been struggling with this off and on over the last couple weeks and I'm not sure to look for a solution.
Here's what I'm trying to do:

Schools send checks covering workshop fees, multiple registrations per workshop and per school. Subtotal the amounts of the checks per school. Add the amounts of the paid registration fees per school, and subtract the subtotal from the subtotal of checks. Display the result.

I feel like I'm going in the right direction, but I'm obviously missing something essential because I get this error:

The system has attempted to use an undefined value, which usually indicates a programming error, either in your code or some system code.

Null Pointers are another name for undefined values.

The error occurred in C:\Inetpub\wwwroot\crtis\admin\schoolFin\allSchoolFin_credit.cfm: line 65

63 : </cfquery>
64 :
65 : <cfquery name="getSubTotal" dbtype="query">
66 : SELECT getSTChecks.s_SchoolName AS s_SchoolName, getSTWSCost.s_SchoolName, SUM(getSTChecks.STChecks - getSTWSCost.STWSCost) AS SubTotal
67 : FROM getSTChecks, getSTWSCost

I would be grateful for either a nudge toward some reading (CFWACK?) or if someone wants to take a look at my code and make a suggestion, that would be most welcome.
1.7K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Oct 29, 2008 Oct 29, 2008
> Null Pointers are another name for undefined values.

I have only skimmed the code, but noticed the initial query uses LEFT JOINs. So it is possible the values you are attempting to sum may be NULL. Sometimes QoQ have problems with queries that contain NULL values. Try replacing the null values with a default number like 0.

The syntax may vary, but most databases support the COALESCE function. You can use it to return an alternate value if a column value is null.
http://en.wikipedia.org/wiki/Null_(SQL)#COALESCE

SELECT COALESCE(wrp.CheckAmount, 0) AS wrp_CheckAmount, ....etc...


> <cfquery name="getSubTotal" dbtype="query">

BTW, I think you are also missing a WHERE clause in the getSubTotal query


That said, it may be possible to do the sums in your intial query. Assuming you are not using all of the extra values elsewhere in the page.




Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Oct 29, 2008 Oct 29, 2008
Thanks so much for taking a look!

Re the nulls - the only place where I could think that null values were being accessed was the WorkshopRegPaymentID in the WorkshopRegistration table, so I just went ahead and changed those to '0'. No luck.

Then I thought, hmmm, maybe I don't need that value after all, since all I'm trying to do at this point is grab the checks for each school and the paid registrations for each school. (Later I'll need to connect the payment id's, since I want to build something that will apply payments for each registration and attribute them to certain checks.) I commented those lines out (just in case), and made the other changes you suggested.

So here's where I'm at now - I seem to have moved forward somewhat, but now it's telling me that "wr.WorkshopSessionID" could not be bound. Very puzzling.
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Oct 29, 2008 Oct 29, 2008

> Re the nulls - the only place where I could think that null values were being
> accessed was the WorkshopRegPaymentID in the WorkshopRegistration table, so I
> just went ahead and changed those to '0'. No luck.

Well, there may not necessarily be literal nulls in your tables. They can occur as a result of the LEFT JOINs. With OUTER joins, if there are no matching records in the outer table(s), a NULL will be returned instead. That is why you must use COALESCE to replace the nulls with another value.
http://en.wikipedia.org/wiki/JOIN#Outer_joins


> but now it's telling me that "wr.WorkshopSessionID" could not be bound. Very puzzling.
> FROM WorkshopRegistration as wr, WorkshopRegPayment as wrp

Remove the extra reference to ", WorkshopRegPayment as wrp". But you will still get an error because some of its columns are still referenced in the SELECT list.

So do you actually need all of the columns in your SELECT list? (Still trying to get a handle on all the relationships.) If not, there may be a simpler query that would get you the totals needed without all of the QoQ's...

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Oct 29, 2008 Oct 29, 2008
>So do you actually need all of the columns in your SELECT list?

I guess not... I think at first I was going to use the same query for the subtotal display and also the page where I attribute payments to checks. So I guess I could get rid of the session name, date, and event id and name. And I really don't need the county id - I just left it there because I didn't want to take the time to fix the output table yet. (Good grief - I told you it was a mess!)

So - I'm using the WorkshopSessionID's to connect the registrations to the workshop session records (which have the cost in them). The EmployeeID's are connecting the schools with the the registrations, and the SchoolID's are connecting the checks with the schools. (Still getting that pesky '"wr.WorkshopSessionID" could not be bound' error.)
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Oct 29, 2008 Oct 29, 2008
Hooray! I think this did the trick! Thank you so kindly for your patience and for sharing your knowledge!

Here's the final code:

<cfquery datasource="#db#" name="paidReg">
SELECT
wr.EmployeeID AS wr_EmployeeID,
wr.WorkshopRegistrationID AS wr_WorkshopRegistrationID,
wr.WorkshopSessionID AS wr_WorkshopSessionID,
wr.WorkshopRegPaymentID AS wr_WorkshopRegPaymentID,
wr.WorkshopPaid AS wr_WorkshopPaid,
wr.WorkshopCompleted AS wr_WorkshopCompleted,

wrp.WorkshopRegPaymentID AS wr_WorkshopRegPaymentID,
COALESCE(wrp.CheckAmount,0) AS wrp_CheckAmount,
wrp.SchoolID AS wrp_SchoolID,

wes.WorkshopSessionID AS wes_WorkshopSessionID,
COALESCE(wes.WorkshopSessionCost,0) AS wes_WorkshopSessionCost,

e.EmployeeID AS e_EmployeeID,
e.SchoolID AS e_SchoolID,

s.SchoolID AS s_SchoolID,
s.SchoolName AS s_SchoolName

FROM WorkshopRegistration as wr

LEFT JOIN WorkshopRegPayment AS wrp
ON wr.WorkshopRegPaymentID = wrp.WorkshopRegPaymentID
LEFT JOIN WorkshopEventSessions AS wes ON wr.WorkshopSessionID = wes.WorkshopSessionID
LEFT JOIN Employee AS e ON wr.EmployeeID = e.EmployeeID
INNER JOIN School AS s ON e.SchoolID = s.SchoolID

WHERE wr.WorkshopPaid = 'True'
AND wr.WorkshopCompleted = 'True'
AND wes.WorkshopSessionCost <> 0

ORDER BY s_SchoolName
</cfquery>

<!--- use a QoQ to calculate preliminary subtotals for Checks Received--->
<cfquery name="getSTChecks" dbtype="query">
SELECT s_SchoolName, SUM(wrp_CheckAmount) AS STChecks
FROM paidReg
GROUP BY s_SchoolName
</cfquery>

<!--- use a QoQ to calculate preliminary subtotals for WorkshopSessionCost--->
<cfquery name="getSTWSCost" dbtype="query">
SELECT s_SchoolName, SUM(wes_WorkshopSessionCost) AS STWSCost
FROM paidReg
GROUP BY s_SchoolName
</cfquery>

<cfquery name="getSubTotal" dbtype="query">
SELECT getSTChecks.s_SchoolName AS s_SchoolName, getSTWSCost.s_SchoolName, SUM(getSTChecks.STChecks - getSTWSCost.STWSCost) AS SubTotal
FROM getSTChecks, getSTWSCost
WHERE getSTChecks.s_SchoolName = getSTWSCost.s_SchoolName
GROUP BY s_SchoolName
</cfquery>


<!--- join it back to your main query using another a QoQ--->
<cfquery name="paidReg" dbtype="query">
SELECT paidReg.*, getSubTotal.SubTotal, getSubTotal.s_SchoolName AS s_SchoolName
FROM paidReg, getSubTotal
WHERE paidReg.s_SchoolName = getSubTotal.s_SchoolName
</cfquery>
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Oct 29, 2008 Oct 29, 2008
> Still getting that pesky '"wr.WorkshopSessionID" could not
> be bound' error.)

> FROM WorkshopRegistration as wr, WorkshopRegPayment as wrp

You are missing the LEFT JOIN .. INNER JOIN ... syntax between those two tables. So the database is probably getting confused. Try reverting to what you had in your original query:

FROM WorkshopRegistration as wr
LEFT JOIN WorkshopRegPayment AS wrp
ON wr.WorkshopRegPaymentID = wrp.WorkshopRegPaymentID
....


But you still need to add COALESCE(..) around the columns used in the QoQ SUM (ie wrp_CheckAmount, wes_WorkshopSessionCost) to try and avoid the nullpointerexception.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Oct 29, 2008 Oct 29, 2008
Glad it is working now.

If you do not need those extra columns, I am relatively certain there is a simpler query that could give you the totals. If I get a chance to review the sql in greater depth later, I may post some suggestions.

Cheers



Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Oct 29, 2008 Oct 29, 2008
That would be lovely. I'm all for simpler ways of doing things!
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Oct 29, 2008 Oct 29, 2008
Oh dear - I just checked something I should have checked before -

I tried outputting just the check amount subtotals, and they're coming up goose eggs - so I need to play with this a little more. I will re-post the code when I figure out why.
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Oct 29, 2008 Oct 29, 2008
I had to separate the check amounts from the session cost query - it seems like the WHERE statement was resulting in the goose eggs.

Updated code:
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Oct 29, 2008 Oct 29, 2008

> Schools send checks covering workshop fees, multiple registrations per workshop
> and per school. Subtotal the amounts of the checks per school. Add the amounts of
> the paid registration fees per school, and subtract the subtotal from the subtotal
> of checks. Display the result.

Can you describe the workshop tables involved, and post a small sample of the pertinent values to show how they related?

WorkshopEvent
WorkshopEventSessions
WorkshopRegistration
WorkshopRegPayment

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Oct 29, 2008 Oct 29, 2008
Certainly -

WorkshopEvent - I involved this table because at some point I was planning on displaying the full title of the event sessions, which includes the event name (WorkshopEventName) and the session name. It doesn't have anything to do with the payment info.

WorkshopEventSessions - The pertinent values from this table would be the session id, session name, session date, session location, and session cost (WorkshopSessionID, WorkshopSessionName, WorkshopSessionDate, WorkshopSessionLocation, WorkshopSessionCost). The name, date, and location would be used for displaying the workshop info, and the id and cost to relate the table to the WorkshopRegistration table.

WorkshopRegistration - These are records representing registrations for workshops. The pertinent values would be the registration id (WorkshopRegistrationID), the employee id (representing the registered attendee, which would link to the Employee table, where each record contains a school id, which would link to the School table), the registration payment id (WorkshopRegPaymentID - this will hold the id of the payment associated with each registration in the WorkshopRegPayment table), a WorkshopPaid column (boolean) and a WorkshopCompleted column (also boolean).

WorkshopRegPayment - This table holds information about payments made to us by different schools to cover registration fees. The pertinent fields are the id (WorkshopRegPaymentID), the school id showing which school sent us the check, and the check amount (CheckAmount).
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Oct 29, 2008 Oct 29, 2008
Okay, then leaving out WorkshopEvent for a moment:

* WorkshopEventSessions - details about the workshop itself
* WorkshopRegistration - who is registered for the workshop session(s)
* WorkshopRegPayment - links checks (ie payments) to registered employees for a given school

MarianneStone wrote:
> WorkshopRegPayment - This table holds information about payments made to us
> by different schools to cover registration fees. The pertinent fields are the id
> (WorkshopRegPaymentID), the school id showing which school sent us the check,
> and the check amount (CheckAmount)

Unless I am missing a connection missing here.. if WorkshopRegPayment contains the school ID, you can get the total payments made (for each school) without ever joining to the WorkshopRegistration table.

You would only need to join to WorkshopRegistration to get the paid registrations, for each school. I assume the difference between the two values represents un-applied payments. Is that correct? For example, let us say you have one check for School ABC:

[WorkshopRegistration] Check# 123 CheckAmount: $500.00
[WorkshopRegPayment] (applies to)
- workshop: A employee: JOHN session cost: $150.00
- workshop: A employee: BOB session cost: $150.00

The unapplied (or remaining) balance for School ABC is $200.00
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Oct 29, 2008 Oct 29, 2008
> FROM WorkshopRegistration as wr
> LEFT JOIN WorkshopRegPayment AS wrp ON
> wr.WorkshopRegPaymentID = wrp.WorkshopRegPaymentID

Hmm... on second thought ... I am missing a connection. If payments are only linked through the registrants table, then what is the difference between these two values:

> Subtotal the amounts of the checks per school. Add the amounts of the > paid registration fees per school





Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Oct 30, 2008 Oct 30, 2008
Sorry for the delay - was in a meeting this a.m.!

I wanted to keep the payments (check info) separate from the registration info, because sometimes the schools send checks to cover multiple workshop events. So that's why the check info would be linked through the registrant table (many-to-one relationship).

The final goal is to create a page where I will display all the unpaid registrations for a school, and also all the available funds that I could use to pay those registrations; I would select the registrations I want to pay for, then select the check I want to use to pay for them.

As I'm writing this, it occurred to me that I really do need, at that point, to show the funds available from each check, not the total amount, since I want to attribute specific payment records to various registration records. But the page you're helping me with is necessary to show that there is a certain amount of funds available from whatever combined check amounts not already used. At some point this will become available for viewing by the schools so that they can see if they have available credit due to overpayment or if someone doesn't attend who was paid for.
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Oct 30, 2008 Oct 30, 2008
> I wanted to keep the payments (check info) separate from the registration info, because sometimes
> the schools send checks to cover multiple workshop events.

Yes, that makes sense. I think what feels off to me is the "WorkshopPaid" flag. It would be easy to over-allocate check payments by marking too many records as "paid". In other words, mark 10 registrants as paid (at $100 each) when the total check amount was only $500.00.

> But the page you're helping me with is necessary to show that there is a certain amount of funds
> available from whatever combined check amounts not already used

Do you actually have a way of distinguishing between checks that were already allocated and ones that have a remaining balance .. or are you trying to determine that on-the-fly using sql?

What database are you using?

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Oct 30, 2008 Oct 30, 2008
> It seems like, in the long run, I wouldn't need the 'Paid' field

Well, the bigger issue is that there is no detailed accounting of which amounts were applied when. So small changes (like adjusting the WorkShop cost amount) could have an unintended cascade effect. But another question is what do you do with wrong or uneven check amounts? Say a school sends a check for $532.62. But the workshops for their employees only cost $500.00. There is $32.62 left over. Since you are not storing amounts, how do you apply the remaining amount ... or can you even apply it?

> I'm using MS SQL for the active database

To just calculate the overall totals per school, I would probably create two views. Something like the attached. Once you have them, you can join them together to get the totals.

BTW, you do not have to use views. But if you are going to reuse the query logic, it makes more sense to write it once as a view. Then you can reuse it many times.







Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Oct 30, 2008 Oct 30, 2008
Thank you for the code! Yes, this is much simpler way of going about things.

>Well, the bigger issue is that there is no detailed accounting of which amounts were applied when

There currently are notes on the paper registrations showing which checks in what amount were received on what date that were applied to that specific registration - the problem is that one has to manually go through them to add them up. If I didn't want to connect them with the larger application (which we use to register people, track their attendance and payment etc.) I might just enter everything into an Excel spreadsheet, indeed, that was the former solution - but I need to do more than that. You do bring up a good point - I need to have another field that records the date the payment was applied to the registration - something I know how to do!

>So small changes (like adjusting the WorkShop cost amount) could have an unintended cascade effect

The workshop costs don't change much - they have been $12 per session forever for the regular workshops, and sometimes $25 for the more intensive ones; never any fractions created by cents. It's all pretty straightforward (thank goodness!) I suppose the costs might change eventually, but it would only change for a specific workshop, and the cost would be set well in advance of the payments being applied. So I don't think there would ever be a cascade effect. I will note and remember this, though, in case I ever learn how to do this stuff really well and have the opportunity to build something that is more active/fluid, more like what I imagine a registration site for public workshops that accepts and applies registrations and payments given online, immediately, and with messy things like tax and other odd fees. My solution would certainly not work for that. It's all very "this office" specific.

>Since you are not storing amounts, how do you apply the remaining amount ... or can you even apply it?

Oh, but I am storing them - the total check amount is stored in WorkshopRegPayments, and the application of that payment would be stored in the appropriate registration records. The leftover would sit there until it was "applied" to other registrations. I do plan to somehow show an updated amount per check as the registrations are updated with the payment info - but it will also depend on me to add up multiples of $12 or $25 in my head as I select the registrations (something I think I can manage ;D).
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Oct 30, 2008 Oct 30, 2008
> SELECT getSTChecks.s_SchoolName AS s_SchoolName, getSTWSCost.s_SchoolName,
> SUM(getSTChecks.STChecks - getSTWSCost.STWSCost) AS SubTotal
> ....
> I suppose the costs might change eventually, but it would only change for a specific workshop,
> and the cost would be set well in advance of the payments being applied. So I don't think
> there would ever be a cascade effect.

I must be missing something, because I do not see how you could avoid it. I understand you track the total check amounts in the payments table. But you are using wes_WorkshopSessionCost and the "Paid" flag to calculate the amounts of registrations that are paid. So ... change the workshop cost .. and you instantly change those totals.

>Since you are not storing amounts, how do you apply the remaining amount ... or can you even apply it?

> but it will also depend on me to add up multiples of $12 or $25 in my head as I select the registrations
> (something I think I can manage ;D).

It sounds like it would probably work out in most cases, except if the check amount was wrong 😉
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Oct 30, 2008 Oct 30, 2008
>It would be easy to over-allocate check payments ...
>Do you actually have a way of distinguishing between checks that were already allocated...

I have a large pile of paper (registrations and copies of checks) with notes on them! 😄 The goal of this project is to be able determine the allocation with SQL. Unfortunately I am in the position of both having to do the work that the application I am building will eventually do, *and* building the application. The silver lining is that I think I'll build something very useful to the person who steps in after me (who will possibly not be a web designer, but more of an admin) because I will know what they will need to get the work done efficiently.

It seems like, in the long run, I wouldn't need the 'Paid' field, because I could use the 'WorkshopRegPaymentID' field to indicate payment. Until then, though, I need to keep it because in another part of this project, I'm displaying rosters that show 'paid' and 'completed' that involve that field.

I'm using MS SQL for the active database. I do some work with Access locally.
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Oct 31, 2008 Oct 31, 2008
>So ... change the workshop cost .. and you instantly change those totals.

The cost wouldn't change for the workshops that were already attended and marked paid. If we told them that the workshop was $12, it would stay $12. (This is a Catholic organization - very, *very* little changes around here ;D)

I do understand what you're saying about totals changing; mistakes are sometimes made - I recently set up something for invoicing, and when we printed and sent them out, one of the workshop sessions was incorrectly priced, so some of the invoices were wrong - but it was a simple thing to fix, since we're in constant communication with the schools (there are a little over 60 of them, but usually no more than 5 or so are represented at a workshop). In this case, we are offering them a check for the overage, or credit toward other workshops (which is another one of the reasons I'm trying to work out something that shows the funds left over, just in case). It happens very seldom, only once in the 3 years I've been here, and it only affected about three schools.

If something like this happened after we already applied payments sent, it would just mean (if the workshop changed from higher to lower) that the schools would have extra money to apply toward future workshops, or (if the workshop changed from lower to higher) if it was our mistake, we would probably eat it. They all will be sending teachers in the future, so it isn't a question of whether or not they'll want to take a workshop again!

>It sounds like it would probably work out in most cases, except if the check amount was wrong 😉

If the check amount is wrong, there are a few different options. We can send the check back and request the correct amount, or we can keep the check, only record the correct amount (we are not accounting or finance so if I only record the amount of the check we're going to use it's fine) and send them a check for the overage. In this case I usually make a note in the 'Memo' field with the actual amount of the check.
Once again, I realize this wouldn't work for a "real world" application - but like I said, if I ever have the opportunity (and skill!) to develop something like that, I would take all of those things into account. I guess it would be good practice now to do it, but frankly, I don't have the luxury of time to worry about it. The workshops keep happening, the checks are piling up! and I'm also in charge of tracking and correcting the registrations, adding new teachers to the db, posting the workshops to the website, etc., etc. - and in the mean time, building something that will allow me to do this all from an interface instead of directly with the db.
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Oct 31, 2008 Oct 31, 2008
> I do understand what you're saying about totals changing;
> ..
> Once again, I realize this wouldn't work for a "real world" application - but like I said, if I ever
> have the opportunity (and skill!) to develop something like that, I would take all of those things
> into account. I guess it would be good practice now to do it, but frankly, I don't have the luxury
> of time to worry about it.


Okay. As long as you are aware of the issue. I just wanted to be sure it would not take you by surprise two months down the road ;-)
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Contributor ,
Oct 31, 2008 Oct 31, 2008
>Okay. As long as you are aware of the issue. I just wanted to be sure it would not take you by surprise two months down the road ;-)

I do appreciate that 🙂 I would rather think about it now than be slapping my forehead later!

Once again, you have been *exceedingly* helpful and delightful. Thank you so much, and Happy Hallowe'en!
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Valorous Hero ,
Oct 31, 2008 Oct 31, 2008
LATEST
You are very welcome! Happy Halloween to you too.

Cheers
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Resources